Server data from the Official MCP Registry
Branchable LLM history DAG + encrypted context capsules agents can save, restore, and crypto-shred.
Branchable LLM history DAG + encrypted context capsules agents can save, restore, and crypto-shred.
ForkMind is a well-architected local-first LLM debugging tool with proper authentication delegation, secure crypto practices, and permissions aligned to its purpose. Minor concerns around filesystem path validation in capsule operations and environment variable exposure in headers do not materially impact security given the server's local-only default binding and the user-controlled nature of the upstream credentials. Supply chain analysis found 14 known vulnerabilities in dependencies (0 critical, 9 high severity). Package verification found 1 issue.
5 files analyzed Β· 20 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
This plugin requests these system permissions. Most are normal for its category.
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-medhovarsh-forkmind": {
"args": [
"-y",
"forkmind"
],
"command": "npx"
}
}
}From the project's GitHub README.
Local-first LLM state branching & debugging. ForkMind treats AI context
windows like a Git repository: it captures every LLM call into a local
.forkmind/ directory, visualizes the conversation as a Directed Acyclic Graph
(DAG), and lets you branch alternative prompts or model params from any point
in the history β all on your machine, no cloud, no account.
Works with any OpenAI-compatible API, defaulting to free, open-source models via Ollama. Also supports Anthropic and any hosted free tier (Groq, OpenRouter, Together, vLLM, LM Studio).

Live demo: a conversation tree with a branch off the root, the node inspector (request/response, tokens, provenance), and the Fork from here dialog.

Debugging agentic / tool-calling flows means re-running the same prompt with tiny tweaks over and over. ForkMind records each run as a node, so you can:
Everything is plain JSON on disk. No database. No telemetry.
# Run without installing (published on npm)
npx forkmind init
npx forkmind start
# β¦or install the CLI globally
npm install -g forkmind
forkmind start
No npm registry needed either β ForkMind runs straight from the git link, and the dashboard builds automatically on install:
# Run without installing, from GitHub
npx github:medhovarsh/forkmind init
npx github:medhovarsh/forkmind start
# β¦or clone to hack on it
git clone https://github.com/medhovarsh/forkmind
cd forkmind && npm install
ForkMind ships a Claude Code plugin (skill + /forkmind command) so Claude knows
when and how to drive it β same install flow as any marketplace plugin:
/plugin marketplace add Medhovarsh/forkmind
/plugin install forkmind
The plugin bundles:
forkmind skill β Claude reaches for ForkMind whenever you ask it to debug
a prompt, compare models, branch from a past turn, or regression-test a call./forkmind command β start / branch / test / mcp on demand.forkmind-debugger agent β runs model/prompt comparisons in an isolated
context and returns a compact verdict instead of dumping transcripts..forkmind/ history
(recall attempts, trace lineage, self-correct) with zero manual config.The CLI is still what runs the proxy + dashboard; the plugin is the glue that teaches Claude to use it.
# 1. Install a free local model
# (install Ollama from https://ollama.com first)
ollama pull llama3
# 2. Init + start ForkMind
npx github:medhovarsh/forkmind init # create .forkmind/ in your project
npx github:medhovarsh/forkmind start # proxy on http://localhost:4500 + dashboard
# 3. Point your code at the proxy (see SDK below), make some calls
# 4. Open the dashboard
open http://localhost:4500
npm i openai # the wrapper extends the official SDK
const { ForkMindOpenAI } = require('forkmind');
const client = new ForkMindOpenAI({
apiKey: 'ollama', // ignored by Ollama; required by SDK
upstream: 'http://localhost:11434', // free local open-source models
});
// Each call is recorded; sequential calls auto-chain into a conversation tree.
const res = await client.chat.completions.create({
model: 'llama3',
messages: [{ role: 'user', content: 'Explain backpropagation simply.' }],
});
Run the full example:
node examples/chain.js
The SDK wrapper is convenience, not a requirement. ForkMind's proxy speaks the
OpenAI-compatible wire protocol, so capture works from any language: set
your client's base URL to http://localhost:4500/v1 and you're recorded. Chain
turns into a tree by passing back the x-forkmind-node-id from the previous
response as the next request's x-forkmind-parent header (the JS wrapper just
automates this).
# Python β official openai client, zero ForkMind code
from openai import OpenAI
client = OpenAI(base_url="http://localhost:4500/v1", api_key="ollama")
res = client.chat.completions.create(
model="llama3",
messages=[{"role": "user", "content": "Explain backpropagation simply."}],
extra_headers={"x-forkmind-upstream": "http://localhost:11434"},
)
# read res via .with_raw_response to grab x-forkmind-node-id and chain the next call
# curl β anything that can POST JSON
curl http://localhost:4500/v1/chat/completions \
-H 'content-type: application/json' \
-H 'x-forkmind-upstream: http://localhost:11434' \
-d '{"model":"llama3","messages":[{"role":"user","content":"hi"}]}' -i
# response header `x-forkmind-node-id: <id>` β pass as `x-forkmind-parent` next call
Go, Ruby, Rust, Java β same deal: base URL + the two headers. The dashboard, branching, MCP, and regression testing all work regardless of source language.
ForkMind ships thin adapters for the two biggest JS LLM ecosystems. Both route through the same proxy, so capture, branching, the dashboard, MCP, and regression all work unchanged β no model-class swap, no callbacks.
npm i @langchain/openai @langchain/core
const { ChatOpenAI } = require('@langchain/openai');
const { forkmind } = require('forkmind/langchain');
const fm = forkmind({ upstream: 'http://localhost:11434' }); // free local Ollama
const model = new ChatOpenAI({
apiKey: 'ollama',
model: 'llama3',
configuration: fm.configuration, // baseURL β proxy + chaining fetch
});
await model.invoke('Explain backpropagation simply.');
// sequential calls on `fm` auto-chain; fm.setParent(id) to branch from a node.
npm i ai @ai-sdk/openai
const { generateText } = require('ai');
const { forkmindOpenAI } = require('forkmind/vercel');
const openai = forkmindOpenAI({ upstream: 'http://localhost:11434' });
const { text } = await generateText({
model: openai('llama3'),
prompt: 'Explain backpropagation simply.',
});
// openai.setParent(id) / openai.resetParent() control the branch point.
Both honor FORKMIND_PROXY (proxy base URL) and take an explicit baseURL /
upstream per instance.
ForkMind is provider-agnostic β it forwards your auth headers verbatim and lets you set the upstream per client. Anything OpenAI-compatible just works:
| Provider | upstream | apiKey |
|---|---|---|
| Ollama (local) | http://localhost:11434 | any string |
| LM Studio (local) | http://localhost:1234 | any string |
| Groq (free tier) | https://api.groq.com/openai | gsk_... |
| OpenRouter | https://openrouter.ai/api | sk-or-... |
| Together | https://api.together.xyz | your key |
| OpenAI | https://api.openai.com (default) | sk-... |
new ForkMindOpenAI({ apiKey: process.env.GROQ_API_KEY,
upstream: 'https://api.groq.com/openai' });
You can also override per request with the x-forkmind-upstream header if you
call the proxy directly instead of via the SDK.
npm i @anthropic-ai/sdk
const { ForkMindAnthropic } = require('forkmind');
const client = new ForkMindAnthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
await client.messages.create({ model: 'claude-3-5-sonnet-latest', max_tokens: 512,
messages: [{ role: 'user', content: 'hi' }] });
your app βββΆ ForkMindOpenAI (baseURL = localhost:4500/v1)
β injects x-forkmind-parent
βΌ
ForkMind proxy (Express, :4500)
β forwards verbatim (your key, your upstream)
βΌ
provider (Ollama / Groq / OpenAI / ...)
β response
βΌ
proxy reconstructs + saveNode() βββΆ .forkmind/nodes/<id>.json
β returns x-forkmind-node-id
βΌ
wrapper chains it as the next call's parent
sha256(request + parentId) β first 12 hex chars.
Same prompt under the same parent collapses to one node. The ID doesn't depend
on the response, so it can be returned as a header even before a streamed body
finishes.ForkMind ships an MCP server so an AI agent
can read its own .forkmind/ history mid-task and self-correct β recall what it
already tried, see how it reached a state, or search past attempts.
forkmind mcp # stdio MCP server (or: forkmind-mcp)
One-line install via Smithery (configured in
smithery.yaml) β run it from your project root so it sees
your .forkmind/:
npx -y @smithery/cli install forkmind --client claude
β¦or register it manually with any MCP client (Claude Desktop / Claude Code / Cursor / Cline):
{
"mcpServers": {
"forkmind": {
"command": "npx",
"args": ["-y", "github:medhovarsh/forkmind", "mcp"]
}
}
}
Tools exposed:
| Tool | Purpose |
|---|---|
forkmind_recent | Newest captured turns (compact) |
forkmind_get_node | Full request + response for one node |
forkmind_lineage | Rootβnode path β the exact context that produced a state |
forkmind_children | Sibling branches forking from a node |
forkmind_search | Substring search across all requests/responses |
forkmind_stats | Tree totals: nodes, roots, leaves, providers |
forkmind_context_save | Offload context into an encrypted DAG capsule |
forkmind_context_list | List saved capsules (title, digest, size, age) |
forkmind_context_digest | Digest + segment map β cheap pre-restore probe |
forkmind_context_restore | Full or per-segment restore, integrity-verified |
forkmind_context_forget | Irreversible crypto-shred (requires id echo) |
forkmind_context_replicas | Replica (RAID) health, optional sync |
The server reads the .forkmind/ in its working directory β point the client's
cwd at your project.
Most context managers treat a full window as a cache-eviction problem: truncate and lose it. ForkMind capsules invert that β persist first, verify, then compact. A capsule is an immutable, content-addressed DAG of context segments, AES-256-GCM encrypted on disk, restorable in full or one segment at a time.
# Save (items JSON from a file or stdin), get back a 12-char handle
echo '{"title":"auth debug","items":[{"role":"user","content":"..."}]}' \
| forkmind context save --digest "oauth loop root-caused; fix in token.js"
forkmind context list # all capsules, newest first
forkmind context show 9f3ac21b7e04 # decrypt + verify + print
forkmind context verify 9f3ac21b7e04 # DAG integrity: parents, acyclicity, hashes
forkmind context forget 9f3ac21b7e04 --confirm 9f3ac21b7e04 # crypto-shred
Same engine over HTTP (POST/GET/DELETE :4500/api/contextβ¦) and via five MCP
tools, so agents can archive their own context mid-task and pull it back later.
The Claude Code plugin ships a forkmind-archivist skill + subagent that
teaches Claude the offload contract: save β verify on disk β only then drop
it from the window.
Guarantees:
.forkmind/ (~/.forkmind-keys/); an accidentally committed
.forkmind/ leaks only ciphertext and structure.Mirror capsules to any number of extra filesystem targets (second disk, synced folder, network mount). Replicas hold ciphertext + manifests only β keys are never replicated. If the primary copy is lost or bit-rots, restore self-heals from the first replica that passes verification; healed copies get no trust shortcut (full integrity check still runs).
forkmind context replicas add D:\backup\forkmind # add target + sync
forkmind context replicas list # coverage per target
forkmind context replicas sync # catch up offline targets,
# propagate tombstones
Forgetting reaches every copy: reachable replicas are shredded immediately;
a replica that was offline gets its stale ciphertext removed on the next
sync (tombstone propagation) β and it was unreadable anyway, since the
capsule key died at forget time. Tombstones also make heal refuse to
resurrect anything forgotten.
Tweaking a system prompt or swapping a model can silently degrade results. ForkMind lets you pin a known-good captured node as a baseline, then re-run its exact request later and check the new output for drift.
# 1. Pin a good node (grab its id from the dashboard or forkmind_recent)
forkmind regression pin a1b2c3d4e5f6 \
--name octopus-fact \
--contains "hearts" \
--regex "blue|copper" \
--min-similarity 0.5
# 2. List / remove cases
forkmind regression list
forkmind regression remove octopus-fact
# 3. Re-run after changing prompts/models (exit code 1 if any case fails β CI-ready)
forkmind regression run # keyless local (Ollama)
forkmind regression run --key $GROQ_API_KEY --upstream https://api.groq.com/openai
Each case checks the replayed output against:
contains β substrings that must appearnot-contains β substrings that must NOT appearregex β patterns that must matchmin-similarity β Jaccard word-overlap vs the baseline (drift guard;
defaults to 0.3 so a wildly different answer fails even without explicit
assertions). LLM output is non-deterministic, so prefer assertions over exact
match.Cases are JSON in .forkmind/regressions/ β commit them to share baselines and
gate prompt changes in CI.
.forkmind/..forkmind/ layout.forkmind/
βββ nodes/
β βββ a1b2c3d4e5f6.json # one node per turn
β βββ ...
βββ contexts/ # encrypted context capsules
β βββ 9f3ac21b7e04/
β βββ manifest.json # public: DAG shape, hashes, opt-in digest
β βββ seg-<id>.enc # AES-256-GCM ciphertext per segment
βββ tombstones.json # forgotten capsule ids (never resurrected)
βββ manifest.json # version + root node ids
Node schema:
{
"id": "a1b2c3d4e5f6",
"parentId": null, // null = root
"timestamp": "2026-01-01T00:00:00.000Z",
"request": { /* the exact request body */ },
"response": { /* full or stream-reconstructed response */ },
"meta": { "provider": "openai", "upstream": "http://localhost:11434", "stream": true },
"children": ["..."] // child node ids
}
| Command | Does |
|---|---|
forkmind init | Create .forkmind/ in the current directory |
forkmind start | Start the proxy (:4500) + serve the dashboard if built |
forkmind context save/list/show/verify/forget | Encrypted context capsules (see above) |
Env vars: FORKMIND_PORT, FORKMIND_HOST (default 127.0.0.1 β loopback
only; set 0.0.0.0 to expose on the LAN at your own risk),
FORKMIND_OPENAI_UPSTREAM, FORKMIND_ANTHROPIC_UPSTREAM, FORKMIND_PROXY
(SDK target base URL), FORKMIND_KEY_DIR (capsule master-key location,
default ~/.forkmind-keys).
npm install # installs proxy + dashboard (npm workspaces)
npm test # jest: hashing, storage, stream reconstruction, API
npm run dashboard:dev # vite dev server on :5173, proxies API to :4500
npm run dashboard:build
npm run lint
Publishing is tag-driven via .github/workflows/release.yml (needs an
NPM_TOKEN repo secret with publish rights):
npm version patch # bumps package.json + tags
git push --follow-tags # tag push β CI lints, tests, builds dashboard, publishes
prepack rebuilds dashboard/dist so the tarball always ships the UI.
See CONTRIBUTING.md.
.forkmind/ historyBe the first to review this server!
by Modelcontextprotocol Β· Developer Tools
Web content fetching and conversion for efficient LLM usage
by Modelcontextprotocol Β· Developer Tools
Read, search, and manipulate Git repositories programmatically
by Toleno Β· Developer Tools
Toleno Network MCP Server β Manage your Toleno mining account with Claude AI using natural language.