CLI
The cortex binary exposes two surfaces over the kernel: CLI and MCP. Every non-interactive read command supports --json for machine consumption; output is styled at a TTY and plain when piped. For cross-session views use cortex sessions --json or cortex show <taskId> --json.
Global flags
| Flag | Meaning |
|---|---|
-C, --workspace <dir> | workspace/repository directory (defaults to cwd) |
--json | emit machine-readable JSON instead of the styled view |
Shell completion
Install completion with cobra's built-in command, e.g. cortex completion zsh > "${fpath[1]}/_cortex" (or bash / fish). Every command that takes a <taskId> then tab-completes task IDs — with the goal shown as the description — reading the central cross-repo store plus any repo-local/custom case store selected with -C, so you never type a base32 ID by hand:
cortex show <TAB> # → task_06FK… (fix cart total) task_06FM… (add coupon codes)Commands
cortex open <goal>
Preferred entry point for agent-driven work. It resumes matching work or starts one case, so a retry after a lost response is safe.
cortex open "Fix post-login checkout redirect" \
--surface code --surface browser \
--actor agent-auth --idempotency-key checkout-redirect \
--criterion 'checkout_return=Login started at checkout returns to checkout'An --idempotency-key is the strongest identity and returns its existing case even after completion. Without one, Cortex resumes the newest active case with the same normalized goal, mode, workspace, current branch, and acceptance contract. When a new case is created, --parent links delegated work to a case in the same workspace and both parent and child records are updated. Resuming returns existing metadata unchanged. --criterion id=statement registers an immutable success rule; the same id and exact statement must later appear in a typed verification claim.
| Flag | Default | Meaning |
|---|---|---|
--mode | change | change | investigate | review |
--risk | medium | low | medium | high |
--surface (repeatable) | code | code, browser, terminal, artifact, secret |
--actor | — | stable, non-secret person/agent identifier |
--parent | — | parent task ID for same-workspace delegated work |
--idempotency-key | — | stable, non-secret retry identity |
--criterion (repeatable) | — | immutable id=statement success rule; at most 64 |
--seed (repeatable) | — | note/packet path to stamp into orientation evidence (≤8 × 16 KiB) |
mode=review biases later investigate rounds toward git changed-files + codemap review instead of open-ended semantic search (vecgrep only at --depth deep). Use --seed for vault notes or handoff packets that should orient the case without becoming verification proof.
cortex start <goal>
Always create a fresh case and orient it (git identity + tool health). It remains useful for manual work that intentionally must not resume an existing case; retrying it can create another case.
cortex start "Fix post-login checkout redirect" --surface code --surface browser --risk medium| Flag | Default | Meaning |
|---|---|---|
--mode | change | change | investigate | review |
--risk | medium | low | medium | high |
--surface (repeatable) | code | code, browser, terminal, artifact, secret |
--criterion (repeatable) | — | immutable id=statement success rule; at most 64 |
--seed (repeatable) | — | note/packet path to stamp into orientation evidence (≤8 × 16 KiB) |
cortex investigate <taskId> <question>
Route a question causally: bounded discovery first, then the top file/symbol candidates are expanded through codemap, recording provenance (derivedFrom) on the structural evidence.
cortex investigate task_06FK… "where is the OAuth return URL handled"| Flag | Meaning |
|---|---|
--surface (repeatable) | override the routing surfaces |
--depth | quick | standard | deep |
Depth and surface overrides are validated before Cortex invokes an adapter. Unknown values fail explicitly instead of silently falling back to a different route or investigation cost.
Each round also has a wall-clock budget — quick 20s / standard 45s / deep 90s (or the caller's tighter deadline). When the budget is exhausted, Cortex returns the evidence gathered so far instead of hanging until an MCP gateway timeout; stage-2 structure is skipped if the budget is already gone.
--depth deep widens the per-tool candidate budget and decomposes a compound question ("where is X created, how is Y validated, and where is Z enforced") into up to five targeted sub-queries, each searched separately. The split is a whitespace-gated heuristic — code tokens such as std::sort, URLs, and spaceless ternaries survive intact — and a question that does not decompose runs unchanged. quick and standard never decompose.
Discovery hits are quality-gated before they become evidence: heading-only, bare-import, and punctuation-fragment chunks are filtered (import lines are kept when the question itself asks about imports), junk paths (.agent/, dist/, node_modules/, case stores, …) are dropped, keyword fallback is capped at 8 hits, and when every remaining hit scores below 0.10 the round records zero facts and reports "no strong candidates". Treat that as nothing found — rephrase the question or ask about a specific symbol — not as weak evidence. The summary also states when the structural (codemap) stage ran but returned no results, so discovery-only evidence is never dressed up as resolved structure.
When semantic discovery (vecgrep) cannot run — no index in the workspace, or the binary is missing — Cortex falls back to a literal git grep over tracked files so discovery still has a zero-dependency floor (git is the only hard requirement). The matches are recorded as low-confidence code_location candidates (one per file, with a snippet) and can still be expanded by the structural stage on that round. Follow-up investigate rounds then stick to the git-grep floor until cortex setup reports both specialist indexes ready or stale again — so a slow or broken vecgrep/codemap path is not re-paid on every question. Indexed-but-drifted (stale) is still queryable and does not collapse to needs_index. This fallback fires only when semantic search is unavailable; a clean search that legitimately finds nothing is reported as such, never papered over with literal noise. When hybrid search fails on an existing index (embedder/profile), Cortex retries once as keyword before degrading.
cortex route [question]
Export the executable routing matrix for agents and gateway instructions:
cortex --json routePass a question to resolve one decision, or repeat --surface to override the detected surface. Unknown surfaces fail instead of silently falling through.
cortex --json route --surface browser "the login flow is wrong"cortex recall-cases <query>
Search the cross-case recall index (veclite) for prior resolved hypotheses and definitive receipts related to a query — the prior disproofs to read before re-deriving a theory. Best-effort: no veclite configured → empty, never an error.
cortex recall-cases "where is the login redirect handled" --repo liftclub --limit 5| Flag | Meaning |
|---|---|
--repo | scope to a repository name (empty = cross-repo) |
--limit | max prior cases to return (default 5) |
cortex reindex-cases
Backfill the cross-case recall index from active central sessions under $XDG_STATE_HOME/cortex/sessions/**:
cortex --json reindex-casesThe command is idempotent. It uses each origin workspace's redaction policy and the same sensitivity exclusions as live indexing. The JSON report separates sessionLoadFailed from record-level failed, counts every active central session directory (including an unreadable case.json), continues scanning after individual failures, then exits non-zero if either failure count is non-zero. Archives and repository-local cases_dir overrides are intentionally outside this central backfill.
cortex plan <taskId>
The planning gate. Rejects plans with no disproof path, and change tasks with no boundary.
cortex plan task_06FK… \
--hypothesis "returnTo is dropped :: run login-from-checkout browser flow" \
--support 1=ev_06FJ… \
--file src/auth/callback.ts --symbol HandleCallback \
--uncertainty "unsure whether state signing also strips it"| Flag | Meaning |
|---|---|
--hypothesis (repeatable) | a statement; supports the statement :: disproof shorthand |
--disprove (repeatable) | disproof for the matching --hypothesis (by position) |
--support (repeatable) | strict one-based hypothesis-index=evidence-id[,evidence-id...]; IDs must belong to this task |
--confidence | band for the hypotheses (default low) |
--file / --symbol (repeatable) | the change boundary |
--boundary-reason | why these are the expected change set |
--verify (repeatable) | required verifiers (e.g. codemap_review, cairntrace_flow) |
--timeout (repeatable) | strict tool=duration override; each tool may appear once |
--uncertainty | explicit statement of what remains uncertain (required) |
Configured verifier names from cortex.yaml may be supplied as either unit or command:unit. When --verify is omitted, every configured command verifier is included alongside the defaults derived from the task's surfaces. Configured argv is still blocked by default: a trusted launcher must set CORTEX_APPROVE_COMMANDS=1, otherwise verify records an honest blocked receipt.
cortex begin-change <taskId>
Claim bounded ownership and enter changing before editing:
cortex begin-change task_06FK… --actor agent-auth --ttl 15mThe task must be a planned change with a declared boundary. The actor is required; TTL defaults to 15 minutes and must be between one second and one hour. A same-owner retry is idempotent (an explicit TTL also renews the heartbeat). A competing active actor is rejected.
CLI operators can manage a long-lived lease directly:
cortex lease renew task_06FK… --actor agent-auth --ttl 30m
cortex lease release task_06FK… --actor agent-authAn expired lease cannot be renewed; reacquire with begin-change. Completion and abort release an active lease while retaining its audit record.
cortex verify <taskId>
Run the required verifiers, detect scope drift, and write receipts.
cortex verify task_06FK… \
--claim "Login started at checkout returns to checkout" \
--claim-id checkout_return \
--claim-surface browser \
--claim-verifier cairntrace \
--claim-contract specs/cairntrace/checkout_return.yml \
--actor agent-auth \
--browser-spec specs/cairntrace/checkout_return.yml| Flag | Meaning |
|---|---|
--claim (repeatable) | a user-facing claim to prove |
--claim-id (repeatable) | optional stable ID for each claim; required to prove a registered criterion |
--claim-surface (repeatable) | explicit code, browser, terminal, artifact, or secret surface; repeat once per claim |
--claim-verifier (repeatable) | optional exact verifier (codemap, cairntrace, glyphrun, fcheap, tvault, or command:<name>); omit entirely or repeat once per claim |
--claim-contract (repeatable) | required exact spec path/configured check/capability selector for each typed claim; repeat once per claim |
--claim-spec (repeatable) | one self-contained typed claim — id=…|surface=…|verifier=…|contract=…|<statement> — so a claim's attributes need not be repeated in lockstep across the coupled flags above |
--changed-file (repeatable) | override changed files (derived from git otherwise) |
--browser-spec | cairntrace spec path (proves browser claims) |
--terminal-spec | glyphrun spec path (proves terminal claims) |
--artifact-ref | fcheap stash ID/URI for an artifact claim |
--secret-project | tvault project for a value-free capability claim |
--no-auto-specs | disable automatic selection of covering browser/terminal specs |
--no-op | acknowledge that a change task intentionally produced no diff; does not create a pass |
--from-plan | materialize typed claims from registered acceptance criteria and the plan's verification requirements |
--ack-drift | acknowledge unexpected files on a risk: high change so verification may proceed |
--actor | change-lease owner; defaults to the active lease owner when the task is leased |
--claim-spec bundles a whole typed claim into one value (recognized keys id, surface, verifier, contract; everything else is the statement, which may itself contain = or |):
cortex verify task_06FK… \
--claim-spec "id=checkout_return|surface=browser|contract=specs/cairntrace/checkout_return.yml|Login started at checkout returns to checkout" \
--browser-spec specs/cairntrace/checkout_return.ymlSupplying --claim-surface opts into typed claims and requires the matching --claim-contract. When --claim-id is used, repeat it once per claim. Typed routing is exact: a claim is not_run unless that exact verifier/contract ran. A registered criterion additionally requires the same ID and byte-for-byte statement. Legacy --claim without typed flags remains available but infers the surface heuristically.
Repository-configured checks execute when the process launching Cortex sets CORTEX_APPROVE_COMMANDS=1 or when cortex setup --trust-commands has stored a matching workspace+argv digest in $XDG_CONFIG_HOME/cortex/command-grants.json. cortex.yaml cannot authorize its own arbitrary argv. Without approval, the requirement remains blocked and the canonical assessment stays non-green.
cortex remember <taskId> <outcome>
Persist the outcome to durable memory and complete the task.
cortex remember task_06FK… "returnTo was dropped; fixed and browser-verified" --tag auth| Flag | Meaning |
|---|---|
--importance | 0..1 importance for durable memory (default 0.5) |
--tag (repeatable) | tags for recall |
--unverified | explicitly accept a partial or unverified completion when adequate proof could not be completed |
--accept-failed | explicitly accept a failed completion — records a failed outcome, not a green one |
--accept-open-children | complete a parent while child tasks are still in-flight |
These acknowledgments preserve legacy tasks honestly; they do not bypass an explicitly registered acceptance contract. Every registered criterion needs current bound proof before completion.
cortex status <taskId>
Phase, unresolved hypotheses, scope drift, missing verification, and (with --detail full) tool health plus discovery index readiness (index / fixCommand for vecgrep and codemap). JSON includes case revision, actor/parent/children, lease, pending decision, structured actions, and one canonical verificationOutcome: verified, partial, failed, or unverified. For registered criteria (and legacy stable named claims), JSON also includes a bounded claimProofs manifest with exact total/truncation metadata, receipt/batch identity, binding, revision/diff digest, and non-sensitive evidence references.
cortex show and Studio use one task-locked composite projection. They retain the 200 newest evidence, command, and phase ledger records and return exact evidenceTotal / timelineTotal counts plus a truncation warning; use read-evidence or timeline for older detail.
Human context, decisions, and handoff
Record provenance-bearing context without pretending it is proof:
cortex note task_06FK… "support confirmed this affects only invited users" \
--kind constraint --origin human --actor alice --ref ticket://AUTH-42--kind is observation | decision | constraint | handoff; --origin is human | agent | reviewer; confidence is only low | medium. Notes are redacted human_report evidence and cannot satisfy verification by themselves.
Pause on one bounded human choice, then resume the exact phase:
cortex decision request task_06FK… \
--question "Which migration should we use?" --requester agent-auth \
--option 'safe=Safe migration|More rollout time' \
--option 'fast=Fast migration|Higher rollback risk'
cortex decision answer task_06FK… dec_06FM… --answer safe --responder alice
cortex decision resume task_06FK… # crash recovery only: answer persisted, phase did not resumeA request requires at least two unique option IDs and an explicit consequence for each. While the case is needs_human_decision, normal lifecycle work is paused and the case remains active.
Export a bounded transfer packet as Markdown or JSON:
cortex handoff task_06FK… # Markdown to stdout
cortex handoff task_06FK… -o handoff.md # Markdown file
cortex --json handoff task_06FK… # structured packet
cortex handoff task_06FK… --compact # short LLM-readable tip + top claims + next--compact prints a tip-sized Markdown packet (goal, state, top claims, open items, next command, warnings) instead of the full transfer projection — useful when another model only needs continuation context.
General handoff JSON is hard-capped at 128 KiB and excludes sensitive evidence/receipt content. For a complete verified task, Cortex instead budgets the primary JSON at 90 KiB so local-agent's 96 KiB result ceiling is respected: it preserves every non-sensitive named claim and referenced verifier batch, strips non-proof context first, and omits all receipts with an explicit warning if the complete proof closure still cannot fit. Markdown files are created owner-readable/writable only (0600 on POSIX systems).
The packet contains current state, revision, actor/parent/children/lease coordination metadata, plan, hypotheses, at most 20 recent evidence facts, the latest verifier runs plus named-claim receipts still current for the same revision/diff, decisions, the verification assessment, and executable actions. Raw tool output is excluded. Use -C <workspace> when the case lives in a repo-local or custom cases_dir.
cortex review
Evidence-backed review of a branch or pull request. Resolves the diff (base…HEAD), gathers structural + semantic context, runs the verifiers over the change (structural review plus the behavioral specs that cover it), and completes with a verdict — approve / request-changes / needs-verification — where every claim is backed by a receipt.
cortex review # current branch vs its fork point with the default branch
cortex review --base release/2.1 # against a specific base
cortex review --pr 42 # fetch + review a PR (GitHub or Bitbucket)
cortex review --surface browser # also auto-run the browser specs covering the change| Flag | Meaning |
|---|---|
--base <ref> | base to diff from (default: merge-base with the default branch) |
--head <ref> | ref to review (default: current branch) |
--pr <N> | fetch and review a pull/merge request, host-agnostic by git ref |
--surface (repeatable) | code (default), browser, terminal |
--risk | low / medium (default) / high |
--claim (repeatable) | an extra user-facing claim to prove |
A PR is fetched by git ref (GitHub pull/N/head, Bitbucket pull-requests/N/from) — no host CLI required. When a host can't be fetched by ref (e.g. Bitbucket Cloud), Cortex tells you to check out the branch and re-run with --base. Inspect the full review with cortex status <taskId> --detail full.
Audit & monitor (across every repo)
Cortex stores sessions in a central, XDG-organized location ($XDG_STATE_HOME/cortex/sessions/<repo>/<taskId>/ by default), so these commands see all your work regardless of which repository it belongs to — one place to audit and monitor. All support --json.
Choosing a read command — they overlap on purpose; pick by scope:
| You want… | Use |
|---|---|
| One screen of a single session, from any directory (the default human view) | cortex show <taskId> |
| The agent-checkpoint view: phase, hypotheses, scope drift, missing verification, tool health | cortex status <taskId> |
| A session's chronological feed (phases + evidence + tool calls + verification) | cortex timeline <taskId> |
| Outcome + evidence-trail metrics, incl. time-in-phase (per-task or workspace aggregate) | cortex metrics [taskId] |
| Every session across every repo (filter by repo/active/stale/query) | cortex sessions |
| A cross-repo rollup (completion, verification, where work sits) | cortex overview |
show is the recommended single-session view; status, timeline, and metrics are focused projections of the same session (and timeline/metrics are also exposed to operators via the MCP all profile), so nothing is lost by starting with show.
cortex sessions (sess)
Every session across every repo, newest first: repo · phase · age · verification · goal.
cortex sessions # everything, everywhere
cortex sessions --repo billing # only sessions whose repo/slug matches
cortex sessions --active # only in-flight (non-terminal)
cortex sessions --stale # in-flight but untouched beyond --stale-after (default 24h)
cortex sessions --query "billing partial" # case-insensitive AND terms across identity/stateAn in-flight session untouched beyond --stale-after renders its age with a ⚠ — a nudge toward forgotten or stuck work. Add --archived to list retired sessions instead of active ones.
cortex archive <taskId> / cortex unarchive <taskId>
Retire a finished session — move it (a terminal session: complete / abandoned / blocked) out of the active tree into $XDG_STATE_HOME/cortex/archive/, so sessions / overview / studio stay focused on live work as history accumulates. The data is preserved and reversible with unarchive; nothing is deleted, and in-flight sessions are refused. View the archive with cortex sessions --archived.
cortex prune
Bulk-retire forgotten in-flight sessions. Lists the active sessions that have not advanced within --older-than (default 7d — more conservative than the 24h monitoring "stale" flag). Dry run by default: it reports what would be pruned and changes nothing. With --apply, each stale session is aborted (recording the reason) and archived — honest because the abort records why it was retired, and recoverable because cortex unarchive <taskId> restores it. Use --repo to prune one repository only.
cortex prune # dry run — list in-flight sessions idle > 7d
cortex prune --older-than 30d # idle > 30 days
cortex prune --apply # abort + archive them (reversible)
cortex prune --repo myrepo --apply # one repository onlycortex rm <taskId> (delete)
Destructive, irreversible. Permanently deletes a session's directory and everything under it — this is the only destructive operation in Cortex. Prefer cortex archive if you just want a finished session out of the way; archiving is reversible, rm is not.
Guards:
- Terminal sessions only. In-flight (non-complete/abandoned/blocked) sessions are refused — complete, abort, or archive one first.
- Dry run by default. Without
--force,rmonly prints the directory that would be deleted; nothing is removed. Pass--forceto actually delete. - Works on a session in either the active tree or the archive.
cortex rm <taskId> # dry run — shows what would be deleted
cortex rm <taskId> --force # permanently deletes it (no undo)cortex show <taskId> (view)
A full one-screen view of a single session: phase badge, loop stepper, hypotheses, verification receipts, time-in-phase (with elapsed), and recent activity. Central sessions are located by ID from any directory. For a repo-local or custom cases_dir, pass -C <workspace>; you still do not need to cd there. (cortex status remains workspace-scoped.) --json returns the whole view.
cortex overview (dash)
A cross-repo rollup: totals, active/stale counts, completion and verified-completion rates, mean time to complete, and a per-repo breakdown. The "how am I using cortex overall" dashboard.
cortex timeline <taskId> (activity)
A session's chronological activity — phase transitions, evidence, audited tool calls, and verification receipts — merged and time-sorted. Central sessions work from any directory; pass -C <workspace> for a repo-local or custom case store. This is the reader for a case's audit log.
Other
| Command | Purpose |
|---|---|
cortex resolve <taskId> <hypId> --status … --reason … | mark a hypothesis confirmed/challenged/rejected (history retained) |
cortex metrics [taskId] | observability: per-task outcome + evidence trail (incl. time-in-phase), or the workspace aggregate |
cortex list (ls) | all tasks in the current workspace, newest first (for cross-repo, use cortex sessions) |
cortex doctor | environment + a cross-repo session snapshot + specialist tool health (JSON with --json) |
cortex init | write a starter cortex.yaml, detecting your test runner (Go/Rust/Node/Python) as a command verifier; refuses to clobber an existing config unless --force |
cortex setup | read-only readiness check — git repo, cortex.yaml, and whether codemap/vecgrep are installed and indexed (via cheap native status probes: vecgrep --lightweight, codemap --skip-stale, not dummy search). Reports ready / stale / needs_index / error honestly — drift is stale (still queryable), not needs_index; --trust-commands grants configured verifier argv outside the repo |
cortex config | resolved workspace/storage paths, budget, recall policy, safe verifier metadata (argv omitted), redaction count, and applied cortex.yaml sources |
cortex abort <taskId> <reason> | stop a task without deleting evidence |
cortex read-evidence <taskId> <evidenceId> | print a full evidence record (with its rawRef) |
cortex read-artifact <taskId> <ref> [--path file] [--max-bytes N] [--allow-binary] | preview a task-owned raw ref or task-referenced fcheap ref; path must be safe/relative; discovery ≤512 entries/100 files; binary requires explicit opt-in; 32 KiB default/128 KiB cap |
cortex serve (mcp) | run the MCP server over stdio; compact agent profile by default |
cortex serve --profile agent exposes 17 lifecycle, collaboration, evidence, and recall tools for a model's normal working context. cortex serve --profile all exposes 24 tools by adding seven cross-repository monitoring/session-administration operations for an operator-oriented MCP client. See MCP server.
cortex migrate
Moves a legacy ~/.cortex (or $CORTEX_HOME-collapsed) tree onto the split XDG layout — config.yaml → $XDG_CONFIG_HOME/cortex, sessions//archive//anything else → $XDG_STATE_HOME/cortex, cache/ → $XDG_CACHE_HOME/cortex. Dry run by default — it reports every planned move without touching disk; pass --apply to actually perform them. It is all-or-nothing: if any XDG destination already exists, the whole migration is blocked (nothing moves) so it can't leave a half-migrated state where moved sessions become invisible under the surviving ~/.cortex — resolve the conflict and re-run. If ~/.cortex ends up empty afterward, it's removed. With $CORTEX_HOME still set, or with no legacy ~/.cortex present, it's a no-op that explains why (--json reports this as note, applied: false).
cortex migrate # dry run — see what would move
cortex migrate --apply # actually move config.yaml/sessions/archive/cacheExit behavior
An operational error returns a non-zero exit and prints Error: … to stderr. Rejected gates (e.g. a plan with no disproof path) return a non-zero exit with a clear reason — the phase is left unchanged so you can correct and retry.