[{"localId": "https://terraphim.ai/releases/", "https://atomicdata.dev/properties/name" : "Releases", "https://terraphim.ai/properties/url" : "https://terraphim.ai/releases/", "https://atomicdata.dev/properties/description" : "

Releases

\n

Stay up-to-date with the latest Terraphim AI releases.

\n

Latest Release: v1.16.31

\n

Released: 7 April 2026

\n

Download from GitHub | GitHub Releases

\n

Quick Install

\n
curl -fsSL https://raw.githubusercontent.com/terraphim/terraphim-ai/main/scripts/install.sh | bash\n
\n

Available Binaries

\n

v1.16.31 ships pre-built binaries for 7 platforms:

\n\n

Three binaries in each release:

\n\n

Installation

\n

Choose your preferred method:

\n
# Universal installer (recommended)\ncurl -fsSL https://raw.githubusercontent.com/terraphim/terraphim-ai/main/scripts/install.sh | bash\n\n# Homebrew\nbrew tap terraphim/terraphim && brew install terraphim-ai\n\n# Cargo\ncargo install terraphim-agent\ncargo install terraphim-cli\n
\n

Installation Guide

\n

All Releases

\n

View complete release history on GitHub Releases.

\n

Release Channels

\n

Stable

\n

Stable releases are recommended for production use. They have been thoroughly tested and are the most reliable version.

\n

Latest Stable: v1.16.31

\n

Development

\n

Development releases contain the latest features and improvements but may have more bugs. Use these for testing new features.

\n

Check the main branch for development builds.

\n

Upgrade Guide

\n

From Any Version to Latest

\n
# Universal installer (recommended)\ncurl -fsSL https://raw.githubusercontent.com/terraphim/terraphim-ai/main/scripts/install.sh | bash\n\n# Cargo\ncargo install terraphim-agent --force\ncargo install terraphim-cli --force\n
\n

Configuration Compatibility

\n

Terraphim maintains backward compatibility for configuration files across minor versions. Major version bumps (e.g., 1.x to 2.0) may require configuration updates.

\n

Verify Your Installation

\n

After installation or upgrade, verify your version:

\n
terraphim-agent --version\nterraphim-cli --version\n
\n

Beta Testing

\n

Want to test new features before they're released?

\n

Join our Discord server and look for #beta-testing channel. Beta testers get early access to new features and help shape product.

\n

Security Updates

\n

Security updates are released as soon as they're available. Stay informed by:

\n\n

Need Help?

\n

If you encounter issues with a release:

\n
    \n
  1. Search existing issues
  2. \n
  3. Create a new issue
  4. \n
  5. Join Discord community for support
  6. \n
  7. Visit Discourse forum for discussions
  8. \n
\n", "https://terraphim.ai/properties/date" : "2026-04-03", "https://atomicdata.dev/properties/tags" : {}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/how-tos/command-rewriting-howto/", "https://atomicdata.dev/properties/name" : "Command Rewriting How-To", "https://terraphim.ai/properties/url" : "https://terraphim.ai/how-tos/command-rewriting-howto/", "https://atomicdata.dev/properties/description" : "

How-To: Learning-Driven Command Rewriting

\n

This guide shows how to use terraphim-agent to rewrite shell commands before\nexecution — for example npm install -> bun add or pip install -> uv add — by plugging a knowledge-graph-backed thesaurus into your AI coding\nagent's tool-execution hook.

\n

The mechanism composes three pieces that already exist in terraphim-agent:

\n
    \n
  1. A Logseq-style knowledge graph of command synonyms under\n~/.config/terraphim/docs/src/kg/ (or any role-configured path).
  2. \n
  3. terraphim-agent replace — Aho-Corasick replacement that rewrites text\nusing a role's compiled thesaurus.
  4. \n
  5. A plugin hook in your AI agent (OpenCode, Claude Code, etc.) that\nintercepts every Bash tool call, pipes the command through replace,\nand writes the result back into the tool's args.
  6. \n
\n

Prerequisites

\n\n

1. Curate the knowledge graph

\n

Each concept is one markdown file. The filename stem becomes the concept\nkey; the H1 heading provides the display name used as the replacement; the\nsynonyms:: line lists terms that should be rewritten to it.

\n

Example ~/.config/terraphim/docs/src/kg/bun install.md:

\n
# bun add\n\nInstall dependencies using Bun package manager.\n\nsynonyms:: npm install, yarn install, pnpm install, npm i, yarn add, pnpm add\n
\n

Conventions that matter in practice:

\n\n

Seed set shipped with the Terraphim Engineer role

\n\n\n\n\n\n\n\n\n
FileMaps toCovers
bun.mdbunnpm, yarn, pnpm
bun install.mdbun addnpm install, yarn install, pnpm install, npm i, yarn add, pnpm add
bun run.mdbun runnpm run, yarn run, pnpm run
bunx.mdbunxnpx, pnpx, yarn dlx
uv.mduvpip, pip3, pipx
uv add.mduv addpip install, pip3 install, pip add, pipx install, python -m pip install
uv sync.mduv syncpip install -r requirements.txt
\n

2. Verify with the CLI

\n
printf "npm install express" \\\n  | terraphim-agent replace --role "Terraphim Engineer" --fail-open --json\n
\n

Expected output:

\n
{"result":"bun add express","original":"npm install express","replacements":1,"changed":true}\n
\n

Flags worth knowing:

\n\n

3. Flush the cache after KG edits

\n

Terraphim caches compiled thesauri in a SQLite database at\n/tmp/terraphim_sqlite/terraphim.db (path configured by\ncrates/terraphim_settings/default/settings.toml). Editing a KG markdown\nfile does not invalidate this cache; replace keeps returning the old\nmapping until you flush it.

\n
sqlite3 /tmp/terraphim_sqlite/terraphim.db \\\n  "DELETE FROM terraphim_kv WHERE key LIKE 'thesaurus_%' OR key LIKE 'document_ripgrep_%';"\n
\n

Because /tmp/ is wiped on reboot, a fresh boot always gives the\nup-to-date thesaurus.

\n

4. Wire up the hook (OpenCode example)

\n

OpenCode plugins expose tool.execute.before(input, output) where\noutput.args.command is the mutable shell command about to run. The same\npattern works in Claude Code via the PreToolUse hook script, just with\nshell-stdin instead of a JS closure.

\n
// ~/.config/opencode/plugin/terraphim-hooks.js\nconst REWRITE_MODE = process.env.TERRAPHIM_REWRITE_MODE || "suggest"\nconst REWRITE_ROLE = process.env.TERRAPHIM_REWRITE_ROLE || "Terraphim Engineer"\nconst AUDIT_LOG    = `${process.env.HOME}/Library/Application Support/terraphim/rewrites.log`\n\n// Narrow whitelist of commands whose argument grammar survives a synonym swap.\nconst REWRITEABLE_HEADS =\n  /^\\s*(npm|yarn|pnpm|npx|pnpx|pip|pip3|pipx|python\\s+-m\\s+pip|python3\\s+-m\\s+pip)\\b/i\n\nexport const TerraphimHooks = async ({ $ }) => ({\n  "tool.execute.before": async (input, output) => {\n    if (input.tool !== "Bash" || !output.args?.command) return\n    const command = output.args.command\n\n    const agent = `${process.env.HOME}/.cargo/bin/terraphim-agent`\n\n    // Always run the destructive-command guard first.\n    const g = await $`${agent} guard ${command} --json --fail-open 2>/dev/null || echo '{"decision":"allow"}'`\n    const guard = JSON.parse(g.stdout)\n    if (guard.decision === "block") {\n      throw new Error(`BLOCKED: ${guard.reason}`)\n    }\n\n    const isGitCommit   = /git\\s+(-C\\s+\\S+\\s+)?commit/i.test(command)\n    const isRewriteable = REWRITEABLE_HEADS.test(command)\n    if (!isGitCommit && !isRewriteable) return\n\n    const res     = await $`echo ${command} | ${agent} replace --role ${REWRITE_ROLE} --fail-open --json 2>/dev/null`\n    const parsed  = JSON.parse(res.stdout)\n    const rewrite = (parsed.result || "").trim()\n    if (!parsed.changed || !rewrite || rewrite === command) return\n\n    const line = [\n      new Date().toISOString(), REWRITE_MODE,\n      isGitCommit ? "git-commit" : "pkg-mgr",\n      command.replace(/[\\t\\n\\r]/g, " "),\n      rewrite.replace(/[\\t\\n\\r]/g, " "),\n    ].join("\\t") + "\\n"\n    await $`mkdir -p "$(dirname ${AUDIT_LOG})" < /dev/null && printf %s ${line} >> ${AUDIT_LOG}`\n\n    if (REWRITE_MODE === "apply" || isGitCommit) {\n      output.args.command = rewrite\n    }\n  },\n})\n
\n

Design notes:

\n\n

5. Confirm end-to-end

\n

With the hook installed and the cache flushed, open your agent, ask it to\nrun npm install express, and inspect the audit log:

\n
tail -n 5 ~/Library/Application\\ Support/terraphim/rewrites.log\n
\n

You should see a line like:

\n
2026-04-15T11:32:51.129Z    suggest    pkg-mgr    npm install express    bun add express\n
\n

In suggest mode the command still executes as npm install express; in\napply mode the agent actually runs bun add express.

\n

6. Capturing user corrections (preview)

\n

terraphim-agent learn hook --format <claude|codex|opencode> has three\nmodes driven by --learn-hook-type:

\n\n

At present these corrections are stored but not yet fed back into the\nreplacement thesaurus. Closing that loop is tracked as future work — see\nthe accompanying GitHub issue \"Learning-driven command correction: Phase 2\n& 3\".

\n

Troubleshooting

\n

replace returns the original unchanged.\nRun terraphim-agent search \"<synonym>\" --role \"<role>\" — if the concept\nappears, the KG is loaded but the synonym is not. Confirm the synonym is on\nthe synonyms:: line (case-insensitive; commas separate entries). Flush\nthe cache (section 3) and retry.

\n

Failed to load thesaurus: NotFound(\"thesaurus_...\") in stderr.\nCosmetic. The agent looked for a pre-compiled JSON thesaurus first, didn't\nfind one, and fell back to building from markdown. Expected on first run.

\n

Hook does nothing in OpenCode.\nCheck the plugin loaded: grep terraphim-hooks ~/.local/share/opencode/log/$(ls -t ~/.local/share/opencode/log/ | head -1).\nYou should see a line like service=plugin path=...terraphim-hooks.js loading plugin. If absent, the plugin file is in the wrong directory —\nOpenCode autoloads from ~/.config/opencode/plugin/ and\n~/.config/opencode/plugins/.

\n

Commands get double-rewritten on retry.\nThe hook only touches tool.execute.before; the agent does not loop back\nthrough the hook on its own retries. If you see double rewrites, check\nwhether input.tool === \"Bash\" is spelt exactly — OpenCode passes\n\"Bash\", not \"bash\".

\n", "https://terraphim.ai/properties/date" : "2026-04-15", "https://atomicdata.dev/properties/tags" : {}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] }{"localId": "https://terraphim.ai/docs/crates/", "https://atomicdata.dev/properties/name" : "Crate Reference", "https://terraphim.ai/properties/url" : "https://terraphim.ai/docs/crates/", "https://atomicdata.dev/properties/description" : "

Crate Reference

\n

Terraphim AI is a modular Rust workspace comprising 54 crates. Each crate has a single responsibility and can be used independently or composed into larger systems. All crates are available in the terraphim-ai monorepo.

\n

Core Engine

\n

The foundational crates that power Terraphim's deterministic knowledge graph search.

\n\n\n\n\n\n\n\n\n\n\n\n\n
CrateDescription
terraphim_automataAho-Corasick automata for searching and processing knowledge graphs. The core matching engine.
terraphim_rolegraphRole-based knowledge graph module. Maps search roles to domain-specific graph views.
terraphim_typesCore types crate shared across the entire workspace.
terraphim_configConfiguration loading and management for all Terraphim components.
terraphim_settingsSettings handling library for runtime preferences and defaults.
terraphim_serviceService layer handling user requests and responses for the Terraphim core.
terraphim_middlewareMiddleware for searching haystacks (pluggable data source backends).
terraphim-markdown-parserMarkdown parser for extracting structured content from knowledge base files.
terraphim_persistencePersistence layer with Persistable trait and DeviceStorage backends (memory, SQLite, redb).
terraphim_build_argsBuild argument management for compile-time feature configuration.
terraphim_test_utilsShared test utilities and fixtures for all Terraphim crates.
\n

Binaries and CLIs

\n

User-facing executables and command-line tools.

\n\n\n\n\n\n\n
CrateDescription
terraphim_agentTerraphim AI Agent CLI with interactive REPL, session search, learning capture, and ASCII graph visualisation.
terraphim-cliCLI tool for semantic knowledge graph search with JSON output for automation and scripting.
terraphim_serverHTTP server handling the core logic of Terraphim AI. Provides REST API and knowledge graph backend.
terraphim_updateShared auto-update functionality for all Terraphim AI binaries.
terraphim_validationRelease validation system ensuring binary and asset integrity before publishing.
\n

Agent Orchestration (AI Dark Factory)

\n

OTP-inspired agent management system for running autonomous AI coding agents.

\n\n\n\n\n\n\n\n\n\n\n\n
CrateDescription
terraphim_orchestratorAI Dark Factory orchestrator wiring spawner, router, and supervisor into a reconciliation loop.
terraphim_spawnerAgent spawner with health checking, output capture, and lifecycle management.
terraphim_routerUnified routing engine for LLM and agent providers (keyword routing, tier selection).
terraphim_agent_supervisorOTP-inspired supervision trees for fault-tolerant AI agent management.
terraphim_agent_applicationOTP-style application behaviour for the Terraphim agent system.
terraphim_agent_messagingErlang-style asynchronous message passing system for AI agents.
terraphim_agent_registryKnowledge graph-based agent registry for intelligent agent discovery and capability matching.
terraphim_agent_evolutionAgent evolution and self-improvement tracking.
terraphim_workspaceWorkspace management for agent execution including lifecycle, hooks, and isolation.
terraphim_multi_agentMulti-agent system built on roles with rust-genai integration.
\n

Knowledge Graph Intelligence

\n

Advanced crates for KG-powered reasoning, task planning, and goal management.

\n\n\n\n\n\n\n\n\n\n\n\n
CrateDescription
terraphim_kg_orchestrationKnowledge graph-based agent orchestration engine for coordinating multi-agent workflows.
terraphim_kg_agentsSpecialised knowledge graph-based agent implementations.
terraphim_kg_linterLinter for markdown-based Terraphim KG schemas (commands, types, permissions).
terraphim_goal_alignmentKnowledge graph-based goal alignment system for multi-level goal management and conflict resolution.
terraphim_task_decompositionKnowledge graph-based task decomposition for intelligent task analysis and execution planning.
terraphim_rlmRecursive Language Model (RLM) orchestration for structured reasoning chains.
terraphim_hooksUnified hooks infrastructure for knowledge graph-based text replacement and validation.
terraphim_file_searchKnowledge-graph scored file search integration.
terraphim_codebase_evalCodebase evaluation system with manifest types and metrics aggregation.
terraphim_negative_contributionNegative contribution analysis for identifying anti-patterns and risks.
\n

Haystack Integrations

\n

Pluggable data source connectors for searching external systems.

\n\n\n\n\n\n\n
CrateDescription
haystack_coreCore traits and types for all Terraphim haystack integrations.
haystack_atlassianAtlassian (Confluence, Jira) integration for searching enterprise knowledge bases.
haystack_discourseDiscourse forum integration for fetching posts and messages.
haystack_grepappGrep.app integration for searching code across GitHub repositories.
haystack_jmapJMAP email protocol integration for searching email (Fastmail, etc.).
\n

Session and Usage Analytics

\n

Tools for analysing AI coding assistant sessions and tracking usage.

\n\n\n\n\n\n
CrateDescription
terraphim_sessionsSession management for AI coding assistant history. Search across Claude Code, Cursor, and Aider sessions.
terraphim-session-analyzerAnalyse AI coding assistant session logs to identify agent usage patterns.
terraphim_ccusageClaude Code usage tracking and cost analysis.
terraphim_usageGeneral usage telemetry and analytics.
\n

DevOps and Infrastructure

\n

Deployment, CI/CD, and infrastructure management.

\n\n\n\n\n\n\n\n\n\n
CrateDescription
terraphim_symphonySymphony orchestration service. Reads issues from trackers and dispatches coding agent sessions.
terraphim_trackerIssue tracker abstraction for Gitea and Linear with PageRank-based prioritisation.
terraphim_github_runnerGitHub Actions runner with Firecracker sandbox integration.
terraphim_github_runner_serverHTTP server for the GitHub Actions runner service.
terraphim-firecrackerSub-2-second VM boot optimisation system for sandboxed agent execution.
terraphim_mcp_serverModel Context Protocol (MCP) server exposing Terraphim tools to AI assistants.
terraphim_onepassword_cli1Password CLI integration for secret management.
terraphim_atomic_clientAtomic Data Server client for managing stores and agents.
\n

Chat and Assistants

\n

Multi-channel AI assistant interfaces.

\n\n\n
CrateDescription
terraphim_tinyclawMulti-channel AI assistant for Telegram, Discord, and CLI.
\n

Language Bindings

\n

Cross-language bindings for using Terraphim from Python, Node.js, and WebAssembly.

\n\n\n\n\n\n
CrateDescription
terraphim_automata_pyPython (PyO3) bindings for terraphim_automata. Fast autocomplete and text processing for knowledge graphs.
terraphim_rolegraph_pyPython bindings for terraphim_rolegraph. Knowledge graph operations for AI agents.
terraphim-automata-node-rsNode.js (NAPI) bindings for Terraphim's Aho-Corasick matcher.
terraphim-automata-wasmWebAssembly bindings for terraphim_automata. Runs in the browser.
\n

Browser Extensions

\n\n\n
CrateDescription
terrraphim-automata-wasm (extension)WASM core for the Terraphim browser extensions (Sidebar and Autocomplete).
\n
\n

Quick Install

\n
# Install the agent (interactive REPL + session search)\ncargo install terraphim-agent\n\n# Install the CLI (JSON output for automation)\ncargo install terraphim-cli\n
\n

Or use the universal installer:

\n
curl -fsSL https://raw.githubusercontent.com/terraphim/terraphim-ai/main/scripts/install.sh | bash\n
\n

Architecture

\n

The crate dependency graph follows a layered architecture:

\n
    \n
  1. Types and Config (bottom): terraphim_types, terraphim_config, terraphim_settings
  2. \n
  3. Core Engine: terraphim_automata, terraphim_rolegraph, terraphim_persistence
  4. \n
  5. Service Layer: terraphim_service, terraphim_middleware, haystack integrations
  6. \n
  7. Agent System: terraphim_spawner, terraphim_router, terraphim_agent_supervisor
  8. \n
  9. Orchestration: terraphim_orchestrator, terraphim_kg_orchestration, terraphim_symphony
  10. \n
  11. User Interfaces (top): terraphim_agent, terraphim-cli, terraphim_server, terraphim_tinyclaw
  12. \n
\n

Contributing

\n

Each crate has its own README.md with specific build instructions and examples. See the Contribution Guide for the overall workflow.

\n

Source: github.com/terraphim/terraphim-ai

\n", "https://terraphim.ai/properties/date" : "2026-04-12", "https://atomicdata.dev/properties/tags" : {}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/docs/graph-embeddings/", "https://atomicdata.dev/properties/name" : "Graph Embeddings", "https://terraphim.ai/properties/url" : "https://terraphim.ai/docs/graph-embeddings/", "https://atomicdata.dev/properties/description" : "

Graph Embeddings

\n

Terraphim uses a fundamentally different approach to semantic search compared to traditional vector embeddings. Instead of dense numerical vectors, Terraphim leverages graph structure embeddings where ranking is determined by the number of synonyms and related concepts connected to a query term in the knowledge graph.

\n

What are Graph Embeddings in Terraphim?

\n

Unlike vector embeddings that represent concepts as points in a high-dimensional semantic space, Terraphim represents concepts as nodes in a knowledge graph. Each node is a normalized term, and edges represent co-occurrence relationships between terms found in documents.

\n

The key insight is that rank is defined by the number of synonyms connected to a concept. When you search for a term, Terraphim expands your query to include all synonyms and related concepts from the knowledge graph, then traverses the graph to find documents that mention these connected concepts.

\n

Graph Structure

\n
    "raft" ----(edge)---- "consensus"\n       |                    |\n    (edge)               (edge)\n       |                    |\n    "leader" ----(edge)---- "election"\n
\n

When you search for \"consensus algorithms\", the graph traverses from the matched node to connected nodes, finding documents that mention related concepts like \"raft\", \"leader election\", and so on.

\n

How It Works

\n

The Terraphim Graph (scorer) uses unique graph embeddings with the following ranking algorithm:

\n
total_rank = node.rank + edge.rank + document_rank\n
\n

Where:

\n\n

Query Expansion

\n

When you search, Terraphim:

\n
    \n
  1. Matches your query terms against the thesaurus (normalized terms and synonyms)
  2. \n
  3. Expands the query to include all connected synonyms and related concepts
  4. \n
  5. Traverses the graph to find documents containing these terms
  6. \n
  7. Ranks documents by aggregating scores from multiple graph paths
  8. \n
  9. Returns results with explainable match reasons
  10. \n
\n

Technical Details

\n

Core Implementation

\n

The graph embedding system is implemented in crates/terraphim_rolegraph/src/lib.rs:

\n\n

Symbolic Embeddings

\n

For domain-specific embeddings (e.g., medical), the SymbolicEmbeddingIndex in crates/terraphim_rolegraph/src/medical.rs builds embeddings from IS-A hierarchies, allowing for hierarchical concept relationships.

\n

Configuration

\n

The system is configured via config/atomic_graph_embeddings_config.json:

\n
{\n  "roles": {\n    "Atomic Graph Embeddings": {\n      "relevance_function": "terraphim-graph"\n    }\n  }\n}\n
\n

The terraphim-graph relevance function enables graph-based ranking.

\n

Use Cases

\n

Semantic Search with Relationship Awareness

\n

Graph embeddings excel when content relationships matter more than simple keyword matching:

\n\n

Example: Learning Assistant

\n

With a learning knowledge graph:

\n\n

Comparison with Vector Embeddings

\n

Why Graph Embeddings?

\n\n\n\n\n\n\n
FeatureVector EmbeddingsGraph Embeddings
RepresentationDense vectorsGraph structure
ExplainabilityBlack boxFull traceability
Queries expandImplicit via distanceExplicit via synonyms
Relationship captureLearns patternsEncodes relationships
Domain adaptationRequires retrainingAdd to thesaurus
\n

The Transparency Advantage

\n

Unlike vector embeddings where you don't know WHY a document matched, Terraphim's graph embeddings show:

\n
    \n
  1. Which terms matched: The exact thesaurus entries that triggered
  2. \n
  3. Graph paths: The path from query term through the graph to the document
  4. \n
  5. Ranking breakdown: How node.rank + edge.rank + document_rank was computed
  6. \n
\n

This makes results fully auditable and debuggable.

\n

Example Usage

\n

CLI Search

\n
# Search with the Engineer role\nterraphim-agent search "graph embeddings" --role engineer\n
\n

This returns results for:

\n\n

Programmatic Usage

\n
use terraphim_rolegraph::RoleGraph;\nuse terraphim_types::{Thesaurus, RoleName};\n\n// Create rolegraph with domain knowledge\nlet thesaurus = build_domain_thesaurus();\nlet role_name = RoleName::new("Engineer");\nlet mut graph = RoleGraph::new(role_name, thesaurus).await?;\n\n// Index documents\nfor doc in documents {\n    graph.insert_document(&doc.id, doc);\n}\n\n// Query - automatically expands to synonyms\nlet results = graph.query_graph("distributed systems", None, Some(10))?;\n
\n

Configuration

\n

Enable graph embeddings in your config:

\n
{\n  "roles": {\n    "Your Role": {\n      "relevance_function": "terraphim-graph",\n      "kg": {\n        "knowledge_graph_local": {\n          "path": "./docs/your-domain"\n        }\n      }\n    }\n  }\n}\n
\n

Next Steps

\n\n", "https://terraphim.ai/properties/date" : "2026-04-04", "https://atomicdata.dev/properties/tags" : {}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/docs/installation/", "https://atomicdata.dev/properties/name" : "Installation", "https://terraphim.ai/properties/url" : "https://terraphim.ai/docs/installation/", "https://atomicdata.dev/properties/description" : "

Installation

\n

Choose the installation method that best suits your needs and platform.

\n

Quick Install (Recommended)

\n

The universal installer automatically detects your platform and installs the appropriate version.

\n
curl -fsSL https://raw.githubusercontent.com/terraphim/terraphim-ai/main/scripts/install.sh | bash\n
\n

Package Managers

\n

Homebrew (macOS/Linux)

\n
brew tap terraphim/terraphim && brew install terraphim-ai\n
\n

This installs terraphim-agent, terraphim-cli, and terraphim_server.

\n

Cargo (Rust)

\n

Install using Cargo, Rust's package manager.

\n
# Install agent with interactive TUI\ncargo install terraphim-agent\n\n# Install CLI for automation\ncargo install terraphim-cli\n
\n

Debian/Ubuntu

\n

Download the .deb package from the latest release:

\n
curl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent_1.16.32-1_amd64.deb\nsudo dpkg -i terraphim-agent_1.16.32-1_amd64.deb\n
\n

Platform-Specific Guides

\n

Linux

\n

Binary Download

\n

Download the latest release from GitHub:

\n
# x86_64 (GNU)\ncurl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent-1.16.32-x86_64-unknown-linux-gnu.tar.gz\ntar -xzf terraphim-agent-1.16.32-x86_64-unknown-linux-gnu.tar.gz\nsudo mv terraphim-agent terraphim-cli terraphim_server /usr/local/bin/\n\n# x86_64 (MUSL / static)\ncurl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent-1.16.32-x86_64-unknown-linux-musl.tar.gz\n\n# ARM64 (MUSL)\ncurl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent-1.16.32-aarch64-unknown-linux-musl.tar.gz\n\n# ARMv7 (MUSL)\ncurl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent-1.16.32-armv7-unknown-linux-musleabihf.tar.gz\n
\n

Build from Source

\n
# Clone the repository\ngit clone https://github.com/terraphim/terraphim-ai.git\ncd terraphim-ai\n\n# Build all binaries\ncargo build --release\n\n# Install\nsudo cp target/release/terraphim_server /usr/local/bin/\nsudo cp target/release/terraphim-agent /usr/local/bin/\nsudo cp target/release/terraphim-cli /usr/local/bin/\n
\n

macOS

\n

Binary Download

\n
# Apple Silicon (ARM64)\ncurl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent-1.16.32-aarch64-apple-darwin.tar.gz\ntar -xzf terraphim-agent-1.16.32-aarch64-apple-darwin.tar.gz\nsudo mv terraphim-agent terraphim-cli terraphim_server /usr/local/bin/\n\n# Intel (x86_64)\ncurl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent-1.16.32-x86_64-apple-darwin.tar.gz\n\n# Universal (Fat binary)\ncurl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent-1.16.32-universal-apple-darwin.tar.gz\n
\n

Build from Source

\n

Requires Xcode command line tools.

\n
git clone https://github.com/terraphim/terraphim-ai.git\ncd terraphim-ai\ncargo build --release\nsudo cp target/release/terraphim_server /usr/local/bin/\nsudo cp target/release/terraphim-agent /usr/local/bin/\nsudo cp target/release/terraphim-cli /usr/local/bin/\n
\n

Windows

\n

Binary Download

\n
# Download and extract\ncurl -LO https://github.com/terraphim/terraphim-ai/releases/latest/download/terraphim-agent-1.16.32-x86_64-pc-windows-msvc.zip\n
\n

Extract the zip and add the directory to your PATH.

\n\n

Build from Source

\n

Requires Rust for Windows.

\n
git clone https://github.com/terraphim/terraphim-ai.git\ncd terraphim-ai\ncargo build --release\n# Binaries will be in target\\release\\\n
\n

Library Bindings

\n

npm (Node.js / Bun)

\n

The @terraphim/autocomplete package provides NAPI bindings for autocomplete and knowledge graph functions.

\n
npm install @terraphim/autocomplete\n
\n

Python (PyPI)

\n

The terraphim-automata package provides PyO3 bindings for text matching and autocomplete.

\n
pip install terraphim-automata\n
\n

Browser Extensions

\n

Two browser extensions are available for developer-mode installation:

\n\n

Install from source:

\n
git clone https://github.com/terraphim/terraphim-ai.git\ncd terraphim-ai/browser_extensions\n
\n

Then load unpacked in Chrome at chrome://extensions (enable Developer Mode). Coming to the Chrome Web Store soon.

\n

See browser_extensions/INSTALL.md for detailed instructions.

\n

Verification

\n

After installation, verify that Terraphim is working:

\n
# Check version\nterraphim-agent --version\n# terraphim-agent 1.16.32\n\nterraphim-cli --version\n# terraphim-cli 1.16.32\n\n# Start the server\nterraphim_server\n\n# In another terminal, use the agent\nterraphim-agent\n
\n

Troubleshooting

\n

Permission Denied

\n

If you get a permission denied error, make the binary executable:

\n
chmod +x /usr/local/bin/terraphim_server\nchmod +x /usr/local/bin/terraphim-agent\nchmod +x /usr/local/bin/terraphim-cli\n
\n

Command Not Found

\n

Ensure that the installation directory is in your PATH:

\n
# For bash\necho 'export PATH=$PATH:/usr/local/bin' >> ~/.bashrc\nsource ~/.bashrc\n\n# For zsh\necho 'export PATH=$PATH:/usr/local/bin' >> ~/.zshrc\nsource ~/.zshrc\n
\n

Rust Version Issues

\n

Ensure that you have a recent Rust version:

\n
rustc --version  # Should be 1.75.0 or later\nrustup update stable\n
\n

Next Steps

\n\n", "https://terraphim.ai/properties/date" : "2026-01-27", "https://atomicdata.dev/properties/tags" : {}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/docs/quickstart/", "https://atomicdata.dev/properties/name" : "Quickstart", "https://terraphim.ai/properties/url" : "https://terraphim.ai/docs/quickstart/", "https://atomicdata.dev/properties/description" : "

Quickstart Guide

\n

Get up and running with Terraphim AI in just 5 minutes.

\n

Step 1: Install Terraphim

\n

Choose your preferred installation method:

\n

Option A: Universal Installer (Recommended)

\n
# Single command installation with platform detection\ncurl -fsSL https://raw.githubusercontent.com/terraphim/terraphim-ai/main/scripts/install.sh | bash\n
\n

Option B: Homebrew (macOS/Linux)

\n
brew tap terraphim/terraphim && brew install terraphim-ai\n
\n

Option C: Cargo

\n
# Install agent with interactive TUI\ncargo install terraphim-agent\n\n# Install CLI for automation\ncargo install terraphim-cli\n
\n

Need more options?

\n

Step 2: Start Server

\n

Terraphim server provides HTTP API and knowledge graph backend.

\n
terraphim_server\n
\n

By default, server runs on http://localhost:8080.

\n

You should see output like:

\n
[INFO] Terraphim Server v1.16.32 starting...\n[INFO] Server listening on http://localhost:8080\n[INFO] Knowledge graph initialized\n
\n

Step 3: Use the Agent

\n

In a new terminal, start the interactive agent:

\n
terraphim-agent\n
\n

You'll see a welcome message and can start typing commands:

\n
Terraphim AI Agent v1.16.32\nType 'help' for available commands\n\n> search rust async\nFound 12 results for 'rust async'\n\n> roles select engineer\nRole set to: Engineer (optimising for technical depth)\n\n> search patterns\nFound 8 results for 'patterns'\n
\n

Common Agent Commands

\n

Here are the most useful commands to get started:

\n
> search <query>              # Search knowledge graph\n> roles select <name>         # Set search role (engineer, architect, etc.)\n> connect <term1> <term2>     # Link two terms in knowledge graph\n> import <file>               # Import markdown file into knowledge graph\n> export <format>             # Export knowledge graph (json, csv)\n> status                      # Show server status and statistics\n> help                        # Show all available commands\n
\n

Step 4: Import Your Content

\n

Import your markdown files or documentation:

\n
# Import a single file\nimport ~/notes/project-a.md\n\n# Import entire directory\nimport ~/Documents/knowledge-base/\n
\n

Step 5: Configure Data Sources

\n

Configure Terraphim to search different sources:

\n
# Search GitHub repositories\nsource add github https://github.com/terraphim/terraphim-ai\n\n# Search StackOverflow\nsource add stackoverflow rust tokio\n\n# Search local filesystem\nsource add filesystem ~/code/ --recursive\n
\n

Step 6: Explore Features

\n

Semantic Search

\n
> search how to implement async channels in rust\n
\n

Role-Based Filtering

\n
> roles select architect\n> search system design patterns\n
\n

Knowledge Graph Exploration

\n
> connect tokio async\n> show tokio\n
\n

CLI Automation

\n

For automation and scripting, use the CLI instead of REPL:

\n
# Search and get JSON output\nterraphim-cli search "async patterns" --format json\n\n# Import files programmatically\nterraphim-cli import ~/notes/*.md --recursive\n\n# Set role and search\nterraphim-cli search "rust error handling" --role engineer\n
\n

Example Workflow

\n

Here's a complete example workflow:

\n
# 1. Start the server (in one terminal)\nterraphim_server &\n\n# 2. Import your codebase (in another terminal)\nterraphim-agent\n> import ~/my-project/src/\n\n# 3. Search for information\n> search error handling patterns\n\n# 4. Set role for better results\n> roles select senior-engineer\n\n# 5. Search again with role context\n> search error handling patterns\n\n# 6. Export results\n> export json > search-results.json\n
\n

Next Steps

\n\n

Getting Help

\n

If you run into issues:

\n
    \n
  1. Search existing GitHub issues
  2. \n
  3. Create a new issue
  4. \n
  5. Join Discord community for support
  6. \n
  7. Visit Discourse forum for discussions
  8. \n
  9. Contact us at alex@terraphim.ai
  10. \n
\n", "https://terraphim.ai/properties/date" : "2026-01-27", "https://atomicdata.dev/properties/tags" : {}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/docs/terraphim-config/", "https://atomicdata.dev/properties/name" : "Terraphim Config structure", "https://terraphim.ai/properties/url" : "https://terraphim.ai/docs/terraphim-config/", "https://atomicdata.dev/properties/description" : "

Terraphim config structure

\n

Most of the functionality is driven from the config file.

\n

[global]

\n

section for global parameters - like global shortcuts

\n

Roles

\n
[[roles]]\n
\n

For example I can be engineer, architect, father or gamer. In each of those roles I will have a different concens which are driving different relevance/scoring and UX requirements.

\n

Roles are the separate abstract layers and define behaviour of the search for particular role. It's roughly following roles definition from ISO 42010 and other systems engineering materials and at different point in time one can wear diferent heat (different role).

\n

Each role have a

\n\n

The powers roughly follows:

\n\n

Terraphim powers - skills

\n
[[Skill]]\n
\n

Parameters:

\n\n

Haystack is a source, can be PubMed, Github, Coda.io, Notion.so etc.\nHaystack arguments

\n", "https://terraphim.ai/properties/date" : "2022-02-21", "https://atomicdata.dev/properties/tags" : {"categories":["Documentation"],"tags":["terraphim","config","plugins"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/docs/contribution/", "https://atomicdata.dev/properties/name" : "Contribution Guidelines", "https://terraphim.ai/properties/url" : "https://terraphim.ai/docs/contribution/", "https://atomicdata.dev/properties/description" : "

General guidelines for contributing to the project.

\n

Main goals

\n

Be data driven

\n\n

Engineering approach

\n

Even for conceptual topics such as ethics or enterprise architecture, there should be path to be implemented in real would: student's head or software working in production considered to be real world.

\n", "https://terraphim.ai/properties/date" : "2021-12-15", "https://atomicdata.dev/properties/tags" : {"categories":["Documentation"],"tags":["contribute","zola"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/docs/donate/", "https://atomicdata.dev/properties/name" : "Support project by contributing", "https://terraphim.ai/properties/url" : "https://terraphim.ai/docs/donate/", "https://atomicdata.dev/properties/description" : "

This is the beginning of an exciting great new journey: support open-source projects by donating or contributing.

\n

Terraphim AI is partially supported by Innovate UK via the Eureka funding program up to 60% of costs, under grant 600594, \"ATOMIC\", jointly with our collaborators Ontola - the team behind Atomic Data Server and Protocol.\nBut for the rest of the costs, we need your help.

\n

Introducing a Donation-driven roadmap

\n

After several months of agonising over which license to release Terraphim AI under, I created a new repository with the two most liberal licenses open source MIT and APACHE2.\nWe may build a commercial service on top of Terraphim Core(Cortex), but the core and our promise that it is open-sourced to allow you all to build on top of Terraphim AI, with a privacy-first, building AI tooling right way around: you don't need to move your data. You codify and move your knowledge where it needs to be and helps you to get things done the most.

\n

Donation-driven roadmap

\n

To support the project's development, we introduce a \"donation-driven roadmap\": if you want a feature, vote for it not only with your thumb but with your money.\nIn exchange:

\n\n

Sponsor the features on our GitHub page or propose a new idea in GitHub discussions

\n", "https://terraphim.ai/properties/date" : "2020-08-31", "https://atomicdata.dev/properties/tags" : {"categories":["donations","open-source"],"tags":["donate","support"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/sentrux-vs-terraphim-eval-comparison/", "https://atomicdata.dev/properties/name" : "Sentrux vs Terraphim: Two Approaches to AI Code Quality Evaluation", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/sentrux-vs-terraphim-eval-comparison/", "https://atomicdata.dev/properties/description" : "

As AI agents write more and more production code, the question shifts from \"can the agent write code?\" to \"can we verify the code is good?\" Two tools tackle this from opposite ends: Sentrux measures structural health, Terraphim measures semantic completeness. Neither is complete without the other.

\n

The Problem They Both Solve

\n

An AI agent that generates 500 lines of syntactically correct Rust can still degrade a codebase. It might introduce tight coupling, leave behind unimplemented stubs, create circular dependencies, or raise the cyclomatic complexity past any reasonable threshold. Standard CI pipelines catch compilation errors and failing tests. They do not catch architectural erosion.

\n

Both Sentrux and the Terraphim evaluation toolkit are designed to close that gap. They just do so from fundamentally different perspectives.

\n
\n

Sentrux: Structural Analysis

\n

Sentrux (v0.5.7, MIT, 27.7k lines of Rust) is a real-time structural analysis engine. It parses source code into an AST using tree-sitter, builds a dependency graph, and computes a quality signal from 0 to 10,000.

\n

Five Root Cause Metrics

\n

Sentrux computes a geometric mean across five orthogonal dimensions:

\n\n\n\n\n\n\n
MetricWhat it captures
ModularityFan-in and fan-out between modules; god file detection
AcyclicityCircular dependency count and which files participate
DepthMaximum dependency chain length; instability score
EqualityCyclomatic complexity distribution (Gini coefficient); large files
RedundancyDead functions; duplicate code groups
\n

These are structural facts derived from the AST and dependency graph, not text patterns. Sentrux does not care what the code says; it cares how it connects.

\n

How It Works with Agents

\n

Sentrux ships a native MCP server with nine tools. The intended agent workflow is:

\n
sentrux.scan("/path/to/project")\n  -> { quality_signal: 7342, files: 139, bottleneck: "modularity" }\n\nsentrux.session_start()\n  -> baseline saved\n\n... agent writes code ...\n\nsentrux.session_end()\n  -> { pass: false, signal_before: 7342, signal_after: 6891,\n       summary: "Quality degraded during this session" }\n
\n

The agent gets a precise numeric verdict with a named bottleneck. It can iterate: check the bottleneck, fix it, call rescan, repeat.

\n

The GUI

\n

Sentrux includes a live treemap built with egui and wgpu. Files are sized by metric contribution and glow when modified. Dependency edges are drawn between coupled files. A file system watcher (notify) feeds changes over crossbeam-channel to the renderer in real time. The same process that runs the GUI hosts the MCP server, so you can watch architectural changes happen as the agent works.

\n

Language Support

\n

52 languages via tree-sitter plugins. Each plugin is a plugin.toml and a tags.scm query file. No Rust required to add a language.

\n
\n

Terraphim Evaluation Toolkit: Semantic Completeness

\n

The Terraphim approach lives across two production crates in terraphim-ai: terraphim_codebase_eval and terraphim_negative_contribution. These are not a conceptual framework or a shell script wrapper; they are typed Rust libraries integrated into the agent review pipeline.

\n

The Manifest System (terraphim_codebase_eval)

\n

The evaluation manifest is a TOML file that describes a before/after comparison at the git SHA level:

\n
[[haystacks]]\nid = "baseline"\npath = "/srv/repo"\ncommit_sha = "abc123"\nstate = "baseline"\n\n[[haystacks]]\nid = "candidate"\npath = "/srv/repo"\ncommit_sha = "def456"\nstate = "candidate"\n\n[[roles]]\nrole_id = "code-reviewer"\ndescription = "Reviews for bugs and maintainability"\nterm_sets = ["bug-patterns", "code-smells"]\n\n[roles.scoring_weights]\nsearch_score = 1.0\ngraph_density = 0.8\nentity_count = 1.0\n\n[[queries]]\nquery_text = "highlight potential bugs"\nrole_id = "code-reviewer"\nexpected_signal = "increase"\nconfidence_threshold = 0.6\n\n[thresholds]\nimproved_pct = 10.0\ndegraded_pct = 5.0\ncritical_test_failures = 0\n
\n

Roles define the evaluation perspective. Each role carries named term sets (Aho-Corasick dictionaries built from domain knowledge graphs) and per-dimension scoring weights. Queries specify what to search for and in which direction the score should move. The manifest is validated for referential integrity before execution: any query that references a non-existent role is rejected at load time, not at runtime.

\n

The verdict logic is explicit: if the weighted score increases by more than improved_pct, the contribution is classified as Improved; if it drops by more than degraded_pct, it is Degraded; any new test failure triggers immediate Degraded regardless of scores.

\n

The EDM Scanner (terraphim_negative_contribution)

\n

The Explicit Deferral Marker (EDM) scanner answers a specific and critical question: did the agent ship stubs as production code?

\n

It uses the Aho-Corasick automata to detect markers in Rust source that indicate deferred implementation:

\n\n

The scanner is production-only by design. It automatically skips:

\n\n

Suppression is available per-line: // terraphim: allow(stub) silences the finding on that line only. Every finding carries a file path, line number, severity, category, confidence (0.95), and a suggestion drawn from the thesaurus URL metadata.

\n

The scanner outputs a ReviewAgentOutput struct consumed directly by the Terraphim review pipeline. An agent that ships one todo!() in production code fails the gate.

\n
\n

Side-by-Side Comparison

\n\n\n\n\n\n\n\n\n\n\n
DimensionSentruxTerraphim EDM ScannerTerraphim Manifest Eval
Core mechanismtree-sitter AST + dependency graphAho-Corasick on EDM pattern thesaurusAho-Corasick on domain KG + weighted scoring
What it measuresArchitecture: coupling, cycles, complexityIncomplete implementations in production codeSemantic quality delta between two git SHAs
Language scope52 languagesRust only (production files)Any language with KG term sets
Unit of comparisonQuality signal delta within a sessionPass/fail per fileBefore/after manifest with role-weighted scores
Agent integrationMCP server (9 tools, session lifecycle)ReviewAgentOutput struct in review pipelineEvaluationManifest loaded per evaluation run
False positive riskLow (graph-structural, not text)Very low (exact stub patterns, test exclusions)Medium (depends on KG quality)
Customisationrules.toml (layer boundaries, thresholds)// terraphim: allow(stub) suppressionKG term sets, role weights, query direction
Live feedbackYes (file watcher, treemap, MCP)No (batch scan)No (batch manifest)
Verdict granularityNamed bottleneck + per-metric breakdownFinding list with file:line and suggestionImproved / Degraded / Neutral with percentage
\n
\n

Where They Complement Each Other

\n

These tools are not alternatives. They operate at different layers of the quality stack:

\n

Sentrux answers: Is the architecture getting worse?

\n

Terraphim EDM Scanner answers: Did the agent leave stubs in production code?

\n

Terraphim Manifest Eval answers: Did the agent improve or degrade domain-specific semantic quality across these two commits?

\n

A complete agent quality gate combines all three:

\n
    \n
  1. sentrux session_start before the agent begins work
  2. \n
  3. Agent writes code
  4. \n
  5. sentrux session_end to verify no structural degradation
  6. \n
  7. Terraphim EDM scan to verify no stubs shipped to production
  8. \n
  9. Terraphim manifest eval (optional, for domain-specific semantic coverage) comparing the baseline and candidate SHAs
  10. \n
\n

If any gate fails, the contribution is blocked. The agent gets specific, actionable feedback: a named structural bottleneck from Sentrux, a file and line number from the EDM scanner, or a percentage degradation from the manifest evaluator.

\n
\n

Choosing Your Starting Point

\n

If you are instrumenting an AI agent pipeline today, start with the Terraphim EDM scanner. It requires no configuration beyond pointing it at your Rust source. It has a binary pass/fail verdict, zero false positives on well-written production code, and integrates directly into the existing ReviewAgentOutput pipeline.

\n

Add Sentrux when you want continuous architectural visibility. The MCP integration means the agent can self-correct in real time rather than discovering structural problems only at gate check.

\n

Add the Terraphim manifest evaluation when you have a domain knowledge graph and want to verify that the agent's changes improve semantic coverage in your specific domain, not just compile and pass tests.

\n

Together, they give you three independent quality signals that a capable agent must satisfy simultaneously: structural soundness, implementation completeness, and semantic improvement.

\n
\n

Further Reading

\n\n", "https://terraphim.ai/properties/date" : "2026-04-29", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","code-quality","AI-agents","evaluation","comparison","sentrux"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/sub-millisecond-context-knowledge-graphs/", "https://atomicdata.dev/properties/name" : "Sub-Millisecond Context: How Aho-Corasick Automata Replace Embedding Calls", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/sub-millisecond-context-knowledge-graphs/", "https://atomicdata.dev/properties/description" : "

Vector embedding calls are the hidden tax on every RAG pipeline. You pay latency, you pay API cost, you get probabilistic results that vary run to run. There is a class of problem where none of that is acceptable. This post shows how Terraphim replaces embedding calls with Aho-Corasick finite-state automata -- deterministic, auditable, and under one millisecond for 1.4 million patterns.

\n

The Problem with Embedding-Based Context

\n

When you call an embedding API to retrieve context for an LLM prompt, three things happen:

\n
    \n
  1. You pay latency. Even fast embedding models add 20-100ms per call. At scale, this compounds.
  2. \n
  3. You get probabilistic results. Two runs on the same input may return different top-k documents depending on float precision and index state.
  4. \n
  5. You lose auditability. A cosine similarity score tells you nothing about why a document was retrieved.
  6. \n
\n

For general-purpose assistants, these tradeoffs are acceptable. For domain-specific systems -- medical, legal, engineering -- they are not. A system that cannot explain its retrieval decisions cannot be trusted.

\n

The Aho-Corasick Alternative

\n

Aho-Corasick is a classical multi-pattern string matching algorithm. Given a dictionary of N patterns, it builds a finite-state automaton at construction time and then scans any input text in O(n) time regardless of how many patterns are in the dictionary.

\n

Terraphim builds knowledge graph automata on top of this: each node in the automaton is a domain concept, edges encode synonyms and related terms, and matching returns not just a span but a structured entity with graph position.

\n
Input text: "patient presents with BRAF V600E mutation"\n                                    |\n                            Aho-Corasick scan\n                                    |\n         Match: "BRAF V600E" -> node: Gene:BRAF, variant: V600E\n                                    |\n                            Graph traversal\n                                    |\n         Edges: BRAF -> Treats <- Vemurafenib\n                BRAF -> TestedBy <- Cobas 4800 assay\n                BRAF -> Contraindicated <- Sorafenib (paradoxical activation)\n
\n

The match is deterministic. The traversal is deterministic. The context injected into the prompt is always the same for the same input.

\n

Architecture

\n
┌─────────────────────────────────────────────────────┐\n│                   Input Text                        │\n└───────────────────────┬─────────────────────────────┘\n                        │\n              ┌─────────▼──────────┐\n              │  Aho-Corasick FSM  │  < 1ms for 1.4M patterns\n              │  (terraphim_automata│\n              └─────────┬──────────┘\n                        │ matched spans + normalized terms\n              ┌─────────▼──────────┐\n              │   Thesaurus Layer  │  synonym expansion,\n              │  (terraphim_types) │  canonical form resolution\n              └─────────┬──────────┘\n                        │ NormalizedTerm { url, rank, ... }\n              ┌─────────▼──────────┐\n              │   Role Graph       │  27 node types, 65 edge types\n              │  (terraphim_       │  Jaccard + path distance scoring\n              │   rolegraph)       │\n              └─────────┬──────────┘\n                        │ ranked context passages\n              ┌─────────▼──────────┐\n              │   Prompt Builder   │  inject into LLM prompt\n              └────────────────────┘\n
\n

Each stage is a Rust crate with a stable public API. You can use any layer independently.

\n

Getting Started

\n

Install

\n
cargo add terraphim_automata terraphim_types terraphim_rolegraph\n
\n

For Python (via PyO3 bindings):

\n
pip install terraphim-automata\n
\n

For JavaScript/TypeScript (via WASM):

\n
npm install @terraphim/automata\n
\n

Build an Automaton from a Thesaurus

\n

The thesaurus is a JSON file mapping term strings to NormalizedTerm records. Terraphim ships pre-built thesauri for SNOMED CT, UMLS, and software engineering domains. You can also build your own from markdown knowledge graph files.

\n
use terraphim_automata::{load_thesaurus_from_json, find_matches};\n\nlet thesaurus_json = std::fs::read_to_string("snomed-tier1.json")?;\nlet thesaurus = load_thesaurus_from_json(&thesaurus_json)?;\n\nlet text = "Patient presents with BRAF V600E mutation and melanoma stage IV.";\nlet matches = find_matches(text, thesaurus, true)?; // true = leftmost-longest\n\nfor m in &matches {\n    println!("{:?} at {:?}", m.term, m.pos);\n}\n
\n

find_matches is O(n) in the input length. On an M2 MacBook Pro, matching 1.4 million SNOMED patterns against a 500-word clinical note completes in 0.3ms.

\n

Add Knowledge Graph Traversal

\n

Once you have matched entities, traverse the role graph to collect supporting context:

\n
use terraphim_rolegraph::RoleGraph;\n\nlet graph = RoleGraph::from_kg_path("~/.config/terraphim/kg/medical/")?;\n\nfor m in &matches {\n    let context = graph.traverse(&m.normalized_term, depth: 2)?;\n    // context contains related concepts, evidence paths, ranked passages\n}\n
\n

The traversal depth controls how far to expand from each matched entity. Depth 1 gives direct neighbours (synonyms, treatments, contraindications). Depth 2 adds second-degree connections (clinical trials, guidelines, variants).

\n

Measured Impact: MedGemma with and without KG Context

\n

We ran identical clinical cases through Google's MedGemma model with and without Terraphim knowledge graph grounding:

\n\n\n\n\n
CaseRaw MedGemma (no KG)With Terraphim KG Grounding
BRAF V600E Melanoma\"BRAF inhibitor (e.g., Dabrafenib + Trametinib)\" -- vague class suggestionVemurafenib 450mg orally once daily -- specific drug and dose
CYP2D6 Codeine SensitivityOxycodone 5 mg/mL -- wrong drug entirelyCodeine 60mg every 6h -- correct drug from KG context
EGFR NSCLCOsimertinib 80mg (correct on this run; prior run hallucinated 800mg -- a 10x overdose)Osimertinib 80mg -- consistently correct per FLAURA trial
\n

Without graph grounding, the LLM gives vague class-level suggestions, recommends the wrong drug, or produces dosing errors that vary between runs. With Terraphim KG grounding, every recommendation is specific, correct, and reproducible.

\n

Evaluation results across 36 real inference runs

\n\n\n\n\n
RunPass RateSafety GateKG GroundingAvg Latency
CPU18/18 (100%)100%83.3%165.3s
GPU #118/18 (100%)100%77.8%23.5s
GPU #218/18 (100%)100%83.3%24.8s
\n

36 total inference calls. Zero safety failures. No mocked responses.

\n

The LLM latency dominates (23-165 seconds depending on hardware). The Terraphim matching and graph traversal contributes under 1ms to each call.

\n

Why This Matters Beyond Medical

\n

The medical case is the hardest version of the problem: the stakes are high, the domain is large (1.4M SNOMED terms), and incorrect context causes real harm. The same architecture applies anywhere you need deterministic, auditable retrieval:

\n\n

System Footprint

\n

The full stack -- MedGemma 4B + SNOMED automata + role graph -- runs on a single machine in under 4GB RAM. There is no vector database daemon to operate, no embedding API to call, and no GPU required for the retrieval layer.

\n
terraphim_automata (Aho-Corasick FSM, 1.4M patterns): ~800MB RAM\nMedGemma 4B (quantised):                             ~2.8GB RAM\nRole graph (27 node types, 65 edge types):            ~120MB RAM\nTotal:                                                ~3.7GB\n
\n

Compare this to a typical embedding-based RAG stack: embedding model (~500MB) + vector database process (~1-2GB) + embedding API latency per call.

\n

Key Numbers

\n\n

Further Reading

\n\n

The theory behind automata-based context injection, when to use it versus embeddings, and how to compose it with LLM routing is the subject of Chapters 5-7 of Context Engineering with Knowledge Graphs (launching 2026).

\n

Source: github.com/terraphim/terraphim-ai -- 42 Rust crates, WASM-ready, MCP-native, Apache 2.0.

\n", "https://terraphim.ai/properties/date" : "2026-04-29", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","knowledge-graph","Aho-Corasick","FST","context-engineering","tutorial"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/frontend-developer-agent-walkthrough/", "https://atomicdata.dev/properties/name" : "Building a Front-End Developer Agent with Knowledge Graphs and Code Search", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/frontend-developer-agent-walkthrough/", "https://atomicdata.dev/properties/description" : "

We have published a comprehensive walkthrough showing how to build a specialised front-end developer agent using Terraphim's knowledge graph system, dual haystacks, and deterministic search. This post walks through the key concepts and links to the full guide.

\n

Why a Front-End Developer Agent?

\n

Front-end development spans a vast surface area: CSS layout, accessibility, TypeScript types, Svelte reactivity, build tooling, performance, testing, and more. When you search for \"how do I make this accessible?\" or \"what's the SvelteKit pattern for form validation?\", you want answers that understand your domain -- not generic web search results.

\n

Terraphim's deterministic knowledge graph approach means every search result is grounded in concepts you define, ranked by relevance, and fully reproducible. No hallucination, no non-deterministic LLM output.

\n

What the Agent Does

\n

The front-end developer agent combines three capabilities:

\n
    \n
  1. \n

    Knowledge Graph: 18 concept files covering responsive design, accessibility, Svelte/SvelteKit patterns, TypeScript, CSS layout, state management, build tools, testing, performance, and more. Each concept has synonyms that resolve deterministically via Aho-Corasick matching.

    \n
  2. \n
  3. \n

    Local Search (Ripgrep): Searches your project files -- .svelte, .ts, .css, .md -- using the knowledge graph to boost conceptually relevant files.

    \n
  4. \n
  5. \n

    Global Code Search (GrepApp): Searches millions of public GitHub repositories for TypeScript code patterns via the grep.app API, filtered to TypeScript for modern front-end relevance.

    \n
  6. \n
\n

Results from both haystacks are merged and ranked using TerraphimGraph, a hybrid scoring algorithm that combines knowledge graph concept matching with TF-IDF rescoring. In testing, a query for \"svelte component\" returned 13 results with TerraphimGraph versus 1 result with the simpler BM25Plus scorer. The 18 concept files with 358 synonyms actively influence ranking, not just display.

\n

The Knowledge Graph

\n

Each concept is a Markdown file with a heading, description, and synonym list:

\n
# Svelte Patterns\n\nSvelte-specific patterns for building reactive, compiled frontend\napplications using runes, stores, and SvelteKit conventions.\n\nsynonyms:: Svelte, SvelteKit, rune, $state, $derived, $effect,\n$props, bind, each block, await block, load function, +page.svelte\n
\n

When you search for $derived or +page.svelte, the Aho-Corasick automaton matches it to the \"Svelte Patterns\" concept in O(n+m) time. The matching is case-insensitive and leftmost-longest, so \"CSS grid\" matches as one term rather than two separate words.

\n

If no exact match exists, a TF-IDF fallback kicks in using trigger:: directives for semantic similarity.

\n

Hybrid Scoring: Why TerraphimGraph

\n

Terraphim offers multiple relevance functions. For a knowledge-graph-backed agent, terraphim-graph is strictly superior to the simpler bm25plus:

\n\n\n\n\n\n
AspectBM25PlusTerraphimGraph
KG concepts affect rankingNo (display only)Yes (graph + TF-IDF hybrid)
Term co-occurrenceNot usedBoosts related documents
KG link insertionDisabledEnabled in results
TF-IDF rescoringNot applied30% weight boost
\n

TerraphimGraph uses a two-pass scoring system. Pass 1 builds a co-occurrence graph from Aho-Corasick matches and ranks documents by total_rank = node_rank + edge_rank + document_rank. Pass 2 applies TF-IDF rescoring at 30% weight. Documents containing co-occurring concepts (e.g., \"svelte\" + \"component\" + \"state management\") score higher than those matching only one term.

\n

Svelte and SvelteKit Focus

\n

The knowledge graph is tuned for Svelte/SvelteKit development with TypeScript:

\n\n

The GrepApp haystack is filtered to language: \"typescript\" rather than JavaScript, reflecting the modern Svelte/SvelteKit ecosystem.

\n

Quick Start

\n
# Build the agent\ngit clone https://github.com/terraphim/terraphim-ai.git\ncd terraphim-ai\ncargo build --release\n# Enable GrepApp haystack support\ncargo build --release -p terraphim_middleware --features grepapp\ncargo install --path crates/terraphim_agent\n\n# Set up the front-end developer role\nterraphim-agent setup --template frontend-engineer --path ~/projects\n\n# Search across local files and GitHub\nterraphim-agent search "flexbox responsive layout"\n
\n

Architecture in Brief

\n
Query: "flexbox responsive layout"\n    |\n    v\n[Auto-route] -> Front-End Developer role\n    |\n    v\n[Aho-Corasick] -> CSS Layout + Responsive Design concepts\n    |\n    v\n[Ripgrep]       [GrepApp (TypeScript)]\n    |                |\n    v                v\n[TerraphimGraph hybrid scoring:\n  Pass 1: KG graph ranking (node + edge co-occurrence)\n  Pass 2: TF-IDF rescoring (30% weight boost)]\n              |\n              v\n      Ranked results\n
\n

MCP Integration with AI Coding Agents

\n

The terraphim_mcp_server binary exposes all knowledge graph tools via the Model Context Protocol, so any MCP-compatible AI coding agent can use your front-end developer KG during coding sessions.

\n

opencode (~/.config/opencode/opencode.json):

\n
{\n  "mcp": {\n    "terraphim": {\n      "type": "local",\n      "command": ["~/.cargo/bin/terraphim_mcp_server"],\n      "environment": { "TERRAPHIM_DATA_PATH": "~/.terraphim" }\n    }\n  }\n}\n
\n

Claude Code (~/.claude.json):

\n
{\n  "mcpServers": {\n    "terraphim": {\n      "type": "stdio",\n      "command": "~/.cargo/bin/terraphim_mcp_server",\n      "env": { "RUST_LOG": "error" }\n    }\n  }\n}\n
\n

After configuration, the AI agent gains access to 18 MCP tools: search, autocomplete_terms, replace_matches, terraphim_find_files, terraphim_grep, and more. Queries auto-route to the Front-End Developer role when front-end terms are detected.

\n

For Cursor, Windsurf, or any HTTP-based MCP client, start the SSE server: terraphim_mcp_server --sse --bind 127.0.0.1:8000.

\n

Read the Full Walkthrough

\n

The complete step-by-step guide covers:

\n\n

Read it at: docs/walkthroughs/frontend-developer-agent.md

\n

What Comes Next

\n

This walkthrough demonstrates the deterministic, KG-first approach. Natural extensions include:

\n\n

The knowledge graph pattern is universal: define concepts, add synonyms, point at haystacks, and search. No training, no fine-tuning, no API keys for the deterministic path.

\n", "https://terraphim.ai/properties/date" : "2026-04-23", "https://atomicdata.dev/properties/tags" : {"tags":["Terraphim","walkthrough","knowledge-graph","grepapp","Svelte","SvelteKit","TypeScript","agent"],"categories":["Technical"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/why-graph-embeddings-matter/", "https://atomicdata.dev/properties/name" : "Why Graph Embeddings Matter", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/why-graph-embeddings-matter/", "https://atomicdata.dev/properties/description" : "

Vector databases are probabilistic and slow. Graph embeddings are deterministic and sub-millisecond. If you are building context for an AI coding agent — or any system where you need to know why a result came back — the difference is not academic. It changes what your application is allowed to promise.

\n

The Pitch in One Paragraph

\n

Terraphim represents concepts as nodes in a knowledge graph and ranks them by how many synonyms and edges connect them. There is no embedding model, no GPU, no per-query distance computation in a 1024-dimensional space. There is an Aho-Corasick automaton built once, queried in O(n+m+z) time over the input length plus the number of matches. The mechanism is described in detail on the Graph Embeddings reference page; this post is about why it matters.

\n

The Numbers

\n

Three numbers carry the argument. Each is reproducible on a laptop.

\n\n

For comparison, a typical vector-DB nearest-neighbour query lands in the 5–50 ms range after you have paid the embedding API call (50–500 ms) and the network round-trip. We are not in the same regime.

\n

Three Consequences

\n

The numbers are interesting on their own. The reason they matter is what they let you build.

\n

1. Full Explainability

\n

Every match in Terraphim traces back to a specific edge in the knowledge graph and a specific synonym in a specific role. There is no \"the model said so.\" When a search returns a document, you can show the user exactly which terms matched, which role's graph supplied the synonym, and which edges connected them. That is not a debugging nicety — it is a regulatory requirement in any domain where you have to defend a decision after the fact. Healthcare, legal, finance, government. Vector search by construction cannot do this.

\n

2. No Training, No Retraining, No Fine-Tuning

\n

Adding a new concept is a text edit. You write the synonym down, you point Terraphim at the file, the graph rebuilds in 20 ms. There is no training run, no GPU bill, no \"we need to schedule a retrain on the new corpus.\" This collapses the loop between noticing a gap and fixing the gap from days or weeks to seconds. For an AI coding agent that needs to learn a project's vocabulary as you onboard, this is the difference between a working tool and a stalled rollout.

\n

3. Language-Agnostic Without Language Detection

\n

Because matching is done on normalised terms — synonyms you supply explicitly — the same node in the graph can carry English, French, Russian, and Mandarin labels at no extra cost. There is no language-detection step, no per-language embedding model, no separate index. The query \"consensus\" and the query \"консенсус\" both reach the same node if you have told the graph they are synonyms. Stop-word lists become irrelevant: if a word is not in the graph, it does not match, full stop.

\n

What This Lets You Do

\n

The pieces above are infrastructure. The story arc continues:

\n\n

How to Apply

\n

If you want to wire this into your own project, the Command Rewriting How-to walks through the moving parts: where to put your synonyms, how the role graph is built, how hooks call the matcher.

\n

The mechanism — automata, ranking formula, ASCII walk-through — is on the Graph Embeddings reference page. Read that next if you want the data structures.

\n

Why Bother Saying This Out Loud

\n

The current default in the AI tooling ecosystem is to reach for a vector database the moment anyone mentions \"semantic search.\" It is the path of least resistance because the tools are well-marketed and the API surface is familiar. But for a large class of problems — explainability-first systems, on-device agents, anywhere you need a hard latency budget or a hard explainability guarantee — graph embeddings are the better-engineered answer. Not the only answer; the better one for that class.

\n

The promotion campaign over the next few weeks goes deeper: a sub-millisecond context article walks through the FST/Aho-Corasick implementation, and the Context Engineering with Knowledge Graphs book (launching in May) puts it in the wider context of moving from RAG to context graphs.

\n

Until then: read the reference, try the how-to, and let us know in Discourse what you build with it.

\n", "https://terraphim.ai/properties/date" : "2026-04-22", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","graph-embeddings","knowledge-graph","aho-corasick","context-engineering"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/terraphim-search-in-claude-code-and-opencode/", "https://atomicdata.dev/properties/name" : "Plug Terraphim Search into Claude Code and opencode (CLI First, MCP When You Need It)", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/terraphim-search-in-claude-code-and-opencode/", "https://atomicdata.dev/properties/description" : "

Your AI coding agent already has a knowledge graph. It is just not yours yet. The model knows GitHub, Stack Overflow, and the public training corpus -- it has no idea that in your project npm should be bun, that RFP is shorthand for acquisition need, or that the email about the Stripe receipt for the Obsidian licence lives in your Fastmail mailbox. This post shows the smallest path to fixing that for both Claude Code and opencode, using Terraphim and the three roles we have published over the last week (Terraphim Engineer, Personal Assistant, System Operator).

\n

Two paths. CLI first.

\n

What \"integrate\" means here

\n

The host -- Claude Code or opencode -- needs a way to ask your role-aware Terraphim setup a question and get back ranked, source-attributed results. The model decides when to ask. The role decides which haystacks to search. Terraphim's terraphim-graph ranker decides which results come back first.

\n

Concrete example. You are working in opencode and you type:

\n
/tsearch "System Operator" RFP\n
\n

The slash command runs against the System Operator role. The role's knowledge graph normalises RFP to its INCOSE-canonical form acquisition need. The Aho-Corasick matcher walks the role's haystack (1,347 Logseq pages from the terraphim/system-operator repository). The top hit comes back ranked 13 -- Acquisition need.md -- with the synonyms:: line that mapped your query to it visible in the snippet. The model now has the right page in its context window and can answer your follow-up without a hallucinated INCOSE handbook reference.

\n

This works in both hosts because both speak the same two integration languages: shell-out slash commands and MCP servers. We are going to use both.

\n

Path A -- CLI via slash command

\n\n

terraphim-agent already exists, takes --role and --limit, and writes ranked results to stdout. There is nothing to build. Both Claude Code and opencode let slash commands shell out via Bash. So a two-line command file is the entire integration.

\n

One file, two hosts

\n

Drop this at ~/.claude/commands/tsearch.md (and an identical copy at ~/.config/opencode/command/tsearch.md -- both hosts read the same frontmatter shape):

\n
---\ndescription: Terraphim search across configured roles. Usage: /tsearch [role] <query>\nallowed-tools: Bash(terraphim-agent search:*), Bash(terraphim-agent-pa search:*)\n---\nRun `terraphim-agent search --role "<role>" --limit 5 "<query>"` (or\n`terraphim-agent-pa search ...` if the role is "Personal Assistant" and\nthe query needs the JMAP haystack). Return the top results as a numbered\nlist with title, source path/URL, and a 120-char snippet.\n
\n

That is it. The allowed-tools line auto-approves the two CLI invocations so the model does not have to ask permission per call. Restart the host (or reload commands) and /tsearch is live.

\n

Why fast enough

\n

terraphim-agent reads its persisted role state at start (low milliseconds), runs the query against the role's haystacks, and returns. For a typical knowledge-graph query against the Terraphim Engineer role on a laptop, the round trip from slash command to formatted output is well under a second. The agent already has the typed CLI -- --role, --limit, --format json -- so there is nothing the MCP layer adds for the search-only flow.

\n

Three example queries

\n
/tsearch "Terraphim Engineer" rolegraph\n/tsearch "System Operator" RFP\n/tsearch "Personal Assistant" invoice    # uses terraphim-agent-pa wrapper for JMAP\n
\n

The Personal Assistant case is the most interesting because it crosses surfaces -- Obsidian notes interleave with jmap:///email/<id> URLs from your Fastmail mailbox, ranked by the same terraphim-graph scoring. The wrapper script injects JMAP_ACCESS_TOKEN from 1Password at call time so the secret never lands on disk; the bare terraphim-agent continues to work for the other five roles without paying the unlock cost.

\n

Path B -- MCP server (when you want typed tools)

\n

The CLI path is enough for search. If you want the model to call search as a first-class tool with structured JSON parameters -- alongside autocomplete_terms, autocomplete_with_snippets, four flavours of fuzzy autocomplete, build_autocomplete_index, and update_config_tool -- that is what terraphim_mcp_server exposes. It reads the same ~/.config/terraphim/embedded_config.json, so the role list is identical.

\n

Build and install

\n
cd ~/projects/terraphim/terraphim-ai\ncargo build --release -p terraphim_mcp_server --features jmap\ncp target/release/terraphim_mcp_server ~/.cargo/bin/terraphim_mcp_server\n
\n

For the Personal Assistant role, mirror the existing terraphim-agent-pa wrapper at ~/bin/terraphim_mcp_server-pa so the JMAP token flows through op run instead of being baked into config.

\n

Register

\n

opencode -- add to ~/.config/opencode/opencode.json under mcp:

\n
"terraphim":    { "type": "local", "command": ["/Users/alex/.cargo/bin/terraphim_mcp_server"] },\n"terraphim-pa": { "type": "local", "command": ["/Users/alex/bin/terraphim_mcp_server-pa"] }\n
\n

Claude Code -- one shell command per server:

\n
claude mcp add terraphim    /Users/alex/.cargo/bin/terraphim_mcp_server\nclaude mcp add terraphim-pa /Users/alex/bin/terraphim_mcp_server-pa\nclaude mcp list      # both should show as Connected\n
\n

The model now sees mcp__terraphim__search and mcp__terraphim_pa__search (plus the autocomplete tools) in its tool list.

\n

SessionStart primer (both paths)

\n

Slash commands and MCP tools are useless if the model does not know the roles exist. Extend the SessionStart hook in ~/.claude/settings.json to print a one-screen role index when each session starts:

\n
printf '\\n--- Terraphim search via /tsearch [role] <query> ---\\n'\nprintf '  Terraphim Engineer  (Rust/agent KG)\\n'\nprintf '  Personal Assistant  (Obsidian + Fastmail JMAP, use terraphim-agent-pa for email)\\n'\nprintf '  System Operator     (INCOSE/MBSE Logseq KG)\\n'\nprintf '  Context Engineering Author, Rust Engineer, Default\\n'\n
\n

Equivalent hook in opencode. Cost: one screen of context per session. Benefit: the model picks the right role on the first try instead of guessing.

\n

When to pick which path

\n\n\n\n\n\n\n
CLI (Path A)MCP (Path B)
New binariesNoneterraphim_mcp_server plus wrapper
Cold start~50-200 ms per call~10-50 ms per call (long-lived process)
Tools exposedsearch onlysearch + 4 autocomplete + build_autocomplete_index + update_config_tool
Works in any hostYes -- anything that runs a slash commandOnly hosts that speak MCP
Token handlingterraphim-agent-pa wrapperterraphim_mcp_server-pa wrapper
\n

For the search-across-roles flow, CLI is enough. Add MCP when the model needs autocomplete-as-you-type, when you want it to manage role configuration without leaving the conversation, or when you are using a host where the typed-tool surface matters more than the cold-start cost.

\n

You do not have to choose. Wire both. The slash command above defaults to CLI and falls back to MCP if the binary is missing -- the two paths coexist cleanly because they read the same role config.

\n

Why this is the right shape

\n

Most \"AI assistant + knowledge base\" integrations end up tightly coupled to a specific host. Vendor X's plugin marketplace, Vendor Y's tool format. Terraphim takes the opposite stance: the role configuration lives in your filesystem, the haystacks live in your filesystem (or your mailbox), the ranker runs in a process you own, and the integration with the AI host is the thinnest possible shim -- a slash command or an MCP server, both of which are commodity surfaces.

\n

Yesterday the Personal Assistant role was a private setup on one laptop. Today it is callable from inside two different AI coding hosts via a one-file slash command. Tomorrow you can add Cursor or Aider with the same two-line wrapper because the integration surface is terraphim-agent search, not vendor-specific-tool-protocol-v3.

\n

The expensive part of context engineering is not the ranker. It is the vocabulary in the knowledge graph and the haystacks the role can reach. The integration layer should not be allowed to compete for that budget. CLI-first keeps it small.

\n

Try it

\n
# Build (or install the published crate when JMAP feature lands on crates.io)\ncd ~/projects/terraphim/terraphim-ai\ncargo install --path crates/terraphim_agent --features jmap\n\n# Configure roles -- copy the snippets from the how-tos linked below\n$EDITOR ~/.config/terraphim/embedded_config.json\n\n# Install the slash command\nmkdir -p ~/.claude/commands ~/.config/opencode/command\ncp ~/projects/terraphim/terraphim-ai/docs/src/howto/mcp-integration-claude-opencode.md \\\n   /tmp/tsearch.md  # adapt to your slash command file shape\n\n# Reload roles\nterraphim-agent config reload\n\n# Try\nterraphim-agent search --role "Terraphim Engineer" --limit 3 "rolegraph"\n
\n

Step-by-step in the docs: Plug Terraphim Search into Claude Code and opencode.

\n

For the underlying engine, start with Why Graph Embeddings Matter. For the two roles this integration most cleanly exposes, see Personal Assistant and System Operator.

\n", "https://terraphim.ai/properties/date" : "2026-04-18", "https://atomicdata.dev/properties/tags" : {"tags":["Terraphim","claude-code","opencode","mcp","knowledge-graph","developer-tools","integration"],"categories":["Technical"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/disciplined-engineering-ai-systems/", "https://atomicdata.dev/properties/name" : "Disciplined Engineering: How We Build AI Systems That Actually Work", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/disciplined-engineering-ai-systems/", "https://atomicdata.dev/properties/description" : "

AI coding agents are making us worse engineers, unless we add discipline back. Here is what we do instead of vibe coding, and how you can do it too in 30 seconds.

\n

The Vibe Coding Problem

\n

Every AI-generated pull request we review has the same pattern:

\n\n

The agent shipped code. It even passed the tests. But the tests were written by the same agent that wrote the code, optimising for the metric rather than understanding the problem.

\n

The missing piece is not better models. It is engineering discipline. AI agents need the same rigour humans use: understand the problem before coding, verify against the design, validate against requirements. We encoded this as executable skills that any AI coding agent can follow.

\n
\n

The research evidence behind this framework, including language-specific scaling laws and the 30% adoption gap between code intelligence research and production harnesses, is the subject of our next article.

\n
\n

The V-Model: Adding Discipline Back

\n

We built a V-model for AI agents. The left side asks \"what should we build?\" The right side asks \"did we build it correctly?\"

\n

\"The

\n

Phase 1: Research

\n

Before writing any code, the agent must understand the problem space:

\n\n

Phase 2: Design

\n

Create a specification before implementation:

\n\n

Phase 3: Implementation

\n

Write code with tests from the start:

\n\n

Phase 4: Verification

\n

Verify against the design, not just tests:

\n\n

Phase 5: Validation

\n

Validate against the original requirements:

\n\n

terraphim-skills: 32+ Executable Disciplines

\n

We packaged the V-model as executable skills you can add to any AI agent:

\n
npx skills add terraphim/terraphim-skills\n
\n

This installs skills that enforce:

\n\n

Each skill is a self-contained prompt that guides the agent through the phase's inputs, outputs, and quality gates.

\n

Quality Gates: The Judge System

\n

Our judge system (Kimi K2.5) catches what humans miss:

\n\n

Automated quality gates, zero manual overhead. Every PR reviewed before it merges.

\n

Guard Rails in Practice

\n

AI agents do not type commands into a terminal. They invoke tools programmatically, and they do not always get it right. \"Cleaning up build artefacts\" becomes rm -rf ./src (one-character typo). \"Resetting to last commit\" becomes git reset --hard (uncommitted work gone). You need a safety net that operates between the agent and your shell.

\n

We use two layers of guard rails:

\n

Layer 1: git-safety-guard (a terraphim-skill that runs as a PreToolUse hook):

\n\n

Layer 2: Destructive Command Guard (DCG) by Jeff Emanuel, integrated via tool hooks:

\n\n

The architecture is simple: the agent calls a bash tool, the hook pipes the command to DCG as JSON, DCG pattern-matches against known destructive commands, and blocks execution before damage occurs. The agent receives an error explaining why, and can adjust its approach.

\n

Real Example: AI Dark Factory

\n

We run 12+ AI agents overnight on a single machine, coordinated by a Rust orchestrator. Each agent follows the V-model:

\n\n

Every agent's output passes through the judge system before merge. The morning routine is reviewing verdicts, not debugging overnight chaos. When an agent produces a NO-GO verdict, the PR is flagged with the specific issues: missing test coverage, undocumented API changes, or security concerns.

\n

This is disciplined engineering at scale: not process overhead, but automated quality gates that catch problems before they compound.

\n

Conclusion

\n

The gap between what AI agents can do and what they should do is real. It is not a technology gap: it is a discipline gap. The V-model and 32+ executable skills we built are available today:

\n
npx skills add terraphim/terraphim-skills\n
\n

Add discipline back. Your future self will thank you.

\n
\n

Deeper dive: The V-model and quality gates we use are detailed in Chapters 3-4 of \"Context Engineering with Knowledge Graphs\". Coming soon.

\n

Related posts:

\n\n", "https://terraphim.ai/properties/date" : "2026-04-17", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","ai","engineering","v-model","developer-tools","coding-agents","discipline"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/guarding-opencode-with-dcg/", "https://atomicdata.dev/properties/name" : "Guarding OpenCode with Destructive Command Guard", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/guarding-opencode-with-dcg/", "https://atomicdata.dev/properties/description" : "

AI coding assistants are fast, productive, and occasionally catastrophic. One misplaced rm -rf, one accidental git reset --hard, and hours of uncommitted work vanish.

\n

Jeffrey Emanuel (@Dicklesworthstone) built Destructive Command Guard (dcg): a Rust binary with SIMD-accelerated pattern matching, 49+ security packs, and a fail-open design. It is one of the best tools to come out of the AI agent safety space, and it solved a problem we had been fighting with regex hacks.

\n

This post shows how we integrated dcg with OpenCode using its plugin hook system, so destructive commands are intercepted before they run.

\n

The Problem

\n

AI agents do not type commands into a terminal. They invoke tools programmatically, and they do not always get it right:

\n\n

You need a safety net that operates between the agent and your shell.

\n

The Architecture

\n

OpenCode v1.4+ exposes a plugin hook system. Hooks are top-level keys on the Hooks interface:

\n
interface Hooks {\n  "tool.execute.before"?: (input, output) => Promise<void>;\n  "tool.execute.after"?:  (input, output) => Promise<void>;\n}\n
\n

The \"tool.execute.before\" hook fires before every tool call. It receives the tool name and arguments, and can throw an error to abort execution. This is exactly where a command guard belongs.

\n

DCG is Jeffrey's Rust binary that reads a JSON payload from stdin and exits 0 (allow) or 2 (block). Our contribution was the plugin that wires dcg into OpenCode's hook system:

\n
OpenCode agent\n    |\n    | calls bash tool: "rm -rf ./build"\n    v\n"tool.execute.before" hook\n    |\n    | spawns: echo '{"tool":"bash","args":{"command":"rm -rf ./build"}}' | dcg\n    v\ndcg (Rust, SIMD-accelerated pattern matching)\n    |\n    | exit code 2 + reason on stderr\n    v\nhook throws Error --> command never executes\n
\n

The Plugin

\n

The complete plugin is roughly 60 lines:

\n
import { spawn } from 'child_process';\n\nconst callDcgHook = (toolCall) => {\n  return new Promise((resolve, reject) => {\n    const dcg = spawn('dcg', [], {\n      env: { ...process.env, DCG_FORMAT: 'json' }\n    });\n\n    let stdout = '';\n    let stderr = '';\n\n    dcg.stdout.on('data', (data) => { stdout += data.toString(); });\n    dcg.stderr.on('data', (data) => { stderr += data.toString(); });\n\n    dcg.on('close', (code) => {\n      if (code === 0) {\n        try { resolve(JSON.parse(stdout)); }\n        catch { resolve({ allowed: true }); }\n      } else {\n        reject(new Error(stderr || 'dcg blocked command'));\n      }\n    });\n\n    dcg.stdin.write(JSON.stringify(toolCall));\n    dcg.stdin.end();\n  });\n};\n\nexport const DcgGuard = async ({ client }) => {\n  return {\n    "tool.execute.before": async (input, output) => {\n      if (input.tool !== 'bash') return;\n\n      const toolCall = {\n        tool: 'bash',\n        args: { command: output.args.command }\n      };\n\n      try {\n        await callDcgHook(toolCall);\n      } catch (error) {\n        throw new Error(\n          `dcg blocked destructive command: ${output.args.command}\\n\\n` +\n          `${error.message}\\n\\n` +\n          `This command was blocked to protect your system.`\n        );\n      }\n    }\n  };\n};\n
\n

What Got Fixed: A Subtle API Mismatch

\n

The original plugin used a nested structure:

\n
return {\n  tool: {\n    execute: {\n      before: async (input, output) => { ... }\n    }\n  }\n};\n
\n

This looks intuitive but is wrong. In OpenCode's plugin API, tool is reserved for registering new tools (each needing a description, args, and execute function). The hook \"tool.execute.before\" is a top-level dotted key on the Hooks object, not a nested path.

\n

The fix:

\n
return {\n  "tool.execute.before": async (input, output) => { ... }\n};\n
\n

This distinction matters. OpenCode iterates over tool entries expecting ToolDefinition objects. When it found { before: ... } instead, it called .execute(args, ctx) on it, which was undefined. Hence the error: def.execute is not a function.

\n

What DCG Blocks

\n\n\n\n\n\n\n\n\n
CategoryExamples
Git history destructiongit reset --hard, git push --force, git branch -D
Uncommitted work lossgit checkout — ., git restore file, git clean -f
Stash destructiongit stash drop, git stash clear
Filesystem damagerm -rf outside /tmp
Database operationsDROP TABLE, FLUSHALL (via packs)
Container destructiondocker system prune, docker-compose down --volumes
Infrastructureterraform destroy, kubectl delete namespace
\n

Safe operations pass through silently: git status, git add, git commit, git push (without --force), git stash, git checkout -b, and all non-destructive commands.

\n

Key Design Decisions

\n

Default-allow. Unrecognised commands pass through. DCG blocks only known dangerous patterns. This prevents false positives from blocking legitimate work.

\n

Whitelist-first. Safe patterns (like git checkout -b) are checked before destructive patterns. Explicitly safe commands are never accidentally blocked.

\n

Sub-millisecond latency. Jeffrey's implementation uses SIMD-accelerated substring search via Rust's memchr crate. Commands without \"git\" or \"rm\" bypass regex matching entirely. The guard adds no perceptible delay.

\n

Fail-open. If dcg crashes or produces unexpected output, the plugin catches the error and defaults to allowing the command. A broken guard should never break your workflow. A safety system that slows down the developer will be disabled by the third day. A safety system that is invisible will run forever.

\n

Extending with Packs

\n

DCG ships with a modular pack system. Enable additional protection categories in ~/.config/dcg/config.toml:

\n
[packs]\nenabled = [\n    "database.postgresql",\n    "containers.docker",\n    "kubernetes",\n    "cloud.aws",\n]\n
\n

Or via environment variable:

\n
export DCG_PACKS="containers.docker,kubernetes"\n
\n

Installation

\n
# 1. Install dcg\ncurl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/destructive_command_guard/master/install.sh" | bash\n\n# 2. Install the plugin\nmkdir -p ~/.config/opencode/plugin\ncurl -fsSL https://raw.githubusercontent.com/jms830/opencode-dcg-plugin/main/plugin/dcg-guard.js \\\n  -o ~/.config/opencode/plugin/dcg-guard.js\n\n# 3. Restart OpenCode\n
\n

Conclusion

\n

The OpenCode plugin API's \"tool.execute.before\" hook is a clean interception point for safety guards. Combined with Jeffrey Emanuel's dcg and its fast pattern matching, you get protection against destructive commands with zero workflow friction. The plugin is small, the guard is fast, and the safety net catches the mistakes that matter.

\n

Instructions are suggestions. Guards are guarantees.

\n
\n

DCG is built by Jeffrey Emanuel — see his destructive_command_guard repository and the broader agentic coding flywheel ecosystem for more agent safety tooling.

\n

This post is part of the Disciplined Engineering series. See also: Teaching AI Agents with Knowledge Graph Hooks and Teaching AI Agents to Learn from Their Mistakes.

\n

Source: DCG plugin gist and opencode-dcg-plugin repository

\n", "https://terraphim.ai/properties/date" : "2026-04-17", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","ai","opencode","developer-tools","rust","safety","coding-agents"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/personal-assistant-role-jmap-obsidian/", "https://atomicdata.dev/properties/name" : "Personal Assistant Role: One Search Across Email and Notes", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/personal-assistant-role-jmap-obsidian/", "https://atomicdata.dev/properties/description" : "

Most \"personal AI\" tools split your context across silos: one search box for email, another for notes, a third for your chat history. Terraphim treats every source as a haystack on the same role, so a single query crosses all of them. This post shows how to wire up the two most common personal sources -- email via JMAP and notes in an Obsidian vault -- under a new Personal Assistant role.

\n

Why a unified role matters

\n

The mental tax of personal search is not the typing. It is the deciding. \"Did I read that in an email or write it in a note?\" Each silo you skip is a context switch with no useful payload. Once Terraphim is the front door for both surfaces, the question collapses to \"where is the thing about X\" and the role's terraphim-graph ranking serves whichever source actually has the strongest signal.

\n

The Personal Assistant role uses two haystacks under one role:

\n\n

Ranking is the same terraphim-graph scoring as every other Terraphim role: an Aho-Corasick automaton built from the Obsidian vault contributes synonyms specific to your project vocabulary, then both haystacks share the same rank ladder. Notes and email interleave by relevance, not by source.

\n

What you get

\n\n

A 4 GB process on your laptop holds the whole working set; queries return in single-digit milliseconds for the local side and a few hundred for the remote JMAP round trip.

\n

Wiring sketch

\n

The role config is roughly thirty lines of JSON: two haystacks, one knowledge-graph pointer, no LLM. The Fastmail token is not in the config -- it is injected at runtime via op run from 1Password into the JMAP_ACCESS_TOKEN environment variable, so the secret never lands on disk:

\n
exec op run --account my.1password.com \\\n  --env-file=<(echo 'JMAP_ACCESS_TOKEN=op://VAULT/ITEM/credential') \\\n  -- /Users/alex/.cargo/bin/terraphim-agent "$@"\n
\n

Wrap that in ~/bin/terraphim-agent-pa, chmod +x, and the JMAP haystack lights up only for queries that ask for it. The other roles keep using the bare terraphim-agent and never pay for the 1Password unlock.

\n

Why graph embeddings make this practical

\n

The reason a unified role works at all -- not just for two haystacks but for any reasonable number -- is that Terraphim's graph-embeddings layer is sub-millisecond and deterministic. There is no per-query embedding API call to amortise across sources, no vector database to keep in sync, no opaque ranker that has to be retrained when you add a new haystack. The matching is byte-level Aho-Corasick traversal of an automaton built once at role-load time. We wrote up the engine in detail at Why Graph Embeddings Matter; this Personal Assistant role is one application of that engine.

\n

Try it

\n

The end-to-end how-to is in the docs: install the prerequisites, add the JSON snippet, write the wrapper, run three verification queries.

\n

Read the how-to: Personal Assistant Role on docs.terraphim.ai

\n

One caveat worth surfacing up front: the published terraphim-agent on crates.io does not yet ship with the JMAP haystack (the haystack_jmap dependency is not published either). For email search you need to build from local source with cargo build --release -p terraphim_agent --features jmap. The how-to walks through the two Cargo.toml edits required.

\n

What is next

\n

Personal Assistant is the smallest useful instance of \"Terraphim as the front door for everything I read.\" Calendar (CalDAV), contacts (CardDAV), browser bookmarks, RSS, and AI session logs are all natural follow-ups -- each is a single haystack entry on the same role. The pattern composes; the cost stays linear in haystacks, not quadratic in cross-source queries.

\n

If you want the underlying engine, start with Why Graph Embeddings Matter. If you want to wire knowledge-graph hooks into your AI coding agent on the same machine, Teaching AI Coding Agents with Knowledge Graph Hooks covers that side of the same engine.

\n", "https://terraphim.ai/properties/date" : "2026-04-17", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","personal-assistant","jmap","obsidian","knowledge-graph","fastmail"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/system-operator-logseq-knowledge-graph/", "https://atomicdata.dev/properties/name" : "System Operator Demo: A Logseq Knowledge Graph Drives Enterprise MBSE Search", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/system-operator-logseq-knowledge-graph/", "https://atomicdata.dev/properties/description" : "

Terraphim's System Operator role is the demo we point people at when they want to see a real Logseq knowledge graph drive search. 1,347 Logseq pages, 52 of them carrying explicit synonyms:: lines, covering Model-Based Systems Engineering vocabulary -- requirements, architecture, verification, validation, life cycle concepts. This post walks the demo end-to-end and shows the piece people miss: the KG is doing real work, not just re-ranking text matches.

\n

What the demo is

\n

The terraphim/system-operator repository on GitHub is a Logseq vault -- flat folder of markdown files under pages/, one page per concept, with Logseq's bullet-tree syntax for structure and Terraphim-format synonyms:: lines for the knowledge-graph layer. Two things make it a useful demo rather than a toy:

\n
    \n
  1. Real MBSE vocabulary. The synonyms are not invented; they track the INCOSE Systems Engineering Handbook v.4, the V-Model, and SEMP conventions. When you type RFP, the automaton normalises it to acquisition need because that is what the handbook calls it.
  2. \n
  3. Real scale. 1,347 markdown files is enough to expose cold-start behaviour (~5-10 seconds to index on a laptop) without being so large it obscures the ranking signal.
  4. \n
\n

Run it

\n

There is an automated setup script in the repo. As of today it clones to a durable path under ~/.config/terraphim/system_operator instead of /tmp, so the vault survives a reboot:

\n
./scripts/setup_system_operator.sh\n
\n

Then either drive the role via the server --

\n
cargo run --bin terraphim_server -- \\\n  --config terraphim_server/default/system_operator_config.json\ncurl "http://127.0.0.1:8000/documents/search?q=RFP&role=System%20Operator&limit=5"\n
\n

-- or via the terraphim-agent CLI after adding the role entry to ~/.config/terraphim/embedded_config.json:

\n
terraphim-agent config reload\nterraphim-agent search --role "System Operator" --limit 5 "RFP"\n
\n

The full config snippet and the embedded_config.json entry are in the README_SYSTEM_OPERATOR.md.

\n

The piece people miss

\n

Search-over-notes tools usually describe ranking in terms of \"it uses a knowledge graph\". That sentence hides a lot. Is the graph actually consulted at query time? Is it just a post-hoc re-ranker on top of BM25? Does it expand synonyms? On what vocabulary?

\n

Terraphim exposes the answer directly. validate --connectivity prints which words in your query the automaton matched and what canonical terms they normalised to:

\n
$ terraphim-agent validate --role "System Operator" --connectivity \\\n    "RFP business analysis life cycle model business requirements documentation tree"\n\nConnectivity Check for role 'System Operator':\n  Connected: false\n  Matched terms: ["acquisition need", "business or mission analysis",\n                  "business requirements", "documentation tree",\n                  "life cycle concepts"]\n
\n

Five query fragments, five canonical matches. RFP collapsed to acquisition need (its synonym, from Acquisition need.md in the vault). business analysis collapsed to business or mission analysis (INCOSE terminology). life cycle model collapsed to life cycle concepts. None of this is text matching -- the word RFP does not appear in the canonical page body; it lives in the synonyms:: line.

\n

Once a query is normalised, the ranker walks the graph. A document that mentions acquisition need directly outranks one that mentions it through three synonym hops, and both outrank a document that mentions none of the canonical terms at all. Ranks come back with concrete integer scores -- [13] on a top result, not an opaque 0.87 cosine.

\n

How it compares to the Personal Assistant role

\n

We wrote up the Personal Assistant role yesterday: a private per-user role that indexes a Fastmail mailbox plus an Obsidian vault. Same engine, same ranker, different haystacks. The knowledge graph there is a small kg/ folder inside the user's vault with 14 synonym files covering personal vocabulary (bun with npm/yarn/pnpm synonyms, odilo, invoice, meeting).

\n

The two roles expose the same pattern at two scales:

\n\n\n\n\n\n\n
System OperatorPersonal Assistant
KG size52 synonym files, 1,300-concept vocabulary14 synonym files, ~30-concept personal vocabulary
Haystacks1 (Logseq repo)2 (Obsidian vault + Fastmail JMAP)
SourcePublic GitHub repoPrivate user files and mailbox
AudienceDemos, onboarding, public showcaseOne user
LifetimeFrozen per releaseEdited daily, rebuilt in 20 ms per edit
\n

Both use terraphim-graph ranking. Both build an Aho-Corasick automaton once at role-load time. Both run in a 4 GB process on a laptop with no cloud round-trip. The only interesting difference is the vocabulary, which is exactly the separation of concerns a knowledge-graph-first design is supposed to deliver.

\n

Why this matters for teams evaluating MBSE tooling

\n

If you are evaluating Terraphim for a systems engineering group, the System Operator role is the honest starting point. It runs on a laptop against a public vault; you can check that every synonym mapping traces back to a concrete page; you can diff the pages/ folder against the INCOSE handbook and argue about terminology. When your team's own vocabulary diverges (every organisation's does), you clone the repo, edit synonyms:: lines, and the graph rebuilds in 20 milliseconds without a retraining step.

\n

The expensive part of enterprise search is not the ranker. It is the vocabulary. A deterministic graph makes the vocabulary an asset you curate, not a black box you tune.

\n

Try it

\n
git clone https://github.com/terraphim/terraphim-ai\ncd terraphim-ai\n./scripts/setup_system_operator.sh\ncargo run --bin terraphim_server -- \\\n  --config terraphim_server/default/system_operator_config.json\n
\n

Or cut to the CLI if you already have terraphim-agent installed -- the embedded_config.json snippet is in the README.

\n

For the underlying engine, start with Why Graph Embeddings Matter. For the personal-productivity analogue, see the Personal Assistant role post.

\n", "https://terraphim.ai/properties/date" : "2026-04-17", "https://atomicdata.dev/properties/tags" : {"tags":["Terraphim","system-operator","logseq","knowledge-graph","mbse","systems-engineering"],"categories":["Technical"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/teaching-ai-agents-to-learn-from-mistakes/", "https://atomicdata.dev/properties/name" : "Teaching AI Agents to Learn from Their Mistakes", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/teaching-ai-agents-to-learn-from-mistakes/", "https://atomicdata.dev/properties/description" : "

AI coding agents make the same mistakes over and over. We built a learning system that captures failures, stores corrections, and feeds them back into future sessions — turning every error into institutional memory.

\n
\n

Builds on Why Graph Embeddings Matter — the deterministic engine that makes \"remember this correction forever\" cheap. Apply the pattern in your own project via the Command Rewriting How-to.

\n
\n

The Problem: Groundhog Day for AI Agents

\n

Every AI coding agent session starts from zero. Claude Code runs npm install, gets corrected, switches to bun — and tomorrow does it again. A force-push to main gets blocked, the agent learns why, then forgets by next session.

\n

In our previous post on Knowledge Graph Hooks, we showed how Aho-Corasick automata can intercept and transform agent commands in real time. But interception is reactive. What if the agent could remember its past failures and avoid repeating them?

\n

The Solution: Terraphim Learning Capture

\n

Terraphim's learning system operates as a closed loop with three stages:

\n
Failed Command --> PostToolUse Hook --> Learning Store --> Query at Session Start\n
\n

Stage 1: Automatic Capture

\n

A PostToolUse hook fires after every tool execution in Claude Code. When a command exits with a non-zero status, the hook calls terraphim-agent learn hook, which persists the failure as a structured markdown file:

\n
---\nid: 6b99a8924fad4f2aaeadf5450e76730c\ncommand: npm install react\nexit_code: 127\nsource: Global\ncaptured_at: 2026-04-04T18:43:07+00:00\n---\n
\n

The hook is fail-open — if terraphim-agent is unavailable, it exits silently. Development is never blocked.

\n

Stage 2: Human Corrections

\n

Raw failures are useful, but corrections make them actionable. Any developer (or the agent itself) can attach a correction:

\n
$ terraphim-agent learn correct <id> --correction "Use 'bun add react' instead"\n
\n

The learning file is updated in place:

\n
---\nid: 6b99a8924fad4f2aaeadf5450e76730c\ncommand: npm install react\nexit_code: 127\ncorrection: "Use 'bun add react' instead"\n---\n
\n

Stage 3: Query Before Repeating

\n

At the start of a session, or when encountering a familiar error, the agent queries the learning store:

\n
$ terraphim-agent learn query "npm"\n\nLearnings matching 'npm'.\n  [G] [cmd] npm install lodash (exit: 1)\n     Correction: Use 'bun add lodash' instead. Terraphim hooks enforce bun over npm.\n  [G] [cmd] npm install react (exit: 127)\n     Correction: Use bun instead of npm/yarn/pnpm. 'bun add react' or 'bun install'.\n
\n

The agent sees past mistakes with their corrections before taking action. No more Groundhog Day.

\n

How the Hook Works

\n

The PostToolUse hook is a shell script that receives JSON from Claude Code on stdin after every Bash tool call:

\n
#!/bin/bash\nset -euo pipefail\n\n# Find terraphim-agent binary\nAGENT="$HOME/.cargo/bin/terraphim-agent"\n[ -x "$AGENT" ] || exit 0  # Fail-open\n\n# Read tool result from stdin\nINPUT=$(cat)\n\n# Capture failures as learnings\n$AGENT learn hook --format claude <<< "$INPUT" 2>/dev/null || true\n
\n

The learn hook subcommand parses the Claude Code tool result format, extracts the command and exit code, and writes a learning file only when the exit code is non-zero.

\n

What Gets Captured

\n\n\n\n\n\n\n
SignalCaptured?Example
Non-zero exit codeYesnpm install (exit 127)
Force push attemptsYesgit push --force origin main (exit 1)
Compilation errorsYescargo build (exit 101)
Successful commandsNoOnly failures are stored
Duplicate failuresDeduplicatedSame command + exit code within a session
\n

Real Evidence: What Our Agents Have Learnt

\n

Here is actual data from our production learning store, accumulated across weeks of development sessions:

\n

Package manager enforcement — 3 npm entries, all corrected to bun:

\n
[G] [cmd] npm install lodash (exit: 1)\n   Correction: Use 'bun add lodash' instead.\n[G] [cmd] npm install react (exit: 127)\n   Correction: Use bun instead of npm/yarn/pnpm.\n
\n

Git safety — 29 push failures captured, including one critical correction:

\n
[G] [cmd] git push --force origin main (exit: 1)\n   Correction: NEVER force push to main. Use feature branches and PRs.\n
\n

These corrections are not just documentation. They are queryable institutional memory that agents consult before repeating the same mistakes.

\n

Integration with Knowledge Graph Hooks

\n

The learning system complements the Knowledge Graph Hooks we described previously. Together they form two layers of defence:

\n\n\n\n
LayerMechanismTiming
PreventionKG hooks intercept npm install and replace with bun installBefore execution
LearningPostToolUse hook captures failures that slip throughAfter execution
\n

If a new pattern appears that the knowledge graph does not cover, the learning system captures it. A developer adds a correction. Optionally, the pattern gets promoted to a knowledge graph entry for permanent interception.

\n
New failure captured --> Correction added --> Pattern promoted to KG --> Hook intercepts automatically\n
\n

The Learning Store

\n

Learning files are stored as markdown in ~/Library/Application Support/terraphim/learnings/ (macOS) or ~/.local/share/terraphim/learnings/ (Linux). Each file is a standalone document:

\n
---\nid: 1c8a4548-1434-a346-cd641131202a\ncommand: git push --force origin main\nexit_code: 1\nsource: Global\ncaptured_at: 2026-04-02T15:31:20+00:00\ncorrection: NEVER force push to main. Use feature branches and PRs.\n---\n\n## Command\n\n`git push --force origin main`\n\n## Error Output\n\n
\n

rejected

\n
\n## Suggested Correction\n\n`NEVER force push to main. Use feature branches and PRs.`\n
\n

Being plain markdown, these files are:

\n\n

CLI Reference

\n
# List recent learnings\nterraphim-agent learn list\n\n# Query by pattern (full-text search)\nterraphim-agent learn query "pattern"\n\n# Add correction to a learning\nterraphim-agent learn correct <id> --correction "what to do instead"\n\n# Hook mode (called by PostToolUse, reads JSON from stdin)\nterraphim-agent learn hook --format claude\n
\n

Setting It Up

\n

1. Install the PostToolUse hook

\n

Create ~/.claude/hooks/post_tool_use.sh:

\n
#!/bin/bash\nset -euo pipefail\nAGENT="$HOME/.cargo/bin/terraphim-agent"\n[ -x "$AGENT" ] || exit 0\nINPUT=$(cat)\n$AGENT learn hook --format claude <<< "$INPUT" 2>/dev/null || true\n
\n

2. Register in Claude Code settings

\n

Add to .claude/settings.json:

\n
{\n  "hooks": {\n    "PostToolUse": [{\n      "matcher": "Bash",\n      "hooks": [{\n        "type": "command",\n        "command": "~/.claude/hooks/post_tool_use.sh"\n      }]\n    }]\n  }\n}\n
\n

3. Start using it

\n

Failed commands are captured automatically. Query them with terraphim-agent learn query.

\n

What Comes Next

\n

The learning system is the foundation for richer agent memory:

\n\n

The goal is not to make agents perfect on the first try. It is to make them incapable of making the same mistake twice.

\n

Conclusion

\n

AI coding agents are powerful but amnesiac. Every session starts fresh, every mistake is rediscovered. Terraphim's learning capture system closes this gap with a simple, fail-open hook that turns failures into institutional memory.

\n

The pattern is straightforward: capture failures automatically, attach corrections manually, query before acting. No training required, no model fine-tuning, no prompt engineering beyond what you already do.

\n

Your agents will still make mistakes. They just will not make the same mistakes.

\n

Resources

\n\n", "https://terraphim.ai/properties/date" : "2026-04-05", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","ai","learning","hooks","knowledge-graph","claude-code","developer-tools"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/learning-via-negativa/", "https://atomicdata.dev/properties/name" : "Learning via Negativa: How Terraphim Remembers What You Keep Getting Wrong", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/learning-via-negativa/", "https://atomicdata.dev/properties/description" : "

You know what is embarrassing? Making the same mistake for the tenth time. Last week, I typed docker-compose up instead of docker compose up. The command failed. I sighed. I corrected it. Three days later? Same thing. Same sigh. Same correction.

\n
\n

Builds on Why Graph Embeddings Matter — the deterministic engine that lets Terraphim store and replay corrections in microseconds. Apply the pattern in your own project via the Command Rewriting How-to.

\n
\n

The Problem Nobody Talks About

\n

This is not just about typos. Developers repeat the same failed patterns constantly:

\n\n

The AI agents we use? They are even worse. Claude Code, Codex, Cursor: they all make the same mistakes, over and over, because they have no long-term memory of what went wrong.

\n

We are not learning from our failures. We are just repeating them.

\n

The Solution: Learning via Negativa

\n

What if your terminal learned from every failed command?

\n

That is exactly what Terraphim's Learning via Negativa system does. It captures every failed command, extracts the mistake pattern, and builds a knowledge graph that corrects you in real-time.

\n

The name comes from the Latin \"per negativa\": learning by knowing what is wrong. It is the pedagogical equivalent of \"do not touch the hot stove\" after you have already touched it.

\n

Here is how it works:

\n
You type "docker-compose up"\n        |\nCommand fails (docker-compose is deprecated)\n        |\nHook captures: command + error + context\n        |\nKnowledge graph maps: "docker-compose" -> "docker compose"\n        |\nNext time: Terraphim auto-replaces and suggests the correct command\n
\n

The Technical Implementation

\n

This is not a wrapper script or a hack. It is a native Rust system built into terraphim-agent that captures, stores, and corrects command mistakes.

\n

1. The Capture Hook

\n

The hook intercepts failed commands from your AI agent:

\n
// crates/terraphim_agent/src/learnings/capture.rs\n\nuse serde::{Deserialize, Serialize};\n\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub struct FailedCommand {\n    pub command: String,\n    pub exit_code: i32,\n    pub stderr: String,\n    pub working_directory: String,\n    pub timestamp: DateTime<Utc>,\n    pub tags: Vec<String>,\n}\n\n/// Capture a failed command and extract the mistake pattern\npub async fn capture_failed_command(\n    command: &str,\n    exit_code: i32,\n    stderr: &str,\n    context: &CommandContext,\n) -> Result<FailedCommand, CaptureError> {\n    // Only capture non-zero exit codes (actual failures)\n    if exit_code == 0 {\n        return Err(CaptureError::CommandSucceeded);\n    }\n\n    // Filter out test commands: we do not learn from intentional failures\n    if is_test_command(command) {\n        return Err(CaptureError::TestCommand);\n    }\n\n    // Extract mistake patterns from the command\n    let tags = extract_mistake_tags(command, stderr);\n\n    let failed = FailedCommand {\n        command: redact_secrets(command),\n        exit_code,\n        stderr: stderr.clone(),\n        working_directory: context.cwd.clone(),\n        timestamp: Utc::now(),\n        tags,\n    };\n\n    // Store as markdown for human readability\n    store_learning(&failed).await?;\n\n    Ok(failed)\n}\n
\n

The hook is fail-open by design: never blocks your workflow if capture fails.

\n

2. Building the Correction Knowledge Graph

\n

Once captured, mistakes become nodes in a knowledge graph that maps wrong to correct:

\n
// crates/terraphim_rolegraph/examples/learning_via_negativa.rs\n\nuse terraphim_rolegraph::RoleGraph;\nuse terraphim_types::{NormalizedTerm, NormalizedTermValue, Thesaurus};\n\n/// Build knowledge graph for command corrections\nfn build_correction_thesaurus() -> Thesaurus {\n    let mut thesaurus = Thesaurus::new("Command Corrections".to_string());\n\n    // Docker corrections\n    thesaurus.insert(\n        NormalizedTermValue::new("docker-compose up".to_string()),\n        NormalizedTerm::new(1, NormalizedTermValue::new(\n            "docker compose up".to_string()\n        )),\n    );\n\n    // Git corrections\n    thesaurus.insert(\n        NormalizedTermValue::new("git push -f".to_string()),\n        NormalizedTerm::new(2, NormalizedTermValue::new(\n            "git push --force-with-lease".to_string()\n        )),\n    );\n\n    // Cargo corrections\n    thesaurus.insert(\n        NormalizedTermValue::new("cargo buid".to_string()),\n        NormalizedTerm::new(3, NormalizedTermValue::new(\n            "cargo build".to_string()\n        )),\n    );\n\n    thesaurus\n}\n
\n

3. Real-Time Correction

\n

The correction happens automatically via Terraphim's replace tool:

\n
# Without Learning via Negativa (old workflow)\n$ docker-compose up\ndocker-compose: command not found\n# You: sigh, retype, move on\n\n# With Learning via Negativa\n$ docker-compose up\n# Terraphim intercepts, corrects, and shows:\nSuggestion: Did you mean 'docker compose up'? (y/n)\n# You: y, command executes correctly\n
\n

Demo Results

\n

We tested Learning via Negativa with common developer mistakes over a 30-day period:

\n

Correction Examples

\n\n\n\n\n\n\n\n
Wrong CommandErrorCorrection Learned
docker-compose upcommand not founddocker compose up
git push -fremote: denied by protection policygit push --force-with-lease
cargo buiderror: no such subcommandcargo build
npm isntallcommand not foundnpm install
apt updatePermission deniedsudo apt update
git psuhgit: 'psuh' is not a git commandgit push
\n

Knowledge Graph Growth

\n
Week 1:  12 corrections captured\nWeek 2:  34 corrections captured (cumulative)\nWeek 3:  58 corrections captured (cumulative)\nWeek 4:  89 corrections captured (cumulative)\n\nTop mistake categories:\n  - Docker commands: 28%\n  - Git commands: 24%\n  - Cargo/Rust: 18%\n  - npm/yarn: 15%\n  - System commands: 15%\n
\n

Why This Matters

\n

Most AI tools have no memory. Claude Code is brilliant but stateless. Cursor remembers your files, not your mistakes. GitHub Copilot suggests code but forgets that docker-compose has been deprecated for two years.

\n

Learning via Negativa gives your AI agent a memory for failure.

\n

It transforms every error from a one-time annoyance into a permanent lesson. The more you use it, the smarter it gets. And because it is built on the knowledge graph architecture, it does not just match strings: it understands context.

\n

You typed git push -f in a repo with protected branches? It learns that -f is wrong in that context. You use docker-compose in a project with a compose.yaml file? It learns the new syntax applies here.

\n

Getting Started

\n
# Install terraphim-agent\ncargo install terraphim-agent\n\n# Install the learning hook for Claude Code\nterraphim-agent learn install-hook claude\n\n# Verify it is working\nterraphim-agent learn list\n\n# Query your mistakes anytime\nterraphim-agent learn query "your mistake"\n\n# Or use the replace tool for real-time corrections\necho "docker-compose up" | terraphim-agent replace\n
\n

The Bigger Picture

\n

Learning via Negativa is more than a feature: it is a philosophy. Every failure contains information. Every error message is feedback. The trick is capturing that signal instead of just ignoring the noise.

\n

We have spent decades building systems that celebrate successes. It is time we built systems that learn from failures too.

\n

Your terminal should remember what you keep getting wrong. That is not just smart: that is how humans actually learn.

\n
\n

Links

\n\n
\n

Terraphim: Your AI agent's memory for mistakes.

\n", "https://terraphim.ai/properties/date" : "2026-02-20", "https://atomicdata.dev/properties/tags" : {"tags":["Terraphim","rust","cli","ai-agents","developer-tools","learning","knowledge-graph"],"categories":["Technical"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/multi-haystack-roles-grepapp/", "https://atomicdata.dev/properties/name" : "Introducing Multi-Haystack Roles: Local + Global Code Search", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/multi-haystack-roles-grepapp/", "https://atomicdata.dev/properties/description" : "

Today we are announcing a significant enhancement to Terraphim's engineer roles: multi-haystack support. FrontEnd Engineers and Python Engineers now have access to both local code search (via Ripgrep) and global GitHub search (via GrepApp) in a single query.

\n

The Problem: Siloed Search

\n

Traditionally, developers face a frustrating choice when searching for code:

\n
    \n
  1. Search locally - Fast, but limited to your own codebase
  2. \n
  3. Search GitHub - Broad, but requires leaving your workflow
  4. \n
\n

When you are stuck on \"how do I use this library?\" or \"what's the idiomatic way to solve this?\", you need both: your local context for project-specific code, and global examples from the broader community.

\n

The Solution: Dual Haystacks

\n

Starting with Terraphim v1.8.1, select engineer roles now come with dual haystacks:

\n

FrontEnd Engineer

\n\n

Python Engineer

\n\n

Rust Engineer v2 (already available)

\n\n

How It Works

\n

When you search as a FrontEnd or Python Engineer, Terraphim queries both sources simultaneously:

\n
Your Query: "how to use useEffect"\n    |\n+-------------------+     +--------------------+\n|  Local Ripgrep    |     |  GrepApp           |\n|  (your code)      |     |  (GitHub repos)    |\n+---------+---------+     +---------+----------+\n          |                         |\n          +-----------+-------------+\n                      |\n           Combined Results\n           (ranked by relevance)\n
\n

The results are merged and ranked according to your role's relevance function:

\n\n

This means you get the best of both worlds: your project's specific implementations AND real-world examples from popular repositories.

\n

Real-World Use Cases

\n

Learning a New Library

\n

You are trying to use react-query for the first time. A single search shows:

\n\n

Debugging Common Patterns

\n

You are debugging a Python asyncio issue. Your search returns:

\n\n

Discovering Idioms

\n

You want to know the \"Pythonic\" way to do something. Instead of reading docs, you can see:

\n\n

Technical Implementation

\n

Under the hood, this uses our existing GrepApp integration:

\n
Haystack {\n    location: "https://grep.app".to_string(),\n    service: ServiceType::GrepApp,\n    read_only: true,\n    fetch_content: false,\n    extra_parameters: {\n        let mut params = HashMap::new();\n        params.insert("language".to_string(), "python".to_string());\n        params\n    },\n}\n
\n

The extra_parameters field allows language-specific filtering:

\n\n

GrepApp returns structured results from millions of GitHub repositories, complete with:

\n\n

Graceful Degradation

\n

We know network availability is not guaranteed. If GrepApp is unreachable:

\n\n

This follows our philosophy: local-first, enhance with global.

\n

What's Next

\n

This is just the beginning. We are planning:

\n
    \n
  1. \n

    More roles with dual haystacks:

    \n\n
  2. \n
  3. \n

    Configurable filters:

    \n\n
  4. \n
  5. \n

    Enhanced ranking:

    \n\n
  6. \n
\n

Try It Now

\n

If you are already using Terraphim v1.8.1+, you can try the new roles immediately:

\n
# Switch to FrontEnd Engineer (with dual haystack)\nterraphim-agent onboard --role frontend-engineer\n\n# Switch to Python Engineer (with dual haystack)\nterraphim-agent onboard --role python-engineer\n\n# Search as usual: both local and global results appear\nterraphim-agent search "async def"\n
\n

The Bigger Picture

\n

Multi-haystack roles represent a fundamental shift in how we think about code search:

\n

Old model: One haystack per role, choose your scope\nNew model: Multiple haystacks per role, get comprehensive results

\n

This aligns with how developers actually work: they do not want to choose between \"my code\" and \"the world's code\" — they want both, intelligently combined.

\n

As we expand this pattern to more roles and add more haystack types (MCP servers, Atomic Data, AI assistants), Terraphim becomes not just a search tool, but a knowledge synthesis engine for developers.

\n

Feedback Welcome

\n

Have ideas for other haystack combinations? Want to see this pattern applied to other roles? Let us know:

\n\n
\n

Related Reading:

\n\n

Terraphim: Search your world.

\n", "https://terraphim.ai/properties/date" : "2026-02-16", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","release","features","grepapp","haystack","code-search"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/native-hook-support/", "https://atomicdata.dev/properties/name" : "Native Hook Support: terraphim-agent Now Learns from Your Mistakes", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/native-hook-support/", "https://atomicdata.dev/properties/description" : "

We are announcing native hook support for terraphim-agent v1.8.1. This feature captures failed commands from AI agents (Claude Code, Codex, OpenCode) and learns from them, creating a personal knowledge base of mistakes and corrections. No more jq dependency, no more bash wrappers: just terraphim-agent learn hook.

\n

The Problem

\n

If you are using AI agents like Claude Code, you have probably experienced this:

\n
    \n
  1. Agent suggests: cargo buid (typo)
  2. \n
  3. Command fails with error
  4. \n
  5. You fix it: cargo build
  6. \n
  7. The mistake is forgotten
  8. \n
  9. Next session: Same typo, same failure
  10. \n
\n

Every developer has their own \"greatest hits\" of mistakes:

\n\n

These mistakes are personal, contextual, and valuable: if only we could remember them.

\n

The Solution: Native Hook Support

\n

With terraphim-agent v1.8.1, we have introduced a complete learning system:

\n
# One-command setup\nterraphim-agent learn install-hook claude\n\n# That's it. Every failed command is now captured automatically.\n
\n

How It Works

\n
Claude Code executes Bash command\n        |\nCommand fails (exit code != 0)\n        |\nHook captures: command + error + context\n        |\nStored as Markdown: ~/.local/share/terraphim/learnings/\n        |\nQuery anytime: terraphim-agent learn query "cargo buid"\n
\n

Key Features

\n

1. Native Implementation

\n\n

2. Universal Support\nWorks with Claude Code, Codex, and OpenCode:

\n
terraphim-agent learn install-hook claude\nterraphim-agent learn install-hook codex\nterraphim-agent learn install-hook opencode\n
\n

3. Fail-Open Design\nNever blocks your workflow. If capture fails, the command still executes.

\n

4. Smart Filtering

\n\n

5. Rich Context\nEach learning includes:

\n\n

Live Demonstration

\n

Let us prove it works with a realistic scenario:

\n

Step 1: Set Role

\n
$ terraphim-agent setup --template rust-engineer-v2\nConfiguration set to role 'Rust Engineer v2'\n
\n

Step 2: Capture Mistake

\n
# Simulate Claude Code making a typo\necho '{"tool_name":"Bash","tool_input":{"command":"cargo buid"},...}' \\\n  | ~/.config/claude/terraphim-hook.sh\n
\n

Step 3: Verify Capture

\n
$ terraphim-agent learn list\nRecent learnings:\n  1. [G] cargo buid (exit: 101)\n
\n

Step 4: Query Mistake

\n
$ terraphim-agent learn query "cargo buid"\nLearnings matching 'cargo buid':\n  [G] cargo buid (exit: 101)\n
\n

Multi-Role Engineering

\n

We have also added 4 new engineer role templates, each with different ranking methods:

\n\n\n\n\n\n
RoleRankingUse Case
FrontEnd EngineerBM25PlusJavaScript/TypeScript development
Python EngineerBM25FPython with field-weighted ranking
Rust Engineer v2TitleScorerDual haystack (docs.rs + local)
Terraphim Engineer v2TerraphimGraphGraph embeddings + hybrid KG
\n

Each role learns differently and optimises search for its domain.

\n

The Complete Learning Cycle

\n
+-------------------------------------------------------------+\n|  1. LEARN                                                    |\n|     Command fails -> Hook captures -> Markdown stored        |\n|     Works with Claude, Codex, OpenCode                       |\n+-------------------------------------------------------------+\n|  2. QUERY                                                    |\n|     Search patterns -> Find similar mistakes                 |\n|     Pattern matching on command + error                      |\n+-------------------------------------------------------------+\n|  3. CORRECT                                                  |\n|     Add corrections: learn correct <id> --correction         |\n|     Future: Auto-suggest from knowledge graph                |\n+-------------------------------------------------------------+\n|  4. REPLACE                                                  |\n|     Real-time suggestions via replace --role <role>          |\n|     Uses thesaurus for context-aware corrections             |\n+-------------------------------------------------------------+\n
\n

Installation

\n
# Install latest terraphim-agent\ncargo install terraphim-agent\n\n# Install hook for your AI agent\nterraphim-agent learn install-hook claude\n\n# Verify installation\nterraphim-agent learn --help\n
\n

Verification and Validation

\n

This release passed rigorous quality gates:

\n\n

What's Next

\n
    \n
  1. Auto-suggest: Query learnings in real-time during command entry
  2. \n
  3. Learning insights: Analytics on most common mistakes per role
  4. \n
  5. Team sharing: Optional sync of learnings across team members
  6. \n
  7. IDE integration: VS Code extension for inline suggestions
  8. \n
\n

Get Started

\n
# Install\ncargo install terraphim-agent\n\n# Set up your role\nterraphim-agent setup --template rust-engineer-v2\n\n# Install hook\nterraphim-agent learn install-hook claude\n\n# Start learning from your mistakes\n
\n

Links

\n\n
\n

Terraphim: Your AI agent's memory for mistakes.

\n", "https://terraphim.ai/properties/date" : "2026-02-16", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","rust","cli","ai-agents","developer-tools","learning"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/zvec-vs-terraphim-comparison/", "https://atomicdata.dev/properties/name" : "zvec vs Terraphim: Two Paths to Semantic Search", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/zvec-vs-terraphim-comparison/", "https://atomicdata.dev/properties/description" : "

When it comes to semantic search, there are fundamentally different architectural approaches. Alibaba's zvec and Terraphim represent two distinct philosophies: neural embeddings vs. knowledge graphs, scale vs. interpretability, dense vectors vs. co-occurrence relationships.

\n

The Core Philosophy

\n

zvec: Neural Embeddings at Scale

\n

zvec is a lightweight, in-process vector database built on Alibaba's battle-tested Proxima engine. It transforms documents into high-dimensional vectors using neural embedding models (BERT, OpenAI, etc.), then uses Approximate Nearest Neighbour (ANN) algorithms like HNSW to find similar documents.

\n

Key Characteristics:

\n\n

Terraphim: Knowledge Graphs for Understanding

\n

Terraphim takes a radically different approach. Instead of converting documents to opaque vectors, it builds a knowledge graph from term co-occurrences. Each concept becomes a node, relationships become edges, and relevance is calculated by traversing this graph structure.

\n

Key Characteristics:

\n\n

Architectural Comparison

\n
+-------------------------------------------------------------+\n|                         zvec                                 |\n+-------------------------------------------------------------+\n|  Document -> Neural Encoder -> Dense Vector -> HNSW Index    |\n|                                                    |         |\n|  Query -> Neural Encoder -> Query Vector -> ANN Search -> K  |\n+-------------------------------------------------------------+\n                              vs\n+-------------------------------------------------------------+\n|                       Terraphim                              |\n+-------------------------------------------------------------+\n|  Document -> Term Extraction -> Co-occurrence -> Graph       |\n|                                                   |          |\n|  Query -> Aho-Corasick Match -> Graph Traversal -> Ranked    |\n+-------------------------------------------------------------+\n
\n

Data Structures

\n\n\n\n\n\n\n
ComponentzvecTerraphim
Storage UnitCollection (table-like)RoleGraph (knowledge graph)
Document IDStringString
RepresentationsDense/Sparse vectors (768-dim+)Nodes, Edges, Thesaurus
Index TypesHNSW, IVF, Flat, InvertedHash maps + Aho-Corasick
PersistenceDisk-based collectionsJSON serialisation
\n

Query Semantics

\n

zvec Query:

\n
import zvec\n\n# Semantic similarity via vector comparison\nresults = collection.query(\n    zvec.VectorQuery("embedding", vector=[0.1, -0.3, ...]),\n    topk=10,\n    filter="category == 'tech'"\n)\n# Returns: documents with similar vectors (cosine similarity)\n
\n

Terraphim Query:

\n
// Graph traversal with term expansion\nlet results = role_graph.query_graph(\n    "async programming",\n    Some(0),  // offset\n    Some(10)  // limit\n);\n// Returns: documents ranked by graph connectivity\n// Matched nodes: "async", "programming", "concurrency", "tokio"\n
\n

Feature Matrix

\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FeaturezvecTerraphim
Dense EmbeddingsNativeNot used
Sparse VectorsBM25 supportedBM25/BM25F/BM25Plus
Knowledge GraphNoCore architecture
ANN SearchHNSW/IVF/FlatNot applicable
SQL-like FiltersSQL engineGraph-based filtering
ExplainabilityLow (black box)High (show path)
Synonym ExpansionVia embedding modelVia thesaurus
Role/Persona SupportNoRoleGraphs
Multi-HaystackSingle collectionMultiple sources
Built-in RerankersRRF, WeightedGraph ranks directly
QuantisationINT8/FP16Not needed
Hybrid SearchVectors + FiltersGraph + Haystacks
\n

Performance Characteristics

\n

zvec (Benchmarks from 10M vector dataset)

\n\n

Terraphim (Observed Performance)

\n\n

When to Use Which

\n

Choose zvec When:

\n
    \n
  1. \n

    You need to search billions of documents

    \n\n
  2. \n
  3. \n

    You are building RAG systems with LLMs

    \n\n
  4. \n
  5. \n

    You need image/audio similarity search

    \n\n
  6. \n
  7. \n

    Exact semantic similarity matters

    \n\n
  8. \n
\n

Choose Terraphim When:

\n
    \n
  1. \n

    You need explainable results

    \n\n
  2. \n
  3. \n

    You have domain-specific knowledge

    \n\n
  4. \n
  5. \n

    You are building personal knowledge management

    \n\n
  6. \n
  7. \n

    You need role-based search

    \n\n
  8. \n
\n

Code Comparison

\n

Document Indexing

\n

zvec (Python):

\n
import zvec\n\nschema = zvec.CollectionSchema(\n    name="docs",\n    vectors=zvec.VectorSchema("emb", zvec.DataType.VECTOR_FP32, 768),\n)\n\ncollection = zvec.create_and_open(path="./data", schema=schema)\n\n# Documents must have pre-computed embeddings\ncollection.insert([\n    zvec.Doc(\n        id="doc1",\n        vectors={"emb": embedding_model.encode("Rust async programming")},\n        fields={"title": "Async in Rust"}\n    ),\n])\n
\n

Terraphim (Rust):

\n
use terraphim_rolegraph::RoleGraph;\nuse terraphim_types::{Document, RoleName};\n\nlet mut graph = RoleGraph::new(\n    RoleName::new("engineer"),\n    thesaurus\n).await?;\n\n// Documents are indexed into the graph\ngraph.index_documents(vec![\n    Document {\n        id: "doc1".into(),\n        title: "Async in Rust".into(),\n        body: "Rust's async/await syntax...".into(),\n        // Graph extracts terms automatically\n        ..Default::default()\n    },\n]).await?;\n
\n

Searching

\n

zvec:

\n
# Vector similarity search\nquery_vec = embedding_model.encode("how to write async code")\nresults = collection.query(\n    zvec.VectorQuery("emb", vector=query_vec),\n    topk=5\n)\n# Results ranked by cosine similarity\n
\n

Terraphim:

\n
// Graph-based search\nlet results = graph.query_graph("async code", None, Some(5))?;\n// Results ranked by:\n// 1. Node rank (concept frequency)\n// 2. Edge rank (relationship strength)\n// 3. Document rank (occurrence count)\n
\n

Can They Work Together?

\n

Absolutely. Here are some integration patterns:

\n

1. Hybrid Retrieval

\n

Use zvec for initial broad retrieval, Terraphim for reranking:

\n
# Step 1: zvec ANN for candidate retrieval\ncandidates = zvec_collection.query(query_vector, topk=100)\n\n# Step 2: Terraphim graph reranking\n# Load candidates into temporary graph\n# Re-rank based on knowledge graph connectivity\n
\n

2. Explainable Vector Search

\n

Use Terraphim's graph to explain zvec results:

\n
User: "Why did this document match?"\nSystem:\n  - zvec: "Vector similarity: 0.92"\n  - Terraphim: "Matched via concepts: async -> tokio -> concurrency"\n
\n

Conclusion

\n

zvec and Terraphim solve semantic search with fundamentally different approaches:

\n\n

The exciting possibility is combining both: zvec's scale with Terraphim's explainability. The future of semantic search might just be hybrid.

\n

References

\n\n
\n

Have you used zvec or Terraphim? We would love to hear about your experiences on GitHub Issues.

\n", "https://terraphim.ai/properties/date" : "2026-02-16", "https://atomicdata.dev/properties/tags" : {"categories":["Technical"],"tags":["Terraphim","vector-search","knowledge-graph","semantic-search","comparison"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/teaching-ai-agents-with-knowledge-graphs/", "https://atomicdata.dev/properties/name" : "Teaching AI Coding Agents with Knowledge Graph Hooks", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/teaching-ai-agents-with-knowledge-graphs/", "https://atomicdata.dev/properties/description" : "

How we use Aho-Corasick automata and knowledge graphs to automatically enforce coding standards across AI coding agents like Claude Code, Cursor, and Aider.

\n
\n

New: see Why Graph Embeddings Matter for the underlying engine that makes these hooks possible — sub-millisecond, deterministic, fully explainable.

\n
\n

Anthropic Bought Bun. Claude Still Outputs npm install.

\n

On December 3, 2025, Anthropic announced its first-ever acquisition: Bun, the blazing-fast JavaScript runtime. This came alongside Claude Code reaching $1 billion in run-rate revenue just six months after public launch.

\n

As Mike Krieger, Anthropic's Chief Product Officer, put it:

\n
\n

\"Bun represents exactly the kind of technical excellence we want to bring into Anthropic... bringing the Bun team into Anthropic means we can build the infrastructure to compound that momentum.\"

\n
\n

Claude Code ships as a Bun executable to millions of developers. Anthropic now owns the runtime their flagship coding tool depends on.

\n

And yet...

\n

Ask Claude to set up a Node.js project, and what do you get?

\n
npm install express\nyarn add lodash\npnpm install --save-dev jest\n
\n

Yet Anthropic's own models still default to npm, yarn, and pnpm in their outputs. The training data predates the acquisition, and old habits die hard.

\n

So how do you teach your AI coding tools to consistently use Bun, regardless of what the underlying LLM insists on?

\n

The Problem: LLMs Don't Know Your Preferences

\n

AI coding agents are powerful, but they're trained on the internet's collective habits—which means npm everywhere. Your team might have standardized on Bun for its speed (25% monthly growth, 7.2 million downloads in October 2025), but every AI agent keeps suggesting the old ways.

\n

Manually fixing these inconsistencies is tedious. What if your knowledge graph could automatically intercept and transform AI outputs?

\n

The Solution: Knowledge Graph Hooks

\n

Terraphim provides a hook system that intercepts AI agent actions and applies knowledge graph-based transformations. The system uses:

\n
    \n
  1. Aho-Corasick automata for efficient multi-pattern matching
  2. \n
  3. LeftmostLongest strategy ensuring specific patterns match before general ones
  4. \n
  5. Markdown-based knowledge graph files that are human-readable and version-controlled
  6. \n
\n

How It Works

\n
Input Text → Aho-Corasick Automata → Pattern Match → Knowledge Graph Lookup → Transformed Output\n
\n

The knowledge graph is built from simple markdown files:

\n
# bun install\n\nFast package installation with Bun.\n\nsynonyms:: pnpm install, npm install, yarn install\n
\n

When the automata encounter any synonym, they replace it with the canonical term (the heading).

\n

Real-World Example: npm → bun

\n

Let's prove it works. Here's a live test:

\n
$ echo "npm install" | terraphim-agent replace\nbun install\n\n$ echo "yarn install lodash" | terraphim-agent replace\nbun install lodash\n\n$ echo "pnpm install --save-dev jest" | terraphim-agent replace\nbun install --save-dev jest\n
\n

The LeftmostLongest matching ensures npm install matches the more specific pattern before standalone npm could match.

\n

Hook Integration Points

\n

Terraphim hooks integrate at multiple points in the development workflow:

\n

1. Claude Code PreToolUse Hooks

\n

Intercept Bash commands before execution:

\n
{\n  "hooks": {\n    "PreToolUse": [{\n      "matcher": "Bash",\n      "hooks": [{\n        "type": "command",\n        "command": "terraphim-agent replace"\n      }]\n    }]\n  }\n}\n
\n

When Claude Code tries to run npm install express, the hook transforms it to bun install express before execution.

\n

2. Git prepare-commit-msg Hooks

\n

Enforce attribution standards in commits:

\n
#!/bin/bash\nCOMMIT_MSG_FILE=$1\nORIGINAL=$(cat "$COMMIT_MSG_FILE")\nTRANSFORMED=$(echo "$ORIGINAL" | terraphim-agent replace)\necho "$TRANSFORMED" > "$COMMIT_MSG_FILE"\n
\n

With a knowledge graph entry:

\n
# Terraphim AI\n\nAttribution for AI-assisted development.\n\nsynonyms:: Claude Code, Claude, Anthropic Claude\n
\n

Every commit message mentioning \"Claude Code\" becomes \"Terraphim AI\".

\n

3. MCP Tools

\n

The replace_matches MCP tool exposes the same functionality to any MCP-compatible client:

\n
{\n  "tool": "replace_matches",\n  "arguments": {\n    "text": "Run npm install to setup"\n  }\n}\n
\n

Architecture

\n

The hook system is built on three crates:

\n\n\n\n\n
CratePurpose
terraphim_automataAho-Corasick pattern matching, thesaurus building
terraphim_hooksReplacementService, HookResult, binary discovery
terraphim_agentCLI with replace subcommand
\n

Performance

\n\n

Extending the Knowledge Graph

\n

Adding new patterns is simple. Create a markdown file in the mdBook source tree under docs/src/kg/ (published at https://docs.terraphim.ai/src/kg/).

\n
# pytest\n\nPython testing framework.\n\nsynonyms:: python -m unittest, unittest, nose\n
\n

The system automatically rebuilds the automata on startup.

\n

Pattern Priority

\n

The LeftmostLongest strategy means:

\n\n

Installation

\n

Quick Setup

\n
# Install all hooks\n./scripts/install-terraphim-hooks.sh --easy-mode\n\n# Test the replacement\necho "npm install" | ./target/release/terraphim-agent replace\n
\n

Manual Setup

\n
    \n
  1. Build the agent:
  2. \n
\n
cargo build -p terraphim_agent --features repl-full --release\n
\n
    \n
  1. \n

    Configure Claude Code hooks in .claude/settings.local.json

    \n
  2. \n
  3. \n

    Install Git hooks:

    \n
  4. \n
\n
cp scripts/hooks/prepare-commit-msg .git/hooks/\nchmod +x .git/hooks/prepare-commit-msg\n
\n

Use Cases

\n\n\n\n\n\n\n
Use CasePatternReplacement
Package manager standardizationnpm, yarn, pnpmbun
AI attributionClaude Code, ClaudeTerraphim AI
Framework migrationReact.ComponentReact functional components
API versioning/api/v1/api/v2
Deprecated function replacementmoment()dayjs()
\n

Claude Code Skills Plugin

\n

For AI agents that support skills, we provide a dedicated plugin:

\n
claude plugin install terraphim-engineering-skills@terraphim-ai\n
\n

The terraphim-hooks skill teaches agents how to:

\n\n

Conclusion

\n

Knowledge graph hooks provide a powerful, declarative way to enforce coding standards across AI agents. By defining patterns in simple markdown files, you can:

\n\n

The Aho-Corasick automata ensure efficient matching regardless of pattern count, making this approach scale to large knowledge graphs.

\n

Next Steps

\n

To wire knowledge-graph hooks into your own project, the Command Rewriting How-to walks through the configuration end to end. To understand why the matching is sub-millisecond and deterministic — and what that lets you promise to your users — read Why Graph Embeddings Matter.

\n

Resources

\n\n", "https://terraphim.ai/properties/date" : "2025-12-28", "https://atomicdata.dev/properties/tags" : {"tags":["Terraphim","ai","hooks","knowledge-graph","claude-code","developer-tools","bun","anthropic"],"categories":["Technical"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/posts/post-0/", "https://atomicdata.dev/properties/name" : "Announcing Terraphim AI", "https://terraphim.ai/properties/url" : "https://terraphim.ai/posts/post-0/", "https://atomicdata.dev/properties/description" : "

We have a few end-to-end demos and user journeys to discuss with early adopters of Terraphim - Privacy Preserving AI assistant.

\n", "https://terraphim.ai/properties/date" : "2023-08-12", "https://atomicdata.dev/properties/tags" : {"tags":["Terraphim","ai","announcement"],"categories":["Announcements"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/local-first/", "https://atomicdata.dev/properties/name" : "Local-First Architecture", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/local-first/", "https://atomicdata.dev/properties/description" : "

Privacy by Architecture, Not by Policy

\n

Terraphim AI is not \"privacy-respecting\" because of a terms-of-service promise. It is private because the architecture makes data exfiltration structurally impossible. All indexing, searching, and knowledge graph traversal happens entirely on your device. There is no cloud dependency, no telemetry, no analytics phone-home.

\n

Design Principles

\n

The search architecture is deliberately non-neural and offline-first:

\n\n\n\n\n\n\n
PrincipleWhat It Means
Offline-firstNo network calls or LLM inference required at search time
DeterministicSame query plus same corpus equals same results, always
ExplainableEvery score decomposes into frequency counts, field weights, or set overlaps
Low footprintApproximately 15-20 MB RAM for a typical knowledge graph; no GPU, no float vectors
Graph-nativeExplicit edges and nodes encode domain relationships, not latent geometry
\n

No Account Required

\n

There is no sign-up, no API key, no subscription. You install Terraphim and it works. Your search history, your knowledge graphs, your indexed documents — all of it stays on your machine under your control.

\n

How It Compares

\n

Traditional enterprise search tools upload your data to cloud servers, process it with proprietary models, and return results through APIs that require authentication and ongoing payment. Terraphim inverts this model entirely:

\n\n

Deployment Options

\n

Terraphim runs wherever you need it: as a native desktop application, a WebAssembly module in your browser, a CLI tool, or a TUI (terminal user interface). For teams that need shared access, Terraphim Private Cloud uses AWS Firecracker microVMs to give each user a dedicated virtual machine with their own TLS certificate — keeping data isolated even in multi-tenant deployments.

\n

Learn More

\n\n", "https://terraphim.ai/properties/date" : "2026-04-05", "https://atomicdata.dev/properties/tags" : {"tags":["privacy","local-first","offline","architecture"],"categories":["Capabilities"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/knowledge-graph/", "https://atomicdata.dev/properties/name" : "Knowledge Graph Engine", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/knowledge-graph/", "https://atomicdata.dev/properties/description" : "

Thousands of Patterns in a Single Pass

\n

At the heart of Terraphim is a knowledge graph engine that uses Aho-Corasick finite state automata for multi-pattern matching. Unlike traditional keyword search, Aho-Corasick matches thousands of patterns simultaneously in O(n) time relative to the text length — regardless of how many patterns are in the graph.

\n

How It Works

\n

The search pipeline operates in stages:

\n
    \n
  1. Lexical Extraction — Aho-Corasick automaton matches all thesaurus terms simultaneously, with case-insensitive, leftmost-longest matching
  2. \n
  3. Graph Traversal — Matched nodes are traversed through the RoleGraph, accumulating node rank, edge rank, and document rank
  4. \n
  5. Statistical Ranking — Pluggable scorers (BM25, BM25F, BM25+, TF-IDF, Jaccard, QueryRatio) rank results
  6. \n
  7. Similarity Re-ranking — Optional fuzzy matching via Levenshtein, Jaro, or Jaro-Winkler distance
  8. \n
\n

Role-Based Knowledge Graphs

\n

Each Terraphim role has its own separate knowledge graph containing concepts relevant to that domain, with all synonyms. A systems engineer, a project manager, and a quality analyst each see the same documents ranked differently based on their role's knowledge graph.

\n

Knowledge graphs are built from industry standards, reference process models, handbooks, and curated taxonomies. Terraphim imports these sources and produces a graph following the SIPOC pattern — concepts at the input and output of processes, with activity names linking them.

\n

Dynamic Ontology

\n

Terraphim's Dynamic Ontology enables schema-first knowledge graph construction:

\n\n

Synonym Control and Multilingual Matching

\n

Users specify synonyms manually and rebuild graph embeddings within 20 milliseconds. This allows matching terms in different languages to the same concept without running language detection. There is no need for a stop-word dictionary — \"The Pattern\" matches exactly as a project name, even though \"The\" would normally be filtered as a stop word.

\n

Learn More

\n\n", "https://terraphim.ai/properties/date" : "2026-04-05", "https://atomicdata.dev/properties/tags" : {"tags":["knowledge-graph","aho-corasick","ontology","semantic-search"],"categories":["Capabilities"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/mcp-server/", "https://atomicdata.dev/properties/name" : "MCP Server Integration", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/mcp-server/", "https://atomicdata.dev/properties/description" : "

Connect Your AI Assistant to Local Knowledge

\n

Terraphim includes a native Model Context Protocol (MCP) server that exposes your local knowledge graphs to AI coding assistants like Claude Code, Claude Desktop, and other MCP-compatible tools. Your AI assistant gains domain-specific context without your data leaving your machine.

\n

Available MCP Tools

\n

Paragraph Extraction

\n

Extract paragraphs from text starting at matched terms, with precise line numbers. Useful for referencing function definitions, getting context around specific patterns, or building documentation with accurate line references.

\n

Knowledge Graph Search

\n

Semantic search that returns full document context with file paths. Unlike plain text search, this leverages your role-based knowledge graph to find documents by their conceptual relationship to your query, not just keyword overlap.

\n

Token Tracking

\n

Monitor token usage across your AI assistant sessions. Track how much context is being consumed and optimise your prompts based on actual usage data.

\n

Role-Based Context Enrichment

\n

Different roles need different context. A systems engineer asking about \"requirements\" needs different search results from a quality analyst asking the same word. Terraphim's MCP server routes queries through the active role's knowledge graph, ensuring your AI assistant receives context that matches your current domain.

\n

How It Differs from Cloud Solutions

\n

Typical AI assistant integrations send your files and context to cloud APIs. Terraphim's MCP server runs locally:

\n\n

Integration with Claude Code

\n

Terraphim works as a Claude Code MCP server, providing knowledge-graph-boosted file search, concept extraction, and role-based context enrichment directly within your development workflow.

\n

Learn More

\n\n", "https://terraphim.ai/properties/date" : "2026-04-05", "https://atomicdata.dev/properties/tags" : {"categories":["Capabilities"],"tags":["mcp","ai-assistant","claude","context-engineering"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/rust-wasm/", "https://atomicdata.dev/properties/name" : "Rust/WASM Performance", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/rust-wasm/", "https://atomicdata.dev/properties/description" : "

Near-Native Speed, Everywhere

\n

Terraphim AI is written in Rust and compiles to WebAssembly. This is not a marketing choice — it is a performance requirement. Knowledge graph inference runs in 5 to 10 nanoseconds. Pipeline processing completes in hundreds of milliseconds. Search queries resolve in sub-millisecond time.

\n

Why Rust

\n

Rust provides memory safety without garbage collection, zero-cost abstractions, and thread safety guaranteed at compile time. For a system that builds and traverses knowledge graphs with thousands of nodes and edges, these guarantees translate directly into reliable performance without unexpected pauses or memory leaks.

\n

Why WebAssembly

\n

WebAssembly allows the same Rust codebase to run:

\n\n

One codebase, compiled to multiple targets, with no performance compromise.

\n

Performance Numbers

\n

The journey from The Pattern to Terraphim AI tells the performance story:

\n\n\n\n\n\n
MetricTraditional ML PipelineThe PatternTerraphim AI
Data processing for training6 days6 hoursHundreds of milliseconds
Inference latencySecondsUnder 2 ms5-10 nanoseconds
RAM footprintGigabytesHundreds of MB15-20 MB
GPU requiredYesNoNo
\n

Benchmarking

\n

Terraphim includes a comprehensive benchmarking framework covering:

\n\n

All benchmarks run on standard hardware — no GPU, no specialised accelerator.

\n

Low Footprint

\n

A typical Terraphim knowledge graph occupies approximately 15-20 MB of RAM. There are no float vectors, no dense embeddings, no GPU memory allocation. This means Terraphim runs comfortably on a laptop, a Raspberry Pi, or a modest cloud instance.

\n

Learn More

\n\n", "https://terraphim.ai/properties/date" : "2026-04-05", "https://atomicdata.dev/properties/tags" : {"categories":["Capabilities"],"tags":["rust","wasm","performance","benchmarks"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/hooks/", "https://atomicdata.dev/properties/name" : "Hooks System", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/hooks/", "https://atomicdata.dev/properties/description" : "

Two-Stage Runtime Validation

\n

Terraphim implements a two-stage runtime validation system for AI-assisted development workflows. Every tool execution and LLM generation passes through hooks that provide both safety and intelligence enhancement.

\n

Stage 1: Guard Stage

\n

The guard stage prevents dangerous operations before any processing occurs:

\n\n

Stage 2: Replacement Stage

\n

The replacement stage enhances text using knowledge graph patterns:

\n\n

Learning from Mistakes

\n

Failed commands are automatically captured by post-tool-use hooks. When a bash command fails, Terraphim records the failure for later review. Over time, you build a searchable history of what went wrong and how it was corrected.

\n
# Review captured learnings\nterraphim-agent learn list\n\n# Query by pattern\nterraphim-agent learn query "npm"\n\n# Add a correction\nterraphim-agent learn correct <id> "use bun instead"\n
\n

This turns individual debugging sessions into institutional knowledge that persists across conversations and team members.

\n

Hook Types

\n

Terraphim supports hooks at four points in the AI workflow:

\n\n\n\n\n\n
HookPurpose
Pre-LLMValidate prompts before generation; block, modify, or require human confirmation
Post-LLMValidate responses; catch harmful content, enforce formatting
Pre-ToolValidate commands before execution; security checks, injection prevention
Post-ToolMonitor results; track performance, capture failures for learning
\n

Configuration

\n

Hooks are configured via TOML and environment variables, with sensible defaults:

\n\n

Deep Dives

\n\n", "https://terraphim.ai/properties/date" : "2026-04-05", "https://atomicdata.dev/properties/tags" : {"categories":["Capabilities"],"tags":["hooks","ai-assistant","learning","security","claude-code"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/kg-file-search/", "https://atomicdata.dev/properties/name" : "KG-Boosted File Search", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/kg-file-search/", "https://atomicdata.dev/properties/description" : "

Beyond Keyword Matching

\n

Traditional file search finds files by name or by text content. Terraphim's KG-boosted file search finds files by their semantic relationship to your domain concepts and role-specific vocabulary.

\n

When you search for \"requirements validation\", Terraphim does not just grep for those words. It traverses your knowledge graph to find documents connected to those concepts through synonyms, co-occurrence edges, and domain relationships. A document titled \"acceptance criteria review\" surfaces because the knowledge graph knows these concepts are related in a systems engineering context.

\n

Multi-Source Search

\n

Terraphim searches across multiple sources simultaneously:

\n\n

Results from all sources are unified, deduplicated, and ranked using a single knowledge graph.

\n

Intelligent Deduplication

\n

When searching across multiple haystacks, the same document often appears in different sources. Terraphim handles duplicates intelligently, merging results and preserving the highest-ranked version rather than showing the same content multiple times.

\n

Role-Specific Relevance

\n

The same search query produces different rankings for different roles:

\n\n

Each role's knowledge graph contains domain-specific concepts and synonyms that reshape how results are scored and ordered.

\n

Context Collections

\n

Terraphim organises searchable content into context collections — curated sets of documents, taxonomies, and vocabulary that define a domain. Collections can be shared across a team or customised per user, providing consistent search relevance without centralised configuration.

\n

Integration with AI Assistants

\n

Through the MCP server, KG-boosted file search is available directly in your AI coding assistant. When Claude Code searches for files, it uses your knowledge graph to find semantically relevant results, not just filename matches.

\n

Learn More

\n\n", "https://terraphim.ai/properties/date" : "2026-04-05", "https://atomicdata.dev/properties/tags" : {"categories":["Capabilities"],"tags":["search","knowledge-graph","semantic","role-based"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/origin-story/", "https://atomicdata.dev/properties/name" : "Origin Story", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/origin-story/", "https://atomicdata.dev/properties/description" : "

Inspired by Science Fiction

\n

The name Terraphim comes from the Relict series of science fiction novels by Vasiliy Golovachev. In Golovachev's universe a Terraphim is an artificial intelligence that lives inside a spacesuit — part of an exocortex — or inside your house or vehicle, designed to help you with your tasks. You carry it with you.

\n

Similar companions are now familiar across modern science fiction. Destiny 2 has Ghost, a small floating AI bound to its Guardian. Star Wars Jedi: Survivor has BD-1, a droid riding on Cal Kestis's back. Same pattern: a compact, mobile, personal intelligence that augments rather than replaces.

\n

That image — small, local, loyal, always with you — drives the engineering choices in the rest of this page. Terraphim runs on your hardware, codifies knowledge as compact graphs rather than heavyweight models, and never ships your data across a boundary. The sci-fi premise is the brief; what follows is how we built it.

\n

From Kaggle to Nanosecond Inference

\n

Terraphim AI did not start as a product. It started as a frustration with how slowly machine learning pipelines process data.

\n

The project's predecessor, The Pattern, grew out of participation in two Kaggle data science competitions. The original ML pipeline could not finish processing data in six days. The Pattern processed the same data for training in six hours and achieved under two-millisecond inference. That hundredfold improvement was not a hardware upgrade — it was a fundamental rethinking of how search and retrieval should work.

\n

Redis Hackathon Platinum Winner

\n

The Pattern was awarded Platinum Winner at the Redis Hackathon, outperforming Nvidia's ML pipeline for BERT QA inference on CPU. The prize confirmed that external experts recognised the approach as genuinely innovative, not merely a clever optimisation.

\n

The results were presented and discussed at a public lecture at Oxford University, Green Templeton College, bringing academic scrutiny to the architecture that would become Terraphim AI.

\n

The Breakthrough: Graph Embeddings Without Attention

\n

Traditional search systems rely on dense vector embeddings and attention mechanisms that are expensive, opaque, and non-deterministic. Terraphim took a different path.

\n

Terraphim Graph Embeddings maintain the position of terms in a sentence without requiring traditional training techniques like attention. Users can specify synonyms manually and rebuild graph embeddings for a role within 20 milliseconds. This allows matching terms in different languages to the same concept without running language detection, and eliminates the need for stop-word dictionaries entirely.

\n

By rethinking from the ground up, Terraphim AI achieves pipeline processing in hundreds of milliseconds and knowledge-graph-based inference in 5 to 10 nanoseconds.

\n

Validated by INCOSE

\n

The methodology has been validated within the INCOSE (International Council on Systems Engineering) community for the Systems Engineering Handbook v.4 and the Systems Engineering Digital Process Model v.1. It was recognised as a valid low-effort substitution for formal model-based systems engineering — particularly valuable for brownfield systems engineering, reverse-engineering, and professional certification.

\n

Why Search is Broken

\n

Research consistently shows the problem Terraphim exists to solve:

\n\n

Terraphim's answer: deterministic, privacy-first, knowledge-graph-powered search that runs entirely on your hardware.

\n

Three Differentiators

\n
    \n
  1. Privacy-first: Rather than transferring data across boundaries, Terraphim codifies and moves knowledge graphs. Runs in your browser via WebAssembly.
  2. \n
  3. Action-oriented ontologies: Focused on required outcomes, not exhaustive recognition. Compact knowledge representations following YAGNI principles.
  4. \n
  5. Role-based knowledge lenses: Separate knowledge graphs per role, with user control over modifications.
  6. \n
\n

Learn More

\n\n", "https://terraphim.ai/properties/date" : "2026-04-17", "https://atomicdata.dev/properties/tags" : {"tags":["history","the-pattern","redis","kaggle","oxford","incose","science-fiction","relict"],"categories":["Capabilities"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/graph-embeddings/", "https://atomicdata.dev/properties/name" : "Graph Embeddings", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/graph-embeddings/", "https://atomicdata.dev/properties/description" : "

Terraphim uses graph embeddings instead of neural vector embeddings. Terms and concepts\nare represented as nodes in a role-specific knowledge graph, with relationships encoded as\nedges. Matching a query against a graph is deterministic, auditable, and fast.

\n

See the full design note for how RoleGraph composes\nAho-Corasick matching with PageRank ordering to produce ranked results in\nsub-millisecond time, without any floating-point vector math.

\n

Why graph embeddings

\n\n

This is a fundamentally different model from dense vector retrieval. It is what makes\nTerraphim run on a laptop, a Raspberry Pi, or inside a browser extension.

\n", "https://terraphim.ai/properties/date" : "2026-04-15", "https://atomicdata.dev/properties/tags" : {"categories":["Capability"],"tags":["graph-embeddings","aho-corasick","knowledge-graph","search"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/multi-haystack/", "https://atomicdata.dev/properties/name" : "Multi-Haystack Search", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/multi-haystack/", "https://atomicdata.dev/properties/description" : "

Terraphim roles can be configured with multiple haystacks — named sources of content.\nA single query fans out across every haystack attached to the role and the results come\nback ranked by the role's knowledge graph.

\n

Haystack adapters available today:

\n\n

See the release post Introducing Multi-Haystack Roles: Local + Global Code Search\nfor a walkthrough of combining a local haystack with grepapp to search both your code and\nthe world's code in one query.

\n", "https://terraphim.ai/properties/date" : "2026-04-15", "https://atomicdata.dev/properties/tags" : {"categories":["Capability"],"tags":["haystack","search","grepapp","code-search"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/terraphim-agent/", "https://atomicdata.dev/properties/name" : "terraphim-agent CLI", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/terraphim-agent/", "https://atomicdata.dev/properties/description" : "

terraphim-agent is a command-line AI agent that searches before it answers. It runs\nlocal knowledge graph queries, imports session history from Claude Code and Cursor,\ncaptures failed commands via post-tool-use hooks, and surfaces past corrections when\nyou encounter a recurring error.

\n

Install it with one command:

\n
cargo install terraphim-agent\n
\n

What it does

\n\n

See the command rewriting how-to and the blog post\nTeaching AI Agents to Learn from Their Mistakes\nfor worked examples.

\n", "https://terraphim.ai/properties/date" : "2026-04-15", "https://atomicdata.dev/properties/tags" : {"categories":["Capability"],"tags":["agent","cli","ai-agents","learning"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/evaluation/", "https://atomicdata.dev/properties/name" : "Automata Evaluation", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/evaluation/", "https://atomicdata.dev/properties/description" : "

The evaluation framework measures how accurately the Aho-Corasick automata classify terms in\nreal documents. Give it a JSON file of hand-labeled documents and it returns micro-averaged\nprecision, recall, and F1, a per-term breakdown, and a list of terms that consistently\nproduce false positives.

\n

When to use it

\n\n

Ground-truth file format

\n
[\n  {\n    "id": "doc1",\n    "text": "tokio powers async rust applications",\n    "expected_terms": [\n      { "term": "tokio",  "category": null },\n      { "term": "rust",   "category": null },\n      { "term": "async",  "category": null }\n    ]\n  }\n]\n
\n

Each term must match the normalized term value (nterm) stored in the thesaurus.

\n

Running an evaluation

\n
use terraphim_automata::evaluation::{evaluate, load_ground_truth};\n\nlet docs = load_ground_truth(Path::new("ground_truth.json"))?;\nlet result = evaluate(&docs, thesaurus);\n\nprintln!("F1: {:.2}", result.overall.f1);\nfor report in &result.per_term {\n    println!("  {} precision={:.2} recall={:.2}",\n        report.term, report.metrics.precision, report.metrics.recall);\n}\nfor err in &result.systematic_errors {\n    println!("  SYSTEMATIC FP: {} in {} documents", err.term, err.false_positive_count);\n}\n
\n

How metrics are computed

\n

Metrics are micro-averaged: true positives, false positives, and false negatives are\nsummed across all documents before dividing.

\n

A term is flagged as a SystematicError when it appears as a false positive in 2 or more\ndocuments. Matching is case-insensitive; each term is counted at most once per document.

\n

Source: crates/terraphim_automata/src/evaluation.rs

\n", "https://terraphim.ai/properties/date" : "2026-04-16", "https://atomicdata.dev/properties/tags" : {"categories":["Capabilities"],"tags":["evaluation","automata","testing","quality"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/capabilities/listener-dispatch/", "https://atomicdata.dev/properties/name" : "Gitea Agent Dispatch", "https://terraphim.ai/properties/url" : "https://terraphim.ai/capabilities/listener-dispatch/", "https://atomicdata.dev/properties/description" : "

The listener dispatch feature lets you run terraphim-agent subcommands by mentioning the\nagent in a Gitea issue or comment. The result is posted back as a formatted markdown comment.

\n

Triggering a command

\n

Mention the agent in a Gitea comment with a subcommand and arguments:

\n
@adf:worker search "knowledge graph" --role engineer\n@adf:worker evaluate --role engineer\n@adf:worker learn list\n
\n

The listener parses the text after @adf:, validates it through three security layers, runs\nthe command, and posts the output back to the same issue.

\n

Security

\n

Three checks must all pass before the process is spawned:

\n

1. Shell metacharacter rejection — Input containing |, ;, &, `, $, (,\n), <, or > is rejected immediately. No shell is involved in execution, but this\nprevents confusion if the input is ever logged or replayed.

\n

2. Subcommand allowlist / denylist — Only known safe subcommands are permitted.\nDenied subcommands (listen, repl, interactive, setup, update, sessions)\nare blocked even if added to extra_allowed_subcommands.

\n

3. CommandGuard — A pattern-based guard runs on the full command string before\nprocess spawn. It blocks destructive patterns such as git reset --hard.

\n

Configuration

\n

Enable dispatch in your listener config JSON:

\n
{\n  "identity": { "agent_name": "worker" },\n  "gitea": {\n    "base_url": "https://git.terraphim.cloud",\n    "owner": "terraphim",\n    "repo": "terraphim-ai"\n  },\n  "dispatch": {\n    "timeout_secs": 300,\n    "max_output_bytes": 48000,\n    "specialist_routes": {\n      "evaluate": "eval-bot"\n    }\n  }\n}\n
\n

specialist_routes routes specific subcommands to a named agent rather than running locally.

\n

Output

\n

The comment posted back to Gitea includes the exit code, elapsed time, stdout in a code\nblock, and stderr in a collapsible section. Output is capped at 48 KB. Commands that exceed\n5 minutes are killed and marked **TIMED OUT**.

\n

The --robot flag is always appended, so output is machine-readable JSON regardless of the\nuser's default format.

\n

Source: crates/terraphim_agent/src/shell_dispatch.rs, crates/terraphim_agent/src/listener.rs

\n", "https://terraphim.ai/properties/date" : "2026-04-16", "https://atomicdata.dev/properties/tags" : {"categories":["Capabilities"],"tags":["gitea","agent","dispatch","security","automation"]}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] },{"localId": "https://terraphim.ai/how-tos/command-rewriting-howto/", "https://atomicdata.dev/properties/name" : "Command Rewriting How-To", "https://terraphim.ai/properties/url" : "https://terraphim.ai/how-tos/command-rewriting-howto/", "https://atomicdata.dev/properties/description" : "

How-To: Learning-Driven Command Rewriting

\n

This guide shows how to use terraphim-agent to rewrite shell commands before\nexecution — for example npm install -> bun add or pip install -> uv add — by plugging a knowledge-graph-backed thesaurus into your AI coding\nagent's tool-execution hook.

\n

The mechanism composes three pieces that already exist in terraphim-agent:

\n
    \n
  1. A Logseq-style knowledge graph of command synonyms under\n~/.config/terraphim/docs/src/kg/ (or any role-configured path).
  2. \n
  3. terraphim-agent replace — Aho-Corasick replacement that rewrites text\nusing a role's compiled thesaurus.
  4. \n
  5. A plugin hook in your AI agent (OpenCode, Claude Code, etc.) that\nintercepts every Bash tool call, pipes the command through replace,\nand writes the result back into the tool's args.
  6. \n
\n

Prerequisites

\n\n

1. Curate the knowledge graph

\n

Each concept is one markdown file. The filename stem becomes the concept\nkey; the H1 heading provides the display name used as the replacement; the\nsynonyms:: line lists terms that should be rewritten to it.

\n

Example ~/.config/terraphim/docs/src/kg/bun install.md:

\n
# bun add\n\nInstall dependencies using Bun package manager.\n\nsynonyms:: npm install, yarn install, pnpm install, npm i, yarn add, pnpm add\n
\n

Conventions that matter in practice:

\n\n

Seed set shipped with the Terraphim Engineer role

\n\n\n\n\n\n\n\n\n
FileMaps toCovers
bun.mdbunnpm, yarn, pnpm
bun install.mdbun addnpm install, yarn install, pnpm install, npm i, yarn add, pnpm add
bun run.mdbun runnpm run, yarn run, pnpm run
bunx.mdbunxnpx, pnpx, yarn dlx
uv.mduvpip, pip3, pipx
uv add.mduv addpip install, pip3 install, pip add, pipx install, python -m pip install
uv sync.mduv syncpip install -r requirements.txt
\n

2. Verify with the CLI

\n
printf "npm install express" \\\n  | terraphim-agent replace --role "Terraphim Engineer" --fail-open --json\n
\n

Expected output:

\n
{"result":"bun add express","original":"npm install express","replacements":1,"changed":true}\n
\n

Flags worth knowing:

\n\n

3. Flush the cache after KG edits

\n

Terraphim caches compiled thesauri in a SQLite database at\n/tmp/terraphim_sqlite/terraphim.db (path configured by\ncrates/terraphim_settings/default/settings.toml). Editing a KG markdown\nfile does not invalidate this cache; replace keeps returning the old\nmapping until you flush it.

\n
sqlite3 /tmp/terraphim_sqlite/terraphim.db \\\n  "DELETE FROM terraphim_kv WHERE key LIKE 'thesaurus_%' OR key LIKE 'document_ripgrep_%';"\n
\n

Because /tmp/ is wiped on reboot, a fresh boot always gives the\nup-to-date thesaurus.

\n

4. Wire up the hook (OpenCode example)

\n

OpenCode plugins expose tool.execute.before(input, output) where\noutput.args.command is the mutable shell command about to run. The same\npattern works in Claude Code via the PreToolUse hook script, just with\nshell-stdin instead of a JS closure.

\n
// ~/.config/opencode/plugin/terraphim-hooks.js\nconst REWRITE_MODE = process.env.TERRAPHIM_REWRITE_MODE || "suggest"\nconst REWRITE_ROLE = process.env.TERRAPHIM_REWRITE_ROLE || "Terraphim Engineer"\nconst AUDIT_LOG    = `${process.env.HOME}/Library/Application Support/terraphim/rewrites.log`\n\n// Narrow whitelist of commands whose argument grammar survives a synonym swap.\nconst REWRITEABLE_HEADS =\n  /^\\s*(npm|yarn|pnpm|npx|pnpx|pip|pip3|pipx|python\\s+-m\\s+pip|python3\\s+-m\\s+pip)\\b/i\n\nexport const TerraphimHooks = async ({ $ }) => ({\n  "tool.execute.before": async (input, output) => {\n    if (input.tool !== "Bash" || !output.args?.command) return\n    const command = output.args.command\n\n    const agent = `${process.env.HOME}/.cargo/bin/terraphim-agent`\n\n    // Always run the destructive-command guard first.\n    const g = await $`${agent} guard ${command} --json --fail-open 2>/dev/null || echo '{"decision":"allow"}'`\n    const guard = JSON.parse(g.stdout)\n    if (guard.decision === "block") {\n      throw new Error(`BLOCKED: ${guard.reason}`)\n    }\n\n    const isGitCommit   = /git\\s+(-C\\s+\\S+\\s+)?commit/i.test(command)\n    const isRewriteable = REWRITEABLE_HEADS.test(command)\n    if (!isGitCommit && !isRewriteable) return\n\n    const res     = await $`echo ${command} | ${agent} replace --role ${REWRITE_ROLE} --fail-open --json 2>/dev/null`\n    const parsed  = JSON.parse(res.stdout)\n    const rewrite = (parsed.result || "").trim()\n    if (!parsed.changed || !rewrite || rewrite === command) return\n\n    const line = [\n      new Date().toISOString(), REWRITE_MODE,\n      isGitCommit ? "git-commit" : "pkg-mgr",\n      command.replace(/[\\t\\n\\r]/g, " "),\n      rewrite.replace(/[\\t\\n\\r]/g, " "),\n    ].join("\\t") + "\\n"\n    await $`mkdir -p "$(dirname ${AUDIT_LOG})" < /dev/null && printf %s ${line} >> ${AUDIT_LOG}`\n\n    if (REWRITE_MODE === "apply" || isGitCommit) {\n      output.args.command = rewrite\n    }\n  },\n})\n
\n

Design notes:

\n\n

5. Confirm end-to-end

\n

With the hook installed and the cache flushed, open your agent, ask it to\nrun npm install express, and inspect the audit log:

\n
tail -n 5 ~/Library/Application\\ Support/terraphim/rewrites.log\n
\n

You should see a line like:

\n
2026-04-15T11:32:51.129Z    suggest    pkg-mgr    npm install express    bun add express\n
\n

In suggest mode the command still executes as npm install express; in\napply mode the agent actually runs bun add express.

\n

6. Capturing user corrections (preview)

\n

terraphim-agent learn hook --format <claude|codex|opencode> has three\nmodes driven by --learn-hook-type:

\n\n

At present these corrections are stored but not yet fed back into the\nreplacement thesaurus. Closing that loop is tracked as future work — see\nthe accompanying GitHub issue \"Learning-driven command correction: Phase 2\n& 3\".

\n

Troubleshooting

\n

replace returns the original unchanged.\nRun terraphim-agent search \"<synonym>\" --role \"<role>\" — if the concept\nappears, the KG is loaded but the synonym is not. Confirm the synonym is on\nthe synonyms:: line (case-insensitive; commas separate entries). Flush\nthe cache (section 3) and retry.

\n

Failed to load thesaurus: NotFound(\"thesaurus_...\") in stderr.\nCosmetic. The agent looked for a pre-compiled JSON thesaurus first, didn't\nfind one, and fell back to building from markdown. Expected on first run.

\n

Hook does nothing in OpenCode.\nCheck the plugin loaded: grep terraphim-hooks ~/.local/share/opencode/log/$(ls -t ~/.local/share/opencode/log/ | head -1).\nYou should see a line like service=plugin path=...terraphim-hooks.js loading plugin. If absent, the plugin file is in the wrong directory —\nOpenCode autoloads from ~/.config/opencode/plugin/ and\n~/.config/opencode/plugins/.

\n

Commands get double-rewritten on retry.\nThe hook only touches tool.execute.before; the agent does not loop back\nthrough the hook on its own retries. If you see double rewrites, check\nwhether input.tool === \"Bash\" is spelt exactly — OpenCode passes\n\"Bash\", not \"bash\".

\n", "https://terraphim.ai/properties/date" : "2026-04-15", "https://atomicdata.dev/properties/tags" : {}, "https://atomicdata.dev/properties/isA": [ "https://atomicdata.dev/classes/Article" ] }]