dsh-longterm-memory
Manifest validObsidian-compatible long-term memory vault plugin for DeepSeek Harness (DSH): local Markdown storage, sidebar management page, token-budgeted recall, durable journal outbox.
DSH Memory Vault · 长期记忆
Long-term memory for DeepSeek Harness, stored as a plain Markdown vault you own.
A first-level sidebar page, four model tools, token-budgeted recall, and a durable
history journal — no database, no telemetry, no cloud. Your memories stay as
Obsidian-compatible .md files on disk.
Install · Features · Configuration · Data safety · Privacy · Development · 简体中文
Project status (2026-10-18).
dsh-longterm-memory@0.1.0is published on npm. The desktop-app plugin entry has not yet been exercised end-to-end in an isolated desktop environment (the Web-profile install is verified); see Install and Project status & limitations.
Why DSH Memory Vault?
Most "agent memory" features are a vector store or a black-box service. DSH Memory Vault makes the opposite trade-off:
- Markdown is the only source of truth. Each memory is a human-readable note with YAML frontmatter. Read, edit, link and back it up in Obsidian or any text editor. There is no proprietary format and no export step.
- The index is disposable.
.dsh-memory/index.jsonis derived data; delete it and the plugin rebuilds it from Markdown. Losing the index never loses a memory. - Recall is budgeted and transparent. Injection is computed per assembly from the current index with explicit token/item caps; the page shows exactly what the model would receive.
- History is durable. Every change is recorded in a journal with before/after digests, reasons and timestamps. A write-ahead outbox keeps history safe across crashes — including the verified window where the Markdown is committed but the journal append has not happened yet.
- Local by default. No network requests, no model calls, no telemetry; the only traffic is the local RPC between the management page and the DSH host.
Features
| First-level sidebar page | Registers a sidebar.panellist entry and a full management page (overview, search, detail, manage, inbox, settings) — not a chat tab. |
| Four model tools | memory_search, memory_get, memory_save, memory_forget (save refuses credential-like content). |
| Automatic extraction | Rule-based, fully local candidate extraction at the real turn/end boundary. Optional model-assisted extraction is off by default. |
| Ranked recall | BM25-style lexical ranking over Markdown, with type/status/tag filters and a token budget. |
| Memory lifecycle | pending → active → stale / superseded / archived / conflict, plus low/medium/high confidence. Low confidence and sensitive content wait in the Inbox for human confirmation. |
| Safe updates | Deterministic dedupe/merge rules: duplicates merge, additions update while keeping sources, contradictions keep both sides, low confidence goes to Inbox. |
| Conflict handling | Conflicting facts are kept side by side, never silently overwritten; a conflict-resolution page supports keep / merge / both. |
| Crash-safe writes | Single-file atomic replace, per-file lock, optimistic checksum concurrency, durable journal outbox with idempotent recovery. |
| Obsidian compatible | The vault carries .obsidian/, [[wikilinks]], stable frontmatter and a human-readable Index/. |
| Bilingual UI | Chinese and English (`language: zh |
No runtime dependency on @deepseek-ai/* | The host half only uses the Cordis context passed in, so DSH internals can change without breaking the bundle. |
Interface
Real acceptance screenshots (headless Chrome, real host data — no mocks):
| Sidebar entry | Management page |
|---|---|
![]() | ![]() |
More: overview · search · manage · inbox · settings · dark theme
How it works
flowchart LR
A[DSH host] -->|tools / prompt section| P[Memory Vault host plugin]
U[Sidebar page] -->|local HTTP RPC| P
P --> V[(Markdown vault<br/>source of truth)]
P --> I[(index.json<br/>derived)]
P --> J[(journal outbox<br/>history)]
P --> Q[(quarantine<br/>unreadable notes)]
V -. rebuild .-> I
J -. recover .-> V
- The host owns the vault, index, journal and extraction; it never calls a model unless you explicitly enable model-assisted extraction with your own provider.
- The management page reads and writes through a loopback-only RPC surface
(
POST /dsh-longterm-memory/api/<method>, 27 methods) guarded by a browser-trust fence (loopback / trusted hosts,Origin,sec-fetch-site). - Recall:
memory_searchand automatic injection share one engine; explicit recall may include retired memories (labelled history), injection only uses current facts.POST /api/previewStandingandPOST /api/previewRecallreturn the exact text that would be injected.
Install
Option A — from npm (recommended)
dsh plugin --profile web add dsh-longterm-memory
Published as
dsh-longterm-memory@0.1.0(latest). The official desktop app manages plugins through its own plugin manager and a reserveddesktopprofile; that path has not been verified end-to-end yet (see status).
Option B — build this repository and install the tarball (verified)
Requires Node.js ≥ 20 and a DSH CLI. Use an isolated DSH_HOME so the test
profile cannot touch your daily DSH profile:
# 1. Build and pack
npm install
npm run build
npm pack # -> dsh-longterm-memory-0.1.0.tgz
# 2. Install into an isolated profile
$env:DSH_HOME = "<temporary dir>" # PowerShell
# export DSH_HOME="<temporary dir>" # bash
dsh plugin --profile lmv add .\dsh-longterm-memory-0.1.0.tgz
# 3. Start
dsh --profile lmv --no-open --port 0
Open the Web UI, click 长期记忆 / Long-term Memory in the sidebar, and choose a vault directory (or let the plugin initialize one). You can also pre-set it:
# <DSH_HOME>/profiles/lmv/cordis.patch.yml
- id: longterm-memory
name: dsh-longterm-memory
config:
vaultPath: 'D:/path/to/DSH Memory'
language: zh
Data-location warning. If
vaultPathis unset, the plugin initializes the default location (~/Documents/DSH Memoryon Windows).DSH_HOMEisolates the profile, not the vault. Always setvaultPathwhen testing.
Quick start
- Install as above and open the page.
- Click 初始化 / Initialize and pick a folder (an existing Obsidian vault works).
- Create a memory with 新建 / New, or let automatic extraction collect candidates at the end of a turn; low-confidence items appear in 收件箱 / Inbox.
- Ask the model something related; the plugin injects the standing section and the tools return ranked hits from the vault.
- Open 设置 / Settings to tune budgets, per-step recall, extraction and language.
Vault layout
DSH Memory/
├── README.md # generated; user edits are preserved
├── Memory Home.md # entry page
├── .obsidian/ # makes Obsidian treat it as a vault
├── Profile/ Preferences/ # profile, long-term preferences
├── Projects/ Projects/State/ # projects and project state
├── Decisions/ Knowledge/ # decisions, knowledge
├── Experiences/ Tasks/ # lessons, tasks
├── Inbox/ # candidates awaiting confirmation
├── Archive/ Conflicts/ # retired / contradictory memories
├── Index/ # human-readable index (regenerated)
├── History/ # change-history notes
└── .dsh-memory/ # config.json, index.json, journal/, quarantine/
Memory types: profile, preference, project, project-state, decision,
knowledge, experience, task. Status: active, pending, stale,
superseded, conflict, archived. Format details:
docs/storage-format.md.
Configuration
All settings are optional; defaults live in src/host/config.ts and can be overridden
from your profile's cordis.patch.yml.
| Key | Default | Meaning |
|---|---|---|
vaultPath | auto-discover / initialize | Absolute memory vault path |
language | zh | UI language (zh / en) |
enableTools | true | Expose the four model tools |
enablePromptSection | true | Inject the standing memory section |
standingBudgetTokens | 700 | Token cap for the standing section |
standingMaxItems | 12 | Item cap for the standing section |
recallBudgetTokens | 600 | Token cap for one recall answer |
recallMaxItems | 8 | Item cap for one recall answer |
enablePerStepRecall | false | Splice retrieved memory into each step (replayed for the rest of the session) |
enableAutoExtraction | true | Rule-based extraction at turn end (local) |
enableLlmExtraction | false | Optional model-assisted extraction (sends turn text to your provider) |
redactSecrets | true | Refuse credential-like candidates |
sensitiveNeedsConfirmation | true | Health/finance/identity content waits for confirmation |
maxCandidatesPerTurn | 5 | Extraction cap per turn |
Data safety
- Atomic single-file writes (temp file + rename) and a per-file lock with stale-lock detection; the lock is released on failure, never leaked.
- Optimistic concurrency: edits carry the expected checksum; a stale edit is rejected with a reload hint instead of overwriting someone else's change.
- Index is rebuildable:
rebuildIndex/syncIndexrecover from a deleted or corrupt index. Corruption diagnostics are surfaced, not hidden. - Durable journal: every change gets a before/after digest, reason and timestamp. A write-ahead outbox recovers when the monthly archive fails, with idempotent re-archiving and content-conflict detection (same event id + different payload is an explicit integrity error, never a silent merge).
- Crash-window tests: commit boundaries are exercised with real child-process SIGKILLs, not simulated exceptions — including "Markdown written, commit marker not yet persisted" and "recovery itself interrupted".
- Quarantine: notes that cannot be parsed safely are isolated, never deleted.
Privacy
- No telemetry and no outbound network calls by default. Host-side acceptance runs showed zero network calls; the only client request target is the local DSH RPC. Browser-runtime network verification of the desktop UI is still pending — see status.
- Model use is opt-in: automatic extraction is rule-based and local; model-assisted
extraction (
enableLlmExtraction) is off and, when enabled, uses the provider you configured in DSH. - Secrets are refused: credential-like content (passwords, API keys, tokens, private keys) is blocked before it reaches the vault; sensitive categories require explicit confirmation.
- Injection is data, not instructions: memories are wrapped and labelled as untrusted data for the model. See docs/privacy.md.
Compatibility
| DSH runtime | >=0.2.1-rc.2 <0.2.2 (engines.dsh; 0.2.0-rc.2 is not supported) |
| Verified DSH version | 0.2.1-rc.2 (host + real headless Chrome acceptance) |
| Node.js | >=20 |
| Platform | Windows (primary), Node path rules elsewhere |
| npm package | dsh-longterm-memory — 0.1.0 published (latest) |
The dsh.compatibility field is informational; engines.dsh is the only decision
source. Details and evidence: docs/compatibility.md.
Development
npm install
npm run build # tsc -> lib/host, esbuild -> lib/client.js
npm run typecheck # tsc --noEmit
npm run lint # contract checks + version-consistency check
npm test # full suite (currently 40 files / 581 cases)
npm run check # build -> typecheck -> lint -> test (clean checkout safe)
npm run pack:plugin # build + npm pack
Tests cover unit, integration, packaging, real HTTP-route validation, and deterministic
fault injection (including real subprocess kills). The browser acceptance scripts are
zero-dependency CDP clients using Node's built-in WebSocket.
Project status & limitations
- Preview: API and storage format may still change;
0.1.0is the first public version. - npm published:
dsh-longterm-memory@0.1.0(2026-10-18); registry installation verified. - Desktop integration pending: the plugin loads in a Web profile and the package installs from a tarball, but a full desktop-app acceptance run in an isolated environment has not been performed. Treat the desktop plugin-manager path as unverified until reported otherwise.
- Known follow-ups: a few concurrency and move-atomicity edge cases remain open;
frontmatter and lock regressions found in review were fixed in
0.1.0and are locked by tests. - Vault location: with
vaultPathunset the plugin initializes~/Documents/DSH Memory. Set it explicitly to keep test data isolated.
Documentation
| Doc | Contents |
|---|---|
| docs/architecture.md | Architecture, DSH API usage, prompt assembly |
| docs/storage-format.md | Markdown / frontmatter / index / journal formats |
| docs/privacy.md | Privacy and threat model |
| docs/compatibility.md | Compatibility contract and evidence |
| docs/verification.md | Verification log and acceptance evidence |
| docs/troubleshooting.md | Recovery and FAQ |
| docs/evidence/ | Screenshots and raw acceptance data |
License
Comments
Loading…
Similar plugins
by mingzeng21
Connect DeepSeek Harness (dsh) to a local Obsidian vault: search, read, write, move, and trash notes.
★ 29
↓ 748/wk
MIT
TypeScript
Oct 15, 2026
dsh plugin --profile web add dsh-obsidianby SYMlp
Markdown folder long-term memory plugin for DeepSeek Harness (dsh): one file per fact, human-editable, git-versionable
★ 0
MIT
TypeScript
Aug 20, 2026
dsh plugin --profile web add dsh-markdown-memoryby CuteSamurai24
Small file memory for DeepSeek Harness. The model writes markdown, the host injects it.
★ 0
MIT
JavaScript
Aug 18, 2026
dsh plugin --profile web add dsh-md-memoryby guntur-d
Persistent cross-session memory plugin for DeepSeek Harness: workspace-scoped durable facts with memory_write/list/search/forget tools and bounded prompt injection
★ 0
TypeScript
Aug 14, 2026
dsh plugin --profile web add @guntur-d/dsh-memoryby bonerush
Project documents and long-term memory as plain Markdown in a dedicated Obsidian vault: six mem_* tools (search, read, write, log, brief, admin), one budgeted recall injection at the first step of a s
★ 8
MIT
JavaScript
Oct 12, 2026
dsh plugin --profile web add dsh-obsidian-memby disc0nct
A persistent memory plugin for DeepSeek Harness that enables agents to store and recall information across sessions — DSH-native tools with atomic storage, validation, and concurrency-safe reads
★ 0
MIT
JavaScript
Aug 22, 2026
dsh plugin --profile web add @deepseek-ai/dsh-tool-memory
