Second brain for Claude Code & OpenCode: distills how your patterns and knowledge evolve over time.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent — or use 1-click editor setup below.
One-click editor setup isn’t available for this listing yet — we don’t have a confirmed install command, and we’d rather show nothing than point your editor at the wrong package or host. Follow the project’s own setup instructions, linked above.
witness turns a stream of text into a dated record of how its subject changed. Feed it your AI coding sessions and it tracks how you think and work. Feed it market commentary, research notes, or any document stream and it tracks how that changed instead. One pure-Go binary, a local SQLite archive plus plain markdown, served to your agent over MCP.
The thing it is built around is change over time, with provenance. When an attribute's value changes, witness does not overwrite it — it closes the old value with a date and opens a new one, and records which source records drove the shift. So the archive answers "how did this get here", not just "what is true now".
"Aah, you were at my side, all along. My true mentor... My guiding moonlight..." — Ludwig, the Holy Blade
1. Watch your own growth as you work with AI. Install it into Claude Code or OpenCode and it captures your sessions in the background — no prompting, no ritual. It distills how your thinking, workstyle, habits, and blind spots shift over months, with evidence for every claim. This is the setup witness ships configured out of the box.
It is reflection-oriented, not clone-oriented: the point is to let your agent understand you, and to leave you a re-readable record of how you thought and grew. It is a pure tool, not a coach — it captures, structures, and serves. Building a coach on top ("you've done this three times…") is left to other projects that read its output.
2. Build a change-history over any text corpus. Write a lens — a prompt describing what to notice
and which dimensions to track — point witness ingest at NDJSON records, and the same four-stage
engine runs. Nothing about the machinery is person-specific: raw records → observations → dated
facets → narrative.
A worked example, run end to end while writing this section. A regime lens over market commentary,
in an archive with no person lens enabled at all: 7 news records became 22 observations and 13
facets. Then the regime flipped hawkish→dovish, and the archive recorded it as history rather than
replacing it:
Five facets closed and reopened that way in one review. The generated brief even flagged that its own earlier sequencing thesis had been falsified by the new data — which is the whole point of keeping the history instead of the latest snapshot.
Honest caveat: the engine is general, but everything witness ships is person-shaped — the
built-in default lens, the example lens, and the summary prompts all say "notice things about the
person". For a non-person corpus you write your own lens (three files) and, if you want, override the
summary prompt with one file. There is no market-lens or research-lens preset yet; the machinery is
domain-agnostic, the batteries included are not.
witness is the answer if you've ever wanted to:
witness ingest.Contents: How it works · Lenses · Example · Reading the archive · Commands · Install · Configuration · Your data
Four layers — one ground-truth, three derived and regenerable from it:
| Layer | Kind | What it is |
|---|---|---|
| raw (L0) | ground truth | Every turn captured verbatim — from stable Claude Code hook fields (UserPromptSubmit.prompt, Stop.last_assistant_message) or OpenCode's local SQLite session DB (message/part text). Append-only, never LLM-touched. |
| observations (L1) | derived | A cheap per-session worker mines atomic, evidence-anchored observations about you, tagged by lens. Append-only. |
| facets (L2) | derived, bi-temporal | A periodic reviewer synthesizes observations into evolving facets, each keeping its change history (valid_from/valid_to) — so the archive answers "how did I change," not just "who am I now." Old values are never deleted. |
| profile (L4) | derived narrative | A short, human-readable markdown summary distilled from the facets — one per lens plus a cross-lens unified portrait. Generated on read: witness profile (or MCP get_profile) rebuilds it only if the facets changed, so an unread profile costs nothing. A cached read is instant; a rebuild takes ~13s. |
The archive is collect-only / pull-only: witness captures and distills everywhere, but never
injects anything into a session. Nothing is pushed — you (or an agent) read the profile on demand.
raw/observations/facets live in a single embedded SQLite database (witness.db); the profile is
plain markdown under profile/.
Every observation/facet carries a lens tag:
default — global, runs on every session, cross-domain. This is the part no single-domain
tracker can be: it sees that "diagnoses gaps precisely" fires in math and coding and career.math) — domain-specific lenses you register once and enable
globally. witness lens register math ./math/ adds the definition (a directory) to a central
registry; witness lens enable math makes it run on every session (alongside default). Lenses
are shared, not tied to any repo, so the same math lens covers all your math work.A lens is a directory of three files:
The one rule to remember: each prompt file is used verbatim as the system prompt and replaces
the built-in default prompts — it doesn't extend them — so each must be self-contained,
including its output JSON schema (the tool appends the transcript / observations as the user
message, but injects no schema for you).
Two complete, copy-paste-ready lenses ship as starting points. Copy the directory and rewrite the dimensions and prose for your domain:
prompts/lens/example/ — a person lens (math learning), for tracking
someone as they work.prompts/lens/corpus-example/ — a non-person lens (market
regime), for tracking a subject that is not you. Start here for research notes, a knowledge base,
incident reports, or any document stream; its README explains what has to change when the subject
stops being a person.register stores a copy — editing the original afterward has no effect until you re-register.
enable is the separate switch that makes it actually run.
Per-lens models (optional). By default every lens rides the default models (witness config set triage_model / distill_model). A rare heavy lens can pin a stronger model just for itself —
without paying for it on every session — by adding extract_model / review_model to its
lens.json:
Omit a field (or leave it empty) to ride the default. Since register stores a snapshot, edit the
registered copy under <witness-data-dir>/lenses/<name>/lens.json — or edit the source and
re-register. Verify what a lens resolved to with witness lens show <name>.
Factual signals from GitHub, npm, and our automated checks — not a rating.
No reviews yet — be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/witness)<a href="https://allmcps.com/mcp/witness"><img src="https://allmcps.com/api/badge/witness?style=directory" alt="Witness on AllMCPs" /></a>