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 | shOn Windows, in PowerShell:
iwr -useb https://mindrealm.ai/install.ps1 | iexRe-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 withtar -xzf, make it executable withchmod +x mind, and movemindonto a directory in yourPATH(for example/usr/local/bin). - Windows: download
mind-windows-<arch>.zip, extractmind.exe, and add its folder to yourPATH.
Authenticate
However you installed it, sign in once before reviewing:
mind loginReview
From inside a repository connected to your GitHub App, review your changes (diff-only by default, or --full-scan for the whole repo):
mind reviewCommands
| Command | What it does |
|---|---|
mind login | Authenticate. Opens your browser. |
mind setup | Detect your agent(s) and set up the stop-hook auto-fix loop. |
mind review | Review your changed files. Diff-only by default. |
mind analyze | The hook entry point your agent calls when it stops. You won’t run it by hand. |
mind feedback | Review past runs and record feedback on findings, or report a bug or feature request. |
mind logout | Log out and remove stored credentials. |
mind version | Print the CLI version. |
mind --help | List every command and flag. |
Review categories
Mindrealm reviews Go, Python, TypeScript, and Rust across these categories:
| Category | Looks for |
|---|---|
| Hygiene | Dead code, unused exports, magic values, leftover markers, naming. |
| Reliability | Unhandled errors, swallowed exceptions, resource leaks, missing timeouts. |
| Architecture | Coupling, cohesion, duplication, oversized types and interfaces. |
| Performance | Work inside loops, unbounded growth, repeated expensive calls. |
| Concurrency | Unawaited calls, detached tasks, blocking work in async paths. |
| Security | Hardcoded secrets, SQL/command/code injection, dangerous taint flow. |
| Structure | Long functions, deep nesting, long parameter lists, large files. |
| Testing | Missing or weak assertions, skipped tests, mock abuse, test pollution. |
| Language gates | Your 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.
| Flag | Effect |
|---|---|
--full-scan | Scan the entire repository, not just changed files (paid plan). |
--diff-only | Only report findings in changed files (the default). |
--commit <sha> | Review files changed in a specific commit. Implies diff-only. |
--staged | Only staged changes. |
--unstaged | Only unstaged changes. |
--analyzer <id,...> | Run only these analyzers, comma-separated. |
--min-severity / --max-severity | Bound the findings shown. One of note, improve, must_fix, block. |
--show-suppressed | Include suppressed findings in the output. |
--format text|json | Output format. |
--enable-go-test | Run the go-test gate (off by default for speed). |
--enable-pytest | Run the pytest gate (off by default for speed). |
--enable-js-test | Run the JS test gate, jest or vitest (off by default for speed). |
--no-gates | Disable 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 hereSuppress a range with a begin/end pair:
// mind:disable-begin generated block
// ... lines here are not reviewed ...
// mind:disable-endA 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 feedbackGive 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 call | Means |
|---|---|
agree | You agree with the finding. |
disagree | You disagree with the finding. |
request-changes | You want changes before this finding is resolved. |
manual-fix-applied | You fixed it by hand rather than as suggested. |
skip | Move 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:
| Part | What it does |
|---|---|
match | Pick what to look at: an import, function, call, type, symbol, file, or the whole review. |
where | Filter the match with a condition over import paths, call reachability, structure, and names. |
def | Name a reusable condition once and share it across rules. |
| action | When 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:
| Verb | Aliases | Severity |
|---|---|---|
block | Block tier. Stops the change at a gate. | |
mustfix | fix | Must be fixed before merge. |
suggest | improve | Improve tier. Worth addressing. |
nit | note, nitpick | Note 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 now | Coming 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.
| Gate | Tools | Default |
|---|---|---|
| Build and type checks | go build, go vet, tsc, cargo check | on |
| Linters | golangci-lint, ruff, vulture, eslint, cargo clippy | on |
| Module hygiene | go mod tidy, go mod verify | on |
| Test runners (slow) | go test, cargo test, pytest, jest/vitest | off |
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: trueThe 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-scanOr store it once with mind login --token for repeated local headless use:
mind login --token mind_ci_xxxxx
mind reviewThe 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:
| Code | Meaning |
|---|---|
0 | Review passed. |
1 | A blocking finding. Fails the build. |
2 | Config or credential problem, for example a revoked token. |
3 | Network or service problem. |
4 | Invalid 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
| Key | Default | Meaning |
|---|---|---|
timeout | 60s | Request timeout. |
diff_only | true | Review only changed files (the default). |
full_scan | false | Review the whole repository instead (paid plan). |
min_severity | none | Hide findings below this severity (note, improve, must_fix, block). |
max_severity | none | Hide findings above this severity. |
disabled_analyzers | none | A list of analyzers to turn off, by full ID, short name, or concern. |
require_reason | false | Require a reason on every mind:disable directive. |
show_suppressed | false | Include suppressed findings in output. |
gates.go_test | false | Run the go-test gate. |
gates.cargo_test | false | Run the cargo-test gate. |
gates.pytest | false | Run the pytest gate. |
gates.js_test | false | Run the JS test gate (jest or vitest, auto-detected). |
output | none | Output template overrides. See Output templates below. |
thresholds | none | Per-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 matchesEnvironment variables
These override the matching config keys.
| Variable | Default | Overrides |
|---|---|---|
MIND_TIMEOUT | 60s | timeout |
MIND_FINDING_TEMPLATE | default | output.finding_template |
MIND_HEADER_TEMPLATE | default | output.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:
| Key | Default | Meaning |
|---|---|---|
long_function_threshold | 75 | Lines before a function is flagged. |
large_file_threshold | 1500 | Lines before a file is flagged. |
interface_size_threshold | 10 | Methods before an interface is flagged. |
method_count_must_fix | 20 | Methods before a type must be split. |
type_cohesion_must_fix | 600 | Cohesion score before a type is flagged. |
duplicate_code_block_min_lcs_similarity | 75 | Minimum 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}}