Everything on one page. For detailed explanations, follow the links to the relevant doc.
#include <name.h> // splice in a header library
on flag { } // green flag
on click { } // sprite clicked
on clone { } // started as a clone
on key "space" { } // key pressed
on receive "msg" { } // broadcast received
on backdrop "name" { } // backdrop switched to
on timer > 10 { } // timer exceeds value
on loudness > 50 { } // microphone loudness exceeds value
define blockName(p1, p2) { } // custom block definition
define blockName(p1, p2) returns {
return value // custom block that returns a value
}
if condition { }
if condition { } else { }
if condition { } else if condition { } else { } // elif also works
elif condition { } // alias for else if
repeat 10 { }
forever { }
repeat until (condition) { }
while (condition) { }
do { } while (condition) { } // body always runs once, then test condition
for [i] from 1 to 10 { }
pyfor [item] in [list] { } // iterate over every element of a list
match [score] { // switch is an alias
case 100 { }
case 90, 95 { } // multiple values per case
default { }
}
break // leave the innermost loop (forever, repeat, while, do..while only)
continue // skip to next iteration of the innermost loop
wait(seconds)
wait until condition
stopAll()
stopThis()
stopOtherScripts()
createClone()
createClone("SpriteName")
deleteClone()
yield() // pause one tick (= wait 0)
// Aliases
clone() // createClone("_myself_")
stopMe() // stopThis()
Broadcast-based pseudo-coroutines with parameter passing and lifecycle management.
// Define
scratchroutine name(param1, param2) {
// params are readable as [param1], [param2] inside the body
checkCancel() // stop immediately if cancel has been requested
}
// Launch (fire and forget — equivalent to broadcast)
launch name(arg1, arg2)
// Await (block until done — equivalent to broadcastAndWait)
await name(arg1, arg2)
// Cancel (set cancel flag — routine stops at next checkCancel())
cancel name
// Query (boolean: is the routine currently running?)
if isRunning(name) { }
wait until not isRunning(name)
set [x] to value
change [x] by amount
[x] += n [x] -= n [x] *= n [x] /= n
[x]++ [x]-- // increment / decrement (sugar for change by 1 / -1)
showVariable([x])
hideVariable([x])
&[x] // address of global variable x
*[p] // dereference pointer p (read value)
set *[p] to value // write through pointer
[p][i] // pointer indexing: read at offset p + i
alloc(n) // allocate n cells on heap, return pointer
free(p) // free heap cells at pointer p
Everything dereferences and allocates in one expression — useful for building linked lists and dynamic structures.
Declare a group of related stage variables. Variables are auto-created on compile if they don't exist.
struct player { x, y, hp, speed }
struct enemy { x, y, hp, type }
set [player.x] to 0
set [player.hp] to 100
if [player.hp] <= 0 { say("dead") }
Typing [ in the editor shows all struct.field] completions. Typing [player. shows that struct's fields only.
Compile-time named constants. Substituted inline — no Scratch variables, no runtime cost.
enum {
STATE_IDLE = 0,
STATE_WALK = 1,
STATE_DEAD = 2,
MAX_HP = 100,
GREETING = "hello"
}
set [state] to STATE_IDLE // compiles to: set [state] to 0
if [state] = STATE_DEAD { } // compiles to: if [state] = 2 { }
say(GREETING) // compiles to: say("hello")
- Values must be number or string literals — no expressions, no variables
- Omit
= valueto default to0 enums(plural) is an accepted alias- Names are bare (no
[brackets]) and resolve anywhere an expression is valid - Multiple
enumblocks in the same file are merged; later entries win on collision
listAdd(item, [list])
listDelete(index, [list])
listDeleteAll([list])
listInsert(item, index, [list])
listReplace(index, [list], item)
showList([list])
hideList([list])
[list].length() // number of items
[list].item(index) // item at 1-based index
[list][i] // shorthand for .item([i])
[list].contains(value) // boolean
[list].indexOf(value) // 1-based index, or 0 if absent
[list].sort() // sort in place, ascending (Shell sort — O(n^1.5), no recursion required)
[list].sort("desc") // sort in place, descending
// Aggregates (used in `set [x] to …` only)
set [total] to [list].sum() // sum of all numeric items
set [lo] to [list].min() // minimum numeric item
set [hi] to [list].max() // maximum numeric item
set [n] to [list].count(value) // count items equal to value
// Ergonomic aliases (list first, then args — more natural argument order)
append([list], item) // listAdd
push([list], item) // listAdd
remove([list], index) // listDelete
insert([list], index, item) // listInsert
replace([list], index, item) // listReplace
clear([list]) // listDeleteAll
// Bulk population
populateList([list], value, count, clearFirst) // fill with repeated value
populateArray([list], value, count, clearFirst) // alias — identical behavior
// count: any number, or the literal `max` (compiles to 200,000 — Scratch's effective ceiling)
// clearFirst: true/false literal, or a runtime expression
move(steps)
turnRight(degrees)
turnLeft(degrees)
setDirection(degrees) // 0=up 90=right 180=down -90=left
turnTo(degrees) // alias for setDirection()
pointTowards("target") // "_mouse_" or sprite name
goTo(x, y)
goTo("target")
glide(secs, x, y)
glide(secs, "target")
setX(x) setY(y)
changeX(dx) changeY(dy)
bounce()
setRotationStyle("all around" | "left-right" | "don't rotate")
goToFront() goToBack()
moveForward(n) moveBackward(n)
// Reporters
xPos yPos direction
distanceTo("target")
say(message)
sayFor(message, secs)
think(message)
thinkFor(message, secs)
switchCostume("name")
nextCostume()
switchBackdrop("name")
switchBackdropAndWait("name")
nextBackdrop()
setSize(percent)
changeSize(amount)
show() hide()
setEffect("effect", value) // color fisheye whirl pixelate mosaic brightness ghost
changeEffect("effect", amount)
clearEffects()
// Reporters
size costumeNum costumeName
penDown() penUp() // aliases: down() up()
penClear()
stamp()
setPenColor(color) // #hex literal, or a string/expression
setPenSize(size)
changePenSize(amount)
setPenColorParam("param", value) // color saturation brightness transparency
changePenColorParam("param", amount)
// same commands, pen.* namespaced form:
pen.down() pen.up() pen.clear() pen.stamp()
pen.setColor(color) pen.setSize(size) pen.changeSize(amount)
pen.setColorParam("param", value) pen.changeColorParam("param", amount)
play("name")
playUntilDone("name")
stopSounds()
setVolume(percent)
changeVolume(amount)
setSoundEffect("PITCH" | "PAN LEFT/RIGHT", value)
changeSoundEffect("PITCH" | "PAN LEFT/RIGHT", amount)
clearSoundEffects()
// Reporter
volume
broadcast("message")
broadcastAndWait("message")
touching("_edge_" | "_mouse_" | "SpriteName") // boolean
key("key name") // boolean
askAndWait("question")
answer mouseDown mouseX mouseY
timer loudness size
costumeNum costumeName volume
username daysSince2000
resetTimer()
currentTime("year" | "month" | "date" | "day" | "hour" | "minute" | "second")
distanceTo("target")
xOf("sprite") yOf("sprite") directionOf("sprite")
costumeNumOf("sprite") costumeNameOf("sprite")
sizeOf("sprite") volumeOf("sprite")
setDragMode("draggable" | "not draggable")
abs(n) round(n) floor(n) ceiling(n) ceil(n)
sqrt(n) exp(n) pow10(n) ln(n) log(n)
sin(deg) cos(deg) tan(deg)
asin(n) acos(n) atan(n)
random(min, max)
clamp(value, min, max)
join(str1, str2)
letterOf(index, string) // 1-based
contains(string, substring) // boolean
"string".length()
[var].length()
Short, friendlier names for commonly-used functions. These compile to exactly the same blocks as their canonical counterparts.
// Motion
step(n) → move(n)
forward(n) → move(n)
left(degrees) → turnLeft(degrees)
right(degrees) → turnRight(degrees)
front() → goToFront()
back() → goToBack()
turnTo(degrees) → setDirection(degrees)
// Pen
down() → penDown()
up() → penUp()
// Looks / output
print(msg) → say(msg)
println(msg) → say(msg)
// Control
clone() → createClone("_myself_")
stopMe() → stopThis()
// Events
send("msg") → broadcast("msg")
sendAndWait("msg") → broadcastAndWait("msg")
// Sensing
ask("question") → askAndWait("question")
// Lists (list-first argument order)
append([list], val) → listAdd(val, [list])
push([list], val) → listAdd(val, [list])
remove([list], idx) → listDelete(idx, [list])
insert([list], idx, val) → listInsert(val, idx, [list])
replace([list], idx, val) → listReplace(idx, [list], val)
clear([list]) → listDeleteAll([list])
breakpoint // pause execution here; open the debug bar
When a breakpoint is hit at runtime, Scratchpiler's debug bar slides in at the bottom of the overlay. Click Resume ▶ to continue execution. You can hit multiple breakpoints in sequence — each one pauses and waits.
Compiles to four blocks: sets [__dbg_at__] to 1, sets [__dbg_resume__] to 0, waits until [__dbg_resume__] = 1, then clears [__dbg_at__]. The overlay polls __dbg_at__ every 100ms to detect the pause.
__asm__ volatile(
looks_say("123"); // real opcode name, not the friendly alias
motion_movesteps(69);
)
__asm__ volatile(
data_changevariableby(counter, 5); // bare name = register (variable reference)
)
__asm__ volatile unsafe(
some_opcode_we_dont_know("hi"); // allowed, no correctness guarantee
)
Uses parentheses, not braces — see asm.md if you just typed { and got a wall of errors. Full opcode/register/unsafe reference: docs/asm.md.
+ - * / mod // arithmetic
< > = != <= >= // comparison (!=, <=, >= desugar to not(...) forms)
a < b < c // chained comparisons (middle operand evaluated twice)
and or not // boolean
cond ? a : b // ternary conditional
true false // boolean literals
42 3.14 -5 // numbers
"hello" // strings (double quotes only)
"score is {[score]}" // string interpolation
"literal {{brace}} is {{}}" // {{}} escapes literal braces
[varName] // variable reference
#ff6600 // hex color
true false // boolean literals
// Everything after // is stripped by the tokenizer, never to be seen by the VM.
"space" "enter" "up arrow" "down arrow" "left arrow" "right arrow"
"a" through "z" "0" through "9"
| Key | Action |
|---|---|
Alt+M |
Open / close scratchpiler overlay |
Ctrl+Enter |
Compile & inject (the moment of truth) |
Ctrl+S |
Compile & inject (for standard editor muscle memory) |
Alt+Shift+F |
Format / auto-indent (hiding structural chaos with spacing) |
Ctrl+Space |
Trigger autocomplete (request assistance from Monaco) |
Esc |
Close overlay |
When paused at a breakpoint, click the Resume ▶ button in the debug bar to continue. The bar disappears once execution resumes.
- Save Often: Chrome likes to discard inactive tab states. If your browser crashes because you ran an unyielded
foreverloop, unsaved code is gone. - Warp Mode Speed: Custom blocks default to their Scratch palette settings. If you need speed, edit the prototype in Scratch's graphical editor to "run without screen refresh."
- Decompiler Opacity: Opcode comments like
// unsupportedmean you're using extensions or blocks scratchpiler has not cataloged. Dragging them around in Scratch is your only recourse. - Keep it Simple: Trying to implement a 3D raycaster in a Tampermonkey-injected DSL is a path to enlightenment or madness. Usually the latter.