# Reference: the `cx` command line — v0.18.0-pre.1

> **GENERATED.** Source: `docs-src/llm/reference-cli.md.tmpl`. The help text
> below is the v0.18.0-pre.1 binary's own `--help`, captured at generation
> time — not a transcription. Read `primer.md` first.

## The one rule

```
cx [cx-flags] FILE [program-args...]
```

Flags bind **before** the resource. Everything after the resource is the
program's `argv`. This is the interpreter convention (and shebang-identical),
and getting it backwards is not a usage error — it produces a program that
never got its capability. Since #1424 it is not silent either: an argument
after the file spelled like a cx flag draws one line on STDERR (unless the
program's `[argspec]` declares it), while argv and the exit status stay as
they were:

#### cx flags placed after the file

The run surface is `cx [cx-flags] FILE [program-args...]` — the interpreter
convention. Everything AFTER the file is the PROGRAM's argv (#926), so
`--allow-env` there is a string handed to the program, not a grant handed to
`cx`. The capability is never granted and the program dies at its first
effect. Since #1424 (RULED: OL-10) one line on STDERR says so as it happens —
`cx: '--allow-env' after FILE is program argv, not a cx flag — flags bind
before FILE (cx [flags] FILE [args])` — unless the program's own `[argspec]`
declares that argument. The line is a diagnostic: argv, the rendered result
below and the exit status are exactly what they were.

**Do not write this:**

`prog.cx`
```cx
[?lib 'cx-stdlib/env' as=env]
[probe args=[$count [$env:argv]] home=[$env:var-or-default 'CX_PRIMER_ABSENT' 'unset']]
```

```console
$ cx prog.cx --allow-env
[err code=cx-err:CXER0271 message='E_CAP_DENIED: env capability required for env-var-or-default; none granted (grant via --allow-env)' at='2:39']
```

**Write this:** cx flags placed before the file

`prog.cx`
```cx
[?lib 'cx-stdlib/env' as=env]
[probe args=[$count [$env:argv]] home=[$env:var-or-default 'CX_PRIMER_ABSENT' 'unset']]
```

```console
$ cx --allow-env prog.cx
[probe args=1 home=unset]
```

<sub>Fixtures: `ap-flags-after-file-wrong` / `ap-flags-after-file-right` in `conformance/llm/antipatterns.cxd`</sub>

An inline one-liner uses `-e`, and `cx eval` — a legacy alias of the default
action — still takes a **file**:

#### `cx eval 'PROGRAM'` — the subcommand takes a FILE

`cx eval` is a legacy ALIAS of the default run action and, like it, takes a
FILE. An inline program needs `-e`. The habit of writing
`cx eval '<source>'` (from other interpreters) makes cx try to OPEN the
program text as a path. Two rules avoid the whole class: run files with
`cx FILE`, and reach for `cx -e 'PROGRAM'` only for a one-liner.

**Do not write this:**

`prog.cx`
```cx
[+ 1 2]
```

```console
$ cx eval '[+ 1 2]'
cx eval: error reading program "[+ 1 2]": failed to open file "[+ 1 2]"; code: 2
```

**Write this:** `cx -e 'PROGRAM'` for a one-liner

`prog.cx`
```cx
[+ 1 2]
```

```console
$ cx -e '[+ 1 2]'
3
```

<sub>Fixtures: `ap-cx-eval-inline-wrong` / `ap-cx-eval-inline-right` in `conformance/llm/antipatterns.cxd`</sub>

## Reading program arguments

`env:argv` is ungated (reading your own arguments is not an effect) and
`argv[0]` is the file. `env:parse-args` takes a declarative flag spec.

`prog.cx`
```cx
[?lib 'cx-stdlib/env' as=env]
[probe args=[$count [$env:argv]] home=[$env:var-or-default 'CX_PRIMER_ABSENT' 'unset']]
```

```console
$ cx --allow-env prog.cx
[probe args=1 home=unset]
```

## `cx --help`

```console
$ cx --help
Usage:
  cx [flags] FILE.cx [args...]   Run a CX resource (the default action): parse
                            and evaluate. A pure-data document evaluates to
                            itself. Everything after FILE is the PROGRAM's
                            argv ($env:argv, argv[0]=FILE) — cx flags go
                            BEFORE the file, program args after (the
                            interpreter convention; shebang-identical).
  cx [flags] - [args...]    Run a program from stdin (a pipe into bare `cx`
                            with no FILE also evaluates stdin).
  cx [flags] -e 'PROGRAM' [args...]   Run an inline program (also --expression).
  cx <subcommand> [args]    One of the subcommands below.
  cx -v | --version         Version / build info.
  cx -h | --help            This help.

Run flags (the default action; flags bind BEFORE the resource):
  --cx (default) | --xml | --json | --yaml | --csv | --tsv   render the RESULT
  --data=FILE|-             separate data input: loaded via the data reading
                            and bound as $doc/$input before evaluation; the
                            caller input WINS over the program's data roots.
  --strict                  enforce declared ::T / [returns T] annotations at
                            call boundaries + [?pipe] stage flow (code.md §12.7;
                            default OFF erases annotations — documentation only).
  --manual-clock            run sched under the deterministic :manual clock so
                            [$sched:test-clock-advance] works (stdlib_sched.md
                            §3.3). Default is the production :wall clock, where
                            armed timers fire at blocking points instead.
  Unknown flags BEFORE FILE are hard usage errors (exit 2) — nothing is
  ignored; AFTER FILE a cx-flag spelling is the PROGRAM's argv and warns
  once on stderr, unless the program's [argspec] declares it.
  Capabilities are deny-by-default (spec/03-approved/core/security.md); grant explicitly:
    --allow-read --allow-write --allow-net --allow-env --allow-clock
    --allow-random --allow-subprocess --allow-eval --allow-secret-reveal --allow-keychain
    --allow-common --allow-all
    (three grants take an enforced scope: --allow-net=host[:port],
     --allow-read=PATH and --allow-write=PATH. A PATH is a directory-component
     subtree root — --allow-read=/data admits /data/x and refuses /database;
     the flag repeats and the roots union; a bare grant is the whole
     filesystem. A resource suffix on any OTHER capability is a usage error,
     not a narrowing: that scoping is unimplemented, #1059.)
    --probe is the preset for looking around without changing anything:
     it expands to --allow-read=. --allow-clock, so a probe that writes or
     reaches the network refuses with the ordinary capability error.
    --allow-common is the common working set WITHOUT secret-reveal and keychain;
    --allow-all additionally grants secret-reveal, which declassifies secrets,
    and keychain, which reads the OS keychain (env.md §3.6).

Convert flags (the data reading; an explicit --from selects it):
  cx --from=FMT [--to=FMT] [--compact] [--lossless] [--include-root=DIR] [FILE]
    --from: cx|xml|json|yaml|toml|md|csv|tsv|psv|html|url
            (.xml/.json/.yaml/.toml/.md files auto-detect their format)
    --to:   cx|xml|json|yaml|toml|md|csv|tsv|psv|html|url
  Projection shorthands: --ast --cx --xml --json --yaml --toml --md --csv
                         --tsv --psv --cxcol
  --compact              minimised output
  --lossless             emit round-trip-preserving output (conversions.md
                         0.2/2.2.1): xml carries cx: markers; json/yaml
                         carry the $tag structure envelope plus a `cx:type`
                         sidecar / `!!cx:T` tags — element docs re-import
                         byte-identically (cx/xml/json/yaml targets; other
                         lanes reject the flag)
  --include-root=DIR     resolve [?cx include=...] against DIR first

Subcommands (`cx <subcommand> --help` for details):
  fmt                  Lossless canonical formatter (preserves comments/anchors).
  canonical            Strict canonical text (strips presentation; data-equivalent).
  corpus               Grade module corpus files (.cxd `[case …]` with [in-code …]) with this binary.
  schema               Schema verb family — infer a .cxs from a corpus; convert an XSD; export to JSON Schema; classify compatibility.
  stdlib               Standard-library inventory — enumerate registered modules and print a module's registered source.
  tools                Agent-tool verb family — project command defs to MCP tool descriptors.
  address              Content-address stability drill — re-derive stored pins against a tree.
  hash                 SHA-256 hex of the strict-canonical bytes.
  eq                   Exit 0 iff strict-canonical(A) == strict-canonical(B).
  diff                 Semantic diff (walks the strict-canonical forms).
  lint                 Style + correctness warnings.
  imports              List a file's imports against its calls; --fix adds, removes and sorts its [?lib] lines.
  validate             Validate a document against a CX schema (.cxs).
  eval                 Evaluate a CX program (alias of the default run action; prefer `cx FILE`).
  primer               Print the LLM onboarding primer for THIS binary (#938).
  version              Version / build info (same output as -v / --version).
  select               CXPath query over a document (matches in canonical CX).
  diagram              Render a CX program as a diagram (mermaid/svg/png).
  test                 Run the test-* functions of *_test.cx files (test.md §2.3).
  code-diagram         Mermaid diagram of a CX source (flowchart / erDiagram).
  code-tree            Tree View JSON of a CX source.
  table                Table API over [table[...]] blocks (info / dump / load).
  build                One executable that runs a program (cx build PROG.cx -o OUT).
  scaffold             Typed, commented skeleton on stdout (config/data/doc/log/table).
  xap                  XAP project tooling — scaffold a project (`init`), a composition pattern (`scaffold`), and check (`check-surface`).
  flow                 cx-platform/flow: the local profile (run / validate / simulate / status / diagram) and the standalone runner (serve).
  secrets              cx-platform/secrets: the keystore client verbs (put / rotate / list) — a value is never printed, never read from argv.
  deps                 The repository dependency pins: sync deps/<repo>/ to each deps.cxd sha, or --check it — a stale pin or a drifted checkout is refused, never warned.
  demo                 Self-contained showcase (no file I/O, no network, < 1s).
  lock                 Generate / verify cx.lock from [?lib] directives.
  lsp                  Language server (LSP) on stdio.
  store-serve          Run the CX store service daemon from a config.
  fabric-serve         Run the CX fabric eventing daemon from a config.
  store-health         Store readiness probe (exit 0 iff accepting).
  store-rotate-kek     Rotate a store key-encryption key (re-wrap envelopes).
  store-mint-principal Mint an XSP-AUTH principal offline (seed file + [grant …] stanza).
```

## The verbs, by what you are trying to do

The `--help` capture above is the complete list. This is the same set sorted
by intent.

**Run and inspect**

| Command | Use it for |
|---|---|
| `cx FILE.cx` | run a program **interpreted** (the evaluator), or print a document's canonical form |
| `cx -e 'PROG'` | a one-liner |
| `cx demo` | a self-contained showcase, no I/O, under a second |
| `cx primer` | this documentation set's primer, for the installed binary |
| `cx version` | version and build info (same as `-v` / `--version`) |

**Identity, shape, and correctness**

| Command | Use it for |
|---|---|
| `cx fmt FILE` | lossless format (keeps comments and anchors) |
| `cx fmt --code FILE.cx` | format a program keeping its layout — your line breaks, indentation by form, closers glued, lines past 80 broken |
| `cx canonical FILE` | strict canonical text — what identity is defined over |
| `cx hash FILE` | SHA-256 of the strict-canonical bytes |
| `cx eq A B` / `cx diff A B` | semantic equality / semantic diff |
| `cx lint FILE` | style and correctness findings |
| `cx validate FILE --schema=S.cxs` | schema check |
| `cx corpus FILE.cxd` | grade a module conformance corpus with this binary — the grader a repository runs with no toolchain; `--times` adds each case's in-process time |
| `cx schema infer` / `export` / … | derive a `.cxs`, project it to JSON Schema, classify compatibility |
| `cx select 'PATH' FILE` | one CXPath query, no program |
| `cx --from=json --to=cx f.json` | the convert surface |
| `cx table info` / `dump` / `load` | the `[table[…]]` API |
| `cx scaffold KIND` | a typed, commented skeleton on stdout |

**Understand a program**

| Command | Use it for |
|---|---|
| `cx code-diagram FILE` | Mermaid of a program (`--view=effects` for its capability graph) |
| `cx code-tree FILE` | Tree View JSON of a source |
| `cx diagram FILE` | render a program as mermaid / svg / png |
| `cx tools export MODULE.cx` | project command defs to MCP tool descriptors |
| `cx lsp` | the language server, on stdio |

**Build and ship a feature**

| Command | Use it for |
|---|---|
| `cx xap init NAME` | scaffold a feature |
| `cx xap check-surface DIR` | the surface derivation check |
| `cx lock` | generate / verify `cx.lock` from `[?lib]` imports |
| `cx build [RUN-FLAGS] PROG.cx -o OUT` | **compiled**: one executable that runs the program as `cx [RUN-FLAGS] PROG.cx` does, with no cx install where it runs (same OS and architecture); `OUT --version` names the program and the cx commit that built it |
| `cx build --native [RUN-FLAGS] PROG.cx -o OUT [-- ARG...]` | **compiled**, the same, with the hot pure defs compiled to machine code from a training run (`-- ARG...` are its arguments, for a program that reads `$env:argv`; OUT takes its own when it runs; a C compiler where OUT is built; the link kit beside cx, `make cli-kit`) |
| `cx imports FILE.cx` | list the modules a file imports and calls (used / unused / missing); `--fix -w` adds the missing `[?lib]` lines, removes the unused and sorts them |
| `cx flow run FLOW.cx --env ENV.cx` | run a flow document over a journal — build, release and authoring flows from a checkout, no engine to start |
| `cx flow validate` / `simulate` / `status` | check a flow document, run the runner law over a supplied result table, read a run record back |

**Operate a platform** (the platform profile)

| Command | Use it for |
|---|---|
| `cx store-serve config.cx` | the store service daemon |
| `cx fabric-serve config.cx` | the fabric eventing daemon |
| `cx store-health URL` | readiness probe — exit 0 iff accepting |
| `cx store-rotate-kek …` | rotate a key-encryption key (re-wrap envelopes) |
| `cx store-mint-principal …` | mint an XSP-AUTH principal offline — the clean-state bootstrap |

`reference-platform.md` has the bootstrap walkthrough; `playbook-xap.md` has
the whole arc from feature grammar to hosted surface.

## What the version string tells you

Release-ness is **derived**, never hand-maintained. `cx --version` prints
`cx vX.Y.Z` only when the binary was built from a clean tree at exactly the
annotated release tag matching the repo's `VERSION`. Anything else prints
`cx vX.Y.Z-dev+<commit>` — semantically a pre-release of `X.Y.Z`, which is
what unreleased source is. If you are reporting a bug, the `-dev+` suffix is
the part that matters.

## A retired verb tells you what replaced it

A verb that once existed and no longer does answers with **its own
retirement**, never with "unknown subcommand". `cx store-token` is the
current example — it says the bearer/RBAC plane is gone, that
store credentials are now XSP-AUTH principals granted in the daemon config,
and which verb mints one. Retirement entries are kept indefinitely.

So if a verb you remember is missing from `--help`, **run it** rather than
guessing at a replacement. The tool knows what happened to it.

## Capability grants

```
--allow-read[=PATH] --allow-write[=PATH] --allow-net[=host[:port]] --allow-env
--allow-clock --allow-random --allow-subprocess --allow-eval
--allow-secret-reveal
--probe            # the preset: --allow-read=. --allow-clock
--allow-common     # every capability EXCEPT secret-reveal
--allow-all        # including secret-reveal (declassifies secrets)
```

Deny-by-default, and a denial names the flag that would have allowed it:

`prog.cx`
```cx
[?lib 'cx-stdlib/io']
[$io:write-file "/tmp/out.txt" "hello"]
```

```console
$ cx prog.cx
[err code=cx-err:CXER0271 message='E_CAP_DENIED: write capability required for io-write-file; none granted (grant via --allow-write)' at='2:1']
```

Grant the narrowest thing that works. **Three grants take a scope** —
`--allow-net=host[:port]`, `--allow-read=PATH` and `--allow-write=PATH` — and
the rest are all-or-nothing, which is a reason to prefer a scoped
`--allow-read=./data` over `--allow-common` in anything automated.

A `PATH` scope is a **directory-component subtree root**: `--allow-read=/data`
admits `/data` and `/data/x` and refuses `/database`. The flag repeats and the
roots union; a bare `--allow-read` grants the whole filesystem, as it always
did. Both the path as written and the path after symlinks must fall under a
root, so a symlink out of the granted tree — and a symlink into it from outside
— refuses. A path outside the roots is the ordinary capability refusal
(`cx-err:CXER0271`), naming the path, the roots in force, and the flag to add.

`--probe` is the preset for a read-only look around: it expands to
`--allow-read=. --allow-clock`, and a probe that writes or reaches the network
gets that same refusal.

A resource suffix on any OTHER capability — `--allow-env=HOME`,
`--allow-subprocess=/bin/ls` — is a **usage error** (exit 2, before
evaluation) naming the flag, the suffix it would have ignored, and the bare
spelling that is accepted. Earlier versions took such a suffix, discarded it,
and granted the blanket capability, so the narrower-looking spelling silently
bought wider authority; per-name and per-executable scoping is unimplemented,
and the surface says so rather than pretending.

## Exit codes

| Code | Meaning |
|---|---|
| 0 | success |
| 1 | the program's result carries a COMPUTED `[err]` at any depth, or a check found findings |
| 2 | usage error — an unknown flag, a missing file, a bad invocation |

Exit 1 is about the program's result (R5.13), and the discriminator is
PROVENANCE, not position (RULED: 1099-a, #1099):

- A **computed** `[err]` — one a refusal produced at run time — anywhere in
  the result makes the run exit 1: as the whole result, as a member of a
  sequence / array / map (#1058 T1.1: `[?for [in $n (1)] [yield [/ $n 0]]]`),
  or resting inside an **element** at any depth — `[out [doc [?splice $rows]]]`
  with a refusal among `$rows`, `[doc [?for … [yield [/ $n 0]]]]`. Before
  1099-a the walk stopped at a named element, so the last shape printed its
  refusals and exited 0.
- A **written** `[err …]` — parsed from source, or built by the program's own
  `[err …]` literal — is data echoing itself and exits 0 wherever it sits:
  `[err code=x]` as the top-level form, `{a: [err code=c]}`, `[wrapper [err …]]`,
  `[doc [?splice ([err code=c], 2)]]`.
- Resting is still ruled (CO-2, #975): a contributed member is not propagated
  out of the construction — the document is built around it and printed — and
  the REFUSAL guard sits at the effect boundary (`[$store:put-doc]` on a
  document carrying any err, written or computed, refuses with `CXER0275`).
  The exit status is not a refusal; it is the process saying what it printed.

On exit 1 the run also names the first err on STDERR; STDOUT is unchanged,
because the rendered err is still the program's answer. Do not
read the exit status as a refusal contract: refusal at a boundary is
`CXER0275` (store / http), raised at the boundary, independent of how the
process exits.

Unknown flags are hard errors. Nothing is ignored: a typo'd grant *before* the
file exits 2, and a real cx flag *after* the file is the program's argument —
which still grants nothing, and now says so in one STDERR line unless the
program's `[argspec]` declares it.

## Scripting `cx` from CX

Tooling in this repo is written in CX and run with `cx <file>` — never
`cx eval`, and never a shell wrapper where CX would do. The pattern:

```console
cx --allow-read --allow-write --allow-subprocess --allow-env script.cx --flag value
```

Flags for `cx` first, the script, then the script's own arguments.
