truthd
v0.3.0
Published
Local-first memory MCP server for coding agents — markdown vault + Postgres/pgvector hybrid retrieval with self-superseding hygiene.
Readme
truthd
Memory your coding agents can inspect, edit, and trust.
Durable project memory for Claude Code, Codex, Cursor, and other MCP agents. Plain Markdown is the source of truth; the search index (embedded SQLite or Postgres) is disposable.
Quickstart · Why truthd? · How it works · CLI · MCP tools
Your coding agent learns important decisions, lessons, and project context—but a new session starts from zero. Putting everything in an instruction file eventually fills the context window, while opaque memory stores are difficult to review or correct.
truthd gives agents a durable memory layer without taking ownership of your knowledge:
- Own your memory. Every note is readable Markdown you can edit, grep, review, and commit.
- Find it when the wording changes. Lexical and vector search are fused with recency.
- Keep stale advice out of future sessions. Replaced notes are superseded, not erased.
- Share context across agents. Any MCP-capable agent can use the same project vault.
- Rebuild at any time. Delete the database and regenerate the index from Markdown.
Quickstart
Requirements
- Node.js 22 or newer
- Docker — optional, only for the Postgres backend
- Ollama for local embeddings (optional; lexical-only and OpenAI-compatible modes are supported)
Install
npm install --global truthd
cd your-project
truthdThe three-question wizard creates an embedded SQLite index for the project (default,
zero dependencies — or a shared local Postgres container, if you choose), configures
embeddings, creates memory/, and adds truthd to .mcp.json.
Then teach your coding agent the memory workflow:
truthd integrate # Claude Code (also: codex, cline, cursor)
truthd integrate --print # print the setup prompt for any other agent┌ truthd — agentic memory for your codebase
│
◇ Project name
│ acme-shop
◇ Where should truthd keep the search index?
│ Embedded (SQLite on this machine)
◇ Embeddings
│ qwen3-embedding:0.6b — recommended, fast, 1024 dims
◇ qwen3-embedding:0.6b: 1024 dimensions
◇ Schema is up to date
◇ Wrote .mcp.json, registered "acme-shop" in ~/.truthd/config.json, vault at /home/you/dev/acme-shop/memory
│
└ Attached "acme-shop". Your agent has memory.Now an agent can record and recover project knowledge:
You: Remember that Stripe webhook retries must be deduplicated by event ID.
Agent: Recorded insight:
memory/projects/acme-shop/insights/2026-07-10-stripe-webhook-retries.md
──────────────────── a later session ────────────────────
You: What should I know before changing the Stripe webhook handler?
Agent: The checkout flow must deduplicate webhook retries by Stripe event ID.Commit memory/ and .mcp.json. Your project memory now travels with the repository.
Why truthd?
| Capability | One large instruction file | Database-only memory | truthd | |---|:---:|:---:|:---:| | Human-readable source | ✓ | — | ✓ | | Git history and review | ✓ | — | ✓ | | Hybrid semantic + lexical retrieval | — | Usually | ✓ | | Loads only relevant context | — | ✓ | ✓ | | Explicit stale-memory lifecycle | Manual | Varies | ✓ | | Rebuildable search index | n/a | Rarely | ✓ | | Cross-agent access through MCP | Limited | Varies | ✓ |
The defining choice is simple: the vault is authoritative; the database is not. The index makes retrieval fast, but losing it never means losing the knowledge itself.
How it works
flowchart LR
A[Claude Code · Codex · Cursor] -->|MCP| T[truthd]
T -->|write first| V[(Markdown vault)]
T -->|hybrid retrieval| P[(search index)]
V -->|ingest / rebuild| P
P -->|relevant context| T
T --> AThe index is an embedded SQLite database by default (FTS5 + sqlite-vec, no services),
or Postgres + pgvector if you choose it at truthd init. Retrieval behaves the same
on both.
- Write: a typed MCP tool records a note in the Markdown vault first, then refreshes that note's index chunks.
- Retrieve: full-text and vector results are combined with reciprocal-rank fusion and a recency boost.
- Maintain: every write returns likely overlaps. A hygiene agent can verify them and supersede stale notes.
- Audit: superseded files remain on disk and in Git, but disappear from active retrieval.
What gets committed?
your-project/
├── .mcp.json
└── memory/
├── principles/
├── external/
└── projects/
└── acme-shop/
├── decisions/
├── insights/
├── lessons/
└── experiments/A note is ordinary Markdown with structured frontmatter:
---
id: 2026-07-10-stripe-webhook-retries
type: insight
scope: project
project: acme-shop
title: Stripe webhook retries require deduplication
created: 2026-07-10
status: active
tags: [payments, webhooks]
---
## For future agents
Deduplicate Stripe webhook retries by event ID before processing checkout state.
The handler may receive the same event more than once. Store processed event IDs and
return success for repeats without applying the transition again.Designed for trustworthy local memory
- Embedded index by default: the search index is a local SQLite file under
~/.truthd/db/— no containers, no open ports. - Local by default: the optional Postgres backend is bound to
127.0.0.1; its default credentials are never exposed on other interfaces. - Project isolation: every attached project gets its own index database
(
truthd_<project>) — a SQLite file, or a database in the sharedtruthd-postgresinstance. - Local embeddings: Ollama keeps embedding generation on your machine.
- Explicit hosted mode: when you choose an OpenAI-compatible embedding endpoint,
note chunks are sent to that endpoint; API keys remain environment variables and are
never written to
.mcp.jsonor the registry. - Recoverable by design: the Markdown vault is the backup. Run
truthd ingestto recreate the derived index.
Agent support
| Agent | Setup |
|---|---|
| Claude Code | Run truthd integrate (memory agents, protocol, optional lifecycle hooks) |
| Codex | Run truthd integrate codex |
| Cline | Run truthd integrate cline |
| Cursor | Run truthd integrate cursor |
| Other MCP clients | Use the generated .mcp.json or truthd integrate --print |
truthd itself speaks MCP over stdio. Agent-specific integration only installs the recommended read and hygiene workflow around those tools.
Common workflows
Bootstrap an existing codebase
Use bootstrap-from-git.md to mine durable decisions, lessons, and insights from repository history.
Import an existing Markdown vault
Use migrate-obsidian.md to map Obsidian or plain Markdown notes into truthd's note model.
Inspect usage and retrieval quality
$ truthd usage --days 7
truthd usage — last 7 days
PROJECT NOTES ADDED READS WRITES ZERO-HIT AVG CHARS LAST ACTIVITY
acme-shop 142 9 118 21 3 1204 2026-07-10
docs-site 37 2 40 5 1 988 2026-07-09
TOTAL 179 11 158 26 4 1160 2026-07-10The retrieval_quality_report MCP tool highlights zero-result queries and notes that
are never fetched. truthd consolidate finds near-duplicate notes for agent-reviewed
merging.
CLI at a glance
| Command | What it does |
|---|---|
| truthd | Show status in an attached project; otherwise run the setup wizard. |
| truthd init | Attach or update a project. |
| truthd integrate [agent] | Wire Claude Code (default), Codex, Cline, or Cursor to the memory workflow. |
| truthd status | Check the project, index, embeddings, and note count. |
| truthd usage [--days 7] | Show cross-project read/write and retrieval statistics. |
| truthd hook <event> | Lifecycle hook handler installed by integrate (not run by hand). |
| truthd ingest | Rebuild the index from the Markdown vault. |
| truthd consolidate | Find near-duplicate notes worth merging. |
| truthd migrate | Apply the current database schema. |
See the complete CLI reference for flags, configuration, lifecycle, and troubleshooting. See the agent specification for every MCP tool and its read/write protocol.
Frequently asked questions
The database (SQLite or Postgres) is the vector and full-text index, not the source of truth. It provides hybrid retrieval and query analytics while Markdown keeps the durable data portable and auditable.
SQLite, unless you have a reason. The default embedded backend needs no Docker and no
running services (FTS5 for lexical search, sqlite-vec for vectors) and behaves the same
as Postgres in retrieval. Choose Postgres in the wizard or with
truthd init --storage postgres if you prefer one shared, inspectable database server.
Existing Postgres projects keep their backend on re-run.
Yes — its own index, not its own server. SQLite projects get one file each
(~/.truthd/db/truthd_<project>.db). Postgres projects share one localhost-only
container with one database per project. This isolates vault-relative paths and project
statistics. The default Postgres host port is 5433; use truthd init --port <port>
before the container is first created if that port is occupied.
Yes. Choose provider none or run truthd init --provider none for lexical-only
retrieval. You can configure Ollama or an OpenAI-compatible endpoint later.
Your Markdown notes remain intact. For SQLite, run truthd ingest — the file is
recreated. For Postgres, recreate the database with truthd init, then run
truthd ingest.
Development and releases
- CONTRIBUTING.md — local setup, configuration, and verification
- RELEASING.md — npm Trusted Publishing and release procedure
- docs/CLI.md — complete operational reference
- docs/AGENT_SPEC.md — MCP contract and memory protocol
