Plug Terraphim Search into Claude Code and opencode
Two integration paths. CLI is the recommended starting point: zero new binaries, faster cold start, works in every host that can shell out. MCP earns its keep when you also want autocomplete-as-you-type or update_config_tool exposed to the model. Both paths use the same ~/.config/terraphim/embedded_config.json, so you get all six roles (Terraphim Engineer, Personal Assistant, System Operator, Context Engineering Author, Rust Engineer, Default) in either case.
Path A -- CLI via slash command (recommended)
terraphim-agent search already exists, takes --role and --limit, and returns ranked results to stdout. A two-line slash command in either host wraps it.
Claude Code
Create ~/.claude/commands/tsearch.md:
That is the entire integration. The allowed-tools line auto-approves the two CLI invocations so the model does not have to ask permission for each call.
opencode
Same file, drop it at ~/.config/opencode/command/tsearch.md. opencode reads the same frontmatter shape; no extra setup.
Why this is fast enough
terraphim-agent reads the persisted role state at start (low ms), runs the query against the role's haystacks (Aho-Corasick on local KG plus ripgrep over the haystack folders), and returns. For a typical knowledge-graph query against the Terraphim Engineer role on a laptop, the round trip is well under a second from slash command to formatted output. The agent already has the typed CLI (--role, --limit, --format json) -- no need to layer MCP on top for the common case.
Path B -- MCP server (when you want typed tools)
If you want the model to call search as a first-class tool with structured JSON output -- alongside autocomplete_terms, autocomplete_with_snippets, fuzzy_autocomplete_search, build_autocomplete_index, and update_config_tool -- register terraphim_mcp_server instead. It reads the same config so the role list is identical.
Build the binary
For the Personal Assistant role (JMAP needs JMAP_ACCESS_TOKEN from 1Password), wrap the binary so the secret never lands on disk. Mirror the existing terraphim-agent-pa pattern at ~/bin/terraphim_mcp_server-pa:
#!/usr/bin/env bash
Register in opencode
Add two entries under mcp in ~/.config/opencode/opencode.json:
"terraphim": { "type": "local", "command": ["/Users/alex/.cargo/bin/terraphim_mcp_server"] },
"terraphim-pa": { "type": "local", "command": ["/Users/alex/bin/terraphim_mcp_server-pa"] }Restart opencode. Tools appear as mcp__terraphim__search, mcp__terraphim_pa__search, etc.
Register in Claude Code
The list output should show both servers as Connected.
SessionStart primer (both paths)
Slash commands are useless if the model does not know the roles exist. Extend the SessionStart hook in ~/.claude/settings.json (and the equivalent in opencode) to print a one-screen role index:
Verify
CLI path:
MCP path:
|
| Inside a fresh Claude Code or opencode session, ask the model to list available tools; both mcp__terraphim__search and mcp__terraphim_pa__search should appear if the MCP path is configured.
Auto-routing (CLI and MCP)
Both paths now auto-route the search when no role is specified. The agent scores every configured role's knowledge graph against the query and picks the highest-rank match.
CLI: skip --role and the picked role is printed once on stderr:
[auto-route] picked role "System Operator" (score=3, candidates=4); to override, pass --rolestdout (including --robot and --format json payloads) is unchanged.
MCP: omit the role parameter on the terraphim_search tool. The CallToolResult prepends one text content of the form [auto-route] picked role "<name>" (score=<n>, candidates=<m>); pass role parameter to override so MCP clients can surface the routing decision; the resource contents that follow are unchanged in count and order.
Pass an explicit role to short-circuit auto-routing -- the routing line is suppressed entirely.
Three example queries (one per role)
- Terraphim Engineer:
/tsearch "Terraphim Engineer" rolegraph-- returns hits from~/.config/terraphim/docs/src/. - System Operator:
/tsearch "System Operator" RFP-- KG normalisesRFPtoacquisition need(INCOSE canonical term) and returnsAcquisition need.mdnear the top with a high rank score. - Personal Assistant:
/tsearch "Personal Assistant" invoice-- mixes Obsidian notes withjmap:///email/<id>hits from your Fastmail mailbox. The wrapper script injectsJMAP_ACCESS_TOKENonce per call.
When to pick which path
| | CLI (Path A) | MCP (Path B) |
| --- | --- | --- |
| New binaries needed | None | terraphim_mcp_server + wrapper |
| Cold start | ~50-200 ms per call | ~10-50 ms per call (long-lived process) |
| Tools exposed | search only | search + 4 autocomplete + build_autocomplete_index + update_config_tool |
| Works in any host | Yes -- anything that can run a slash command | Only hosts that speak MCP |
| Token handling | Wrapper script (terraphim-agent-pa) | Wrapper script (terraphim_mcp_server-pa) |
For the search-across-roles flow, CLI is enough. Add MCP when the model needs autocomplete-as-you-type or you want it to manage role configuration without leaving the conversation.
Troubleshooting
terraphim-agent: command not foundin slash command output -- the host is shelling out without your shell environment. Either install viacargo install terraphim_agentto a globally-visible path, or absolute-path the binary in the slash command (/Users/alex/.cargo/bin/terraphim-agent ...).mcp__terraphim_pa__searchreturns zero email hits -- theopCLI needs an active session (op signin); biometric prompts may not surface from non-interactive MCP health checks. Runop signinonce per terminal session before launching the host.- No matches from any role -- run
terraphim-agent config reloadto rebuild the persisted role index fromembedded_config.json. Most empty-result confusion is a stale persisted snapshot. - Personal Assistant only shows notes, never email -- you are calling
terraphim-agentinstead ofterraphim-agent-pa, soJMAP_ACCESS_TOKENis unset. The bare CLI is fine for the other roles.
Related
- Personal Assistant role -- the JMAP + Obsidian role this integration exposes
- System Operator README -- the Logseq MBSE KG
- Command Rewriting How-To -- the hooks-based knowledge-graph integration that runs alongside this search integration