@kinqs/brainrouter-cli 0.3.4 → 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/.env.example +55 -48
  2. package/README.md +102 -142
  3. package/bin/cli.cjs +71 -0
  4. package/dist/agent/agent.d.ts +212 -2
  5. package/dist/agent/agent.js +430 -40
  6. package/dist/cli/banner.d.ts +60 -0
  7. package/dist/cli/banner.js +199 -0
  8. package/dist/cli/cliPrompt.d.ts +69 -0
  9. package/dist/cli/cliPrompt.js +287 -0
  10. package/dist/cli/commands/_helpers.js +6 -6
  11. package/dist/cli/commands/guard.js +75 -10
  12. package/dist/cli/commands/mcp.d.ts +17 -0
  13. package/dist/cli/commands/mcp.js +121 -0
  14. package/dist/cli/commands/memory.js +2 -2
  15. package/dist/cli/commands/obs.js +22 -22
  16. package/dist/cli/commands/session.js +13 -5
  17. package/dist/cli/commands/ui.js +97 -45
  18. package/dist/cli/commands/workflow.d.ts +18 -0
  19. package/dist/cli/commands/workflow.js +314 -43
  20. package/dist/cli/repl.js +219 -132
  21. package/dist/cli/spinner.d.ts +34 -0
  22. package/dist/cli/spinner.js +36 -0
  23. package/dist/cli/statusline.d.ts +67 -0
  24. package/dist/cli/statusline.js +204 -0
  25. package/dist/cli/theme.d.ts +79 -0
  26. package/dist/cli/theme.js +106 -0
  27. package/dist/cli/whereView.d.ts +81 -0
  28. package/dist/cli/whereView.js +245 -0
  29. package/dist/config/config.d.ts +40 -0
  30. package/dist/config/config.js +45 -73
  31. package/dist/index.js +81 -14
  32. package/dist/memory/briefing.d.ts +10 -0
  33. package/dist/memory/briefing.js +69 -1
  34. package/dist/prompt/breadthHint.d.ts +5 -0
  35. package/dist/prompt/breadthHint.js +44 -0
  36. package/dist/prompt/systemPrompt.d.ts +34 -0
  37. package/dist/prompt/systemPrompt.js +124 -108
  38. package/dist/runtime/dangerousCommand.d.ts +53 -0
  39. package/dist/runtime/dangerousCommand.js +105 -0
  40. package/dist/runtime/mcpClient.d.ts +38 -1
  41. package/dist/runtime/mcpClient.js +91 -3
  42. package/dist/state/goalStore.d.ts +98 -17
  43. package/dist/state/goalStore.js +132 -42
  44. package/dist/state/preferencesStore.d.ts +67 -3
  45. package/dist/state/preferencesStore.js +84 -1
  46. package/dist/state/workflowArtifacts.d.ts +63 -2
  47. package/dist/state/workflowArtifacts.js +120 -8
  48. package/dist/tests/_helpers.d.ts +31 -0
  49. package/dist/tests/_helpers.js +91 -0
  50. package/package.json +5 -4
package/.env.example CHANGED
@@ -1,77 +1,81 @@
1
- # BrainRouter CLI agent — environment
1
+ # BrainRouter CLI agent — environment template
2
2
  #
3
- # Copy to brainrouter-cli/.env. Loaded by the CLI at startup.
3
+ # Copy to `brainrouter-cli/.env`. Loaded by the CLI at startup.
4
4
  #
5
5
  # This file is for CLI-AGENT concerns only:
6
- # - chat LLM the terminal agent talks to
7
- # - tool runtime knobs (loop limit, result clamp, MCP timeout)
8
- # - auto-compaction trigger
9
- # - sandbox configuration for run_command
10
- # - web search backend
11
- # - trace logging
12
- # - workspace override
6
+ # 1. Chat LLM (the model the terminal agent talks to)
7
+ # 2. Tool runtime (loop limit, result clamp, MCP timeout, auto-compact)
8
+ # 3. Sandbox (run_command wrapping)
9
+ # 4. Workspace (root override + shared state root)
10
+ # 5. Web search (custom backend for the web_search tool)
11
+ # 6. Observability (trace log path)
13
12
  #
14
- # MCP-server concerns (cognitive extraction, embeddings, reranker, memory
15
- # engine knobs, server auth) live in brainrouter/.env.example.
13
+ # MCP-server concerns (cognitive extraction, embeddings, reranker, judge,
14
+ # memory engine knobs, server auth) live in `brainrouter/.env.example`.
16
15
  #
17
16
  # Why split: the MCP and the CLI are separate processes with different
18
17
  # concerns. The CLI's chat LLM can be a smart cloud model while the MCP's
19
18
  # cognitive extractor is a cheap local one. Their concurrency caps differ
20
19
  # too (CLI default 4, MCP default 2). Keep them independent.
20
+ #
21
+ # All values in this template are blank placeholders. Fill in only what
22
+ # you actually need — most settings have sensible defaults.
23
+
21
24
 
22
- # ==========================================
23
- # Chat LLM (for the agent's own conversation)
24
- # ==========================================
25
+ # =============================================================================
26
+ # 1. Chat LLM (for the agent's own conversation)
27
+ # =============================================================================
25
28
  # Same var names as the MCP, but a separate process — set them here for the
26
29
  # CLI's chat model. Falls back to OPENAI_API_KEY.
27
30
  #
28
31
  # If you don't set BRAINROUTER_LLM_API_KEY here, the CLI also reads it from
29
- # brainrouter/.env as a transitional fallback. Setting it here makes the
32
+ # `brainrouter/.env` as a transitional fallback. Setting it here makes the
30
33
  # CLI's choice explicit and lets you use a different chat model than the
31
34
  # MCP's extractor (e.g. gpt-4o for chat, gpt-4o-mini for extraction).
32
- BRAINROUTER_LLM_API_KEY=your_api_key_here
35
+ BRAINROUTER_LLM_API_KEY=
33
36
 
34
37
  # OpenAI-compatible chat-completions endpoint.
35
38
  # Examples:
36
- # OpenAI: https://api.openai.com/v1/chat/completions
37
- # OpenRouter: https://openrouter.ai/api/v1/chat/completions
38
- # Anthropic via OpenRouter: anthropic/claude-sonnet-4
39
- # LM Studio: http://localhost:1234/v1/chat/completions
39
+ # OpenAI: https://api.openai.com/v1/chat/completions
40
+ # OpenRouter: https://openrouter.ai/api/v1/chat/completions
41
+ # Anthropic via OpenRouter: model id "anthropic/claude-sonnet-4"
42
+ # LM Studio: http://localhost:1234/v1/chat/completions
40
43
  BRAINROUTER_LLM_ENDPOINT=https://api.openai.com/v1/chat/completions
41
-
42
44
  BRAINROUTER_LLM_MODEL=gpt-4o-mini
43
45
 
44
- # Per-call timeout for the CLI's chat LLM. Default: 120000.
46
+ # Per-call timeout for the CLI's chat LLM. Default 120000 (2 min).
45
47
  # BRAINROUTER_LLM_TIMEOUT_MS=120000
46
48
 
47
49
  # Cap on concurrent in-flight chat LLM calls FROM THE CLI PROCESS.
48
- # Default: 4 (separate from the MCP's own cap). Set to 1 for consumer-grade
49
- # local backends; crank to 16+ for cloud APIs.
50
+ # Default 4 (separate from the MCP's own cap). Set to 1 for consumer-grade
51
+ # local backends; raise to 16+ for cloud APIs.
50
52
  # BRAINROUTER_LLM_MAX_CONCURRENT=4
51
53
 
52
- # ==========================================
53
- # Tool runtime
54
- # ==========================================
55
- # Per-tool timeout for CLI → MCP requests. Default: 60000.
54
+
55
+ # =============================================================================
56
+ # 2. Tool runtime
57
+ # =============================================================================
58
+ # Per-tool timeout for CLI → MCP requests. Default 60000.
56
59
  # BRAINROUTER_MCP_TIMEOUT_MS=60000
57
60
 
58
61
  # LLM-visible clamp on a single tool-result body (full text still recorded
59
- # in the transcript on disk). Default: 8000.
62
+ # in the transcript on disk). Default 8000.
60
63
  # BRAINROUTER_MAX_TOOL_RESULT_CHARS=8000
61
64
 
62
- # Hard ceiling on tool-call iterations per turn. Default: 60.
65
+ # Hard ceiling on tool-call iterations per turn. Default 60.
63
66
  # BRAINROUTER_MAX_TOOL_LOOPS=60
64
67
 
65
- # Estimated history-size trigger for auto-`/compact`. Default: 80000 tokens.
68
+ # Estimated history-size trigger for auto-`/compact`. Default 80000 tokens.
66
69
  # BRAINROUTER_AUTO_COMPACT_TOKENS=80000
67
70
 
68
- # ==========================================
69
- # Sandbox (run_command)
70
- # ==========================================
71
+
72
+ # =============================================================================
73
+ # 3. Sandbox (run_command)
74
+ # =============================================================================
71
75
  # Wrap shell commands in the platform sandbox:
72
76
  # macOS: sandbox-exec
73
77
  # Linux: bwrap (preferred) or firejail
74
- # Set 'on' to enable. Off by default.
78
+ # Set `on` to enable. Off by default.
75
79
  # BRAINROUTER_SANDBOX=on
76
80
 
77
81
  # Allow outbound network from sandboxed commands. Off by default.
@@ -81,29 +85,32 @@ BRAINROUTER_LLM_MODEL=gpt-4o-mini
81
85
  # BRAINROUTER_SANDBOX_READ_PATHS=/usr/local:/opt
82
86
  # BRAINROUTER_SANDBOX_WRITE_PATHS=/tmp
83
87
 
84
- # ==========================================
85
- # Workspace
86
- # ==========================================
87
- # Override workspace root the CLI uses for file tools + session key.
88
- # Most users let the CLI auto-detect via git/closest package.json.
88
+
89
+ # =============================================================================
90
+ # 4. Workspace
91
+ # =============================================================================
92
+ # Override the workspace root the CLI uses for file tools + session key.
93
+ # Most users let the CLI auto-detect via git / closest package.json.
89
94
  # BRAINROUTER_WORKSPACE=/path/to/project
90
95
 
91
96
  # Override per-user state root. Default: ~/.brainrouter.
92
97
  # Both the CLI and MCP honor this — set it once and both processes use it.
93
98
  # BRAINROUTER_HOME=/path/to/state
94
99
 
95
- # ==========================================
96
- # Web search
97
- # ==========================================
100
+
101
+ # =============================================================================
102
+ # 5. Web search
103
+ # =============================================================================
98
104
  # Custom search backend for the web_search tool. Must accept
99
- # POST { query, maxResults } → { results: [{ title, url, snippet }] }.
105
+ # POST { query, maxResults } → { results: [{ title, url, snippet }] }
100
106
  # Falls back to DuckDuckGo's Instant Answer API when unset.
101
- # Compatible with Brave Search API wrappers, Tavily, SerpAPI proxies.
107
+ # Compatible with Brave Search API wrappers, Tavily, SerpAPI proxies, etc.
102
108
  # BRAINROUTER_WEB_SEARCH_ENDPOINT=https://your-search-proxy.example.com/search
103
109
 
104
- # ==========================================
105
- # Observability
106
- # ==========================================
110
+
111
+ # =============================================================================
112
+ # 6. Observability
113
+ # =============================================================================
107
114
  # Path for OTEL-style JSONL turn traces. One line per turn/tool span.
108
115
  # Toggle at runtime with /trace on|off.
109
116
  # BRAINROUTER_TRACE_LOG=/path/to/trace.jsonl
package/README.md CHANGED
@@ -1,185 +1,145 @@
1
- # 🧠 BrainRouter Terminal Agent CLI
1
+ # `@kinqs/brainrouter-cli`
2
2
 
3
- A premium, autonomous terminal-based AI coding assistant and REPL that acts as your local agent. It leverages **BrainRouter's memory engine** for cognitive persistence (System 1/2 loops) and provides standard filesystem/terminal tools to solve complex coding tasks autonomously.
3
+ A memory-native terminal agent. Edits files, runs shell commands,
4
+ spawns child agents, and talks to a BrainRouter MCP server for long-term
5
+ recall, skills, and capture.
6
+
7
+ Ships the `brainrouter` binary.
4
8
 
5
9
  ---
6
10
 
7
- ## Features
8
- - **Dual-Tier Connection**: Connects to local MCP servers via standard I/O (stdio) or hosted multi-tenant servers over Streamable HTTP/SSE.
9
- - **Double-Tier Memory Architecture**:
10
- - **System 1 (Heuristic Recall)**: Automatically retrieves active focus scenes, codebase facts, and skills *before* each LLM reasoning cycle.
11
- - **System 2 (Memory Consolidation)**: Autonomously extracts learning points, updates facts, and saves evidence via turn-by-turn memory capture.
12
- - **Local Execution Harness**: Autonomous execution of files editing, directory listing, regex/string grep, and terminal command invocation (safely prompted for user verification).
13
- - **Obsidian Dark / Midnight Ledger Aesthetics**: High-end command line styling, loader animations, and formatted terminal markdown output.
11
+ ## Install
14
12
 
15
- ---
13
+ ```bash
14
+ npm install -g @kinqs/brainrouter-cli
15
+ ```
16
16
 
17
- ## Installation & Setup
18
-
19
- 1. **Build the Monorepo**:
20
- From the repository root:
21
- ```bash
22
- npm install
23
- npm run build
24
- ```
25
-
26
- 2. **Configure Provider and Server Profiles**:
27
- Run the interactive configurator to set up your LLM settings (OpenAI, local endpoints like Ollama/LM Studio) and active server profile.
28
- From the repository root:
29
- ```bash
30
- npm run cli config
31
- ```
32
- Or from the `brainrouter` package subdirectory:
33
- ```bash
34
- node dist/index.js config
35
- ```
36
- This generates and modifies settings stored in `~/.config/brainrouter/config.json`.
17
+ **The `-g` flag is critical.** Without it, npm installs into the current
18
+ directory's `node_modules/` and the `brainrouter` binary ends up at
19
+ `./node_modules/.bin/brainrouter` not on `$PATH`. Symptom: `brainrouter:
20
+ command not found`.
37
21
 
38
- ---
22
+ **Sudo caveat.** Whether you need `sudo` depends on your Node install:
23
+
24
+ | How Node is installed | Use `sudo`? |
25
+ |---|---|
26
+ | Homebrew (`brew install node`) | ❌ No — global prefix is user-writable |
27
+ | nvm / asdf / fnm | ❌ No — same reason |
28
+ | System Node on macOS / Linux | ✅ Yes — global prefix is `/usr/local/...` |
29
+
30
+ Check yours:
39
31
 
40
- ## CLI Usage
41
-
42
- ### Start Interactive Agent Session (REPL)
43
- Starts the agent loop. It will automatically load the active server connection and prime the agent with active codebase memories.
44
- From the repository root:
45
- ```bash
46
- npm run cli
47
- ```
48
- Or to run a specific command:
49
- ```bash
50
- npm run cli chat
51
- ```
52
- Or from the `brainrouter` package subdirectory:
53
- ```bash
54
- node dist/index.js chat
55
- ```
56
- *Tip: You can override the active LLM model via `--model <name>` or profile via `--profile <name>`.*
57
-
58
- Workspace detection:
59
- - By default, BrainRouter uses the nearest project root with `AGENT.md`, `AGENTS.md`, or `.git`.
60
- - If you run from this package directory during BrainRouter development, the CLI promotes the workspace to the monorepo root so tools see the whole project, not only `brainrouter/`.
61
- - Override manually with `--workspace /absolute/path/to/project` or `BRAINROUTER_WORKSPACE=/absolute/path/to/project`.
62
- - In the REPL, run `/workspace` to confirm the active root and session key.
63
-
64
- ### Host Login / Setup Connection
65
- Interactively log in to a hosted HTTP/SSE BrainRouter deployment and test latency/connectivity:
66
- From the repository root:
67
32
  ```bash
68
- npm run cli login
33
+ npm config get prefix
34
+ ```
35
+
36
+ If the path is under `/Users/...`, `/opt/homebrew/...`, or your home dir
37
+ → no sudo. If it's `/usr/local/...` → use sudo.
38
+
39
+ Verify the install:
40
+
41
+ ```bash
42
+ which brainrouter # prints the path to the binary
43
+ brainrouter --version # prints 0.3.5
69
44
  ```
70
45
 
71
46
  ---
72
47
 
73
- ## Interactive REPL Slash Commands
48
+ ## Configure
49
+
50
+ Two configuration surfaces, both one-time:
74
51
 
75
- Within the chat session, type `/` to access commands:
76
- - `/help` — List all available directive commands.
77
- - `/status` — Display active server profile details, LLM model, server latency check, and database size stats.
78
- - `/workspace` — Show active workspace root, launch directory, and BrainRouter session key.
79
- - `/tools` — Show local workspace tools and MCP tools exposed to the LLM.
80
- - `/doctor` — Check active profile, MCP connectivity, plan + session store health, and orchestration tool availability.
81
- - `/skills` — Visualize all loaded BrainRouter skills and categories.
82
- - `/plan` — Show the durable CLI task plan persisted under `.brainrouter/cli/tasks.json`.
83
- - `/transcript [main|sessionKey]` — Show recent persisted transcript entries.
84
- - `/roles` — List built-in agent roles (`explorer`, `architect`, `reviewer`, `worker`, `verifier`) with default access modes.
85
- - `/agents` — List child agent sessions with status, role, label, and elapsed time.
86
- - `/agent <id>` — Show child detail, prompt, final output, and recent transcript.
87
- - `/spawn <role> <prompt>` — Spawn a child agent (parent narrates via the LLM tool call).
88
- - `/wait <id> [timeoutMs]` — Wait for a child agent to finish.
89
- - `/spec <title>` — Runs the **spec-driven-skill** and writes a full `spec.md` to `<workspace>/.brainrouter/cli/workflows/<slug>/spec.md`. Stops for approval before generating tasks.
90
- - `/approve [slug]` — Approves the current (or named) workflow and kicks off the worker + verifier implementation phase, one task at a time, appending to `walkthrough.md`.
91
- - `/workflows` — List durable workflow folders with per-artifact status (`spec.md`, `tasks.md`, `walkthrough.md`).
92
- - `/feature-dev <feature>` — Runs the catalogued **agentic-engineering-workflow** skill with explorer + architect orchestration. Writes `spec.md` and `tasks.md` to the workflow folder, then stops for user approval before worker implementation.
93
- - `/review [scope]` — Runs the catalogued **code-review-and-quality** skill with 3 parallel reviewer agents (correctness, maintainability, conventions).
94
- - `/implement-plan` — Runs the catalogued **incremental-skill** with a worker + verifier loop on the next pending plan item.
95
- - `/skill <name> [input]` — Generic invoker for any skill in your `skills/` catalogue. The CLI fetches the skill body via the MCP `get_skill` tool, falls back to filesystem (`skills/**/SKILL.md`), and hands the agent a structured prompt that embeds the skill instructions plus orchestration affordances (`spawn_agent`, `update_plan`).
52
+ ### 1. The chat LLM and MCP server profile
96
53
 
97
- ### Skill-driven workflows
54
+ ```bash
55
+ brainrouter config # interactive — set LLM provider, model, key, endpoint
56
+ brainrouter login # interactive — set MCP server URL + API key
57
+ ```
98
58
 
99
- The CLI ships with a thin slash → skill mapping (see `brainrouter-cli/src/prompt/skillRunner.ts`). Slash commands do **not** carry monolithic hard-coded prompts; they delegate to the SKILL.md authored under `skills/`. This means improving a workflow is a documentation edit, not a code change. Add a new mapping in `SLASH_TO_SKILL` to expose a new slash command, or use `/skill <name>` to invoke any skill ad-hoc.
59
+ Both write to `~/.config/brainrouter/config.json`.
100
60
 
101
- #### How the skill catalogue is discovered
61
+ For local-model setups (LM Studio / Ollama), point the LLM endpoint at
62
+ `http://localhost:1234/v1/chat/completions` or `http://localhost:11434/v1/chat/completions`.
102
63
 
103
- The CLI resolves a skill body in this order:
64
+ ### 2. (Optional) Runtime knobs `~/.config/brainrouter/cli.env` or `./brainrouter-cli.env`
104
65
 
105
- 1. **MCP `get_skill` tool** the connected MCP server merges *global* skills (the canonical BrainRouter catalogue) with *local* skills the user authored under `<workspace>/skills/` or `<workspace>/projects/*/skills/`. Local skills shadow global ones on name conflict. This is the path used in normal operation.
106
- 2. **Filesystem fallback** (used only when MCP is unreachable) searches, in order:
107
- - `<workspace>/skills/**/SKILL.md`
108
- - `<workspace>/.brainrouter/skills/**/SKILL.md`
109
- - The installed `@kinqs/brainrouter-mcp-server` package directory (resolved via `require.resolve`). This works because the MCP package bundles the canonical catalogue at publish time (see below).
110
- 3. Otherwise the CLI hands the agent a benign placeholder and asks it to use general judgement.
66
+ Only needed if you want to tune sandbox, tool-loop limits, trace logging,
67
+ or web-search backend. See the [`.env.example`](.env.example) bundled with
68
+ this package for the full list. LLM credentials do **not** go here — they
69
+ live in `config.json`.
111
70
 
112
- #### Catalogue bundling at publish time
71
+ ---
113
72
 
114
- The `@kinqs/brainrouter-mcp-server` package ships with the full BrainRouter skill catalogue baked in, so a user who only runs `npm install @kinqs/brainrouter-mcp-server @kinqs/brainrouter-cli` in their own workspace gets all 70+ canonical skills out of the box — no monorepo checkout required.
73
+ ## Run
115
74
 
116
- This is done via two lifecycle scripts in `brainrouter/scripts/`:
75
+ ```bash
76
+ brainrouter # starts the interactive REPL
77
+ brainrouter chat # same — `chat` is the default subcommand
78
+ brainrouter run "summarize the changes in src/" # one-shot non-interactive
79
+ brainrouter agents # list child agent sessions in this workspace
80
+ ```
117
81
 
118
- - `prepack.mjs` runs before `npm pack`/`npm publish`. Copies `skills/`, `agents/`, `references/`, and `docs/` from the monorepo root into the package directory and records what it copied in `.bundled-content.json`.
119
- - `postpack.mjs` runs after pack. Reads the marker and removes exactly what `prepack` added, leaving the working tree clean.
82
+ Inside the REPL, type `/help` for the full slash-command list (60+
83
+ commands across session / memory / workflow / orchestration / observability
84
+ surfaces).
120
85
 
121
- The MCP server's resolver ([brainrouter/src/resolver.ts](../brainrouter/src/resolver.ts)) prefers the package's own `skills/` when present (installed-package mode) and otherwise walks up to the monorepo root (development mode). Both layouts work identically from the CLI's point of view.
86
+ ### Offline mode
122
87
 
123
- ### Durable workflow artifacts (one folder per workflow)
88
+ If the MCP server isn't reachable, the CLI still boots — but only local
89
+ tools (file edits, shell, web fetch, `spawn_agent`) work. Memory recall,
90
+ capture, and skills are disabled until the server is back. The startup
91
+ banner shows `⚠️ OFFLINE MODE` when this happens. Pass `--strict-mcp` to
92
+ make the CLI exit instead of degrading.
124
93
 
125
- All multi-step commands (`/spec`, `/feature-dev`, `/review`, `/implement-plan`) anchor to a workflow slug and write their outputs to:
94
+ ### Stdio mode
126
95
 
127
- ```
128
- <workspace>/.brainrouter/cli/workflows/<slug>/
129
- meta.json # { slug, title, kind, createdAt, updatedAt, status }
130
- spec.md # produced by /spec or /feature-dev phase 3
131
- tasks.md # produced by /feature-dev phase 3
132
- walkthrough.md # appended by /implement-plan as items ship
133
- review.md # produced by /review
134
- ```
96
+ If you'd rather have the CLI spawn the MCP server as a child process
97
+ instead of running it separately, use `brainrouter config` → "Set Active
98
+ Server Profile" `default` (the bundled stdio profile). You don't need
99
+ to run anything else the CLI manages the server's lifecycle.
135
100
 
136
- The orchestration prompts for these commands **require** the agent to call `write_file` with the exact workspace-relative path — no chat-only plans. Use `/workflows` to inspect what's on disk. `getCurrentWorkflow` tracks the most recent one so `/implement-plan` appends to it automatically.
101
+ ---
137
102
 
138
- The system prompt also directs the agent to redirect free-form spec/plan requests to `/spec` or `/feature-dev` instead of producing inline monoliths, so the "one place" rule survives even when you don't type a slash command.
103
+ ## Workspace detection
139
104
 
140
- ### Memory-native flow
105
+ By default, the CLI uses the nearest project root with `AGENT.md`,
106
+ `AGENTS.md`, or `.git`. Override with:
141
107
 
142
- Each parent turn runs three memory queries in parallel before the LLM sees the user prompt:
108
+ ```bash
109
+ brainrouter --workspace /absolute/path/to/project
110
+ # or
111
+ BRAINROUTER_WORKSPACE=/absolute/path/to/project brainrouter
112
+ ```
143
113
 
144
- 1. **`memory_recall`** cognitive memory most relevant to the prompt.
145
- 2. **`memory_working_context`** — current working canvas, so resumed sessions don't reset.
146
- 3. **`memory_task_state`** — open tasks / handover notes for this workspace.
114
+ Inside the REPL, run `/workspace` to confirm the active root and session key.
147
115
 
148
- The merged briefing (secrets redacted via `redactText`) is injected as a system message and the recalled record IDs are tracked through the whole turn. At end-of-turn, `selectCitedRecordIds` heuristically picks the records that actually informed the answer (by ID mention or distinctive content match) and reports them via `memory_mark_cited` — replacing the previous always-empty citation list, so System-1 recall actually learns.
116
+ ---
149
117
 
150
- Child agents (`spawn_agent`) skip the full briefing for speed but accept a `seedRecordIds: string[]` parameter so the parent can hand over what it already recalled. Long child outputs (≥ 6,000 chars) are automatically offloaded to `memory_working_offload` and only a preview + ref handle is returned to the parent — the main context-saving win when synthesizing multiple child reports.
118
+ ## What you also probably want
151
119
 
152
- After every turn, the CLI also asks `memory_contradictions` and surfaces a one-line warning in the REPL when newly-captured beliefs disagree with prior ones, so drift gets caught instead of silently accumulating.
120
+ A BrainRouter MCP server for the cognitive memory. The CLI works without
121
+ it (offline mode) but you lose recall, capture, and skills:
153
122
 
154
- Inspection commands:
123
+ ```bash
124
+ npm install -g @kinqs/brainrouter-mcp-server
125
+ brainrouter-mcp init # one-time: scaffold ~/.config/brainrouter/server.env
126
+ $EDITOR ~/.config/brainrouter/server.env # set BRAINROUTER_LLM_API_KEY, embeddings, etc.
127
+ brainrouter-mcp --http --port 3747 # in a separate terminal
128
+ ```
155
129
 
156
- - `/memory <query>` search long-term cognitive memory (`memory_search`).
157
- - `/recall <query>` — explicit `memory_recall`, no LLM turn.
158
- - `/briefing` — what was recalled before the most recent turn.
159
- - `/scenes` — list active focus scenes.
160
- - `/working` — current working-memory canvas.
161
- - `/forget <recordId>` — archive an obsolete memory.
130
+ Then `brainrouter login` and point at `http://localhost:3747/mcp`.
162
131
 
163
- The workflow commands `/feature-dev`, `/review`, and `/implement-plan` are now required to open with `memory_search` (plus `memory_graph_query` / `memory_file_history` / `memory_task_state` depending on the workflow) and pass `seedRecordIds` to children, so no exploration is ever duplicated across sessions.
132
+ ---
164
133
 
165
- ### Child agent permissions
134
+ ## Docs
166
135
 
167
- Child agents default to the safest mode for their role: `explorer`, `architect`, `reviewer` are `read`; `worker` is `write`; `verifier` is `shell`. Override with `access: "read" | "write" | "shell"` when calling `spawn_agent`. Shell execution from children runs unattended — only grant `shell` to trusted roles like `verifier`.
168
- - `/config` Output active configuration details (with security sanitization for API keys).
169
- - `/compact` Clear the active chat context while keeping the session identity.
170
- - `/clear` Wipe the chat history of the active session.
171
- - `/exit` — Close connections and exit.
136
+ - **Repo**: <https://github.com/kinqsradiollc/BrainRouter>
137
+ - **Memory engine deep-dive**: [BRAINROUTER.md](https://github.com/kinqsradiollc/BrainRouter/blob/main/BRAINROUTER.md)
138
+ - **Maintainer runbook**: [SETUP.md](https://github.com/kinqsradiollc/BrainRouter/blob/main/SETUP.md)
139
+ - **Bugs / requests**: <https://github.com/kinqsradiollc/BrainRouter/issues>
172
140
 
173
141
  ---
174
142
 
175
- ## Autonomous Tool Execution
176
-
177
- The agent coordinates two scopes of tools:
178
- 1. **BrainRouter Memory Tools** (loaded dynamically via the MCP connection): `memory_recall`, `memory_capture_turn`, `list_skills`, etc.
179
- 2. **Local Workspace Tools**:
180
- - `read_file` — Reads content of a workspace file.
181
- - `write_file` — Overwrites or writes a new file.
182
- - `edit_file` — Performs safe single-match string search-and-replace.
183
- - `list_dir` — Lists directory paths.
184
- - `grep_search` — Platform-independent recursive search of code patterns.
185
- - `run_command` — Runs a shell command on your host (always requests manual confirmation first for safety).
143
+ ## License
144
+
145
+ MIT
package/bin/cli.cjs ADDED
@@ -0,0 +1,71 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Thin CommonJS shim that runs BEFORE the real ESM CLI entrypoint.
5
+ *
6
+ * Why CJS for the bin: ESM hoists all `import` statements above any
7
+ * top-level code in the module that owns them. The CLI imports
8
+ * `node:sqlite` transitively via `config/config.ts`, which triggers
9
+ * Node's `ExperimentalWarning` the FIRST time the module is touched —
10
+ * and that happens during import resolution, before any line of code
11
+ * in `src/index.ts` runs. So a warning filter installed inside that
12
+ * file always fires too late.
13
+ *
14
+ * This shim does three things synchronously, with zero ESM imports
15
+ * blocking it, and only then hands off:
16
+ *
17
+ * 1. Remove Node's default "warning" printer.
18
+ * 2. Install a filtered listener that drops `ExperimentalWarning`
19
+ * (sqlite, ESM in older Node) and dotenv self-promotion lines.
20
+ * 3. Override `process.emitWarning` so future direct callers also
21
+ * route through the same filter.
22
+ *
23
+ * Anything BrainRouter itself emits via `process.emitWarning('…',
24
+ * 'BrainRouterWarning')` (or any non-suppressible type) flows through
25
+ * unchanged. NODE_NO_WARNINGS=1 would silence those too, which is why
26
+ * we don't just set that env.
27
+ *
28
+ * The shim then dynamically imports the ESM entry. Dynamic `import()`
29
+ * is the only way to load ESM from CJS; it returns a promise we await
30
+ * so an unhandled rejection during boot still surfaces as an error.
31
+ */
32
+
33
+ function isSuppressibleWarning(message, type) {
34
+ const looksExperimental =
35
+ type === 'ExperimentalWarning' ||
36
+ /experimental feature|SQLite is an experimental/i.test(message);
37
+ const looksDotenvNoise = /dotenv@\d|dotenvx|dotenv\.org/i.test(message);
38
+ return looksExperimental || looksDotenvNoise;
39
+ }
40
+
41
+ for (const listener of process.listeners('warning')) {
42
+ process.removeListener('warning', listener);
43
+ }
44
+ process.on('warning', (warning) => {
45
+ const message = (warning && warning.message) || '';
46
+ const type = (warning && warning.name) || '';
47
+ if (isSuppressibleWarning(message, type)) return;
48
+ process.stderr.write(`(node:${process.pid}) ${type || 'Warning'}: ${message || warning}\n`);
49
+ });
50
+
51
+ const originalEmitWarning = process.emitWarning.bind(process);
52
+ process.emitWarning = function emitWarning(warning, ...rest) {
53
+ const message = typeof warning === 'string' ? warning : (warning && warning.message) || '';
54
+ const type =
55
+ typeof rest[0] === 'string' ? rest[0] :
56
+ (rest[0] && typeof rest[0] === 'object' && 'type' in rest[0]) ? rest[0].type :
57
+ (warning && warning.name) || '';
58
+ if (isSuppressibleWarning(message, type)) return;
59
+ return originalEmitWarning(warning, ...rest);
60
+ };
61
+
62
+ // Path to the compiled ESM entry, resolved relative to this shim.
63
+ const path = require('node:path');
64
+ const url = require('node:url');
65
+ const entry = path.resolve(__dirname, '..', 'dist', 'index.js');
66
+ import(url.pathToFileURL(entry).href).catch((err) => {
67
+ // Surface boot-time errors verbatim — a silent exit would just look like
68
+ // the CLI never started.
69
+ process.stderr.write(`brainrouter: failed to load CLI entrypoint: ${(err && err.stack) || err}\n`);
70
+ process.exit(1);
71
+ });