Skip to main content

ModusBrain Deployment Topologies

ModusBrain supports three deployment shapes. They compose: a single user can mix all three on the same machine without conflict, because every shape resolves to “which ~/.modusbrain/config.json is active right now?” and MODUSBRAIN_HOME controls that selection. This page covers the three topologies, when each fits, and concrete setup recipes. Pair this doc with docs/architecture/brains-and-sources.md (which covers the in-brain organization axes) — that doc is about WHICH database; this doc is about WHERE that database lives.

Quick decision tree

Topologies 2 and 3 stack: a thin-client install can also host per-worktree code engines, and a per-worktree code engine can also point its artifact brain at a remote server.

Topology 1 — Single brain (today’s default)

What you get: one local DB (PGLite for small brains, Supabase for ~1000+ files). All commands work directly against it. modusbrain serve exposes it to a single agent over MCP. When it fits: solo use, single machine, one agent, no Conductor parallelism. This is the default; modusbrain init (no flags) gives you this. Setup:
Nothing else here is special. The other two topologies are variations on “who owns the DB” and “how does the agent talk to it.”

Topology 2 — Cross-machine thin client

What you get: the agent on one machine (“neuromancer”) consumes a brain hosted on another machine (“brain-host”) over HTTP MCP with OAuth. The agent’s machine has NO local engine. All queries, searches, embeddings, and indexing happen on the host. When it fits:
  • Heavy brain (Supabase + autopilot) lives on a beefy machine; agents elsewhere just consume it.
  • You want one source of truth across many machines.
  • Spinning up a parallel local install would create source-ID contention or duplicate work.
The thin client’s ~/.modusbrain/config.json carries a remote_mcp field instead of a local DB connection:
The CLI dispatch guard refuses any DB-bound command (sync, embed, extract, migrate, apply-migrations, repair-jsonb, orphans, integrity, serve) on a thin-client install with a clear error pointing at the remote host. modusbrain doctor runs a dedicated thin-client check set (OAuth discovery, token round-trip, MCP smoke).

Setup

Step 1 — On the host (brain-host):
The register-client command prints a client_id and client_secret. Note both. Scope must include adminsubmit_job (used by modusbrain remote ping) and run_doctor (used by modusbrain remote doctor) both require it. Step 2 — On the thin client (neuromancer):
Pre-flight smoke runs three probes (OAuth discovery, token round-trip, MCP initialize). If any fails, init exits with an actionable error. On success, ~/.modusbrain/config.json gets remote_mcp set and NO local DB is created. Step 3 — Configure your agent’s MCP client. For Claude Desktop / Hermes / openclaw, add a single MCP server entry pointing at the host’s mcp_url with the bearer token from register-client. Example for Claude Desktop’s ~/.config/claude/claude_desktop_config.json:
Step 4 — Verify.
modusbrain sync and friends will refuse with a clear thin-client error naming the mcp_url. That’s the correct behavior — those commands need a local engine that doesn’t exist here.

Re-run guard

Running modusbrain init (no flags) on a machine that already has thin-client config set refuses without --force. This catches the scripted-setup-loop friction where an orchestrator keeps trying to create a local DB. Use modusbrain init --mcp-only --force to refresh thin-client config.

Storing the OAuth secret

Three storage paths in priority order:
  1. MODUSBRAIN_REMOTE_CLIENT_SECRET env var (preferred for headless agents). When set, overrides whatever’s in the config file. The init flow doesn’t persist a config-file copy when the env var was the source.
  2. ~/.modusbrain/config.json with 0600 perms (default for interactive setup; mirrors how Supabase keys are stored today).
  3. macOS Keychain integration is on the roadmap; not in v1.

Topology 3 — Split-engine, per-worktree code + remote artifacts

What you get: each Conductor worktree has its own per-worktree code index (local PGLite, disposable when the worktree dies). Artifacts (plans, learnings, transcripts) still live in a shared brain that all worktrees can see and write to. When it fits:
  • Multiple Conductor worktrees on one machine, all touching the same code repo.
  • You don’t want each worktree’s code-import to clobber the others’ last_commit, source IDs, or symbol tables.
  • You DO want artifacts (plans, learnings, retros, transcripts) to be visible across worktrees.

How it works

MODUSBRAIN_HOME selects which ~/.modusbrain directory is active. Set per worktree:
Each worktree’s modusbrain serve instance binds its own port and indexes its own DB. Multiple modusbrain serve processes coexist fine — they’re separate OS processes with separate config and separate connection pools. The artifact brain runs as a separate modusbrain serve instance with the default ~/.modusbrain (no MODUSBRAIN_HOME override) — or remote, in which case it’s a Topology 2 setup. The agent’s MCP client config lists multiple servers, each with a unique alias. Tool names are namespaced as mcp__<alias>__<tool>, so the agent calls mcp__modusbrain_code__search for code lookups and mcp__modusbrain_artifacts__search for artifact lookups. Per-worktree code brains index source files only — no meeting notes, no people pages, no transcripts. Configure each code brain to use Voyage’s code-tuned model at init time so the config can’t be lost to a later init overwrite:
voyage-code-3 is Voyage’s code-specialized embedding model with head-to-head numbers above their general flagships on code retrieval (voyageai.com/blog). For already-initialized brains, switch with the one-command wipe-and-reinit (preserves every other config field):
(modusbrain config set embedding_model is refused as of v0.37.11.0 because the schema column has to resize alongside the config.) modusbrain reindex --code prints a recommendation when the configured embedding model isn’t code-tuned. Suppress with MODUSBRAIN_NO_CODE_MODEL_NUDGE=1 if you’ve intentionally chosen another provider (single-vendor procurement, compliance, no Voyage key).

CRITICAL: alias-level routing is manual

Topology 3 has no smart per-tool routing inside modusbrain. The agent picks which brain to query when it picks the alias. A wrong alias writes (or queries) the wrong brain silently. This is intentional (explicit beats magic) but real:
  • If the agent calls mcp__modusbrain_artifacts__put_page with code-shaped content, that page lands in the artifact brain forever.
  • If the agent calls mcp__modusbrain_code__search for a question that actually wants artifact context, the search comes back empty.
Mitigations:
  • Name aliases clearly. modusbrain_code vs modusbrain_artifacts is unambiguous; modusbrain vs modusbrain_local is not.
  • Document in your agent’s system prompt or rules which alias goes where. Be explicit about “code questions → modusbrain_code; everything else → modusbrain_artifacts.”
  • Pair Topology 3 with gstack’s per-worktree wiring (which sets the alias names + agent rules consistently across worktrees).

Setup (manual; gstack automates this side)

The modusbrain side requires zero new code — MODUSBRAIN_HOME and --port already exist. Setup looks like:
Then configure the agent’s MCP config with two entries (different aliases, different ports). For Claude Desktop:
The gstack-side wiring (per-worktree home setup, port allocation, automatic MCP config generation, gitignore for the per-worktree DB) is in the gstack repo’s setup-modusbrain skill — it composes these primitives, modusbrain doesn’t have to know about Conductor.

Combining topologies

The three shapes compose. A single machine can run:
  • A thin-client default config pointing at a remote artifact brain (Topology 2).
  • Plus per-worktree code brains under their own MODUSBRAIN_HOME (Topology 3).
  • Each worktree’s modusbrain serve instance is local; the agent’s MCP config lists them alongside the remote artifact brain.
MODUSBRAIN_HOME controls which config file is active for any one CLI invocation. modusbrain serve --port controls which port a server listens on. The agent’s MCP client picks the alias and thus the destination per tool call. There’s no global modusbrain orchestrator that knows about all of them simultaneously — that’s by design.

When NOT to use these topologies

  • Don’t use Topology 2 if your agent only ever runs on the same machine as the brain. A local modusbrain install + modusbrain serve (stdio) is simpler and faster.
  • Don’t use Topology 3 if you only have one Conductor worktree at a time. Per-worktree engines exist to prevent contention; one-at-a-time use has no contention.
  • Don’t use a remote_mcp thin client AND a local engine on the same machine in the same MODUSBRAIN_HOME. The dispatch guard refuses DB-bound commands when remote_mcp is set. If you genuinely want both modes on one machine, use MODUSBRAIN_HOME to separate them (one home for the thin client, another for the local engine).

See also

  • docs/architecture/brains-and-sources.md — in-brain organization (brains vs sources axes).
  • docs/mcp/CLAUDE_DESKTOP.md and siblings — per-client MCP setup.
  • modusbrain init --help and modusbrain auth --help for command-level details.
  • docs/tutorials/ — end-to-end walkthroughs that combine these topologies into working setups (company brain, personal brain, agent integration, etc.).