Wit

CLI reference

The wit binary is both a tool and the model host implementation. Every embedding question — how to wire a data loader, how output paths are chosen — is answered concretely by the CLI's source. This page is the command reference and the wit.sources.json schema.

Commands

wit parse <file>                     AST as JSON
wit check <file>… [--sources f --allow-exec] [--env .env]
                                     dry-run build: parse, load, resolve, expand
wit build <file> [options]           compile to HTML, Markdown or PDF (below)
wit fmt <file> [-w|--write | --check]
                                     re-indent without changing meaning
wit migrate <file|dir>… [-w|--write] rewrite 0.2 syntax as 0.3
wit tour <file>                      the AST as a readable tree
wit tokens [--parser] <file> | -e <source>
                                     the token stream
wit --version | --help
  • wit check runs the same compile() as wit build, so a file that checks clean builds. Non-zero exit on the first error.
  • wit fmt calls format() from @witlang/parser. --check writes nothing and exits 1 when the file would change.
  • wit migrate rewrites every form removed in 0.3 (see Syntax). It reads each file's reference graph, so a chapter's uses are rewritten against the definitions in its shared files. One file without -w prints the result; a directory is searched for .wit files.
  • wit tokens prints raw lexer output; --parser prints the stream the parser walks, after stray markers are demoted to prose — the tool for "why did this prose turn into structure?".

build

wit build <file>
  [-o out.html | out.md | out.pdf]
  [--format html | md | pdf]
  [--raw | --fragment]
  [--template name] [--paper a4 | a5 | letter | legal]
  [--sources wit.sources.json --allow-exec]
  [--env .env]

The output format is inferred from the -o extension (.html or .htm → HTML, .md or .markdown → Markdown, .pdf → PDF) or set with --format. With no -o, the default is a styled HTML document on stdout.

  • --fragment — emit the bare <article> instead of a full page.
  • --raw — use rawThemeCss (the mechanical reset) instead of the house style.
  • --template — build with a bundled template, replacing the file's reference wit/… line or adding one.
  • --paper — the page size, over the template's or the file's own.
  • PDF — renders document-mode HTML, then prints it with a discovered headless Chrome (no browser header or footer). WIT_CHROME overrides the binary.

The external-data host

The CLI is one implementation of the @load seam. env is built in — it returns the process environment (plus an optional --env dotenv file) as a record. Every other alias comes from wit.sources.json:

{
  "sources": {
    "downloads": {
      "run": ["node", "scripts/downloads.js"],
      "format": "json",
      "timeoutMs": 30000
    }
  }
}

format is one of json, csv, tsv, lines, text, svg, or html — seven output formats, plus the built-in env.

The security boundary

Running an aliased program requires --allow-exec. A document can name only an alias, never a command — the command lives in wit.sources.json, which the document author does not control. That separation is the whole security model of the data host.

How parameters reach the program

A document loads an alias with @load downloads load@. Parameters on the use — @load(as: dl, year: 2026) downloads load@ — reach the program two ways, both at once: {{year}} tokens in the run argv are substituted, and the whole parameter object ({ "year": "2026" }) is written to the program's stdin as JSON. as is not passed; it renames the resulting data. CSV and TSV get a minimal header-keyed parse — no quoted fields.

Common mistakes

  • Expecting @load <alias> to run a program without --allow-exec — only env works unguarded.
  • Expecting quoted CSV fields to parse — the parser is minimal.

See also

External data · Embed Wit in an app · Rendering · Errors reference.