CLI reference

August 4, 2026 · View on GitHub

Install details, editor setup, and the full command table.

← Back to README

Install and setup

pnpm docker:up brings up Postgres + Perception in the background; the user-facing surfaces are Sensing and the robrain CLI. npx robrain init-project writes the project instructions that tell each editor's agent to call the Sensing tools at session start and end (CLAUDE.md, AGENTS.md for Codex, and .cursor/rules/robrain.mdc when Cursor is installed).

Self-hosted setup usually needs two keys: ANTHROPIC_API_KEY for extraction and one embedding-provider key for semantic retrieval. If that surprises you, see Why are there two API keys in self-hosted mode?. For a setup with no cloud API keys (Ollama / LM Studio / vLLM), see Fully-local LLM.

No clone needed (robrain up)

The fastest path — no git clone, no pnpm build:

export ANTHROPIC_API_KEY=... OPENAI_API_KEY=...   # or add them to ~/.robrain/stack/.env after the first run
npx robrain@latest up                             # Postgres + Perception from ghcr.io
npx robrain install --self-hosted                 # wire Sensing MCP into your editors
cd /path/to/your/project && npx robrain init-project

robrain up writes a managed stack under ~/.robrain/stack/:

FileRole
docker-compose.ymlRegenerated every run — do not edit
schema.sqlExtracted from the Perception image (version-matched)
.envYour secrets — auto-generated once, never overwritten

Default image: ghcr.io/adelinamart/robrain-perception:<cli-version>. Override with --tag or --image:

npx robrain up --tag latest
npx robrain up --image ghcr.io/adelinamart/robrain-perception:2.3.0

Stop the stack (data volume preserved):

npx robrain down

robrain up and the repo-clone flow (pnpm docker:up) are the same compose project (robrain) with the same container names and Postgres volume (robrain_postgres_data), so you can switch paths without losing data — copy POSTGRES_PASSWORD and PERCEPTION_API_KEY from your existing .env into ~/.robrain/stack/.env if you migrate. Stacks started before v2.3.9 belong to a different compose project; robrain up detects their containers and prints the one-time removal command (the data volume is preserved).

robrain install --self-hosted copies the bundled @robrain/sensing-mcp package into ~/.robrain/mcp/sensing — no clone required. robrain install --hermes materializes the bundled Hermes memory-provider plugin into $HERMES_HOME/plugins/robrain (default ~/.hermes) the same way — see integrations/hermes; combine with --self-hosted to do both in one run. Pass --repo-root (or set ROBRAIN_REPO) when developing in the monorepo; that replaces any package-copied bundle with a symlink into your clone (macOS/Linux) or a fresh copy (Windows).

Portable MCP config (robrain mcp)

For MCP directory listings or a hand-written mcp.json, launch Sensing without running install:

{ "mcpServers": { "robrain-sensing": {
    "command": "npx", "args": ["-y", "robrain", "mcp"]
} } }

After npx robrain up, robrain mcp reads Perception URL and API key from ~/.robrain/config.json. Add an env block with PERCEPTION_API_URL / PERCEPTION_API_KEY to override. For full editor wiring (LLM + embedding keys in the MCP env block), use npx robrain install instead — it writes editor-specific configs under ~/.cursor/mcp.json, ~/.claude.json, etc.

From a clone instead (development)

  • Docker + Docker Compose
  • Node.js 18.18+ (older 18.x + npm 9.6 can break npx bin permissions; upgrade Node or use pnpm dlx robrain), pnpm
  • Anthropic API key (for Haiku extraction)
  • OpenAI, Voyage, or Cohere API key (for embeddings)

From the repository root:

git clone https://github.com/adelinamart/robrain
cd robrain
cp .env.example .env

Edit .env at the repo root (the same keys power Perception in Docker and the CLI install prompts). Paste real keys from Anthropic and your embedding provider — do not commit that file.

ANTHROPIC_API_KEY=
EMBEDDING_PROVIDER=openai
OPENAI_API_KEY=

Keep EMBEDDING_PROVIDER identical between this file and what you select when running install (or set EMBEDDING_PROVIDER in .env and install will pick it up without prompting).

Fully-local LLM (Ollama / LM Studio / vLLM)

Run extraction, chat, and embeddings against a local OpenAI-compatible server — no Anthropic or OpenAI cloud keys required.

Why two base URLs? Perception runs in Docker; Sensing MCP and Synthesis run on the host. One shared .env cannot use a single localhost URL for both:

ProcessNeeds
Perception (Docker)host.docker.internal to reach the LLM server on your machine
Sensing / Synthesis / robrain doctor (host)127.0.0.1 — Node fetch often fails on host.docker.internal

Use your server’s host port and whatever models it serves. The placeholders below are required in shape only — replace <port>, <chat-model>, and <embedding-model>. Keep the /v1 suffix. Common defaults: Ollama 11434, LM Studio 1234, vLLM 8000.

LLM_PROVIDER=openai
EMBEDDING_PROVIDER=openai
# OPENAI_API_KEY=          # optional — local servers usually ignore auth

# Perception in Docker → host machine
OPENAI_BASE_URL=http://host.docker.internal:<port>/v1
# Sensing / Synthesis / doctor on the host
OPENAI_HOST_BASE_URL=http://127.0.0.1:<port>/v1

# Models your local server actually exposes (names from `ollama list`, LM Studio, etc.)
OPENAI_LLM_MODEL=<chat-model>
OPENAI_EMBEDDING_MODEL=<embedding-model>

Ollama-shaped example (not required — swap port/models for yours):

OPENAI_BASE_URL=http://host.docker.internal:11434/v1
OPENAI_HOST_BASE_URL=http://127.0.0.1:11434/v1
OPENAI_LLM_MODEL=llama3.2:3b
OPENAI_EMBEDDING_MODEL=nomic-embed-text

Host-only (no Docker Perception) can set a single OPENAI_BASE_URL=http://127.0.0.1:<port>/v1 and leave OPENAI_HOST_BASE_URL unset.

Clone path

# 1. Start your local server and pull/load the chat + embedding models you chose
#    e.g. ollama pull <chat-model> && ollama pull <embedding-model>

# 2. Put the variables above in repo-root .env (see .env.example)
pnpm docker:up:build          # rebuild Perception so it picks up the env
pnpm install:self-hosted      # writes BOTH URLs into editor MCP env
npx robrain init-project

# 3. Fully quit and reopen the editor (Cmd-Q) so MCP reloads env

No-clone path (robrain up)

Put the same variables in ~/.robrain/stack/.env (created on first robrain up), then:

npx robrain@latest up
npx robrain install --self-hosted
cd /path/to/your/project && npx robrain init-project

install copies OPENAI_BASE_URL and OPENAI_HOST_BASE_URL into ~/.cursor/mcp.json, ~/.claude.json, and ~/.codex/config.toml so Sensing outside the clone does not rely on the repo .env.

Verify

# Perception should show your Docker-side URL
docker exec robrain-perception printenv OPENAI_BASE_URL
curl -sf http://127.0.0.1:3001/health

# Doctor (from the clone / stack .env) should treat the local server as keyless
npx robrain doctor

# Host-side LLM path
pnpm synthesis:dry-run    # clone path

Editor MCP env should contain both URLs:

python3 -c "import json; print(json.load(open('$HOME/.cursor/mcp.json'))['mcpServers']['robrain-sensing']['env'])"

Embedding dimensions: the pgvector column is fixed at 1536. Shorter vectors are zero-padded; longer ones are truncated. Prefer a model that emits 1536 dims, or a matryoshka-capable model with OPENAI_EMBEDDING_DIMENSIONS=1536. Changing the embedding model after decisions exist requires re-embedding — see .env.example.

What init-project writes

robrain init-project writes mode-aware instructions:

  • Free / self-hosted (robrain install --self-hosted): generated CLAUDE.md / Cursor rule / AGENTS.md (Codex) uses only sensing_* tools.
  • Cloud / Control-enabled: generated instructions include both sensing_* and control_* calls.

init-project always writes the same managed RoBrain block into AGENTS.md at the project root (for Codex CLI and any tool that reads AGENTS.md). If Codex CLI is installed (~/.codex/), robrain install also registers robrain-sensing in ~/.codex/config.toml (use --editor codex to configure Codex only).

For Claude Code, init-project also merges a plugin recommendation into .claude/settings.json so teammates who trust the repo get an install prompt from Claude Code itself. Skip with --skip-claude-plugin. Details: plugins/claude-code/README.md.

Where the project id comes from

The id is, in order: --project-id if you pass it → an id pinned in this repo's editor files (CLAUDE.md / AGENTS.md / .cursor/rules/robrain.mdc, including at the repo root when you run from a monorepo subdirectory) → a deterministic hash of the directory path. Adoption stops at the git repo boundary: an id found above your repo (say a stray ~/AGENTS.md) is reported as a hint, never silently joined — pass --project-id <id> to join it deliberately. init-project also refuses to initialize your home directory or a directory with no project markers (.git, package.json, …) unless you pass --force — this keeps robrain install run from the wrong directory from minting a junk project.

Cloud installs configure Sensing in thin mode (ROBRAIN_MODE=cloud): turns ship raw to the managed API, which runs the calibrated extractor server-side. robrain doctor and robrain status understand this mode — a missing local key is not an error in cloud mode.

CLI on your PATH (optional)

If you prefer not to use npx every time, install the package globally, then use the robrain command directly:

npm install -g robrain

Open a new terminal, or in zsh run rehash so your shell picks up the new binary. Then:

robrain install --self-hosted
# …and the same for other commands: robrain init-project, robrain review, etc.

If you get command not found: robrain, either use npx robrain … or ensure your global npm bin directory is on your PATH (see npm prefix -g).

Cursor-specific setup (most reliable path)

robrain init-project automatically writes .cursor/rules/robrain.mdc with alwaysApply: true, so Cursor loads the RoBrain session-lifecycle instructions every session. No copy-paste step is required.

To verify:

cat .cursor/rules/robrain.mdc

If decisions stop landing: the rule file is present, but Cursor's agent sometimes ignores rule content turn-to-turn. Check the Cursor MCP panel for the robrain-sensing server status, then see Decisions captured in the editor but robrain review shows nothing.

Adding more rules will not fix a compliance gap. That is a Cursor-side behavior that Rory Plans cloud layers additional safeguards against (see Free / self-hosted vs Rory Plans cloud).

Codex CLI setup

robrain install (or robrain install --editor codex) writes a marker-bounded robrain-sensing block into ~/.codex/config.toml, including a [hooks] section that points at scripts under ~/.robrain/hooks/codex/ (SessionStart, UserPromptSubmit, Stop — same lifecycle as the Claude Code plugin). Codex asks you to trust the hooks on first run. init-project always updates AGENTS.md at the project root with the same session-lifecycle instructions as CLAUDE.md.

To verify:

grep -A2 'robrain-sensing' ~/.codex/config.toml
grep -A6 '\[hooks\]' ~/.codex/config.toml    # SessionStart / UserPromptSubmit / Stop paths
grep 'project_id=' AGENTS.md
codex mcp list   # optional — confirm robrain-sensing is enabled

Restart the Codex CLI session after install so it reloads MCP config and hooks. If captures stop landing, check PERCEPTION_API_KEY in the managed block (see troubleshooting) and confirm the agent is following the RoBrain section in AGENTS.md.

Upgrading

When a new RoBrain release is out, update every layer you installed: the CLI (npx or global), the Perception Docker image, and editor MCP configs. Postgres data and your .env secrets stay in place — you are not reinstalling from scratch.

Maintainers: see docs/release.md for the full tag → GHCR → npm → MCP registry checklist (including the release guard).

Check what you are running: npx robrain --version. Compare with GitHub — Releases or the latest main branch.

No-clone stack (robrain up)

npx robrain@latest up --tag <version>    # pull new Perception image; same ~/.robrain/stack/.env
npx robrain@latest install --self-hosted   # refresh editor MCP configs + sensing bundle

robrain up recreates the Perception container from the new GHCR image — that is what applies startup DB migrations (a docker pull alone leaves the old process running). Fully quit and reopen editors after install (Cmd-Q on macOS, then reopen).

Self-hosted from a clone (typical)

From the robrain repo root (same directory as docker/ and .env):

git pull
pnpm install && pnpm build
pnpm docker:up:build
pnpm robrain install --self-hosted --repo-root "$(pwd)"
StepWhy it matters
git pull + pnpm buildPicks up CLI, Sensing MCP, and shared package changes
pnpm docker:up:buildRebuilds Perception and applies startup DB migrations — pulling code alone leaves the old container running
robrain install --self-hostedRefreshes MCP server paths and env in Cursor, Claude Code, Codex, and Copilot
Fully quit and reopen editorsClosing a chat does not reload the MCP child process or its environment (Cmd-Q on macOS, then reopen)

Application repos usually do not need init-project again. Re-run it only if release notes call out changes to CLAUDE.md, AGENTS.md, or .cursor/rules/robrain.mdc.

More detail on stale containers and schema drift: Troubleshooting — Stale Perception Docker image.

Global CLI (npm install -g robrain)

npm install -g robrain@latest
npx robrain up --tag latest          # if you use the no-clone stack
npx robrain install --self-hosted    # refresh editor configs + sensing bundle

For the clone path, a global CLI update alone is not enough — Perception still requires pnpm docker:up:build from the repo:

cd /path/to/robrain
git pull && pnpm install && pnpm build
pnpm docker:up:build
pnpm robrain install --self-hosted --repo-root "$(pwd)"

Verify after upgrading

curl -sf "http://localhost:${PERCEPTION_PORT:-3001}/health"
npx robrain status

If captures or review behave oddly after an upgrade, see Troubleshooting.

Why does this code exist?

The judgment layer pays off when you need file-scoped history — decisions plus vetoes, not just “we use Zustand”:

$ npx robrain explain src/store/cart.ts

  src/store/cart.ts 3 decisions

 Chose Zustand over Redux (re-render performance issues in cart) — Mar 15 2024
 Chose optimistic updates over server-confirmed writes (felt slow to users) — Apr 2 2024
 Chose normalised shape over nested objects Apr 18 2024

  Tip: add --why for full rationale and rejected alternatives

With --why for the full picture:

$ npx robrain explain src/store/cart.ts --why

  src/store/cart.ts 3 decisions

  Mar 15 2024  Use Zustand for state management
               because: Redux caused re-render performance issues in cart
               rejected: Redux (re-render perf), MobX (team unfamiliar)

  Apr 2 2024   Chose optimistic updates
               because: server-confirmed felt slow to users
               rejected: pessimistic updates (bad UX on slow connections)

  Apr 18 2024  Chose normalised shape over nested objects
               because: query performance at scale

Works on files, directories, or any path RoBrain has seen in a session. With Synthesis-fed planning_blocks, the same command can surface topic-level truth and cross-corpus conflicts the reactive path never linked.


CLI commands

All commands accept --help for full flag details. Repo-level pnpm scripts live in package.json; CLI commands live in packages/cli.

CommandWhat it does
npx robrain upStart Postgres + Perception from the published GHCR image (no clone); writes ~/.robrain/stack/
npx robrain up --tag <tag>Perception image tag (default: CLI version)
npx robrain up --image <image>Full image override (wins over --tag)
npx robrain downStop the robrain up stack; data volume robrain_postgres_data is preserved
npx robrain mcpRun the bundled Sensing MCP server over stdio (portable mcp.json / MCP directory configs; reads Perception from ~/.robrain/config.json)
pnpm install:self-hostedBuild everything + run robrain install --self-hosted --repo-root . in one shot
pnpm buildCompile all workspace packages (pnpm -r build) — run after pnpm install in the robrain clone
pnpm docker:upStart Postgres + Perception (uses .env)
pnpm docker:up:buildSame, but force a rebuild of Perception
pnpm docker:buildRebuild Perception image without starting
pnpm docker:downStop the stack
pnpm synthesis:buildCompile @robrain/synthesis before running it
pnpm synthesis:dry-runRun Synthesis with SYNTHESIS_DRY_RUN=true (no DB writes)
npx robrain install --self-hostedWire Sensing MCP into detected editors (Claude Code, Cursor, Codex, Copilot); then runs init-project in the current directory by default
npx robrain install --hermesInstall the bundled Hermes memory-provider plugin into $HERMES_HOME/plugins/robrain (combine with --self-hosted)
npx robrain install [--token <token>]Cloud mode (default when --self-hosted is absent): authenticates against Rory Plans, provisions the managed API, wires editors as thin clients — no local LLM/embedding keys needed. Token from roryplans.ai → profile → API tokens (or set RORY_TOKEN)
npx robrain install --editor <claude-code|cursor|copilot|codex>Target a specific editor instead of all detected
npx robrain install --perception-url <url>Override Perception URL for self-hosted (default http://localhost:3001)
npx robrain install --repo-root <path>Dev override: symlink/copy sensing-mcp from the clone (replaces any package-copied bundle; or set ROBRAIN_REPO)
npx robrain install --skip-init-projectWire editors only — do not run init-project in the current directory after install
npx robrain init-projectWarm-start memory from package.json, README, git log; recommends the Claude Code plugin in .claude/settings.json
npx robrain init-project --project-id <id>Override the auto-derived project ID (useful after projects merge)
npx robrain init-project --skip-claude-pluginDo not write the RoBrain plugin recommendation to .claude/settings.json
npx robrain initAlias for init-project
npx robrain projects listList Perception projects with session/decision counts (recover phantom ids)
npx robrain projects merge <from-id> <to-id>Merge one project id into another in the database
npx robrain reviewInspect, edit, or delete captured decisions; conflict “keep” can persist a related_to edge when Perception returns a counterpart id so Synthesis stops re-flagging the pair
npx robrain review --session <id>Review a specific session (default: last session)
npx robrain review --allShow all active decisions, not only the last session
npx robrain review --limit <n>Max decisions to fetch (default: 20)
npx robrain review --historyShow full decision lifecycle including superseded decisions
npx robrain review --approve-allBulk-approve every reviewable decision in the current fetch (no prompts per row)
npx robrain export-memoryExport approved decisions into Claude Code auto-memory files; optional --cwd / --project-id for non-interactive paths (Synthesis F2)
npx robrain export-memory --dry-runPreview the file plan without touching disk
npx robrain export-memory --include-unreviewedAlso export decisions not yet approved (not recommended)
npx robrain export-memory --to <dir>Write to a custom memory dir instead of ~/.claude/projects/<slug>/memory
npx robrain export-memory --ledgerAlso write a single git-committed decisions ledger (default: <project>/decisions.md); DB is source of truth — file is regenerated each run
npx robrain export-memory --ledger <path>Same as --ledger, but write to a custom path under the project root (e.g. docs/decisions.md)
npx robrain export --format interchangeDump the full decision corpus (lifecycle included) as JSONL, one memory per line, format robrain-memory/v1 — spec in docs/memory-interchange.md. JSONL goes to stdout (pipe-friendly); status to stderr
npx robrain export --format interchange --out <file>Same, written to a file instead of stdout; optional --cwd / --project-id
npx robrain outcomesScan git history for revert commits (subject starts with Revert), match them to stored decisions by file overlap + 90-day window, and record revert outcomes (lowers historical_relevance, flags the decision for review)
npx robrain outcomes --since <ref|date>Scan window: a git ref (<ref>..HEAD) or a date git understands (default: "30 days ago")
npx robrain outcomes --dry-runShow matched decisions without recording anything
npx robrain outcomes record <decision-id> --outcome <revert|incident|confirmed>Manually record an outcome; optional --evidence "<text>" (commit hash, incident link)
npx robrain injectGet formatted context to paste into Claude Code
npx robrain inject --query "..."Semantic search for relevant decisions
npx robrain inject --files "..."Get decisions about specific files
npx robrain inject --copyCopy output directly to clipboard
npx robrain inject --allRequest up to 100 decisions (server cap): all unreviewed without --query, or a wider semantic pool with --query
npx robrain inject --limit <n>Cap how many decisions are returned (default: 5)
npx robrain check "<proposal>"Pre-commit veto scan: does the proposal mention a previously rejected option? Deterministic word-boundary match against rejected[] (same scan the editor hooks run pre-task) — no LLM, sub-second. Exit 0 clean, 1 on match (scriptable: robrain check "..." && apply), 2 if Perception unreachable
npx robrain doctorRun install diagnostics for editors, MCP wiring, and Perception connectivity
npx robrain explain <file>Answer "why does this code exist?" for any file
npx robrain explain <file> --whyFull rationale + rejected alternatives per decision
npx robrain explain <file> --copyCopy explain output to the clipboard
npx robrain rule --add "..."Add a Planning rule (Rory Plans cloud — requires planningUrl in config)
npx robrain rule --listList rules from Planning GET /facts when cloud is configured; OSS-only prints guidance
npx robrain rule --type <type>When using --add, set rule type: always_include, always_exclude, or preference (default: preference)
npx robrain statusAuth + Perception/Planning health + active decision count for the current project
npx robrain logoutClear locally stored credentials (Rory Plans token / install state)
pnpm synthesis:runSynthesis — batch job from robrain repo root (pnpm must resolve @robrain/synthesis)
npx robrain synthSelf-hosted only — on Rory Plans cloud, judgment runs server-side and the command says so instead of running. Optional --dry-run, --full, --lookback <n>, --project <id>. No clone needed — runs the Synthesis bundle shipped with the CLI and falls back to ~/.robrain/stack/.env for DATABASE_URL + keys after robrain up. A robrain checkout (ROBRAIN_REPO, or cwd) takes precedence when present.