dsh-plugin-memory
dsh-plugin-memory: a persistent 5-layer memory system plugin for DeepSeek Harness (DSH) — index+topics split, truncation budget, relevance injection, idle LLM auto-extraction, and 6 agent tools.
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 17, 2026
- Updated
- Aug 19, 2026
Introduction
@deepseek-ai/dsh-plugin-memory
English | 中文
Stop starting every session from zero. Give your DeepSeek Harness (DSH) agent a persistent five-layer memory — profile, project context, daily log, and recallable topics — so it remembers you between sessions, not just inside one.
The problem
An agent without memory is a brilliant stranger: every new session it re-learns who you are, what you are working on, and what you decided last week. Prompt stuffing and hand-written notes do not scale — they bloat context, drift out of date, and never get cleaned up.
The insight
Memory is not one bucket, it is five layers with different lifetimes and owners — from a user-owned identity file (L0) down to per-day append-only logs (L3). Each layer gets its own write path, truncation budget, and injection rule, so cold-start context stays cheap while long-term facts actually accumulate.
What it does
| Layer | Where | Purpose |
|---|---|---|
| L0 Global identity | ~/.dsh/AGENTS.md (existing) | Long-term identity & rules — owned by the user, not this plugin. |
| L1 User profile | ~/.dsh/memory/profile.md | Four fixed sections (工作背景 / 个人背景 / 当前关注 / 近期动态), Version-N rotation with .bak. |
| L2 Project semantic | <cwd>/.dsh/memory/MEMORY.md + topic files | Index + topic-file split; injected at session start. |
| L3 Daily memory | <cwd>/.dsh/memory/YYYY-MM-DD.md | One dated file, appended line-by-line, never merged. |
| L4 Method assets | skills (existing) | Out of scope; skills already live in DSH. |
Six mechanisms, in priority order from the spec:
- Index + topic split (L2).
MEMORY.mdis always an index of one-line pointers (≤150 chars each); detailed notes live in<topic>.md. Controls single-file bloat, stays searchable and truncatable. - Truncation budget. The booted index is hard-clamped to 200 lines / 40 000 chars, so cold-start context stays cheap.
- Relevance injection. On each step, the latest user query selects relevant topic files (LLM ranking when
llmis configured, keyword fallback otherwise) and appends them as a<system-reminder data-role="memory">block. Within a session, already-surfaced files are de-duplicated. - Auto-extraction. When a session goes idle, a debounced, best-effort pass sends the recent transcript to the LLM and writes new topic files + index lines. It never overwrites existing memories and degrades silently if the model is unavailable.
- Profile rotation (L1).
memory_profilemerges new facts into the four sections and rotates the version, keeping.bak. - Agent tools. Six model-callable tools let the agent save, recall, search, and forget memories directly.
Quick start
dsh plugin --profile web add github:NattoCB/dsh-plugin-memory
Restart dsh web, and the plugin bootstraps ~/.dsh/memory/ and <cwd>/.dsh/memory/ on first use. No llm route? The plugin still provides index+topics, entry injection, keyword relevance, the agent tools, and profile rotation — only LLM-based extraction and LLM relevance ranking are disabled.
How it works
The plugin registers on two cordis seams, mirroring first-party plugins (dsh-time-context, dsh-tool-todo):
agents— anagent/pre-steplistener (prepended, likedsh-time-context) that injects the entry instruction and relevant memories into the request history as plugin-sourcedusermessages.tools— six tools registered viadefineToolfrom@deepseek-ai/dsh-tools.
Memory is written with Node's fs/promises directly to the memory roots — not through the agent sandbox — because the memory directory is intended persistence, not self-modification. The Instruction Poisoning boundary still applies: memory files are data the agent reads back, never permission grants.
src/
paths.js DSH_HOME / global / project memory root resolution
store.js MemoryStore, DailyMemory (L3), ProfileMemory (L1 rotation)
inject.js entry instruction, relevance reminder, keyword scoring, truncation
llm.js one-shot completion over the harness `llm` service (silent fallback)
index.js plugin entry: pre-step injection, tools, idle auto-extraction
Configuration
Deploy via a DSH plugin entry (see package.json exports):
- id: memory
name: '@deepseek-ai/dsh-plugin-memory'
config:
enableEntryInjection: true # prepend the how-to-save + index block each session
enableRelevance: true # append relevant topic files per step (data-role=memory)
enableExtraction: true # idle-time LLM auto-extraction
maxRelevant: 5 # max files surfaced per step
relevanceTopK: 8 # max candidates the LLM selector may pick from
relevanceBudgetChars: 2000 # per-topic char cap fed to relevance/selector
extractionDebounceMs: 60000 # idle debounce before a pass runs
extractionLookback: 40 # recent events scanned for a pass
llm: # optional; omit provider/model to use keyword-only relevance + no extraction
provider: deepseek
model: deepseek-chat
maxTokens: 1024
Tools the agent can call
| Tool | Scope | Effect |
|---|---|---|
memory_write | global/project | Write/overwrite a topic file; optionally add an index line. |
memory_read | global/project | Read a topic file or MEMORY index. |
memory_search | global/project/both | Keyword search topic files. |
memory_daily | cwd | Append a dated line to <cwd>/.dsh/memory/YYYY-MM-DD.md. |
memory_forget | global/project | Delete a topic file and its index pointer. |
memory_profile | global | Read or merge-and-rotate the single-user profile. |
Data layout (created on first use)
~/.dsh/memory/
MEMORY.md # global index (≤200 lines / 40K chars)
profile.md # L1 profile (Version N)
profile.md.bak # previous version
<topic>.md # topic files
<cwd>/.dsh/memory/
MEMORY.md # project index
YYYY-MM-DD.md # daily memory
<topic>.md # project topic files
The story
This plugin grew out of the memory model of an older harness (WorkBuddy): a user-level profile, project-level semantic memory, and daily logs — plus a decision kernel that says mechanism beats willpower (P0). DSH had none of it, so sessions kept starting from zero. This plugin ports that proven design to DSH's plugin seams and adds the missing pieces (relevance injection, truncation budgets, idle auto-extraction) that make it actually usable.
Differences from the reference spec
- No
<uid>layer. DSH has one user; the profile is~/.dsh/memory/profile.md, not<uid>_memory.md. - No HTTP API / GUI panel. This is a pure harness plugin; GUI integration is the host's concern.
- Extraction is debounced + LLM-driven, not a separate subagent process. The original two-turn
NO_EXTRACTION_NEEDEDsubagent design is preserved in spirit (best-effort, silent degradation) but runs inline on idle to avoid spawning nested agents. - Relevance uses the harness
llmservice when available, degrading to deterministic keyword scoring otherwise.
License
MIT.
Try it: install with one line, restart, and tell your agent something worth remembering — then check ~/.dsh/memory/ a session later. Found a gap in the model? Open an issue or send a PR.