Skip to content

knomit for Claude Code

knomit integrates with Claude Code as a persistent, shared knowledge base — durable, typed, signed facts with provenance that your agents build on instead of re-deriving.

This is not an agent’s private memory store that stashes and replays notes: it is a temporal graph of lessons — learned and discovered — that links, evolves, and can be read as of any moment in its history.

The integration is a balanced hybrid where hooks automate the obvious capture and recall moments, skills (slash commands) handle the deliberate ones, and a CLAUDE.md block carries the philosophy and when-to-use guidance. It deliberately does not auto-inject facts via PreToolUse — recall is a tool the agent reaches for, not a firehose.

From a project’s root:

Terminal window
knomit-bridge claude init [--repo <name> | --lens <name>]

This renders embedded templates into the project:

FileOwnership
.mcp.jsonmerge-required (a companion file is written if one already exists)
.claude/settings.json (hook registration)merge-required
CLAUDE.md (knomit usage block)merge-required
.claude/skills/knomit-*/SKILL.md (all 10 commands)owned — always (over)written
  • --repo defaults to the current directory’s basename.
  • --lens binds the project to a lens instead of a single repo. The two flags are mutually exclusive. See lens mode.
  • Both names are validated against the repo-name grammar [a-z0-9_-]+ before any file is written, so a JSON-hostile value is rejected up front rather than baked into a broken .mcp.json.

The .mcp.json key is derived from the scope

Section titled “The .mcp.json key is derived from the scope”

The mcpServers key is not the constant knomit. It is derived from the scope the bridge is bound to: knomit-lens-<lens> with --lens, knomit-repo-<repo> otherwise. The prefix is applied unconditionally, which makes the mapping injective — a repo and a lens sharing a name, or a repo literally named knomit-repo-x, cannot collide on one key.

Each entry is one bridge connection to a scope — a repo or a lens — not a separate knomit server; a single knomit server hosts all of them. The constant key used to mean a second claude init in a project collided with the first, so its output could not be merged in at all. A derived key makes those entries mergeable.

  • The name budget is 27 characters. Claude Code builds tool names as mcp__<key>__<tool> and the API caps those at 64; the longest knomit tool is knomit_hypothesize. A name that would overflow is rejected at init rather than producing an entry whose tools silently cannot be called.
  • The command identifies a knomit entry, not the key. The hooks select on the knomit-bridge command basename, so a hand-written .mcp.json under any key still binds. The key is consulted only as a fallback, when no entry matched on command — the legacy case, and the wrapper-script or go run case where the command is unrecognisable. A key match is a guess and never dilutes a command match, so an unrelated server that borrowed the knomit- namespace cannot be counted as a second knomit entry.
  • The skills name tools bare (knomit_learn, not mcp__knomit__knomit_learn) so they resolve under whatever key is in play.

All ten are embedded templates under templates/skills/ in the bridge, and claude init writes all ten. Any other skill in a project’s .claude/skills/ is that project’s own — the bridge neither installs nor overwrites it.

CommandWhen to use
/knomit-recall <area>Before non-trivial work — surface invariants, decisions, anti-patterns for an area
/knomit-rememberRight after a discovery, a user correction, or a bug fix that exposed a hidden invariant
/knomit-decided <slug>The moment a tradeoff is resolved (incl. an AskUserQuestion answer), before starting the work it authorizes
/knomit-why <fact-path>Before relying on a fact — walk its provenance and flag stale anchors
/knomit-update <fact-path>A fact’s body/confidence/refs drifted — fix it in place
/knomit-retract <fact-path>A fact is wrong or its subject no longer exists — remove it
/knomit-reviewAfter a burst of fact-writing or a refactor — prune (dedup), distill (synthesis), reflect (methodology)
/knomit-harden [area]Periodic corpus hardening, or after an incident traced to a misapplied fact — adversarially audits facts that are true but compressible into falsehoods, verifies the consequences a hurried reader would derive against the current code, and repairs the trap
/knomit-hypothesizeUser-requested only — generate falsifiable predictions from synthesis facts
/knomit-principleUser-invoked only — author a designer principle (agents must not invoke; validation rejects agent attempts)

Registered in .claude/settings.json, each runs knomit-bridge claude hook <event>:

EventClaude Code triggerWhat it does
session-startSessionStartPre-warms the session as a system reminder: the repo’s global principles (or, until any exist, its top load-bearing invariants) plus the five most recent facts
post-editPostToolUse(Edit/Write/MultiEdit)If an edited file matches a fact’s entities, nudges /knomit-update or /knomit-retract for possibly-stale facts
post-askPostToolUse(AskUserQuestion)Fires after every resolved AskUserQuestion and nudges /knomit-decided before the authorized work begins — the “is this worth recording” filter lives in the skill, not the hook
pre-compactPreCompactScans a wider window for capture-worthy moments and suggests /knomit-remember / /knomit-decided

A lens mounts several repos behind one binding: one is the write repo, the rest are read-only. To scaffold a project against a lens instead of a single repo:

Terminal window
knomit-bridge claude init -lens <name>

The only difference in the scaffold is the argument vector in .mcp.json["--repo", "<name>"] becomes ["--lens", "<name>"]. The skills, the hook registrations, and the CLAUDE.md block are identical:

{
"mcpServers": {
"knomit-lens-work": {
"command": "knomit-bridge",
"args": ["--lens", "work"]
}
}
}

The hooks read the binding out of .mcp.json themselves. A --lens argument puts them in lens mode, where they resolve the lens’s write repo via GET /api/v1/lenses/{name}. --lens wins over --repo if a hand-edited file somehow carries both, in either order. On any resolution failure — server down, unknown lens, malformed response — the hook skips with reason lens_unresolved. A lens-configured session never falls back to the directory basename, because that basename could name an unrelated repo.

The “is this moment worth capturing?” signal is computed entirely in the bridge via regex — there is no server-side /detect endpoint. Intents (correction, discovery, decision, fix-bug, gotcha…) are conversational signals, not fact kinds: a “fix-bug” moment might become an incident or a gotcha fact.

Only pre-compact scans the transcript and runs the intent regexes; post-ask reads just its own hook payload (the questions and the answers). Neither contacts the server. Only session-start and post-edit resolve a repo and read facts, which is why they are the two hooks the lens-mode scope limit applies to.