scratchtext
Write Scratch projects as text, then compile them to a .sb3 file you can open
on scratch.mit.edu. You can also go the other way:
turn an existing .sb3 back into a .scratch file with all its images.
Install
# Global — adds the `scratchtext` command
npm install -g scratchtext
# Or run once without installing
npx scratchtext game.scratch
# Or install straight from the packaged tarball
npm install -g ./scratchtext-1.0.0.tgz
Then use scratchtext anywhere:
scratchtext --help
scratchtext game.scratch # -> game.sb3
scratchtext game.sb3 # -> game/ (source + images)
From source (for development):
npm install
npm run build # compiles src/ -> dist/
npm run dev -- game.scratch # run without building (via tsx)
> The examples below use scratchtext; from a source checkout use
> node dist/cli.js instead.
1. Using your own images
Drop .png, .jpg, or .svg files next to your .scratch file, or in an
images/ or assets/ subfolder, then refer to them by name.
my-game/
├─ game.scratch
└─ images/
├─ cat.png
└─ sky.svg
sprite "Cat" {
costume "cat.png" // shorthand: costume is named "cat"
costume "happy" = "cat.png" // or give it your own name
on flag { say("hi!") }
}
stage {
backdrop "sky" = "sky.svg"
}
- The costume/backdrop size and rotation center come from the real image
dimensions, so pictures appear at their natural size and rotate around their
middle.
- A bare
costume "cat.png" names the costume after the file (cat).
- Need images from somewhere else? Add a search folder:
node dist/cli.js game.scratch --assets ./shared-art
Compile it:
node dist/cli.js game.scratch # -> game.sb3
node dist/cli.js game.scratch -o out.sb3 # -> out.sb3
See examples/images-demo.scratch for a working example.
2. Converting a .sb3 back to text
Point the tool at a .sb3 and it writes a folder containing the .scratch
source plus every costume and backdrop image.
node dist/cli.js game.sb3
game/
├─ game.scratch
├─ game.monitors.json (only if the project shows variable/list watchers)
├─ images/
│ ├─ Cat.png
│ └─ backdrop1.svg
└─ sounds/
└─ beep.wav
- All sprites, the stage, their costumes/backdrops, sounds, positions,
starting costume, variables, and lists are rebuilt.
- Scripts are rebuilt, including
while and for each loops and detached
stacks (kept as script { } blocks). Blocks scratchtext doesn't support
become // [unsupported block: ...] comments so the file still compiles.
- On-screen watchers (monitors) are saved to a
.monitors.json sidecar
and read back automatically when you re-compile — no need to touch it.
- The output folder is ready to re-compile:
node dist/cli.js game/game.scratch.
The round-trip is designed to be faithful: variables/lists keep their identity
even when two share a name, and watchers stay bound to their variables. Re-open
the rebuilt .sb3 in Scratch to confirm before discarding the original.
Choose the output folder with -o:
node dist/cli.js game.sb3 -o rebuilt/
Extensions and custom blocks
Every extension is supported — the built-in libraries (Pen, Music, Text to
Speech, Translate, Video Sensing, Makey Makey) and custom TurboWarp
extensions. When decompiling, any block the tool doesn't have dedicated syntax
for is written as a generic raw block that recompiles exactly:
raw "music_playNoteForBeats" {
input NOTE = 60
input BEATS = 0.25
}
raw "text2speech_setVoice" {
menu VOICE = "text2speech_menu_voices" voices "ALTO"
}
A raw block can also be used as a reporter inside an expression, e.g.
say(raw "myextension_getValue" { }). Directives inside a raw block:
| Directive | Meaning |
|---|
input NAME = | A value input (number, string, or a reporter) |
bool NAME = | A boolean input |
field NAME = | A dropdown/field value (add id "..." for variable fields) |
menu NAME = "opcode" FIELD | An input backed by a dropdown menu block |
substack NAME { ... } | A C-block branch |
mutation "" | Raw mutation data, if the block has any |
The project's extension list is preserved in .meta.json (alongside
monitors) and re-declared automatically on compile.
Command reference
| Command | Does |
|---|
scratchtext game.scratch | Compile to game.sb3 |
scratchtext game.scratch -o out.sb3 | Compile to a named file |
scratchtext game.scratch --assets DIR | Add an image search folder (repeatable) |
scratchtext game.scratch --json | Print project.json instead of writing .sb3 |
scratchtext game.sb3 | Decompile to game/ (source + images) |
scratchtext game.sb3 -o DIR | Decompile into DIR |
Supported image formats: PNG, JPG, SVG. Sounds: WAV (and MP3).
Sounds work like costumes — drop a file in sounds/ (or next to the .scratch)
and reference it:
sprite "Cat" {
costume "cat.png"
sound "meow.wav" // named "meow"
sound "purr" = "purr.wav"
}