zon is a declarative, extensible build tool written in Go. It interprets .zon files—JSON-inspired configuration files with support for evaluation, includes, function definitions, and build recipes. It’s designed to be minimal yet powerful, with strong inspiration from tools like Nix and JSON-e, and suitable for building packages, managing dotfiles, or orchestrating complex workflows.
- Declarative and expressive syntax: inspired by JSON, with extensions for expressions, interpolation, and functions.
- Build caching via content-addressable storage.
- Reproducible output paths, unless explicitly marked
impure. - Parallel and serial evaluation modes.
- Native support for:
let/inbindings,includestatements,output { ... }build expressions,- string interpolation and escape sequences.
- Output as symlinks, JSON, or raw directory paths.
- Can optionally generate a DOT dependency graph.
A simple .zon file for building suckless tools:
let
util = include ./util.zon
in output {
with util.merge,
"name": "apps",
"prefix": ".local",
"paths": [
output {
with util.unpack,
"archive": output {
with util.fetch,
"url": "https://dl.suckless.org/tools/dmenu-5.2.tar.gz",
"checksum": "3829528c849db6f903676fe7e6a48f3735505b6d"
},
"name": "dmenu",
"output": ''
make PREFIX=$out install
''
}
]
}
You can run this with:
zon apps.zonThis fetches, unpacks, and builds dmenu, outputting to a deterministic directory in cache/store.
zon [options] <file.zon> [key=value ...]| Flag | Description |
|---|---|
-f, --force |
Force rebuilding of all outputs |
-d, --dry |
Dry-run: do not execute anything |
-s, --serial |
Run builders sequentially instead of in parallel |
-o, --output |
Symlink output to given name (default: result) |
--no-result |
Disable symlink creation |
--json |
Print result as JSON |
-g, --clean |
Clean orphaned outputs in the store |
--graph |
Write DOT graph to specified file |
--cache |
Cache directory (default: cache/store) |
--log |
Log directory (default: cache/log) |
--interpreter |
Interpreter to use for inline scripts (default: sh) |
output { ... }: defines a build step. Attributes include:"builder"or"output"(script),"args"(array of string args),"source"(working directory),"impure"(disables caching),- custom env vars.
include path: includes and evaluates another.zonfile.let ... in ...: scoped variable definitions.with expr, ...: merges attribute sets (maps).- Strings support
"\(expression)"interpolation.
- Everything is an expression: there are no statements.
- Outputs are hashed based on the full input expression unless marked
impure. - Evaluation is lazy but deterministic.
- Errors include file and position information for debugging.
Beautiful zlib-license