Skip to main content

TypeScratch

A programming language that compiles to Scratch 3 (.sb3) files. Write text, get a runnable Scratch project you can open in scratch.mit.edu or TurboWarp.

The official mascot is Lint Zippy, an original character created for TypeScratch (CC BY-NC-ND 4.0).

extension Pen
// your average comment
s "Sprite1"
when gf clicked {
  say(Hello, World!)(2)
  pen.Down
  goto(10, 20)
  pen.Up
  Points = 0
  Name = Scratch Cat
  Points += 1
}
when spr clicked {
  if (days since 2000) > 120 {
    say(idk)
  }
}

Install

pip install typescratch

On Windows, windows-curses is automatically installed for the IDE.

CLI

typescratch build thing.tysh                    # compile to .sb3
typescratch build thing.tysh --out out.sb3      # specify output
typescratch build thing.tysh --debug             # verbose token/AST dump
typescratch ide thing.tysh                       # launch the terminal IDE
typescratch decompile game.sb3                   # decompile .sb3 to .tysh
typescratch decompile game.sb3 --out game.tysh   # specify output
typescratch fmt game.tysh                        # auto-indent in place
typescratch install user/repo                    # install a package from GitHub
typescratch uninstall repo-name                  # remove a package
typescratch list                                 # list installed packages
typescratch meow                                 # print the Scratch Cat in ASCII art
typescratch version

Or use python -m typescratch build thing.tysh if typescratch is not on PATH.

Library API

import typescratch

# Compile a .tysh file to .sb3 (output defaults to <input>.sb3)
typescratch.file("thing.tysh")
typescratch.file("thing.tysh", out="custom.sb3")

# Compile from a source string
sb3_bytes = typescratch.source('s "S" when gf clicked { say(hi) }')
typescratch.source(src, out="out.sb3")

# Decompile a .sb3 file to .tysh source
from typescratch.decompiler import decompile_sb3
source_code = decompile_sb3("game.sb3")

Language reference

Comments

// line comment (only at the start of a line, after whitespace)
// this is because // is also the floor division operator

Extensions

extension Pen
extension Music
extension Text to Speech
extension Translate
extension Video Sensing
extension Makey Makey
extension micro:bit
extension LEGO BOOST
extension LEGO EV3
extension LEGO WeDo 2
extension Go Direct Force

Sprites and Backdrops

s "Player" xy=100, 50 dir=90 size=110 visible=true rot=all around
b "Stage 1" img=./backdrops/forest.svg

If img= is omitted or the file doesn't exist, the sprite gets the official TypeScratch mascot, Lint Zippy, as its default costume.

Sound and Costume Imports

s "Player"
sound meow from "./meow.wav"
sound jump from "./jump.mp3"
costume walk1 from "./walk1.png"
costume walk2 from "./walk2.png"
when gf clicked {
  playSound(meow)
  switchCostumeTo(walk1)
}

Variables

Score = 0
Name = Scratch Cat
Score += 10
Score -= 5
Score *= 2
Score /= 3
Score++           // increment by 1
Score--           // decrement by 1
showVariable(Score)
hideVariable(Score)

Local Variables (inside custom blocks)

def Compute(base) {
  private result = base * 2
  say(result)
}

Lists

list inventory = [sword, shield, potion]
list scores = [10, 20, 30]

inventory.add(new item)
inventory.delete(1)
inventory.delete(all)
inventory.insert(cool thing, 0)
inventory.replace(1, better sword)
inventory.show
inventory.hide

// List reporters (use in expressions):
X = inventory.item(1)
L = inventory.length
Has = inventory.contains(sword)
Pos = inventory.itemNum(sword)
All = inventory.contents

Hats (events)

when gf clicked { ... }
when spr clicked { ... }
when stage clicked { ... }
when cloned { ... }
when key [space] pressed { ... }
when backdrop switches to [Stage 2] { ... }
when I receive [start game] { ... }
when [loudness] > [10] { ... }
when touching [mouse] { ... }

Motion

move(10)
turnRight(15)
turnLeft(15)
goto(10, 20)
glide(1, 100, 50)
pointInDirection(90)
pointTowards(mouse)
changeX(5)
changeY(5)
setX(100)
setY(50)
ifOnEdgeBounce
setRotationStyle(left-right)

Looks

say(Hello, World!)(2)
say(Just saying)
think(Hmm...)(1)
switchCostumeTo(costume2)
nextCostume
switchBackdropTo(Stage 2)
changeSize(10)
setSize(100)
show
hide
goFront                  // go to front layer
goBack                   // go to back layer
goFwdLyrs(2)             // go forward 2 layers
goBwdLyrs(2)             // go backward 2 layers

Sound

playSound(meow)
playSoundUntilDone(meow)
stopAllSounds
changePitch(10)
setPitch(100)
changeVolume(10)
setVolume(100)
changeSoundEffect(pitch)(10)
setSoundEffect(pitch)(100)
clearSoundEffects

Control flow

wait(1)
waitUntil (cond)
repeat(10) { ... }
forever { ... }
if (cond) { ... }
if (cond) { ... } elif (cond2) { ... } else { ... }
repeatUntil (cond) { ... }
while (cond) { ... }
forEach (i) in (5) { ... }
allAtOnce { ... }
stop(all)
createCloneOf(myself)
deleteThisClone
broadcast(message1)
broadcast(message1) and wait

Operators (in expressions)

5 + 3                  // addition
10 - 4                 // subtraction
6 * 7                  // multiplication
20 / 4                 // division
17 // 5                // floor division (round(17 / 5))
17 mod 5               // modulo
"Hello" & " World"     // string join
5 != 3                 // not equals
5 >= 5                 // greater than or equal
3 <= 5                 // less than or equal
pickRandom(1, 100)
join(Hello, World)
letterOf(1, Hello)
lengthOf(Hello World)
contains(Hello World, World)
round(3.7)
abs(-5)
floor(3.7)  ceiling(3.2)  sqrt(16)
sin(0)  cos(0)  tan(0)  asin(1)  acos(0)  atan(1)
ln(2.7)  log(100)

Comparison: >, <, =, !=, >=, <= Logic: and, or, not

Ternary Expressions

say([if (x > 5) yes else no])
X = [if (Score > 100) winner else loser]

Sensing

ask(What is your name?) and wait
resetTimer

// Reporters:
answer
mouseDown
mouseX
mouseY
loudness
timer
daysSince2000
username
touching(mouse)
touchingColor(#ff0000)
colorIsTouching(#ff0000, #00ff00)
distanceTo(mouse)
keyPressed(space)
attribute(x position, Sprite1)
current(YEAR)

Pen extension

pen.Clear
pen.Down
pen.Up
pen.SetColor(#ff0000)
pen.SetSize(3)
pen.Stamp

Custom blocks (My Blocks)

def Greet(name) {
  say(join(Hello, name))(2)
}

def FastLoop(n) warp=true {
  repeat(n) { move(1) }
}

def Calc(base number, mult number, debug bool) {
  Result = base * mult
  if debug { say(Result) }
}

when gf clicked {
  Greet(Bob)
  FastLoop(100)
  Calc(5, 3, true)
}

Multi-file Projects (fuse)

fuse "helpers.tysh"
fuse "typescratch_packages/my-lib/main.tysh"

Inline other .tysh files into your project. Recursive, so fused files can fuse other files.

Hidden / Hacked / TurboWarp Blocks

resetCounter
incrementCounter
Count = counter
forEach (i) in (5) { say(i) }
allAtOnce { move(10) turnRight(15) }
changeStretch(10)
setStretch(100)
hideAllSprites
switchBackdropToAndWait(Stage 2)
if isTurboWarp { say(Running in TurboWarp!) }
if isTurboWarp? { say(Running in TurboWarp!) }

Error Types

TypeScratch has friendly error types:

  • SyntaxOops: syntax errors (missing braces, unknown tokens)
  • ForgotOops: using an undefined custom block, variable, or broadcast
  • ArgumentOops: calling a custom block with the wrong number of arguments
  • TypeMismatchOops: using a non-boolean where a boolean is expected (reserved for future use)

All errors include line numbers and "Did you mean?" suggestions.

Decompiler

TypeScratch includes a decompiler that converts .sb3 files back to .tysh source code:

typescratch decompile game.sb3
typescratch decompile game.sb3 --out game.tysh

Tested on griffpatch's appel game (8146 lines decompiled with zero unknown blocks).

IDE

TypeScratch includes a terminal-based IDE with syntax highlighting, auto-indentation, and compile/verify buttons:

typescratch ide              # new file
typescratch ide game.tysh    # open existing file

Controls:

  • F5: Compile to .sb3
  • F6: Verify syntax
  • Ctrl+S: Save
  • Ctrl+Q: Quit
  • Arrow keys, Page Up/Down, Home/End

Formatter

typescratch fmt game.tysh              # format in place
typescratch fmt game.tysh --out out.tysh

Package Manager

typescratch install user/repo          # install from GitHub
typescratch install user/repo@v1.0     # install specific tag
typescratch uninstall repo-name        # remove package
typescratch list                       # list installed packages

Packages are cloned into ./typescratch_packages/. Use fuse to include them:

fuse "typescratch_packages/my-lib/main.tysh"

Easter Eggs

typescratch meow    # prints the TypeScratch mascot in ASCII art

Project structure

typescratch/
    typescratch/
        __init__.py          # public API
        __main__.py          # python -m typescratch entry point
        cli.py               # CLI (build, ide, decompile, fmt, install, meow)
        lexer.py             # .tysh tokenizer
        parser.py            # tokens -> AST
        ast_nodes.py         # AST dataclass definitions
        blocks.py            # TypeScratch syntax -> Scratch opcode table
        codegen.py           # AST -> Scratch project.json
        sb3.py               # .sb3 zip packager
        decompiler.py        # .sb3 -> .tysh decompiler
        ide.py               # terminal IDE (curses)
        package_manager.py   # GitHub package installer
        assets.py            # default mascot (Lint Zippy) and backdrop
        errors.py            # SyntaxOops, ForgotOops, ArgumentOops
        lint_zippy.svg       # official mascot (CC BY-NC-ND 4.0)
        logo.svg             # TypeScratch logo
        logo_ascii.txt       # ASCII art logo for the IDE
        meow.txt             # ASCII art for the meow easter egg

License

Apache License 2.0 for the TypeScratch language and compiler.

The TypeScratch mascot "Lint Zippy" (lint_zippy.svg) is licensed under CC BY-NC-ND 4.0. See MASCOT_LICENSE.

GitHub: https://github.com/commit-to-the-git/typescratch

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

typescratch-1.6.7.tar.gz (290.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

typescratch-1.6.7-py3-none-any.whl (301.2 kB view details)

Uploaded Python 3

File details

Details for the file typescratch-1.6.7.tar.gz.

File metadata

  • Download URL: typescratch-1.6.7.tar.gz
  • Upload date:
  • Size: 290.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.2

File hashes

Hashes for typescratch-1.6.7.tar.gz
Algorithm Hash digest
SHA256 ed9a3d1c08abd188aa6a6c93cdf98f1c5bf37b9111918a8d9511faa6cd549d8f
MD5 420d24bf5d566272528a2a2e21bd6058
BLAKE2b-256 5430e8810e7440072d1051e38f4b90dbd265260a25bed9ae242015066b6cd110

See more details on using hashes here.

File details

Details for the file typescratch-1.6.7-py3-none-any.whl.

File metadata

  • Download URL: typescratch-1.6.7-py3-none-any.whl
  • Upload date:
  • Size: 301.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.2

File hashes

Hashes for typescratch-1.6.7-py3-none-any.whl
Algorithm Hash digest
SHA256 40819b1faa75f650ce38791ab6b89dae319581337f2dc22f42732d76f1a7913b
MD5 641c881f23d74c6246ac9a2a8b2a5576
BLAKE2b-256 d400713c136eb87d7e010cd30d2c52841e089fe7d1a737cbabedee94d28974c3

See more details on using hashes here.

Release history Release notifications | RSS feed

1.7.1

2 files

1.7.0

2 files

1.6.8

2 files

This release

1.6.7 This release

2 files

1.6.2

2 files

1.6.0

2 files

1.3.0

2 files

1.1.0

2 files

1.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page