A scripting language for real-time games. Chasm compiles to C99, runs at native speed, and replaces garbage collection with a deterministic three-lifetime memory model that makes every allocation cost visible in the source code.
Game scripts run on a tight loop potentially thousands of times per second. Every invisible allocation, every GC pause, every hidden copy is a frame drop. Languages like Lua and Python hide these costs. Chasm does not.
In Chasm, memory lifetime is part of the syntax. You cannot accidentally allocate into a long-lived region the act of doing so must appear in the source as a function call. The compiler enforces this. There is nowhere for costs to hide.
The result is a language that reads like a scripting language but performs like handwritten C.
This is the core idea. Every value in Chasm exists in exactly one of three memory regions:
Frame < Script < Persistent
| Lifetime | Lives until | Use for |
|---|---|---|
frame |
End of the current tick | Temporaries, intermediate computation |
script |
Hot-reload or explicit reset | Game state that survives across frames |
persistent |
Process exit | High scores, saved data, anything permanent |
Values flow in one direction only upward, from shorter to longer lifetimes. To move a value up, you call a promotion function that is visible in the source:
copy_to_script(x) # frame → script
persist_copy(x) # frame or script → persistentFlowing downward is a compile error. There is no implicit promotion.
In most scripting languages the question "where does this live and when is it freed?" is unanswerable without reading the GC implementation. In Chasm the answer is always in the source. A value annotated :: frame is gone before the next tick begins. A value promoted with copy_to_script costs exactly one copy. A persist_copy costs exactly one copy into a never-freed region.
The memory model is also what makes hot-reload safe. When a script is reloaded, frame state is already gone. script and persistent state is preserved if — and only if — its name, type, and lifetime are unchanged in the new version. The compiler checks this statically before the swap happens.
Allocation is always visible. There is no way to write a Chasm program that silently allocates into a long-lived arena. The promotion call is always in the source. This makes it impossible to accidentally cause GC pressure or frame spikes from allocation patterns you didn't intend.
The type system enforces the lifetime hierarchy. Assigning a frame value to a script variable is a compile error. This catches an entire class of bugs — dangling references to arena memory that has already been cleared — at compile time rather than at runtime.
No runtime, no GC, no VM. The output is plain C99. You can read it, debug it, and profile it with standard tools. The runtime is a single header file (chasm_rt.h). There are no hidden threads, no background collectors, no runtime dependencies beyond libc.
Explicit over implicit. Lifetime promotion is visible. Type annotations are required at declaration sites and function parameters. The pipe operator |> rewrites to normal function calls — no special semantics. What you see is what the compiler generates.
Designed for embedding. Chasm is not a general-purpose language. It is designed to be embedded in game engines the same way Lua is — but without the GC overhead, and with a memory model that integrates naturally with arena-allocating host engines. The host controls all memory through a ChasmCtx passed to every generated function.
| Platform | Status |
|---|---|
| macOS arm64 (Apple Silicon) | ✓ |
| macOS x86_64 (Intel) | ✓ |
| Linux x86_64 | ✓ |
| Windows x86_64 | ✓ |
curl -fsSL https://raw.githubusercontent.com/Chasm-lang/Chasm/main/install.sh | shirm https://raw.githubusercontent.com/Chasm-lang/Chasm/main/install.ps1 | iexBoth scripts detect your platform, download the correct release from GitHub, and add chasm to your PATH.
From source (requires Go 1.21+)
git clone https://github.com/Chasm-lang/Chasm
cd Chasm
go run ./cmd/shazam # installs to ~/.local/bin
go run ./cmd/shazam /usr/local # installs system-wideshazam builds the CLI from source and installs the Cursor/VS Code extension. No Zig required.
chasm run examples/hello_world.chasm
chasm run --engine raylib examples/game/example.chasmcompiler/ — compiler source (written in Chasm)
lexer.chasm
parser.chasm
sema.chasm
codegen.chasm
wasm.chasm
main.chasm
runtime/ — C runtime header included in generated output
chasm_rt.h
bootstrap/ — pre-built bootstrap binaries
bin/
chasm-macos-arm64
chasm-macos-x86_64
chasm-linux-x86_64
chasm-windows-x86_64.exe
engine/ — engine integrations
raylib/ — Raylib 5.5
wasm/ — Canvas2D browser runtime
editors/ — VS Code / Cursor extension
archive/
zig-compiler/ — original Zig compiler (source for bootstrap builds)
install.sh — macOS/Linux one-liner installer
install.ps1 — Windows one-liner installer
SPEC.md — language specification
CHANGELOG.md — version history
