Simple to write. safe to run.
do divmod(a i64, b i64) -> (i64, i64) {
return a / b, a % b
}
do main() {
const name string = "Grayscale"
mut total i64 = 0
for i in range(1, 6) {
total += i
}
mut quotient, remainder = divmod(total, 4)
if remainder == 0 {
println("${name}: ${total} divides evenly")
} or quotient > 3 {
println("${name}: ${total} / 4 = ${quotient} remainder ${remainder}")
} otherwise {
println("${name}: ${total} is small")
}
}
const Shape enum {
Circle(f64)
Rect(f64, f64)
Point
}
const Vec struct {
x i64
y i64
do scale(self Vec, factor i64) -> Vec {
return Vec{x: self.x * factor, y: self.y * factor}
}
}
do area(shape Shape) -> f64 {
when shape {
is Shape.Circle(radius) { return 3.14159 * radius * radius }
is Shape.Rect(w, h) { return w * h }
default { return 0.0 }
}
}
do main() {
mut v = Vec{x: 2, y: 3}
mut scaled = v.scale(factor: 5)
println("scaled: ${scaled.x}, ${scaled.y}")
println("rect: ${area(Shape.Rect(3.0, 4.0))}")
}
import @io
do cleanup() {
println("cleanup ran")
}
do load(path string) -> (string, Error) {
ensure cleanup()
mut content = io.read_file(path) or_return
return content, nil
}
do main() {
mut content, err = load("missing.txt")
if err != nil {
println("could not load file")
} otherwise {
println(content)
}
}
import @math
do main() {
println("sqrt(144) = ${math.sqrt(144.0)}")
}
- Simplicity — Readable, opinionated syntax — bitwise and membership operators are real keywords (
bit_and,bit_xor,not_in), not punctuation — with familiar per-file aliases (fn,switch/case,elif/else,while,defer) for those who prefer them. Helpful compile-time errors & warnings and runtime panics. Useful CLI commands likegray man,gray check,gray new, andgray watch. - Flexibility — Build scripts and dev tooling, cross-platform CLI utilities, HTTP/JSON backend services, SQLite-backed apps, network daemons, and batch data processing, or learning systems programming fundamentals.
- Modularity — Beyond a small builtin core, everything else needs an import. Stdlib modules, your own
.grayor.grayscalefiles, and C headers can all be imported. - Safety — An automatic scope-based arena management memory model with a compile-time pointer checker that proves no pointer is ever readable after its memory is reclaimed, bounds-checked arrays, strings, and maps, overflow-checked arithmetic, division-by-zero protection, nil pointer checks, stack depth guards, NO pointer arithmetic. The guardrails are on unless you explicitly opt in to unsafe operations like raw pointers (
raw()), manual memory management (@mem), threading (@threads), or C interop (extern import)
@arrays · @atomic · @binary · @channels · @chars · @crypto · @csv · @encoding · @fmt · @http
@io · @json · @maps · @math · @mem · @net · @os · @random · @regex
@runtime · @server · @sqlite · @strconv · @strings · @sync · @threads · @time · @uuid
Download the latest release for your platform from the Releases page. No dependencies required.
Requires Go 1.23+ and a C11 compiler with GNU extensions: GCC 11+, Clang 14+, or TinyCC 0.9.27+. Grayscale uses the first of cc, gcc, or clang it finds. Pass --cc <compiler> to gray or gray build to choose another for one run (gray main.gray --cc tcc), or set GRAY_CC or CC. --cc takes precedence over both. GRAY_CC is the compiler gray uses for .gray programs; CC is the compiler make uses to build grayc and the runtime, and gray falls back to it only when GRAY_CC is unset (CC=clang GRAY_CC=gcc make build).
Run make help to list the make targets, or make help TARGET=build to see what one target does and which variables it reads.
| Compiler | macOS | Linux | Windows |
|---|---|---|---|
| Clang | Supported | Supported | Not supported |
| GCC | Supported (Homebrew GCC) | Supported | Supported (MinGW-w64, until TinyCC replaces it) |
| TinyCC | Supported | Not yet supported | Planned |
On macOS, cc and gcc are both Apple Clang unless GCC is installed separately.
git clone https://github.com/grayscale-lang/grayscale.git
cd grayscale
make build
make installmake install, gray update, and gray install also install tab completion
for your shell (bash, zsh, fish, or PowerShell) when its completion directory
is writable, and never edit an rc file. See gray completion in STANDARD.md
for where each shell's script goes.
Grayscale builds on Windows with MinGW-w64.
winget install BrechtSanders.WinLibs.POSIX.UCRT.Base # or: choco install mingw
git clone https://github.com/grayscale-lang/grayscale.git
cd grayscale
make buildmake build, make test, and make clean work the same as on macOS and
Linux. make needs a POSIX shell, which MSYS2 and Git Bash both provide.
The compiler finds MinGW in its default install locations automatically —
it does not need to be on PATH.
Source files end in .gray or .grayscale; both work everywhere and can be mixed in one project.
| Command | Description | Example |
|---|---|---|
gray <file> |
Compile and run | gray main.gray |
gray build <file> -o <name> |
Compile to a distributable binary | gray build main.gray -o myapp |
gray build <file> --emit-c |
Emit generated C source to a file (no binary) | gray build main.gray --emit-c |
gray build <file> --arena-limit=<size> |
Cap arena memory (KB/MB/GB; default: 1GB) | gray build main.gray --arena-limit=256MB |
gray <file> --cc <compiler> |
Compile and run with a chosen C compiler (also on gray build) |
gray main.gray --cc tcc |
gray check <file> |
Type check without compiling | gray check main.gray |
gray test [path...] |
Compile and run #test functions |
gray test ./src/... |
gray watch <file> |
Watch for changes, re-run on save | gray watch main.gray |
gray fmt <path> |
Format .gray and .grayscale source files in place |
gray fmt . or gray fmt ./... |
gray fmt --check <path> |
Check formatting without modifying files (CI gate) | gray fmt --check ./... |
gray doc <file> |
Generate docs from #doc attributes |
gray doc main.gray |
gray new <name> |
Scaffold a new project | gray new myproject |
gray report |
Print system info for bug reports | gray report |
gray verify |
Run the built-in language verification test suite | gray verify |
gray update |
Update to the latest stable version | gray update |
gray update --pre |
Update to the latest pre-release (alpha/beta) | gray update --pre |
gray install <version> |
Install a specific version by exact semver | gray install v0.11.5 |
gray version |
Show version info | gray version |
gray man |
Show help for the man command | gray man |
gray man <module> |
Show info about a stdlib module | gray man strings |
gray man <function> |
Show info about a stdlib function | gray man strings.to_upper |
gray man <struct> |
Show info about a stdlib struct type | gray man HttpRequest |
gray cross build <file> --target <target> |
Cross-compile for another platform via Zig | gray cross build main.gray --target linux-amd64 |
gray cross targets |
List supported cross-compilation targets | gray cross targets |
Every command prints its own usage and flags with gray [command] --help, or equivalently gray help [command]:
gray build --helpNote: Zig is only required for cross-compilation (
gray cross). Native builds use the system C compiler.
gray update # latest stable
gray update --pre # latest pre-release Note: The latest pre-release may be very out of date
gray install v0.11.5 # pin to an exact versiongray update checks for new versions, shows the changelog, and upgrades both the gray CLI and the compiler. Pass --pre to pick up the latest alpha, beta, or rc. Use gray install <version> to install an exact version by semver — downgrades and pre-release tags (e.g. 0.2.0-beta.1) are supported.
Grayscale was previously known as EZ. The ez update command from older EZ versions cannot upgrade to Grayscale automatically. To migrate, uninstall EZ and do a fresh install of Grayscale using the instructions in the Install section above.
- Language standard
- Contributing guide
- Benchmark suite —
make benchmarktimes real-shaped programs
Grayscale is in active development. The language is usable for personal projects and dev tools. Breaking changes may occur frequently.
MIT License - Copyright (c) 2025-Present Marshall A Burns
See LICENSE for details.
Thank you to everyone who has contributed to Grayscale!




























