Memory
dsh-memoir
qinling-melon-farmers/dsh-memoir · ★ 39
A local project memory layer for DeepSeek Harness that persists agent conclusions, lessons, and follow-up actions, with bounded Hot Memory, ranked recall, and Web GUI management across sessions.
安装
dsh plugin --profile web add github:qinling-melon-farmers/dsh-memoirGitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试
For install and environment setup, plus plugin development tutorials, see DSH community docs ↗
README
Table of contents
- 0.9.3 highlights
- Why dsh-memoir
- UI preview
- How it works
- Snapshot recovery and cleanup (0.7.1)
- Agent tools and memory lifecycle
- Automatic distillation
- Local recall and caching
- Web GUI
- Installation and compatibility
- Native sidebar and help
- Offline release highlights
- Storage, privacy, and security boundaries
- Configuration
- Performance and verification
- FAQ
- Development and contributing
0.9.3 targets official npm DSH
0.2.1-rc.2, retaining0.2.0-rc.1 / rc.2and0.2.1-alpha.1 / alpha.2support. It fixes #16's store protection and Hot Memory budget boundaries, plus #17's memory template literals breaking prompt assembly. Upgrade and reload the plugin to protect old snapshots without deleting them or rewriting original memories; #14's affected historical logs still need separate recovery.
中文 · English · Changelog · Releases
A local-first, cross-session project-memory plugin for DeepSeek Harness (DSH). It persists an agent's confirmed work, lessons, and next actions, injects bounded cache-friendly Hot Memory into new sessions, and retrieves long-tail history through local BM25 ranking.
No embeddings, vector database, or cloud memory service. The npm package has zero bundled runtime dependencies; DSH and Zod 4 peers are supplied by the host environment; Zod validates session projections and is not bundled.
[!WARNING] Historical recovery boundary (#14): receipts written by 0.8.1–0.9.0 can prevent sessions from reopening. 0.9.3 retains the prevention introduced in 0.9.1, but upgrading does not rewrite old logs. The npm package includes
dsh-memoir-repair. If an old session still fails, follow the recovery guide: audit first, stop every host and back up, then explicitly apply repair. Preserve the logs; do not downgrade their format. Stop old plugin writes before recovery; disabling auto-distillation alone does not stop manual write tools. #17's prompt output protection does not repair arbitrary old logs. Recovery CLI support is limited to the reviewed backends and formats listed in the recovery guide; upgrading DSH alone does not repair affected logs either.
[!IMPORTANT] 0.9.3 requires DSH
>=0.2.0-rc.1 <0.3.0-0 || >=0.2.1-alpha.1 <0.2.1, with development SDKs pinned to0.2.1-rc.2; it retains the official0.2.0-rc.1 / rc.2and0.2.1-alpha.1 / alpha.2compatibility lines. The version range does not mean every included version has been verified. Retains the visible guide, native settings, four agent languages, separate distillation turns and frozen snapshots. The DSH 0.1.7 line is Memoir0.8.2, but it remains affected by #14; upgrade the host before installing the fixes in 0.9.3.
dsh-memoir@0.7.1fixes lost session snapshots after restart or RAM eviction (#10), supporting DSH 0.1.5-rc.1 / rc.2. It requires>=0.1.5-rc.1 <0.1.6-0; check your host first. Keep0.6.2on DSH 0.1.2, or0.5.6on DSH 0.1.1-rc.2; those older lines do not include this fix.
npm install --global @deepseek-ai/dsh@0.2.1-rc.2
dsh plugin --profile web add dsh-memoir@0.9.3
After upgrading, reload the plugin or restart dsh web. #17's protection takes effect on subsequent prompt assembly; no manual deletion of old snapshots is needed. Updating or removing the plugin does not automatically delete memories.
0.9.3 highlights
- Store protection (#16): future store formats, read errors and failed backups of corrupt files fail closed, refusing further loading or overwriting. A fresh store is allowed only after the damaged original has been preserved. Windows rename failures caused by temporary file contention receive bounded retries and still surface as errors when retries are exhausted.
- Hot Memory budgets (#16): skip candidates that exceed the remaining hard budget and continue looking for smaller entries. If the first entry is oversized, shorten its content and, if necessary, its title against the complete rendered block. Skip it if even the minimum block cannot fit; long titles cannot bypass
hotMemoryMaxTokens. - Template literals (#17): set the official
PromptSectionoptioninterpolate: falseto disable variable interpolation for the memory section. Literals such as{{...}}enter the system prompt verbatim, preventing evaluation or assembly failures. New memories, cached old snapshots and restored disk snapshots all retain their original output; braces, original memory JSON,PROJECT_MEMORY.mdand disk snapshots stay unchanged. Thanks to mikemikimike for the report, output-boundary analysis and old-snapshot approach in PR #18, which helped locate the problem. - DSH rc.2 compatibility: update the SDK baseline to
0.2.1-rc.2, adapting to the JSONL backend's namedapplyexport and log-generation recovery protocol. Project memory remains anchored to the original session project when the execution directory changes. See the recovery guide for the five supported official SDK versions and safety boundaries. Runtime compatibility does not imply recovery of arbitrary historical logs.
Why dsh-memoir
| Capability | What you get |
|---|---|
| Local-first storage | A JSON single source of truth plus per-project PROJECT_MEMORY.md; no memory upload or external service |
| Automatic distill reminder | Reminds the top-level agent after a worked turn, then persists transparently through memoir_record; skips idle, aborted, subagent, and already-recorded turns |
| Bounded Hot Memory | Only high-value memory enters the system prompt under a hard token limit; a frozen session prefix improves prompt-prefix cache hits |
| BM25 ranked recall | Searches Chinese phrases, English keywords, code identifiers, and paths; cross-project Top-K and query LRU caching use one engine |
| Governable memory | Importance, pinning, tags, archive/restore, and supersede lifecycle; similar writes require an explicit update, replacement, or keep-both decision |
| Provenance | Agent writes retain trusted session/turn sources; the Web panel can copy and make a best-effort jump to the original session |
| Complete Web GUI | Bilingual project/global browsing, ranked search, editing, Hot Memory inspection, diagnostics, and live settings, with an independent agent-facing language choice |
It fits personal and local development workflows where a new agent should continue understanding a project. It is not a raw chat backup, multi-user cloud sync service, or vector-semantic knowledge base.
UI preview
0.9.0 component preview with demonstration data. Plugin identity, GitHub, documentation and memory settings stay at the top, before long lists.

How it works
worked turn
│ automatic distill reminder
▼
memoir_record / memoir_update
│
├── ~/.dsh/dsh-memoir.json complete structured history (SSOT)
├── <project>/PROJECT_MEMORY.md readable, committable projection
└── Retrieval Index inverted index + BM25 + query cache
│
├── Hot Memory Selector ──> bounded system-prompt injection
└── memoir_read / Web ────> on-demand long-tail recall
Complete history and Hot Memory are separate layers:
- Full Memory retains every record for the GUI, human review, Markdown projection, and ranked retrieval.
- Hot Memory selects only budgeted actions, lessons, and recent state; the full
PROJECT_MEMORY.mdis never injected. - Session Snapshot durably freezes each session's injection baseline and reuses the original text after restart or RAM eviction. 0.9.3 protects old baselines by disabling variable interpolation for the memory section; injected text and stored snapshots remain unchanged. New writes remain immediately readable by tools and the GUI; automatic injection refreshes in the next new session. Recovery failures explicitly report degraded persistence.
Snapshot recovery and cleanup (0.7.1)
Upgrading to 0.9.3: #17's protection covers both cached and restored disk snapshots. Upgrade and reload the plugin; the disk cleanup steps below are not required for this fix. With variable interpolation disabled for the memory section, old baselines containing template literals are still emitted verbatim, preserving braces and the frozen prefix. This does not repair #14's invalid receipts or other historical log failures.
- Default directory:
$DSH_HOME/dsh-memoir.json.snapshots/, or<storePath>.snapshots/with a custom store. Records are partitioned by data-source/settings hash, language, and session hash. They load on demand without scanning the whole directory at startup. sessionSnapshotMaxbounds RAM only. Disk records have no automatic TTL and survive shrinking, uninstalling, or clearing RAM. Include them in backups. To reclaim disk, stop the relevant DSH processes, back up first, and manually remove records you no longer need to resume. Access after removal establishes a new baseline.- Languages use separate namespaces; switching back restores the original baseline for that language. Budget changes affect new baselines only. Forks/new session IDs do not inherit the parent's frozen record.
- Old sessions whose snapshots were lost before upgrading establish a baseline from current memory once. Memoir does not guess or slice original text out of historical system prompts. Corrupt, inaccessible, or locked records remain unchanged; fallback freezes only in the current process, with diagnostics and a log warning.
- Text is capped at 256 KiB and each record at 2 MiB; exceeding either reports the same degradation. New POSIX directories/files use 0700/0600; Windows access remains governed by directory ACLs. Snapshot files contain memory text and are user data.
- This fix prevents rebuilding recoverable snapshots; it cannot guarantee provider KV-cache retention or hit rates.
Agent tools and memory lifecycle
| Tool | Purpose |
|---|---|
memoir_record |
Write work / lessons / actions / note entries; returns explainable similar/conflicting candidates before mutation |
memoir_update |
Preserve id and creation time while updating content, section, importance, tags, and lifecycle |
memoir_read |
Local ranked recall across project (default) / global / all with compact or full output |
Each entry has importance 1–5. The default, 3, is neutral; pinning adds separate Hot Memory weight. Recall defaults to active. Archived or superseded history remains inspectable and restorable and is never deleted automatically.
Similar-memory governance starts with BM25 candidates, then combines title similarity and Token Jaccard. The plugin surfaces suspected duplicates or conflicts but does not decide truth on its own. The caller must choose:
update: update an existing record in place;supersede: retain old history and mark it as replaced by the new record;force-record: explicitly keep both.
Automatic distillation
0.8.2 diagnostics distinguish reminders, persistence, failures, cancellation, unresolved similarity, and unavailable receipts. Only persisted memoir_record / memoir_update operations suppress reminders; failed calls or unresolved candidates do not count as saves. Host cancellation may follow persistence, so counters can overlap. Correlation with a reminder proves neither causation nor semantic correctness. GUI writes are excluded from Agent-tool counters.
0.8.2 uses public sessionProjections to reconstruct current-turn activity from logs and checkpoints without deprecated snapshotEvents() reads. Each session retains at most 4096 current-turn call IDs, without arguments or content; evicted IDs degrade to session-only provenance. Gate state is capped at 1024 agents and cleared on disposal. Legacy writes have no receipts: a historical call alone cannot prove persistence. BM25 remains lexical retrieval, not guaranteed cross-language semantic matching.
Automatic distillation is an observable agent turn-end reminder, not silent background scraping of every chat. The default 1 / 0 / 1 means every eligible worked turn, no extra cooldown, and at least one tool call.
0.8.2 fixes distillation-induced answer folding for new turns (#13): The public
followupAPI queues a separate memory wrap-up turn instead of using same-turnsteer. A short receipt, empty output or failed wrap-up tool cannot change the original task answer’s turn boundary. Memory provenance still points to the source work turn. Wrap-up turns neither advance the worked-turn cadence nor recursively trigger distillation. This is still visible, cancelable model work—not a free background task—and may increase the displayed turn count.Upgrading does not rewrite history. For same-turn folding already recorded by 0.8.0 / 0.8.1, expand the process disclosure or use Normal (
normal) transcript mode. This fix does not change DSH’s answer selection for arbitrary same-turn continuations from other producers, and does not rely on a “remain silent” prompt.
autoDistillEvery, autoDistillCooldownMin, and autoDistillMinTools are AND conditions isolated per agent. Idle, aborted, subagent, and already-recorded turns do not trigger. Cooldown advances only after a successful reminder. All cadence parameters are live-editable in the GUI.
language independently controls agent-visible tool descriptions and parameters, the distillation prompt, tool results, Hot Memory / PROJECT_MEMORY.md headings, and validation or governance errors. Released 0.8.2 supports zh / en, defaulting to zh. Tool descriptions and subsequent prompts update live without restarting DSH.
0.9.0 adds de (Deutsch) and ru (Русский), explicitly selected in Memory settings rather than inferred from the agent or user messages. Tool names, parameter keys and enums remain unchanged. The GUI remains Chinese/English and existing memory content is not automatically translated. Switching language alone does not rewrite JSON or Markdown; projection headings use the current language on subsequent normal writes. Each of the four languages has its own frozen-snapshot namespace; switching back reuses the previous baseline. Select zh or en before downgrading to 0.8.2.
Local recall and caching
- Chinese 2/3-grams, English words, and code/path identifier tokenization;
- document-side BM25 keeps true term frequency, with a 2.5× title boost plus exact-phrase, section, and recency weighting;
- separate title/body length normalization;
- deduplicated global Top-K shared by project / global / all;
- epoch-aware LRU query cache with one-hour time buckets;
limitand output detail stay outside the key so output shapes share rankings; - the GUI and
memoir_readuse the same RetrievalEngine and expose hits, misses, evictions, hit rate, and last-query latency.
0.9.0 extends word splitting to Unicode letters, combining marks and numbers with NFC normalization, preserving German umlauts and Russian Cyrillic. Original content and existing Chinese/code-identifier rules are preserved. This remains lexical retrieval, not automatic translation, stemming or cross-language semantic search.
Top-5 recall on the fixed quality set is 100%; the repository gate requires at least 90%.
Web GUI
Installing into a compatible DSH web profile registers a native Memory Conversation view and Memory Settings section through official slots. The DSH shell owns layout, navigation, and unload lifecycle; Memoir no longer takes over the legacy sidebar through DOM selectors.
- Project memory and all-project global memory, with project groups collapsed by default and complete lifecycle totals;
- status, section, and keyword filters with BM25 scores;
- add, edit, pin, archive, restore, and supersede;
- copy and best-effort navigation for session/turn provenance;
- Hot Memory Inspector: what the next session will inherit;
- Retrieval Diagnostics: index, query cache, last query, and session snapshot;
- permanent
Browse / Settings / Hot Memory / Diagnosticsnavigation with an independent bounded scroll position per surface; - progressive batches of 20 entries or projects, plus a controlled six-line preview for long memory bodies;
- the native DSH composer-overlay contract, keeping the final memory visible above the conversation composer while the list scrolls fully;
- arrow-key, Home, and End navigation for surface tabs, plus
aria-expandedproject disclosures and visible focus states; - live GUI Chinese/English switching from
<html lang>, with a separatelanguagesetting for agent-facing copy.
The native plugin detail page reuses Memory settings directly, without opening the memory list. Shown below is the native plugin detail page in DSH 0.2.0-rc.1.

Choose German agent-facing copy independently of the English GUI; settings and memory browsing scroll separately.











Installation and compatibility
| Channel | DSH baseline | Installation | Status |
|---|---|---|---|
pinned npm 0.9.3 |
>=0.2.0-rc.1 <0.3.0-0 || >=0.2.1-alpha.1 <0.2.1 |
dsh plugin --profile web add dsh-memoir@0.9.3 |
SDK 0.2.1-rc.2; compatible with 0.2.0-rc.1 / rc.2 and 0.2.1-alpha.1 / alpha.2 |
pinned npm 0.8.2 |
>=0.1.7-rc.1 <0.1.8-0 |
dsh plugin --profile web add dsh-memoir@0.8.2 |
Legacy 0.1.7 line; still affected by #14 |
pinned npm 0.7.1 |
>=0.1.5-rc.1 <0.1.6-0 |
dsh plugin --profile web add dsh-memoir@0.7.1 |
Legacy 0.1.5 line |
pinned npm 0.6.2 |
>=0.1.2-alpha.2 <0.1.3 |
dsh plugin --profile web add dsh-memoir@0.6.2 |
Legacy 0.1.2 line |
pinned npm 0.5.6 |
0.1.1-rc.2 |
dsh plugin --profile web add dsh-memoir@0.5.6 |
rc2 compatibility line |
Source v0.9.3 |
>=0.2.0-rc.1 <0.3.0-0 || >=0.2.1-alpha.1 <0.2.1 |
local build + link: |
SDK 0.2.1-rc.2; development, not compatible with legacy 0.1.x |
Development SDKs are uniformly pinned to 0.2.1-rc.2. Host compatibility in this table is separate from #14 recovery CLI restrictions on backends, file formats and log generations; see SESSION_RECOVERY.md for recovery scope.
Node.js ^22.19.0 || >=24.0.0 is required. 0.7.1 keeps the native conversation.view / settings.section slots and snapshotEvents(). DSH 0.1.5 uses Session log V3, independent of Memoir store v4 / settings v3. Back up DSH_HOME before upgrading DSH; migrated sessions are not guaranteed readable by older hosts. This Memoir release neither migrates nor resets memory and retains frozen session snapshots without enabling new dynamic-prompt behavior.
0.9.3 source (development SDKs / example host: DSH 0.2.1-rc.2):
git clone --branch v0.9.3 https://github.com/Qinling-Melon-Farmers/dsh-memoir.git
cd dsh-memoir
pnpm install --frozen-lockfile
pnpm run build
npm install --global @deepseek-ai/dsh@0.2.1-rc.2
dsh plugin --profile web add "link:/absolute/path/dsh-memoir"
0.8.2 uses native uiWorkspace, conversation.view / settings.section, and the Session V4 producer-owned distillation source. Links open sessions and turn IDs remain copyable; no global DOM turn scrolling is used. Settings inherit the host background and cards use theme layers while preserving skins and independent scrolling. Store v4 / settings v3 / snapshot v1 are unchanged. Back up DSH_HOME before upgrading: host session migration is separate from plugin memory storage.
Native sidebar and help
Released 0.8.2:
- Existing Conversation and Settings entries stay unchanged. The right-sidebar guide now offers Memory for browsing project memory, Hot Memory and diagnostics alongside chat; it never opens automatically or replaces another panel.
- Each sidebar instance follows its own session workspace and reuses the same data layer, with independent active surfaces and scroll state. Conversation and Settings remain available when the optional sidebar service is absent.
- Under Memory settings, the collapsed About & help card shows the plugin version, host range, SDK baseline, maintainer, repository, bilingual documentation, releases and issue links. The plugin repository is explicitly distinct from the current workspace.
- No background update requests, workspace Git-remote inspection or path/memory uploads. Use the host plugin manager to update, after checking the target package’s DSH requirements and prerelease channel. The panel does not auto-upgrade.
0.9.0:
- Plugin identity, version, GitHub project, documentation and Open memory settings move to the top of Conversation, Settings and sidebar panels, before any long memory or configuration list. Detailed compatibility information stays collapsed; no forced navigation or Star prompt.
- Open
dsh-memoiron the native Plugins page to use the same memory-settings form. No duplicate configuration store or registration pretending to be an official plugin; existing entries still work without this host page. - Develop and validate against official npm
0.2.0-rc.1. Check the host version before installation. Memoir 0.8.2 for DSH 0.1.7 is also affected by #14; back up and upgrade both host and plugin, following the compatibility and recovery warning above.
Offline release highlights
The first Memory Conversation opening shows the 0.9.3 highlights without blocking chat: DSH 0.2.1-rc.2 compatibility, #16's store and budget protection, and #17's template-literal protection. It explains that old snapshots need no deletion while #14's affected logs still need separate recovery. Choose “Got it” to stop automatic display for this version in the same browser origin. Reopen anytime from “About & help → View release highlights”. Settings and sidebar panels never open the notice automatically. The image below is explicitly retained as a historical 0.9.0 preview.
The Chinese/English notice is offline: no network requests, uploads, memory changes or conversation edits. Only the acknowledged version is stored locally by the UI. If storage is unavailable, acknowledgment lasts for the current page; Web/Desktop and different origins are not guaranteed to share it.

Storage, privacy, and security boundaries
~/.dsh/dsh-memoir.json structured JSON v4 (single source of truth)
~/.dsh/dsh-memoir.settings.json live GUI setting overrides
<project>/PROJECT_MEMORY.md human-readable projection generated from JSON
- No cloud memory database, embedding API, or vector database;
- an arbitrary absolute path submitted by the browser does not grant write access; panel writes accept only a trusted active workspace or an existing project bucket;
- manual browser records cannot spoof trusted session/turn provenance;
- cross-process writes use an exclusive lock and reread disk inside the critical section, with conservative dead-owner recovery;
- Windows path keys are case-normalized while display paths retain their original form;
PROJECT_MEMORY.mdmay be committed by you, so the user decides whether sensitive content enters Git.
Back up the JSON and project Markdown according to your own policy before upgrades. Removing the plugin does not actively delete them.
Configuration
Every field below can be set in the memoir config row in cordis.patch.yml. Except for enabled, each is also live-editable and persisted from the Memory panel or Settings card.
| Field | Default | Purpose |
|---|---|---|
enabled |
true |
master switch for tools, routes, and prompt injection |
language |
zh |
agent-facing copy; zh / en in 0.8.2, plus de / ru in 0.9.0; independent of GUI language |
announceToAgent |
true |
announce memory tools and rules to the agent |
autoDistill |
true |
enable top-level worked-turn reminders |
autoDistillEvery |
1 |
remind at most once per N worked turns |
autoDistillCooldownMin |
0 |
minimum minutes between successful reminders |
autoDistillMinTools |
1 |
minimum tool calls required in a triggering turn |
hotMemoryTokens |
900 |
normal Hot Memory target budget |
hotMemoryMaxTokens |
1200 |
hard ceiling that no session exceeds |
readDefaultLimit |
8 |
default memoir_read result count |
readMaxLimit |
30 |
live upper bound per recall |
sessionSnapshotMax |
128 |
resident LRU capacity; durable records are not deleted |
queryCacheSize |
128 |
BM25 query LRU capacity |
Shrinking a cache evicts the oldest entries immediately. Existing frozen sessions are not rewritten after budget changes, preserving prompt-prefix stability. “Restore startup configuration” removes Web overrides and returns to profile startup values.
Performance and verification
v0.5.6 benchmark (Node 24.19, 900/1200-token budget; full data in bench/report.md):
| Entries | Index build | Uncached query | Cached query | Injection reduction vs full Markdown |
|---|---|---|---|---|
| 1,000 | 10.5 ms | 1.190 ms | 4.07 µs | 97.6% |
| 10,000 | 126.9 ms | 11.011 ms | 1.45 µs | 99.8% |
| 100,000 | 1.68 s | 126.933 ms | 1.42 µs | about 100% |
Numbers vary by machine and corpus. The important properties are that injection remains bounded and the cache-hit path is independent of total memory size.
Automated regressions cover session projection recovery, cross-process snapshots, writes and cancellation, lifecycle cleanup, BM25 recall, Hot Memory budgets, caching, corrections and project isolation. Curated lexical Top-5 recall is 41/41; fixture results do not measure real-model semantic accuracy, and prefix equality does not guarantee actual billing savings.
FAQ
Does it automatically summarize every chat? It does not silently scrape every conversation. At the end of an eligible turn it reminds the current agent to distill, and the agent writes through a public tool, keeping the process observable and reviewable.
Why does every new memory start at importance 3? Three is the neutral default on a 1–5 scale, so unscored content is neither demoted nor treated as highest priority. Change it through tool arguments or the GUI; pinning has separate weight.
Why is a new write not reinjected immediately in the current session?
The session Hot Memory snapshot is deliberately frozen for prompt-prefix caching. The write is immediately visible to memoir_read and the GUI, and the next session rebuilds automatic injection.
Does it inject all stored memory into context?
No. Only Hot Memory bounded by hotMemoryMaxTokens is injected automatically. Complete history is recalled on demand.
Why is the UI missing after installation?
Confirm the command used --profile web, then fully restart dsh web. Refreshing the browser alone is not enough.
Development and contributing
pnpm install --frozen-lockfile
pnpm run build
pnpm run typecheck
pnpm test
npm run bench
Read CONTRIBUTING.md before submitting changes. See CHANGELOG.md for 0.9.3 changes; the development SDK baseline is DSH 0.2.1-rc.2. See the compatibility table above for older lines and risks. Formal packages are published by the tag workflow through npm OIDC; consult Releases and npm for publication status.
Apache-2.0