v2.8.3 · Technical Architecture

How Monomind
Is Actually Built

An 8-package monorepo wiring Claude Code hooks, local memory, a code knowledge graph, and an SDK-backed org runtime together. Every number below is checked against the current source, not carried over from an old design doc.

8Packages
32CLI Commands
15Background Workers
46Monograph MCP Tools

Architecture

System Overview

Claude Code talks to the CLI package over a hand-rolled stdio JSON-RPC loop. The CLI dynamically imports the other 7 packages as needed — most are libraries, not always-running services.

CLAUDE CODE (IDE / CLI)stdio JSON-RPC ↔ @monoes/monomindcli (packages/@monomind/cli/)@monoes/monomindcli32 commands · dynamically imports the packages below@monoes/hooksRegistry + 15 workers@monoes/memorySQLite + local embeddings@monoes/monographtree-sitter + SQLite graph@monoes/routingopt-in RouteLayer.monomind/metrics/worker JSON outputsSQLite (better-sqlite3)sql.js WASM fallback.monomind/monograph.dbnodes · edges · communitiesStandalone: @monoes/monobrowse (CDP browser automation) · @monoes/monodesign (design intelligence)packages/@monoes/ — path scope matches published npm scope for these two only

Modules

8 Packages

6 live under packages/@monomind/ (cli, hooks, mcp, memory, monograph, routing) — all but cli publish under the @monoes/ npm scope despite the @monomind/ directory name. 2 live under packages/@monoes/ (monobrowse, monodesign), where path and publish scope match.

CLI Entry Point

@monoes/monomindcli

packages/@monomind/cli/

The published CLI package (installed as the `monomind` umbrella from repo root). 32 top-level commands, in-process agent/swarm lifecycle, and a hand-rolled stdio JSON-RPC MCP server — no separate MCP process required for the default transport.

32 commandsstdio JSON-RPCin-process agents
🪝

Hooks & Workers

@monoes/hooks

packages/@monomind/hooks/

Typed HookEvent registry/executor library plus a WorkerManager running 15 background workers (14 statically configured + the always-on progress worker). Bridged into the live dispatch path via .claude/helpers, which is the mechanism Claude Code actually calls.

20 HookEvent types15 workersregistry + executor
🔌

MCP Framework

@monoes/mcp

packages/@monomind/mcp/

MCP server framework powering `mcp start -t http`/`-t websocket` and stdio/in-process transports, with session, connection, resource, prompt, and rate-limiting support. The default stdio setup Claude Code connects to does not import this package — it uses the CLI's own hand-rolled loop.

http/websocketOAuthrate limiting
💾

Memory Backend

@monoes/memory

packages/@monomind/memory/

Lower-level memory backend library — SQLite (better-sqlite3, sql.js WASM fallback) and a pure-JS HNSW index. The live bridge that CLI memory commands and MCP memory tools actually call lives in the CLI package, dynamically importing this one. LanceDB was fully removed in v2.3.1.

SQLitelocal embeddingsHNSW (opt-in)
🗺

Knowledge Graph

@monoes/monograph

packages/@monomind/monograph/

Tree-sitter + SQLite code dependency graph. 14 full tree-sitter grammars (TypeScript's covers JS/JSX/MJS/CJS) plus 5 lightweight regex-based symbol extractors. 19 default MCP tools, 27 more behind MONOGRAPH_MCP_ADVANCED=1 — 46 total.

14 grammars46 MCP toolsPPR rerank on by default
🔀

Semantic Routing

@monoes/routing

packages/@monomind/routing/

Opt-in RouteLayer algorithm: keyword pre-filter, then real embeddings via an isolated worker process, then cosine similarity, then a Haiku LLM fallback below threshold. Reached via `route semantic`, `agent --task`, or MCP hooks_route_semantic — bare `monomind route` uses a separate keyword-only stub instead.

keyword pre-filterout-of-process embeddingsLLM fallback
🌐

Browser Automation

@monoes/monobrowse

packages/@monoes/monobrowse/

Standalone Chrome DevTools Protocol (CDP) client for browser automation — no Playwright, Puppeteer, or Selenium dependency. Powers `monomind browse` and the agent-browser-testing workflow.

native CDPno external binary
🎨

Design Intelligence

@monoes/monodesign

packages/@monoes/monodesign/

Independent frontend design intelligence package — design tokens, antipattern detection, and the monodesign skill. Replaced the earlier set of separate design-agent roles (UI Designer, UX Architect, Brand Guardian, etc.) with one unified system.

design tokensantipattern detection

Memory

Local SQLite, Not a Vector Cloud Service

Three genuinely separate mechanisms share the word "memory" in this codebase. Here's what each one actually is.

01

Local SQLite, not a cloud vector DB

The default memory engine is local SQLite with embedded vectors — better-sqlite3 primary, sql.js WASM as fallback. Embeddings are computed locally with Xenova/all-MiniLM-L6-v2 (384 dimensions). This backs CLI memory store/search, the MCP memory tools, and the Second Brain.

02

LanceDB removed, not replaced-in-place

LanceDB (~600MB of native dependencies) was fully removed in v2.3.1 (2026-07-18) once the local SQLite engine was measured to work for Second Brain retrieval. Some internal comments and a health-check label still say "lancedb" as a stale string literal — cosmetic, not a live dependency.

03

HNSW exists, but it's opt-in

A pure-JS HNSW index ships in the memory package, but it is not on the default search path. It's reachable explicitly via `memory search --build-hnsw`. Don't expect vector-index speedups on a default `memory search` call.

04

A separate JSON pattern store powers hooks/intelligence

Hook and trajectory learning (routing outcomes, edit patterns) is stored in JSON files (patterns.json, auto-memory-store.json), independent of the SQLite backend above. These are three genuinely separate mechanisms that happen to all be called "memory" — not yet consolidated into one system.

Routing

Keyword by Default, Semantic on Request

The routing story has two distinct paths — don't mistake the default for the semantic one.

1
Bare `monomind route "task"` — keyword stub

The default, zero-config path is a lightweight keyword-only router (createKeywordRouter): a fixed if/else chain over ~8 hardcoded categories, always returns confidence 0.75, no embeddings, no learning. It lives in the CLI package, not in @monoes/routing.

2
`route semantic`, `agent --task`, or MCP hooks_route_semantic — real routing

These entry points use @monoes/routing's RouteLayer: a keyword pre-filter first (first match wins, deterministic), then a real embedding model run in an isolated worker process (kept out-of-process because loading onnxruntime in-process causes SIGSEGVs), scored by cosine similarity against each route's centroid.

3
Threshold gate → Haiku LLM fallback

If the best semantic match scores below the configured threshold (default 0.5), routing falls back to a Haiku LLM classification call instead of guessing. This is the only place an LLM call is part of routing itself.

4
Route-outcome correlation, measured by `doctor`

Every routing decision (from either path) can be recorded to route-outcomes.jsonl and later joined against what actually happened, producing accuracy/adherence metrics surfaced by `monomind doctor`.

Hook System

Two Different Things Called "Hooks"

29 CLI subcommands and 20 typed registry events are different mechanisms that happen to share a name — plus 15 background workers underneath both.

29 `hooks` CLI subcommands

  • pre-edit / post-edit, pre-command / post-command, pre-task / post-task
  • session-start, session-end, session-restore, notify
  • route, explain, pretrain, build-agents, transfer, metrics
  • intelligence (trajectory-start/step/end, pattern-store/search, stats, attention)
  • worker, statusline, list, coverage-route, coverage-suggest, coverage-gaps
  • model-route, model-outcome, model-stats

20 typed HookEvent registry/executor values

  • A separate, lower-level mechanism in @monoes/hooks — PreToolUse, PostToolUse, PreEdit, PostEdit, PreRead, PostRead, PreCommand, PostCommand, PreTask, PostTask, TaskProgress, SessionStart, SessionEnd, SessionRestore, AgentSpawn, AgentTerminate, PreRoute, PostRoute, PatternLearned, PatternConsolidated.
  • These are not CLI subcommand names — they're the registry's in-memory event types, dispatched by the live .claude/helpers path, which bridges into this package's WorkerManager.

15 background workers

  • 14 statically configured: performance, health, swarm, git, learning, adr, ddd, security, patterns, cache, map, audit, optimize, consolidate
  • + 1 always-on: progress (registered dynamically, not in the static config)
  • Metrics-producing workers (ddd, map, audit, optimize, consolidate) auto-refresh at session start when their output is missing or older than 6 hours.

Org Runtime v2

SDK-Backed Agent Orgs

monomind org run/serve replaces the older prompt-orchestrated runorg path — each role is a live agent session, not a scripted prompt loop.

Runtime

SDK-backed daemon

monomind org run/serve — each role is a live, in-process Claude Agent SDK session, not a subprocess.

Subcommands

16

run [--dry-run], stop, status, serve, test-loop, logs, report, memory, questions, answer, create, validate, migrate, list, delete, mark-complete.

Inter-agent channel

org_send / Mailbox

The only way roles communicate — plus ask_human for human-in-the-loop and org_recall/org_remember/org_learn for cross-run memory.

Config

.monomind/orgs/<name>.json

Parsed against a zod schema: goal, schedule, run_config (budget, concurrency), and a role list with per-role tool/file/web policy.

Honesty Notes

What We Won't Overclaim

A short list of things that are easy to overstate. We'd rather say them plainly here than have you find out later.

  • Swarm/hive-mind consensus (Byzantine, Raft, Quorum) is single-process vote counting today, not distributed consensus — Gossip and CRDT are planned but not implemented.
  • The default `monomind route` command is a keyword-only stub, not the semantic RouteLayer — don't confuse the two when reading routing output.
  • HNSW vector search exists but is opt-in only (`memory search --build-hnsw`) — it is not part of the default memory search path.
  • The former @monomind/security package was deleted; input validation now lives inline at packages/@monomind/cli/src/utils/input-guards.ts — there is no standalone security package.
  • Exact secret-scanner / injection-detector rule counts are not published here — we'd rather say "built-in secret and injection scanning" than cite a number we haven't verified against the current source.