Cairn is persistent cross-session memory for the DeepSeek Harness — one command to install · nine memory tools + one identity tool · six injection modes. Facts, preferences, conventions, and hard-won lessons survive across sessions: every new conversation starts with last time's experience already on the table.
dsh plugin add --profile web @chenhw7/dsh-memoryBy default an agent has no cross-session memory — what you said last week and what you debugged yesterday all start from zero today.
"We use pnpm now" is gone by the next session; the same build pit swallows you twice; last week's verified conclusions get reconstructed from vibes. Context grows longer while the things that matter keep being re-explained.
Worthwhile signals are extracted, scanned, audited, and stored; the next session opens with a digest of category counts and topic words already present, full text recalled on demand via memory_search / memory_get. Use keeps them fresh, forgetting follows rules.
JSON (the host storage domain) or SQLite (node:sqlite, zero extra dependencies) backends with a one-time migration; cross-process single-writer detection guards against concurrent clobbering. Six tables — entries / audit / suggestions / meta / identity / identity_history — and every change is attributed and audited. Uninstall the plugin, keep the memories.
A hand-rolled Okapi BM25: conservative Latin stemming folds word forms, CJK runs emit unigrams plus adjacent bigrams — "记忆" no longer matches every entry containing "记". Three scopes (global / project / user), summary indexed alongside content, pinned entries surface first.
Three signals (explicit intent / user correction / verified failure streaks) trigger LLM extraction; new entries face the old ones through an IDF-weighted prefilter and one batched consolidation call — duplicates merge, outdated ones supersede with a supersededBy mark. Optional review queue: models propose, you decide.
The memory snapshot freezes at session creation and is reused all session — prefix unchanged, KV-cache fully warm. Six injection modes (digest, the default, ships category counts and topic words) disclose progressively, with standing cost always visible (≈N tokens footer). Optional step-level auto-recall rides the message channel and never touches the system prompt.
SOUL.md is the assistant's character; USER.md is its working profile of you. The assistant rewrites them whole via identity_update in conversation — every version is snapshotted and revertible; you review history in the Identity settings section but never edit directly. Off by default; when enabled, both inject into the system prompt.
Three signals stream through a zero-LLM-cost accumulator: explicit intent ("remember / from now on"), user corrections ("actually, no"), and failure streaks resolved by success. Past the threshold (default 10), exactly one LLM extraction fires.
Every write passes 37 scanner rules and appends an audit record; entries are deduped and consolidated against the store — duplicates merge, outdated ones supersede. The BM25 index is ready as soon as the write lands, and every hit refreshes the freshness stamp.
The snapshot freezes at session creation, and a one-time digest of category counts and topic words lands on the first step (digest mode by default): the model pulls full text via memory_search / memory_get; step-level auto-recall can add relevant memories on the fly — all with visible token cost.
Memories get re-read into future context — they are an attack surface, so defense is two-sided.
37 rules at write time (16 secrets · 17 prompt injections incl. 8 Chinese · 4 exfiltration) — rejected content never lands; every prompt-facing read re-redacts, leaked content renders as [BLOCKED: …]. The original stays inspectable — silent deletion only hides the attack.
Every change appends an audit record: action, source (tool / review / flush / ui / janitor), content preview — 200 rolling with a monotonic seq.
memory_forget demands an explicit confirm: true; batches over the ceiling are refused, pinned entries are exempt and reported, every removal is individually audited.
With confirm-before-write on, every extraction and tool write degrades to a proposal; repeatedly observed proposals float to the top. Edits to existing entries never touch the original before adoption.
The browser console is read-only until a deployment-level switch enables writes — what is trusted is the transport fence, not the storage face.
Forged fence closers in stored content are neutralized at render time; every injection surface declares that the current user request, repository files, and tool output always outrank memory.
The whole store at a glance, with telemetry for background-task failures.
The human-veto desk: hits-descending, the most-raised proposals first.
Scope + workspace filters, BM25 search, category chips, lazy-loaded list.
The mock above illustrates the console UI (numbers are not real). The five settings cards — Memory, Project Notes, Auto Recall, Identity, Automatic Extraction — apply live with no restart; the UI is bilingual. The plugin never writes files into your repository.
Cross-session personal preferences and working habits; a project's team conventions and commit norms; verified pitfalls and fixes from debugging; engineering judgment accumulated over long iterations. It helps an agent accrue experience — it is not a general knowledge base.
Retrieval is purely lexical: BM25 does no semantic vectors, so a paraphrased query misses (synonyms ride on summary indexing). Extraction quality tracks the session model — no extra keys. The host DeepSeek Harness is on the alpha channel (0.1.2-alpha.2); the plugin moves with it. The remote console is transport-trust only, writes off by default.
Version and commit figures are read live from the npm registry and the repo's stats.json (refreshed daily by CI) when you open the page; offline you see the baked snapshot above.