CLI surface
The gaia binary is the bundled CLI that ships with the end user tarball at .gaia/cli/gaia. End users do not invoke it directly in normal use. Skills, hooks, and slash commands invoke it for them.
Contributors working on the CLI source need the surface map. Source lives under .gaia/cli/src/ (contributor-only, excluded from the end user tarball). The bundle is rebuilt by pnpm --filter @gaia-react/cli bundle.
Build layout
Section titled “Build layout”Two binaries get bundled:
.gaia/cli/gaia: end user binary. Entry point:src/index.ts. Ships in the tarball..gaia/cli/gaia-maintainer: maintainer binary. Entry point:src/index.maintainer.ts. Excluded from the tarball.
The end user binary’s src/index.ts does not import any maintainer-only handler, so esbuild tree-shakes maintainer surface out of the end user bundle.
Top-level subcommands
Section titled “Top-level subcommands”All subcommands print a help block on --help, -h, or help. Source path links point at the per-subcommand router under .gaia/cli/src/.
gaia init
Section titled “gaia init”Source: .gaia/cli/src/init/index.ts
Per-step handlers consumed by /gaia-init. Each handler reads and writes .gaia/init-state.json so the slash command can resume on failure.
gaia init strip-branding --title <T>gaia init configure-i18n --locales <list> --strip <bool>gaia init rename --title <T> --kebab <K>gaia init wire-statusline --mode <global|project|skip>gaia init finalizegaia init resume [--from-step <N>]gaia scaffold
Section titled “gaia scaffold”Source: .gaia/cli/src/scaffold/index.ts
Code generators invoked by the new-component, new-hook, new-route, and new-service skills. Each generator reads templates from .gaia/cli/src/scaffold/templates/.
gaia scaffold component <Name>gaia scaffold hook <useFoo>gaia scaffold route <name>gaia scaffold service <name>gaia setup
Section titled “gaia setup”Source: .gaia/cli/src/setup/index.ts
Per-machine clone setup primitives invoked by /setup-cloned-gaia-project. The slash command orchestrates externally-shelled installs (React Doctor, Playwright CLI, Serena MCP, plugins, spec-kit) and calls these primitives to record progress in .gaia/local/setup-state.json.
gaia setup status [--json]gaia setup mark-step <step>gaia setup finalize [--force]gaia setup link-worktree [--json]gaia update
Section titled “gaia update”Source: .gaia/cli/src/update/index.ts
Wired by the /update-gaia skill for the field-aware pnpm-workspace.yaml merge step (Step 7b).
gaia update merge-workspace --baseline <file> --latest <file> --current <file> [--json]A field-aware, read-only verdict oracle for pnpm-workspace.yaml. It parses three YAML files (baseline from the prior GAIA release, latest from the incoming tarball, current working-tree copy) and emits a JSON report of {applied, conflicts, suggestions}. It never writes the workspace file. The /update-gaia skill applies the applied entries with the Edit tool so comments, key order, and quote style survive. The --json flag switches output from the human summary to the raw JSON report.
gaia update-deps
Section titled “gaia update-deps”Source: .gaia/cli/src/update-deps/index.ts
Dependency update primitives invoked by the /update-deps skill.
gaia update-deps run --emit-updates <path>gaia update-deps decline --source <path> --skip <a,b,...>gaia update-deps decline --clearrun discovers outdated packages, classifies them into Wave A (minor/patch) and Wave B (major), and writes a JSON payload to <path>. decline records the groups a developer skipped in the interactive preview into .gaia/local/declined-updates.json (gitignored, local statusline only) so the statusline nudge stops counting them. --source points at the payload written by run --emit-updates; --skip takes a comma-separated list of package or group names, each expanded to its whole companion group. --clear empties the ledger (used when the developer chose “update all”).
gaia fitness
Section titled “gaia fitness”Source: .gaia/cli/src/fitness/index.ts
Presentation helper invoked by the /gaia-fitness skill to render the final report card.
gaia fitness render-card [--cols N]Reads a /gaia-fitness report JSON document on stdin and writes a width-aware ASCII report card to stdout. --cols sets the target terminal width (default: autodetect from process.stdout.columns, fallback 100). The box self-sizes to the longest content line, clamped to 120 columns and to the terminal width, wrapping remediation text to fit. Categories render alphabetically. The FINDINGS block is omitted when the findings array is empty (clean run). The skill pipes the assembled report JSON through this command and pastes the stdout verbatim into its chat reply.
gaia harden-tally
Section titled “gaia harden-tally”Source: .gaia/cli/src/harden/tally.ts
Tallies recurring code-review-audit findings for the /gaia-harden policy-memory loop.
gaia harden-tallyReads the rolling 90-day merged-PR window via gh, extracts each PR’s machine-readable findings block, counts distinct PRs per finding_class at error/warning severity, drops classes already covered by a promoted rule or suppressed by the decline ledger, self-cleans stale ledger entries, and prints the candidate list as JSON to stdout. A class is a candidate when it recurs across 3 or more distinct PRs. Network failures are non-fatal: a gh error yields an empty candidate list rather than aborting. No flags.
gaia harden-ledger
Section titled “gaia harden-ledger”Source: .gaia/cli/src/harden/ledger.ts
Machine-local decline ledger for the /gaia-harden policy-memory loop. The ledger is gitignored so a decline on one machine never vetoes the rule for a teammate.
gaia harden-ledger listgaia harden-ledger record --finding-class <c> --pr-count <n>gaia harden-ledger is-suppressed --finding-class <c> --current-pr-count <n>gaia harden-ledger prune --window-classes <c1,c2,...>list prints the full ledger as JSON. record upserts one entry keyed by finding_class, snapshotting the current PR count at decline time (re-recording overwrites the timestamp and count). is-suppressed exits 0 (suppressed) when an entry exists and fewer than 3 distinct PRs carrying the class have merged since the decline; exits 1 (not suppressed) otherwise. prune removes entries whose finding_class is no longer in the active window, idempotently. Ledger file: .gaia/local/harden/declines.json.
gaia wiki
Section titled “gaia wiki”Source: .gaia/cli/src/wiki/index.ts
Wiki-state primitives consumed by the /gaia-wiki skill (sync, consolidate, lint). The primitives are deterministic; the skill orchestrates them.
gaia wiki state [--json]gaia wiki commit-classify --since <sha> [--json]gaia wiki state-init <sha>gaia wiki state-bump <field> <value>gaia wiki log-prepend --sha <h> --decision <D> --reason "..."gaia wiki page-index [--json]gaia wiki orphansgaia wiki near-collisions [--max-distance N]gaia wiki dead-paths [--json]gaia wiki frontmatter [--json]gaia wiki empty-sections [--json]gaia wiki sync land [--branch-aware]state-init <sha> refuses if wiki/.state.json already exists. state-bump performs an atomic single-field update. sync land lands staged wiki changes via the correct branch strategy.
Where to find tests
Section titled “Where to find tests”Per-subcommand test files sit alongside the source: component.test.ts next to component.ts, etc. The test runner is Vitest. Run from the CLI workspace:
pnpm -C .gaia/cli typecheckpnpm -C .gaia/cli test --runTest fixtures live under .gaia/cli/test-fixtures/.
Surfaces excluded from this reference
Section titled “Surfaces excluded from this reference”Some namespaces in the source are deliberately undocumented in public contributor docs and are not listed above. They remain visible in the source itself; this page intentionally does not enumerate them.