Documentation

The full reference for the mind CLI: install, commands, configuration, hooks, and suppressions. New here? Start with the quick start.

Install

Install the mind CLI on macOS or Linux:

curl -fsSL https://mindrealm.ai/install.sh | sh

On Windows, in PowerShell:

iwr -useb https://mindrealm.ai/install.ps1 | iex

Re-run the same command any time to update. The installer places a single mind binary in one location and touches nothing else: /usr/local/bin or ~/.local/bin on macOS and Linux, %LOCALAPPDATA%\Programs\mind on Windows.

Install manually

Prefer to install by hand? Download the archive for your platform from the releases page:

  • macOS / Linux: download mind-<os>-<arch>.tar.gz, extract it with tar -xzf, make it executable with chmod +x mind, and move mind onto a directory in your PATH (for example /usr/local/bin).
  • Windows: download mind-windows-<arch>.zip, extract mind.exe, and add its folder to your PATH.

Authenticate

However you installed it, sign in once before reviewing:

mind login

Review

From inside a repository connected to your GitHub App, review your changes (diff-only by default, or --full-scan for the whole repo):

mind review

Commands

CommandWhat it does
mind loginAuthenticate. Opens your browser.
mind setupDetect your agent(s) and set up the stop-hook auto-fix loop.
mind reviewReview your changed files. Diff-only by default.
mind analyzeThe hook entry point your agent calls when it stops. You won’t run it by hand.
mind feedbackReview past runs and record feedback on findings, or report a bug or feature request.
mind logoutLog out and remove stored credentials.
mind versionPrint the CLI version.
mind --helpList every command and flag.

Review categories

Mindrealm reviews Go, Python, TypeScript, and Rust across these categories:

CategoryLooks for
HygieneDead code, unused exports, magic values, leftover markers, naming.
ReliabilityUnhandled errors, swallowed exceptions, resource leaks, missing timeouts.
ArchitectureCoupling, cohesion, duplication, oversized types and interfaces.
PerformanceWork inside loops, unbounded growth, repeated expensive calls.
ConcurrencyUnawaited calls, detached tasks, blocking work in async paths.
SecurityHardcoded secrets, SQL/command/code injection, dangerous taint flow.
StructureLong functions, deep nesting, long parameter lists, large files.
TestingMissing or weak assertions, skipped tests, mock abuse, test pollution.
Language gatesYour toolchain linters and type checks (go vet, golangci-lint, ruff, tsc, eslint, cargo clippy).

Every review is deterministic: the same code returns the same findings every run. No model decides what gets flagged.

Review scope

mind review reviews your changed files by default (diff-only), matching what the stop hook reviews. To scan the whole repository:

mind review --full-scan

--diff-only and --full-scan are mutually exclusive, and --commit implies diff-only. On a trial, reviews are limited to diff-only. Whole-repo --full-scan is a paid-plan feature. Both are config-backed: set diff_only or full_scan in mind.yaml.

mind review must run from inside a git repository whose origin is a GitHub repo connected to the Mindrealm GitHub App. Outside a git repo, or with no GitHub origin, it fails fast with a clear message and the install link. Public repos the server can clone work as-is; a private repo the App was never installed on returns a clear not-connected message rather than a raw clone error.

FlagEffect
--full-scanScan the entire repository, not just changed files (paid plan).
--diff-onlyOnly report findings in changed files (the default).
--commit <sha>Review files changed in a specific commit. Implies diff-only.
--stagedOnly staged changes.
--unstagedOnly unstaged changes.
--analyzer <id,...>Run only these analyzers, comma-separated.
--min-severity / --max-severityBound the findings shown. One of note, improve, must_fix, block.
--show-suppressedInclude suppressed findings in the output.
--format text|jsonOutput format.
--enable-go-testRun the go-test gate (off by default for speed).
--enable-pytestRun the pytest gate (off by default for speed).
--enable-js-testRun the JS test gate, jest or vitest (off by default for speed).
--no-gatesDisable all gates (linters, type checks).

On a very large repository, a --full-scan can exceed the review time budget (10 minutes by default). When it does, the review returns a partial result: the findings produced before the deadline, shown with a “Partial analysis” banner. It still blocks on any must-fix, does not fail with zero findings, and the findings it reports are real. For a faster review on a huge repo, narrow the scope with --diff-only or --analyzer.

Suppressions

Disagree with a finding? Silence one check with a mind:disable comment on the line above the code. It stays recorded and reviewable, never hidden. Every suppression is meant to be temporary.

// mind:disable                 Go, TypeScript, Rust
# mind:disable                  Python
// mind:disable unused-export   silence one analyzer by id
// mind:disable unused-export - reason goes here

Suppress a range with a begin/end pair:

// mind:disable-begin generated block
//   ... lines here are not reviewed ...
// mind:disable-end

A bare mind:disable silences every check on that line; naming an id silences just that one. Use Python's # comment prefix, and // for Go, TypeScript, and Rust.

See suppressed findings with mind review --show-suppressed, and require a reason on every directive with require_reason in mind.yaml.

mind:disable silences check findings in your code. Gate output (linters, type checks, tests) is turned off separately, with disabled_analyzers or --no-gates. See Gates.

Feedback

mind feedback opens an interactive menu to tell us when a finding was right or wrong, and to report bugs or request features. Run it with no arguments from anywhere you are signed in:

mind feedback

Give feedback on findings

Pick one of your recent reviews (run mind review first if you have none yet), drill into a finding, and record your call. Each verdict takes an optional reason and is keyed to the finding's stable fingerprint, so it sticks even after you re-run the review.

Your callMeans
agreeYou agree with the finding.
disagreeYou disagree with the finding.
request-changesYou want changes before this finding is resolved.
manual-fix-appliedYou fixed it by hand rather than as suggested.
skipMove on without recording a verdict.

Report a bug or request a feature

The same menu lets you file a bug report or a feature request: give a one-line summary, then a few lines of detail. Mindrealm tags it with your CLI version and current repository so we have the context to act on it.

Custom rules

MindQL lets you encode your team's standards as rules that run across Go, Python, TypeScript, and Rust: no build, no database, and deterministic findings on every run. Rules live in .mind/rules/*.mql and run in every mind review, right alongside the built-in checks.

One rule, four languages

This rule keeps your API layer from importing a database package directly. The same .mql fires on Go, Python, TypeScript, and Rust, with no per-language rewrite:

rule api_no_db {
  match import i
  where i.file.path ~ "internal/api/" and i.imports_package("db*")
  block "api must not import a db package directly"
}

MindQL reads every language through the same import graph, so one rule covers them all. No model decides what gets flagged; the same code produces the same findings on every run.

What a rule looks like

A rule names what to match, filters it with a condition, then emits a finding at a fixed severity:

PartWhat it does
matchPick what to look at: an import, function, call, type, symbol, file, or the whole review.
whereFilter the match with a condition over import paths, call reachability, structure, and names.
defName a reusable condition once and share it across rules.
actionWhen the match passes the filter, emit a finding at this severity (the verbs are below), followed by the message your team sees.

Severity verbs

A rule emits at one fixed severity, so a finding's weight is part of the rule, not a guess:

VerbAliasesSeverity
blockBlock tier. Stops the change at a gate.
mustfixfixMust be fixed before merge.
suggestimproveImprove tier. Worth addressing.
nitnote, nitpickNote tier. A small remark.

More examples

Flag oversized handlers

Flag an oversized HTTP handler: a function reached from a *Handler whose body runs over 80 lines.

rule long_http_handler {
  match func f
  where f.reachable_from("*Handler") and f.body_lines > 80
  improve "split this handler; it is doing too much"
}

Catch queries in loops

Catch a database query that runs inside a loop, where it should be lifted out.

rule query_in_loop {
  match call c
  where c.name ~ "Query" and c.in_loop
  suggest "move this query out of the loop"
}

Add a rule

Drop a .mql file in .mind/rules/ and run mind review. Rules are checked in with your code, so the whole team gets them:

// .mind/rules/detection_suite_reminder.mql
// A rule we run on our own repo: when we change a check,
// it reminds us to add a test for it in the same change.
rule detection_suite_reminder {
  match review
  where any(diff.files,
      (.path ~ "internal/software_code_" and not .is_test)
      or .path == "internal/analysis/analyzer_ids.go")
    and not any(diff.files, .path ~ "internal/detectionsuite")
  suggest "detection changed; add a detectionsuite regression fixture"
}

Keep .mind/rules/ out of .gitignore so the review can see them. If you ignore .mind/, re-include the rules with .mind/* and !.mind/rules/.

What works today

Available nowComing next
Match imports, functions, calls, types, symbols, and the whole review.Metavariable patterns for matching code shapes.
Filter with conditions over import paths, call reachability, and structure.Autofix that rewrites the flagged code for you.
Reusable conditions, fixed severities, deterministic findings, four languages.Rules that carry their own tests.

Want your team's standards encoded as rules without doing it yourself? I'll build them with you.

Gates

Gates run your own toolchain on the machine doing the review: the linters, type checks, builds, and (optionally) tests you already use. They run alongside the deterministic checks and merge into one report, so a compile error, a lint violation, and a design finding all land together. A failing gate can block the review.

Because they run where your environment lives, gates catch what your machine already knows: real build and test failures, not guesses. The trade-off is speed. Linters and type checks are quick and run by default; the test gates are the slow ones and stay off until you opt in.

Why let Mindrealm run them instead of asking the agent to? Agents are unreliable at running a whole toolchain. Asked to run several linters and the test suite, an agent often runs one, a couple, or none, then reports success anyway. The stop hook runs every gate every time and blocks on any failure, so the checks you depend on actually happen on every change.

GateToolsDefault
Build and type checksgo build, go vet, tsc, cargo checkon
Lintersgolangci-lint, ruff, vulture, eslint, cargo clippyon
Module hygienego mod tidy, go mod verifyon
Test runners (slow)go test, cargo test, pytest, jest/vitestoff

Turn the test gates on per project (or globally) when the extra seconds are worth it:

# .mind/mind.yaml
gates:
  go_test: true
  cargo_test: true
  pytest: true
  js_test: true

The JS test gate auto-detects jest or vitest from your package.json. Or enable a test gate for a single run with --enable-go-test, --enable-pytest, or --enable-js-test. To skip every gate for a faster, checks-only pass, use mind review --no-gates or turn them off in config with disabled_analyzers (see Configuration).

The JS test gate detects jest and vitest today; node:test, mocha, and other runners are not supported yet. If a different test runner, another toolchain gate, or a project-specific custom gate would help your team, tell us what you run.

Hook setup

mind setup wires Mindrealm into your agent so it reviews every change automatically. It detects which agents are present (Claude Code, Codex, and Gemini), asks which to set up, and asks where: globally in ~/.claude / ~/.codex / ~/.gemini (the default), or just the current project with --local (.claude / .codex / .gemini in the working directory). Each agent is covered below.

Why a hook? Getting an agent to reliably review its own work or follow a rule does not work. It forgets, skips, or calls itself done. A stop hook runs every time the agent finishes, no matter what. When Mindrealm flags findings it blocks the stop and feeds them back as the agent's next instruction, so the agent fixes them before the work reaches you. That auto-fix loop works on Claude Code, Codex, and Gemini.

Skip the prompts with flags, for example mind setup --platform claude-code,codex,gemini --global --yes.

Claude Code

mind setup --platform claude-code writes a Stop hook and the Bash(mind:*) permission to ~/.claude/settings.json (or .claude/settings.json with --local), and installs the bundled skills. The hook runs as soon as it is written, with no approval step:

{
  "hooks": {
    "Stop": [
      { "hooks": [{ "type": "command", "command": "mind analyze" }] }
    ]
  },
  "permissions": { "allow": ["Bash(mind:*)"] }
}

Codex

mind setup --platform codex writes a Stop hook to ~/.codex/hooks.json (or .codex/hooks.json with --local):

{
  "hooks": {
    "Stop": [
      { "hooks": [{ "type": "command", "command": "mind analyze" }] }
    ]
  }
}

One extra step: Codex requires you to trust hooks before they run. After setup, start Codex and run /hooks to review and trust the Mindrealm Stop hook. It stays inactive until trusted, and Codex re-prompts whenever the command changes.

Gemini

mind setup --platform gemini writes an AfterAgent hook (it fires when the agent loop ends) to ~/.gemini/settings.json (or .gemini/settings.json with --local):

{
  "hooks": {
    "AfterAgent": [
      { "hooks": [{ "type": "command", "command": "mind analyze", "name": "mindrealm-review" }] }
    ]
  }
}

One extra step: Gemini requires you to approve hooks before they run. After setup, start Gemini and run /hooks enable-all (or /hooks enable mindrealm-review). Project-level hooks stay untrusted until approved, and Gemini re-prompts whenever the command changes; /hooks panel shows their status.

Removing the hook

Run mind setup --uninstall to remove it (add --platform claude-code to target one agent, or --local for the current project only). It removes only what setup added, leaving your other hooks and permissions intact, and is a no-op when nothing is installed. On Codex and Gemini you can instead disable the hook from inside the agent with /hooks, without editing any files.

To wire it by hand, drop the matching block into the file above. Support for more agents is coming. The reviewer itself is agent-agnostic: mind review and the GitHub App review code from any agent or author.

Continuous integration

mind login is interactive, so for CI generate a CI token from your dashboard and give it to the CLI headless. The token is organization-scoped, review-only, and revocable, and it stays valid for long runs, so a --full-scan never expires mid-review.

Provide it as the MIND_CI_TOKEN environment variable:

MIND_CI_TOKEN=mind_ci_xxxxx mind review --full-scan

Or store it once with mind login --token for repeated local headless use:

mind login --token mind_ci_xxxxx
mind review

The repository still needs the Mindrealm GitHub App installed: the token authenticates the caller, the app authorizes the repo.

GitHub Actions

Add the token as a repository secret, then run mind review as a step. fetch-depth: 0 gives mind the history it needs to compute the diff:

- uses: actions/checkout@v4
  with:
    fetch-depth: 0            # so mind can diff against the base commit
- run: curl -fsSL https://mindrealm.ai/install.sh | sh
- run: mind review
  env:
    MIND_CI_TOKEN: ${{ secrets.MIND_CI_TOKEN }}

Exit codes

mind review sets its exit code so a CI step fails the build on a blocking finding:

CodeMeaning
0Review passed.
1A blocking finding. Fails the build.
2Config or credential problem, for example a revoked token.
3Network or service problem.
4Invalid arguments.

Machine-readable output

For machine-readable output use mind review --format json (the default is text); each finding carries severity, file_path, line, description, remediation, and analyzer_id.

If your pipeline already runs its own linters, type checks, and tests, mind review --no-gates skips Mindrealm's gate checks while the rest of the review still runs and still blocks on a must-fix.

Configuration

mind reads YAML config from two locations: a project file at .mind/mind.yaml and a global file at ~/.config/mind/mind.yaml. The project file overrides the global one.

Precedence, highest first: a command-line flag, then environment variables (MIND_*), then .env in the current directory, then the project .mind/mind.yaml, then the global ~/.config/mind/mind.yaml, then built-in defaults.

Top-level keys

KeyDefaultMeaning
timeout60sRequest timeout.
diff_onlytrueReview only changed files (the default).
full_scanfalseReview the whole repository instead (paid plan).
min_severitynoneHide findings below this severity (note, improve, must_fix, block).
max_severitynoneHide findings above this severity.
disabled_analyzersnoneA list of analyzers to turn off, by full ID, short name, or concern.
require_reasonfalseRequire a reason on every mind:disable directive.
show_suppressedfalseInclude suppressed findings in output.
gates.go_testfalseRun the go-test gate.
gates.cargo_testfalseRun the cargo-test gate.
gates.pytestfalseRun the pytest gate.
gates.js_testfalseRun the JS test gate (jest or vitest, auto-detected).
outputnoneOutput template overrides. See Output templates below.
thresholdsnonePer-analyzer thresholds. See Thresholds below.

Linters and type checks for all four languages run automatically. Each language also has an opt-in test gate: go-test, cargo-test, pytest, and a JS test gate that runs jest or vitest. See Gates for the full list.

disabled_analyzers accepts a full analyzer ID, a short name, or a concern that matches a whole group. The gate concern turns off every gate at once:

# .mind/mind.yaml
disabled_analyzers:
  - gate                          # all gates
  - software:code:gate:go-test    # one analyzer by full id
  - golangci-lint                 # short name also matches

Environment variables

These override the matching config keys.

VariableDefaultOverrides
MIND_TIMEOUT60stimeout
MIND_FINDING_TEMPLATEdefaultoutput.finding_template
MIND_HEADER_TEMPLATEdefaultoutput.header_template

Thresholds

Thresholds set when the size, coupling, and duplication checks fire. They all live under thresholds in mind.yaml. A few common ones:

KeyDefaultMeaning
long_function_threshold75Lines before a function is flagged.
large_file_threshold1500Lines before a file is flagged.
interface_size_threshold10Methods before an interface is flagged.
method_count_must_fix20Methods before a type must be split.
type_cohesion_must_fix600Cohesion score before a type is flagged.
duplicate_code_block_min_lcs_similarity75Minimum percent similarity to flag duplicate blocks.

More keys exist under thresholds to adjust coupling, duplication, and complexity limits.

Output templates

Customize what your agent sees in the stop-hook output. finding_template and header_template (under output) each accept default or a path to a Go text/template .tmpl file. analyzer_templates maps an analyzer short name to its own template.

Template keys, per finding: Severity, ShortName, AnalyzerID, FilePath, Line, EndLine, Description, Remediation, Value, Threshold. For the header: TotalCount, BlockCount, MustFixCount, SuggestionCount, NitpickCount, BatchSize, HasMore, Findings.

The default finding template:

[{{.Severity}}] {{.ShortName}} — {{.FilePath}}:{{.Line}}: {{.Description}}{{if .Remediation}}
  fix: {{.Remediation}}{{end}}