CLI reference

commitmind is the single binary you install with the quickstart. The installer also creates a shorter mind alias that points at the same binary, and the examples below use it — mind <command> and commitmind <command> are interchangeable. All commands accept --help for a concise inline summary; this page is the prose version.

Exit codes follow the Unix convention: 0 on success, non-zero on failure. Specific non-zero codes are noted per-command where they matter.

mind login

Pair this machine with your CommitMind account via OAuth 2.0 device flow.

mind login [--client-name NAME] [--backend-url URL]

Flags

Example

mind login --client-name "work-laptop"

Prints a short user code, opens the verification URL in your browser, and polls until you approve. The token is stored under ~/.commitmind/auth.json (mode 0600).

mind onboard

Run the unified onboarding wizard — install.sh execs this after placing the binary on disk so a fresh machine flows from curl … | bash to "ready to use" in one continuous Bubble Tea flow.

mind onboard

Steps the wizard walks you through

  1. Welcome — platform / arch / binary-path summary + step preview with ✓ markers next to anything already done on this machine.
  2. PATH — appends the binary's directory to your shell rc files (zsh / bash / fish) when missing. Idempotent + opt-in per shell. Skipped silently when the rc file already references the dir.
  3. Background indexer — installs the user-level launchd plist (macOS) or systemd user unit (Linux). No sudo. Skipped silently when the unit is already on disk.
  4. Menubar tray (macOS only) — generates the .app wrapper + LaunchAgent so the menubar icon appears immediately. Auto-skipped on every other platform.
  5. Sign in — OAuth 2.0 device flow (same as mind login). Skipped silently when a PAT already lives in your token store.
  6. Init wizard — chains into the same flow mind init runs (project picker, editors, coaching, backfill, summary, live execute, done banner).

Every step is idempotent and gated on actual need — re-running mind onboard after a partial flow detects done steps and skips through them.

Non-TTY behaviour

When stdin / stdout aren't TTYs (CI, automated pipelines, headless shells), mind onboard skips the Welcome / PATH / daemon / tray / login screens and chains directly into mind init's inline-prompt path. To complete setup in headless environments, the canonical path is still:

mind login          # device-code OAuth
mind init           # connect this repo

mind init

Connect the current git repo to a CommitMind project. By default renders a Bubble Tea wizard (Welcome → Project → Editors → Coaching → Backfill → Summary → live execute) when stdin AND stdout are TTYs. Auto-disables and falls back to inline prompts when --no-tui, CI=non-empty, NO_COLOR=non-empty, or --mcp-config-only is set.

mind init [--org SLUG] [--project ID_OR_SLUG]
                [--token-name NAME] [--no-hook] [--force]
                [--no-tui] [--no-mcp-config | --mcp-config-only=KEYS]
                [--no-skills] [--no-coaching-hooks]
                [--coaching-hooks=project|user|skip]
                [--no-claude-md] [--no-copilot-instructions]
                [--no-vscode-settings] [--no-gitignore]
                [--no-sync-attach] [--no-backfill]
                [--backend-url URL]

What it does

  1. Picks an org and project (auto-detect by canonical git remote URL first; falls back to the picker when nothing matches or the user chooses "different").
  2. Mints a project-scoped agent token and stores it under ~/.commitmind/projects/.
  3. Installs .git/hooks/post-commit (memory capture) and .git/hooks/pre-commit (review gate, threshold=high).
  4. Wires the commitmind MCP server into selected editors' configs — Claude Code, Claude Desktop, Cursor, VS Code (Copilot Chat).
  5. Installs agent-coaching hooks (project- or user-scope), routing skills, .claude/settings.json deny block, .vscode/settings.json terminal-tab keys, CLAUDE.md routing block, and .github/copilot-instructions.md.
  6. Manages .gitignore so per-developer MCP configs aren't committed.
  7. Attaches the repo to the local sync daemon's projects.json.
  8. Runs the auto-backfill (skip / incremental / full based on the API's view of the project) with a live progress bar.
  9. Auto-commits init's tracked-intent outputs as chore(commitmind): init.
  10. Waits up to 30s for the local symbol index to populate.

Flags

Example

mind init --org acme --project acme/monolith

mind status

Show the active backend, your user identity, and (if run inside a linked repo) the connected project.

mind status [--json] [--repo-dir PATH]

Flags

Exit codes

mind learn

Read this repo's own history and propose its rules, architecture and past decisions — each one citing the commits it came from. Nothing is applied.

mind learn
mind learn --window 100
mind learn --dry-run          # show what it would record, write nothing
mind learn --yes              # record every proposal without asking

Runs entirely on your own coding agent (claude or codex). Nothing is metered, and nothing leaves your machine except what that agent already sends. The pass is tool-free: it reads the commit text you give it and cannot open other files — commit messages are written by anyone who ever contributed to the repo, so they are treated as untrusted input rather than as instructions.

Every proposal must cite a real commit from the window that was read. A candidate that cites nothing, or cites a commit that is not in that window, is dropped rather than shown with a weaker label — a proposal a reviewer cannot check is worse than no proposal.

Each run leads with what it actually looked at, before any result:

reading history on local:claude…
de-duplicating against 262 recorded decision(s)

analyzed 40 of 4057 commits

16 proposal(s): 7 rule, 4 architecture, 5 decision

The analyzed N of M line is the point: history is unbounded, so a run reads a window and says so. 0 duplicates skipped would be meaningless without the corpus size beside it.

What it proposes

Reviewing what it found

Proposals are ordered by how much judgement you have to supply yourself: a boundary that comes with a violation count first, then a rule whose pattern was dry-run against your real code, then a decision that names the alternative it rejected. Everything after that needs you to do the work, so it sorts last.

The top proposals are shown and the rest are counted, not hidden — a list that simply stops reads as the complete answer. Raise --shortlist to see them.

Each one is shown with its commits at the decision point, and you answer y (record), n (skip) or q (stop asking). Quitting keeps what you already accepted; it just stops the questions.

With no terminal — in CI, or behind a pipe — the command prints the shortlist and records nothing rather than waiting on an answer that will never come. Pass --yes to record without being asked.

Flags

Nothing it records becomes active on its own. Rules land advisory and pending, architecture as a capability-doc proposal, decisions as proposed — and each is stamped as machine-inferred so auto-mode's background approvers skip it. A rule derived from commit messages always waits for a person.

Requires a local coding agent. With neither claude nor codex on PATH the command stops and says so — there is no degraded mode, because without a model there is no extraction at all and a partial run would overclaim.

On a repo with no CommitMind project, it still works: rules come back as prose rather than compiled patterns, because the structural dry-run needs the local symbol index that a connected project builds. Each prose rule carries the reason it stayed prose — an unauthorable pattern kind, a pattern too broad to be a convention, or the compile budget already spent — rather than appearing as a weaker result with no explanation.

mind coverage

Show test coverage, parsed from a report your project already produces. Never runs your tests.

mind coverage

Coverage is a runtime measurement — which statements actually executed during a test run — so it can only come from a report your test tooling wrote. Recognised formats, which between them cover every language CommitMind supports:

| Format | Typical producer | Looked for at | |---|---|---| | Go coverprofile | go test -coverprofile | coverage.out | | LCOV | vitest, jest, nyc, llvm-cov | lcov.info, coverage/lcov.info | | Cobertura XML | coverage.py, coverlet, phpunit, tarpaulin | coverage.xml, cobertura.xml, coverage/cobertura-coverage.xml | | JaCoCo XML | JaCoCo (Maven / Gradle) | target/site/jacoco/jacoco.xml, build/reports/jacoco/test/jacocoTestReport.xml, jacoco.xml | | Clover XML | PHPUnit | clover.xml, build/logs/clover.xml | | Istanbul JSON | nyc / vitest json reporter | coverage/coverage-final.json |

When several reports exist — a polyglot repo usually has more than one — every one is listed with its own unit, and they are not combined. Go counts statements and LCOV counts lines; a blended percentage would have no unit.

When no report exists, the output says so explicitly and names the command that would produce one for your stack, inferred from the repo's language mix:

  Not measured. No coverage report found in this repo.

  This is NOT 0% coverage — nobody has produced a report to read.

  This looks like a Go project (74% of source bytes). To produce one:
    go test ./... -coverprofile=coverage.out

"No report" is never reported as 0%: an unmeasured project and an untested one are different claims.

Exit codes

mind flush

Drain the local buffer of commits/observations that failed to post (usually because the API was unreachable during capture).

mind flush [--all] [--repo-dir PATH] [--verbose]

Flags

Exit codes

mind backfill

Walk git history oldest-first and ingest each past commit — plus a short summary observation — into CommitMind. Useful on a freshly-linked repo so the timeline isn't empty.

mind backfill [--repo-dir PATH] [--limit N] [--since DATE]
                    [--quiet] [--verbose] [--no-buffer] [--dry-run]

Flags

Examples

# Import the last 30 days.
mind backfill --since 2026-03-24
 
# Fast preview: how many commits would this touch?
mind backfill --dry-run

mind explain

Resolve a file path or symbol name and emit a fixed-schema envelope of decisions, observations, and commit summaries pertinent to the target — the why behind a piece of code. Pairs with xref (the where-lookup): xref answers "where is this defined / called", explain answers "why does this exist / what context shaped it" — without keyword-guessing into search_memory.

mind explain <file|symbol> [--format=json|markdown]
                                 [--synthesize] [--quiet] [--repo-dir PATH]

Default response is fast (~100ms): full source content (decision rationales + observation bodies + commit messages) inline so the caller can read directly. The MCP tool and PreToolUse hook share this same path — agents read raw content directly, no LLM call.

Pass --synthesize to layer an LLM-produced Why paragraph plus categorized Constraints / Risks at the top. Takes 4–8s for a hot file (Sonnet/Haiku-tier model generation time); useful for human reading from a terminal, not from agents.

Flags

Examples

# Quick context check on a file (raw content, sub-second).
mind explain apps/cli/internal/commands/explain.go
 
# Symbol lookup — resolves to the indexed file(s) it lives in.
mind explain RegisterTaskAdvance
 
# Human-friendly synthesis for a longer reading session.
mind explain pkg/explain/queries.go --synthesize
 
# JSON for tooling.
mind explain pkg/explain/queries.go --format=json

Exit codes

mind doctor

Run a battery of probes against this machine's CommitMind install — daemon health, tokenstore + auth handshake, MCP wiring per editor, and hook installation. On macOS it also classifies any crash reports the daemon has left behind, so a daemon that keeps dying tells you how it died rather than just that it's gone. Pure diagnosis by default; pass --fix to apply the safe-to-fix subset.

mind doctor [--check NAME] [--fix] [--yes] [--json]

Flags

mind usage

Report what background AI has cost on this machine — the transcript harvester, the AI security scan, and the agent worker — broken down by producer and by pass. Reads the daemon's local cache only: no network, no account.

Figures are tokens charged against the agent seat this machine runs on, not dollars. That distinction matters: background AI runs on your own Claude or Codex subscription, which is a rate limit rather than a bill, so the cost of a heavy background pass shows up as your own interactive work being throttled mid-task rather than as an invoice. A dollar figure reads as trivially cheap and hides exactly the problem you are trying to find.

Results are grouped by pass as well as by call, because a pass is what the cadence settings control — one scan can fan out into dozens of batched completions, and a per-call average hides that.

mind usage [--days N]

Flags

A producer whose backend reports no usage is flagged rather than shown as zero: its cost is unknown, not free.

The report closes with your spend ceiling — what the last 24 hours cost against the bound you set, or a note that none is set.

mind usage limit

Bound how many tokens background AI may draw from your agent plan in a rolling 24-hour window. The ceiling is per-machine and covers every AI producer: security review, correctness review, harvest, mind learn, and commit-message composition.

mind usage limit light        # ~2M tokens/day
mind usage limit balanced     # ~8M tokens/day
mind usage limit thorough     # ~30M tokens/day
mind usage limit 500000       # an exact bound
mind usage limit unlimited    # remove the ceiling

Presets are a starting point, not a measurement. They are anchored on a single observed pass — one reviewed commit cost roughly 543K tokens — so treat them as a first guess and adjust once mind usage shows your own numbers. A raw token count is there precisely so you can.

The window is rolling, not a calendar day: there is no moment at which the number resets to zero. It decays continuously as older calls age past 24 hours, which is why the report says "in the last 24 hours" rather than "resets in N".

When the ceiling is reached, background passes are refused, not queued, and the refusal names the setting. A pass already running is never killed — enforcement happens when a pass is admitted, so no work in flight is wasted.

Unset means unlimited. So does an unrecognised value in the config file: a ceiling that cannot be read fails open rather than silently throttling the machine.

mind ui-verify

Helpers for the ui-verify blocks that mind task verify runs (headless Playwright: navigate routes, assert console/network + visible text, capture screenshots). By default that tier is logged-out, so it can only check public pages. ui-verify login saves a real browser session so a block can check pages behind a login too.

mind ui-verify login --url https://app.example.com [--login-path /signin]
mind ui-verify logout --url https://app.example.com

login opens a browser window, waits for you to log in, and saves the session to the CommitMind cache — one file per host, mode 0600, never inside a repo. You type the password, so SSO, 2FA, and magic links all work; the CLI never handles a credential itself. Re-run it when a session ages out.

A block then asks for that session by intent:

```ui-verify
{
  "baseUrl": "https://app.example.com",
  "auth": true,
  "routes": [{ "path": "/acme/get-started", "expect": [{ "text": "Get started" }] }]
}
```

The block never names the file. Blocks live in a task's review_instructions, which sync to the cloud and render on the dashboard, so the path is resolved locally — "auth": {"storageState": "..."} is rejected outright.

Routes stay independent: each one still gets a fresh browser context, merely seeded from the same saved session, so run order never matters.

If the saved session has expired, the app redirects to its login route and the route is reported as session-expired rather than as a wall of failed assertions — one run tells you to log in again. If no session has been saved for that host, the tier skips with the exact command to run.

Flags

Security. The saved session is a live credential in plaintext on disk, and authenticated screenshots captured by a run contain your real pages and are uploaded with the verification record. Use this on workspaces you own.

mind update

Pull the latest CommitMind release. Fetches the manifest from commitmind.dev/dl/latest, downloads the platform-matched binary archive, verifies its SHA-256, and atomically replaces the running binary in place. The daemon is reloaded (launchctl on macOS, systemctl --user on Linux) so the new binary takes effect immediately.

mind update [--check] [--manifest-url URL]

Flags

mind prime

Print this project's CommitMind context as markdown. When stdout is a terminal, renders a scannable human card (recent commits, observations, open tasks). When piped or run with --hook-envelope, renders an agent-shaped payload designed to load into an AI session via a SessionStart hook — no manual prime_session MCP call required.

mind prime [--post-compact] [--hook-envelope]
                 [--quiet] [--no-color] [--repo-dir PATH]

Flags

Exit codes

mind explain

Resolve a file path or symbol name and emit a fixed-schema envelope of decisions, observations, and commit summaries pertinent to the target — the why behind a piece of code. Pairs with xref (the where-lookup): xref answers "where is this defined / called", explain answers "why does this exist / what context shaped it" — without keyword-guessing into search_memory.

mind explain <file|symbol> [--format=json|markdown]
                                 [--synthesize] [--quiet] [--repo-dir PATH]

Default response is fast (~100ms): full source content (decision rationales + observation bodies + commit messages) inline so the caller can read directly. The MCP tool and PreToolUse hook share this same path — agents read raw content directly, no LLM call.

Pass --synthesize to layer an LLM-produced Why paragraph plus categorized Constraints / Risks at the top. Takes 4–8s for a hot file (Sonnet/Haiku-tier model generation time); useful for human reading from a terminal, not from agents.

Flags

Examples

# Quick context check on a file (raw content, sub-second).
mind explain apps/cli/internal/commands/explain.go
 
# Symbol lookup — resolves to the indexed file(s) it lives in.
mind explain RegisterTaskAdvance
 
# Human-friendly synthesis for a longer reading session.
mind explain pkg/explain/queries.go --synthesize
 
# JSON for tooling.
mind explain pkg/explain/queries.go --format=json

Exit codes

mind dashboard

Open the local project dashboard served by the running sync daemon. Requires mind sync daemon (or the launchd / systemd unit installed via mind sync install) to be running.

mind dashboard [--print-url]

Flags

mind review

Run a structured review pass over the repository and print findings — symbol-level diff for the change-scoped modes, project rule violations across all of them. Each finding is severity-tagged (info / low / medium / high / critical).

mind review [--scope working|task|staged|head|all]
                  [--threshold info|low|medium|high|critical]
                  [--format text|json|jsonl-stream]
                  [--limit N] [--path PATH ...]

Scopes

--head-tree <sha> reviews the content of a git tree object instead of the live working tree (--scope=working only). mind commit passes the tree it froze for the commit, so the gate reviews exactly the bytes that will be committed rather than a working tree a concurrent agent may still be writing to — the diff, the changed files and lines, the file contents and the reported head SHA all come from that tree. Rarely useful by hand.

AI review passes

Beyond the deterministic engine, review can run LLM passes on your local coding agent:

Set the project defaults from the dashboard's review-config drawer, so agents, CI, and the review_ai MCP tool inherit them without per-run flags.

Which files are reviewed

The diff scopes review only the files in the change. --scope all enumerates with git ls-files, so it reviews tracked files only — anything gitignored (build output, dist/, .env, local artifacts) is skipped automatically. You don't need to configure anything to keep gitignored generated files out of a review.

For files that are committed but you don't want reviewed — vendored dependencies, checked-in codegen, parser fixtures — add a .commitmindignore at the repo root. .gitignore can't exclude these because they're tracked on purpose. It uses gitignore-style globs matched against repo-relative paths; matches are dropped from --scope all entirely and marked skipped in the diff scopes (so you still see when a commit touches an ignored path).

# .commitmindignore — paths no rule should ever fire against.
# gitignore-style globs, matched against repo-relative paths.
 
vendor/**            # vendored third-party code
**/*.pb.go           # protobuf codegen
**/*.sql.go          # sqlc codegen
**/testdata/**       # parser / rule fixtures
apps/web/dist/**     # a committed build artifact

| File kind | How it's excluded | | --- | --- | | Gitignored (build output, .env, local artifacts) | Automatic — git ls-files skips it; no config | | Tracked but generated / vendored | .commitmindignore.gitignore can't, since they're committed |

.commitmindignore means "never review this path." To silence a specific rule on a path while keeping the others, scope it in that rule's file_patterns instead.

Pre-commit gate

--threshold <sev> exits non-zero (code 7) when at least one finding has severity ≥ <sev>. Pair with mind install-hook to block commits on regressions.

Flags

jsonl-stream event shape

One JSON object per line. Events arrive in this order:

| event | When | Key fields | |-------------|--------------------------------------------|---------------------------------------------------| | progress | Stages: start once, file per file, done once | stage, done, total, path, findings, truncated | | finding | Each deduped finding from the rule pass | severity_label, Path, Line, Message, RuleID | | summary | Once at the end | scope, base_sha, head_sha, files_reported, truncated, counts (per-severity totals) | | error | On orchestrator failure (mid-run) | message |

When an error event lands, no further events follow.

Examples

# Live progress for a project-wide audit
mind review --format=jsonl-stream --scope=all
 
# CI gate (text + threshold pair):
mind review --threshold=high
 
# Pipe the streaming events into jq for ad-hoc filtering:
mind review --format=jsonl-stream --scope=all \
  | jq -c 'select(.event=="finding" and .severity_label=="critical")'

Exit codes

Coverage gate

When the project enables it, mind review --scope=auto — the mode the installed pre-commit hook runs — also checks patch coverage: whether the lines you are staging are covered by tests. Blocks with exit code 8, distinct from the findings gate's 7 so a caller can tell which one fired.

Patch coverage, not the project total, so a legacy repo is never blocked on code nobody touched.

Configuration

When it declines to judge

The gate warns and does not block when it cannot honestly measure:

That last group matters more than it looks. A coverage report records positions in each file as it was when the tests ran, so lines you wrote afterwards appear in no block at all. Silently excluding them would compute "100% of nothing" and pass — precisely when the gate was most needed. It refuses instead.

AI coverage gate

When the project enables it, mind commit also blocks if the AI-judgment pass (logic bugs, missing edge cases, breaking changes) ran but could not finish reviewing the diff — e.g. a slow local agent under heavy machine load. Blocks with exit code 9, distinct from the findings gate's 7 and the patch-coverage gate's 8.

This is separate from an AI finding blocking a commit — judgment findings stay advisory. This gate fires only on a coverage gap: the pass was attempted and did not cover everything.

Configuration

When it blocks

✖ AI coverage gate: the AI-judgment pass could not fully review this diff.

  Not covered:
    apps/api/foo.go

  Narrow the diff and try again:  mind commit -- <path> ...  (commit just those paths)
  Or skip AI judgment for this commit (deterministic rules still gate):  mind commit --no-ai

Suppressions

A suppression marks one finding on one file a false positive. A fresh match is then kept visible as an advisory but never blocks the commit gate — the scoped alternative to disabling a whole rule or running --no-review.

# Mark one finding on one file a false positive (reason + category required).
mind review suppress --file web/icons.ts \
  --heuristic rule:lint/unused-import \
  --reason "used via object shorthand two lines below" --category false-positive
 
# Narrower: silence ONE security finding rather than the whole analyzer.
mind review suppress --file pnpm-lock.yaml \
  --finding security:osv-scanner:CVE-2026-64641 \
  --reason "relocated, not introduced — verified present in the root lockfile" \
  --category false-positive
 
# Suppress everything currently blocking the gate, in one attributed batch.
mind review suppress-gating --reason "…"
 
# See what is suppressed — id, reason, who, when.
mind review suppress-list
 
# Put a finding back in the gate.
mind review suppress-revoke <id>

Pick the flag by the scope you mean. --heuristic silences that heuristic or analyzer on that file — right for a vendored or generated file. --finding silences one finding, identified by its id (security:<tool>:<code>) — right when you have judged one specific CVE or check. Suppressing a single CVE with --heuristic would stop that scanner reporting on the file at all, so a genuine new CVE appearing there later would not gate. The _False positive?_ line printed under each finding already names the narrower form where one exists.

Both can coexist on the same file; they are separate rows.

suppress-list reads the daemon's local mirror, so it needs no network and works offline. Each entry prints the id that suppress-revoke takes. If the daemon has not synced yet it says so explicitly rather than reporting "no suppressions" — an unsynced cache and an empty project are different answers.

Suppressions recorded before attribution shipped display as unattributed: no creator was captured for them, so none is claimed.

suppress-revoke removes the suppression so matching findings gate again on the next review. Unlike the read path it is not best-effort — a failure is reported, because silently failing to revoke would leave you believing a finding is live when it is still suppressed. The local mirror may still list the revoked row until the daemon re-syncs.

mind commit

Commit through CommitMind instead of git commit. It runs the deterministic staged review first (fail-fast — nothing is committed if a finding meets the project gate), composes the message, links the commit to a task, and hands off to git so your normal pre-commit hook still runs.

mind commit [-m MSG ...] [--task ID] [--index | --only-staged]
                  [--no-review] [--no-ai] [--dry-run] [-- <pathspec>...]

mind is the short alias for commitmind, so mind commit is the same command.

What gets committed — the part worth understanding

This is the difference from git commit, and it exists because several agents often share one checkout and one git index.

The attributed narrow runs git add on your task's files, which stages their working-tree content. Any file it stages that wasn't already staged is named in the output, so the widening is never silent.

Gates that can refuse the commit

Use --dry-run to see the verdict over what would be committed without staging, committing, or spending AI-message budget.

The message

With no -m and no --no-ai, the message is generated on your local coding agent from the diff. -m (repeatable, like git) or -F FILE suppress generation; --no-ai opens your editor instead.

The diff it reads is the commit's exact content, frozen up front as a git tree before the review gate runs — so brand-new files are included (they used to be invisible, because git diff cannot report an untracked path), and the gate, this message and the printed file list all describe the same thing. If the files change underneath a commit while it is being prepared — a concurrent agent writing to the same paths — the commit is refused rather than landing with a review verdict for content that was never reviewed.

Prefer -F over -m for anything multi-paragraph: -m routes the text through the shell, where backticks and $(...) execute.

A single CommitMind: task <short-id> line links the commit to the active session's pinned task; --task overrides it, and the line is omitted when nothing is pinned. No Co-Authored-By trailer is added.

Flags

| flag | effect | | --- | --- | | -m, --message | Message paragraph, repeatable. Suppresses AI generation. | | -F, --file | Read the message from a file. Mutually exclusive with -m. | | --task | Task id or short id to link; overrides the session pin, and satisfies task_pin_gate=strict on a shared checkout. Also selects the task whose title is given to the message generator as intent — without it, a bare CLI process on a shared checkout can pick up a peer's pinned task. | | --index | Commit the whole staged index instead of narrowing. | | --only-staged | Commit exactly the index — no narrowing, no auto git add. | | --no-review | Skip the fail-fast staged review. | | --no-ai | Don't generate a message; open the editor. | | --dry-run | Print the gate verdict and stop. Stages nothing, commits nothing. | | --repo-dir | Path to the repo (defaults to cwd). |

mind rules

Print the project rules applicable to a repo-relative file path as markdown — same payload the get_rules_for_this_file MCP tool returns. Designed to fire from a Claude Code PreToolUse hook so an editing agent reads the applicable rules block before every Read / Edit / Write.

mind rules <file> [--quiet] [--repo-dir PATH]

Flags

Exit codes

mind rules verdicts

Report what the AI review checklist has decided about each of your rules, and the gating lifecycle state each of this project's own rules is currently in.

Every review that runs the AI checklist records one verdict per rule — violated, clean or not_applicable. Only violated ever becomes a finding, so this is the only place the rest of the distribution is visible: which rules fire, which never apply, and how close each is to earning or losing a gate.

mind rules verdicts [--json]

Flags

What it shows

Only active project rules appear in the lifecycle table. Pack rules run a separate graduation pipeline, and a pending, disabled or superseded rule is never evaluated at all.

Reads the local cache only — no network, no account, and no daemon required.

Exit codes

mind check

Loads each file from disk, resolves the applicable hard rules, and evaluates them locally — file content never leaves your machine. Output is JSON in the same shape as the server-side POST /api/v1/rules/check response, so dashboard / CI integrations parsing the wire format keep working unchanged.

mind check <file>... [--no-lock] [--require-lock]
                           [--lockfile PATH] [--quiet] [--repo-dir PATH]

Rule source resolution (in order):

  1. .commitmind/rules.lock.json at the repo root if present — offline-capable, deterministic, no network round-trip. Same artifact mind sync rules produces; CI runs identically.
  2. GET /api/v1/rules/applicable per file — automatic fallback when no lockfile exists (or when --no-lock is set).

Flags

Exit codes

mind security audit

Run the chunked whole-repo AI security audit — the same pass the dashboard's whole-repo button runs, from the terminal.

This is the pass that resolves findings in files no current diff touches. The automatic version fires on a main/master tip change but defers execution until the machine is idle (no agent session, no edits for 20 minutes), so on a busy machine it can lag indefinitely. This is the manual escape from that lag.

mind security audit --whole-repo [--yes]

Flags

Two things worth knowing before you run it

Why there is no MCP tool for this

The design protects the property a human armed this, not the request came from a browser. The dashboard run is exempt from the idle-yield rule precisely because a person clicked it, and a command typed at a terminal has the same property. An agent-invoked trigger would not — so the absence of an MCP tool is an architectural fact rather than a convention. An agent that wants an audit has to ask you to run this.

mind install-hook

Render a git pre- or post-commit hook that runs mind review. The pre-commit hook gates git commit on a mind review --scope=auto pass, which resolves the scope from the project's review-gate config (precommit_scope, settable in the dashboard). It defaults to diff — "just the lines I'm committing": the same files as staged, gating identically, but findings on lines your commit did not touch are dropped rather than reported as pre-existing debt on every commit. Set it to staged if you want that debt surfaced (non-blocking) at commit time. When the gate fires, the commit is blocked and the report prints inline. Bypass with git commit --no-verify.

mind install-hook [--threshold info|low|medium|high|critical]
                        [--post-commit] [--force]

Flags

mind sync

Manage the per-machine sync daemon. The daemon keeps each project's local SQLite cache fresh from the API so rule eval, symbol lookups, and other read paths run on-laptop in under 50ms.

mind sync <subcommand>

Subcommands

Pass --help to any subcommand for its specific flags.

mind mcp

Run the CommitMind MCP server that Claude Code, Cursor, and other editors spawn per session. The server reads the agent token minted by mind init and streams JSON-RPC over stdio. You shouldn't normally run this by hand — the Claude Code plugin wires it (or mind init --mcp-config-only=<editor> for Cursor / VS Code).

mind mcp <subcommand>

Subcommands

# Inspect the surface this binary exposes.
mind mcp tool-snapshot | jq '.tools[].name'
 
# What the release pipeline runs.
mind mcp tool-snapshot --version v1.2.3 -o dist/tools.json

tool-snapshot flags

mind whatsnew

Report what changed in CommitMind since a given version: the releases published after it, their notes, and a classified diff of the MCP tool surface — which tools were added or removed, which arguments changed, and which of those can break a call you already wrote.

mind whatsnew [--since vX.Y.Z]

Flags

Changes are grouped by impact on an existing caller: breaking (tool removed, required argument added, argument removed or retyped), additive (tool added, optional argument added, a requirement relaxed), and cosmetic (wording).

Tool-change reporting only works backward to a release that published a schema snapshot. Releases cut before that artifact existed carry none, and for those ranges the command says so explicitly rather than reporting that nothing changed. Treat "could not be determined" as unknown, never as "unchanged".

The same report is available to agents as the whatsnew MCP tool on the tasks surface, with an optional since argument that defaults to the running server's version. That is the form an agent should reach for when it is unsure whether a tool or argument exists in the installed version — the CLI command is for humans at a terminal.

mind sweep

Compare the project's indexed files (every distinct path in project_symbol_index) against this repo's HEAD via git ls-files, then DELETE the index rows for any file no longer in HEAD. Companion to mind backfill --force--force re-queues commits for the staleness worker; sweep cleans up symbol-index rows that no commit will ever re-touch.

mind sweep [--dry-run] [--yes] [--verbose] [--repo-dir PATH]

Flags

Exit codes

mind agent

Run cheap headless workers on agent-ready tasks — the single-task dispatch loop. agent run loads an agent-ready task, assembles its design + relevant memory into a worker prompt, isolates a cheap claude -p worker in a throwaway git worktree, lets it iterate to green, runs the task's acceptance verification against the worker's diff, then surfaces the diff for human review. It runs an escalation ladder — cheap model first, retry with feedback, then a stronger model — and never auto-merges. The worker never sees the acceptance test (it's orchestrator-held), and the retry feedback reports only that a check failed and its kind — never the check command or its assertion values, so the worker can't target the gate.

mind agent run <task-id> [--model SLUG] [--no-escalate] [--max-retries N] [--dry-run] [--repo-dir PATH]

Flags

Gate. The task must be agent-ready (cleared the refinement gate: a runnable verify block in review_instructions + a leaf task with a design_doc). A task that isn't is rejected with a pointer to task_mark_agent_ready.

Entitlement. The coding agent (Mind Code) is a Pro feature, checked at dispatch — a confirmed free-tier org is blocked with an upgrade pointer before any worker spawns. The check runs after --dry-run (a dry run never spends, so it's never gated) and fails open: if the entitlement lookup can't be reached, dispatch proceeds with a warning rather than blocking a paying user on a transient outage. agent queue applies the same check per task.

Outcome. On a passing verify the task advances to review with a note summarising every attempt; the worker's diff stays in the worktree for you to review and merge (or discard with git worktree remove). If the whole ladder fails, the command exits non-zero and (when a salvageable diff survives) leaves the worktree for you to inspect. Local dispatch spends your own claude login.

mind agent queue

Drain the agent-ready queue — pick up every agent-ready task in the project (the orchestrator's queue) and dispatch each one, in turn, through the same escalation ladder as agent run. Tasks already in review (dispatched and awaiting a human) are skipped; nothing is ever auto-merged. This is a one-shot drain, not a long-running poller — re-run it (or wire it to a cron) to pick up newly refined tasks. Workers run sequentially, one worktree at a time.

mind agent queue [--limit N] [--model SLUG] [--no-escalate] [--max-retries N] [--dry-run] [--repo-dir PATH]

Flags

Outcome. Each task that passes verification advances to review in its own worktree; each task that fails the whole ladder is left for the human (its worktree kept) and the drain continues to the next task. The command prints a summary — dispatched / advanced to review / left for human — and exits 0 unless it can't list tasks or you're not inside a git repository (leaving tasks for a human is a normal queue outcome, not a failure).

mind tray (macOS only)

Launch the menu-bar tray — a read-only status surface for the local sync daemon. Polls the daemon's pidfile for at-a-glance state and tails the recent-events log for activity.

mind tray              # launch foreground
mind tray install      # install LaunchAgent (.app + plist)
mind tray uninstall    # remove LaunchAgent

Auto-started by the LaunchAgent installed via mind tray install. Run foreground for debugging or to test the menu without the LaunchAgent. Quit from the menu's "Quit Tray" item — the daemon keeps running.

mind uninstall

Wipe every CommitMind artifact on this machine. Iterates every repo recorded in ~/.config/commitmind/projects.json and removes project-scope artifacts (hooks, MCP entries, .gitignore block, agent skills) in each. Each per-repo wipe auto-commits ONLY the tracked files it touched, with message "chore: remove CommitMind integration" (explicit paths only). The commit is NOT pushed.

After per-repo cleanup, machine-scope artifacts are wiped: the sync daemon stops, launchd/systemd units unload, the menubar tray is removed, caches and ~/.config/commitmind (projects.json, every agent token, the user PAT) are removed, and finally the commitmind binary itself.

mind uninstall [--scope all|project|user] [--dry-run]
                     [--keep-binary] [--keep-daemon] [--keep-git-hook]
                     [--keep-mcp-config] [--keep-tokens]

Flags

mind pack scope

Show, set, or clear the path scope of a subscribed rule pack.

A pack's rules apply to your whole repo unless its subscription carries a path scope. In a monorepo that means a framework pack fires in apps it has nothing to do with — a Next.js pack flagging a raw <img> in a Vite dashboard, for example. Scoping the subscription confines it to the subtree it belongs to.

mind pack scope                                        # list packs + current scopes
mind pack scope --pack nextjs --set 'apps/landing/**'  # narrow it (repeatable)
mind pack scope --pack nextjs --clear                  # back to whole-repo

Flags

When you'd reach for it

A pack rule fires somewhere it obviously shouldn't. Check the scope before concluding the rule is wrong — an unscoped framework pack looks exactly like a mis-installed one. Run it with no flags: unscoped packs are listed as (whole repo), which is the state that produces this confusion.

--set with nothing is refused rather than sent: the server rejects an empty scope on purpose, so a forgotten flag can't silently widen a pack back across the repo. Use --clear when that's what you mean.

Not available here: subscribe / unsubscribe

Deliberately. Unsubscribing removes an entire ruleset and nothing announces the loss — a rule that stops firing is invisible — and subscribing has billing consequences on paid packs. Both belong to a human on the dashboard.

mind task

Anchor work to a CommitMind task from the shell, without MCP. This is what you reach for when the mind MCP server is down, or when a bare CLI process needs to name a task that ambient resolution will not guess.

mind task set-active <task-id>
mind task create --title "..." [--description "..."] [--type feature|bug|chore|refactor|direct]
mind task verify [--task <id>]
mind task attribute [<sha>...] --task <id>
mind task delete <task-id> --yes

set-active / create

Pin an existing task, or create one and pin it. Both register the pin on this session so the anchor-edit gate and mind commit can see it.

Note the pin is bound to the session, so a pin set by a short-lived shell can be reaped when that shell exits. On a shared checkout where several agents are pinned to different tasks, prefer naming the task at the point of use — mind commit --task <id> — over relying on ambient resolution, which deliberately refuses to guess.

delete

Permanently removes a task, including its todos and phase groups.

mind task delete <task-id> --yes

Prefer abandoning in almost every case. Abandoning is a real lifecycle state that stays in the audit trail, and it is the right answer for work that was started and then dropped — scope shifted, another task owns it, it stopped being relevant. Delete is for rows that should never have existed: a task created by mistake and caught immediately, test or scratch tasks, duplicates, or bulk junk an automated run created.

The test: would a reader of the board learn anything from seeing this task closed? If yes, abandon it. If it is just noise, delete it.

--yes is required — deletion is not a lifecycle transition and there is no CLI undo. The cloud keeps a soft-delete record, so recovery is possible server-side by an admin, but not from here.

Local-first like every other write: the row goes immediately and the deletion syncs to cloud in the background, so it works offline. It is also idempotent — deleting a task already gone locally still queues the cloud deletion and succeeds, because the row can be absent locally while present in cloud. The output says which of the two happened.

verify

Runs the task's verification (review_instructions commands plus any ui-verify / api-verify blocks) and records the verdict the done-gate reads. A deterministic review over the changed files also runs and gates on high/critical findings.

Two flags are set only by the hosted Mind Agent dispatch runner and are inert on a normal local run:

attribute

Attach already-made commits to a task.

mind commit links commits automatically by writing a Task: trailer, and mind capture can re-resolve a trailer whose ingest failed. Neither helps a commit that has no trailer at all — a plain git commit, or --no-verify.

That commit is not merely unlabelled. Its task ends up with no attributed commits, so the review gate falls back to "everything changed since the task started" — every peer's files included — and stops converging. Measured on a real task: 129 files for a 12-file change.

mind task attribute --task 2f09966            # HEAD
mind task attribute 637cf93 0548700 --task 2f09966

This does not infer attribution — you name the task, exactly as mind commit --task does at commit time. The rule capture states still holds: the system never guesses which task a trailerless commit belongs to; it only records what you assert.

mind capture (hook-invoked)

Hidden from --help; documented here for operators. Reads a commit via git show and posts it to the CommitMind API. mind init wires this into your .git/hooks/post-commit; you shouldn't normally run it by hand.

mind capture [--sha REV] [--repo-dir PATH] [--quiet] [--verbose] [--no-buffer]

Flags

Recovering a commit whose attribution never landed

The post-commit ingest routes through the local daemon so a CommitMind: task <short-id> trailer resolves into this machine's task_commits. That step is best-effort by design — a commit must never fail because the daemon is down — so a restarting or wedged daemon makes it fall through to the cloud, which does not write local attribution.

When that happens the trailer is never resolved, and the task's review gate widens from "this task's files" to "everything changed since the task started." In a shared checkout with another agent committing, that set grows faster than the scan retires it, and the gate stops converging.

Re-ingest the commit to resolve the trailer that was in the message all along:

mind capture --sha 58381d4

This cannot invent attribution. A commit with no trailer stays unattributed — the honest answer for it — so re-running is safe on anything.

When there was never a trailer

mind capture resolves a trailer that exists. A commit made with plain git commit — or git commit --no-verify, the escape hatch agents reach for when the task-pin gate blocks them — has no trailer to resolve, so capture correctly leaves it alone. Name the task explicitly instead with mind task attribute.