Bounded, layered, approval-gated, auditable cross-session memory for DeepSeek Harness.
A typed ctx.memory seam, a write-approval gate no model path can bypass, and audit trails rebuilt from the session log.
| Surface | Status |
|---|---|
| Harness | DeepSeek Harness 0.1.0-rc.6 |
| Node | `^22.19.0 |
| Platforms | Windows / macOS / Linux (pure host; no native code, no network) |
| Model | Any |
dsh-memento is a capability seam, not another memory warehouse: a typed ctx.memory service, a local SQLite provider (node:sqlite, WAL, 0600, at $DSH_HOME/dsh-memento/memory.db), and its consumers — the memory tool and a frozen snapshot injected into the system prompt.
- The approval gate cannot be bypassed. Every write path (
add/replace/remove/seed) is forced through the approval waterfall inside the service, not in the tool layer.writePolicy: ask | auto | offis model-invisible configuration;replace/remove/consolidatecarry the full text of the entries they change in the approval payload, and a denied write still lands a*-deniedaudit row. - Model-visible ⟺ logged. The injected snapshot lands verbatim in
request/header.system; every write is reconstructable fromapproval/asked+approval/decided+ the plugin's own audit table. - Bounded and honest. Hard per-track/per-layer character budgets (default user 2000 / agent 4000). A full store fails with a structured error (usage + limit) — never truncated, never auto-compacted.
Two tracks × two layers × per-agent key: a user track (facts about the user) and an agent track (environment facts and conventions), each split into user-global and workspace layers, isolated per agentPreset. The snapshot is frozen once per session at first prompt assembly and never changes mid-session.
# 1. install the bundle into your profile
dsh plugin --profile web add "github:PerryLink/dsh-memento#main"
# or from npm (published releases)
dsh plugin --profile web add dsh-memento
# 2. restart and verify the row
dsh --profile web --dump-config | grep -A3 'id: memento'- git channel (latest
main):dsh plugin --profile web add git+https://github.com/PerryLink/dsh-memento.git. - npm channel (published releases):
dsh plugin --profile web add dsh-memento. - tarball channel:
npm packin this repo, thendsh plugin --profile web add ./dsh-memento-<version>.tgz. - uninstall:
dsh plugin --profile web remove dsh-memento(the memory database and session logs are kept).
All tunables are Schemastery Config fields (changeable from cordis.yml). Invalid values fail loudly at load. Override under the memento row.
| Key | Default | Meaning |
|---|---|---|
enabled |
true |
Master switch; false removes the service, tools, snapshot, command, panel, and answerer |
dbPath |
'' → $DSH_HOME/dsh-memento/memory.db |
Absolute, or relative to $DSH_HOME (falls back to ~/.dsh on Windows) |
budgets.user.userGlobal |
2000 |
Hard character budget for the user track's user-global layer |
budgets.user.workspace |
2000 |
Hard character budget for the user track's workspace layer |
budgets.agent.userGlobal |
4000 |
Hard character budget for the agent track's user-global layer |
budgets.agent.workspace |
4000 |
Hard character budget for the agent track's workspace layer |
writePolicy |
'ask' |
Default write policy: ask / auto / off (model-invisible) |
writePolicies |
{} |
Per-track/scope or per-source overrides (e.g. user/workspace, source:claude) |
language |
'en' |
Model-visible and command output language: en / zh |
snapshotOrder |
-50 |
Snapshot section order (after harness identity, before persona) |
maxEntriesPerQuery |
20 |
Default per-query result cap (hard-capped at 1000) |
commandListLimit |
50 |
Entries rendered per /memory list / query |
commandAuditLimit |
10 |
Audit rows rendered per /memory audit |
recall.historyLimitDefault |
8 |
memory_recall sessions scanned by default |
recall.snippetCap |
5 |
memory_recall snippets per session |
recall.snippetChars |
300 |
memory_recall snippet characters |
recall.windowDays |
30 |
memory_recall recency window in days |
panelEntriesLimit |
200 |
Web panel entries page size |
panelAuditLimit |
20 |
Web panel audit rows by default |
auditRetentionDays |
0 |
Audit retention (0 = keep forever) |
proposals.enabled |
true |
Auto-capture a memory proposal after each successful compaction |
proposals.maxChars |
2000 |
Proposal character cap |
proposals.maxPending |
8 |
Pending proposal cap |
| Surface | Kind | Notes |
|---|---|---|
memory |
tool | add/replace/remove/consolidate/query with Save/Skip guidance; writes ride the approval gate |
memory_recall |
tool | Bounded memory matches plus recent session-history matches |
/memory |
command | list · query · add · remove · consolidate · proposals · budgets · audit · export · import <path> · adapters |
| web panel | client drawer | Read-only: browse entries, search, budget bars, audit tail |
| Plugin | What it is | dsh-memento's difference |
|---|---|---|
| dsh-memory-evolve | memory warehouse / evolution loops | a typed service seam, approval gate, and session-log audit; no warehouse ambition |
| dsh-mnemon | memory store helper | protocol + gate + audit, not another store |
| dsh-kb-sieve | knowledge-base sieving | no retrieval engineering: small-corpus substring search, cross-session recall via session_search/sessionQuery |
| dsh-tdai-memory | task-driven memory tooling | budgets are per track×layer and enforced in the service, not best-effort |
| claude-bridge | Claude Code bridging | DSH-native; a future seed(source:'claude') path lets a bridge feed the same store |
| dsh-external/Recall | external agent memory | local-first, zero-network, rides DSH's own approval seam |
| Official MCP memory examples | DSH's stated "memory = external MCP" position | the native first-party complement: same goal, no external server; both coexist |
The name is dsh-memento (published on npm and GitHub). Not dsh-recall (confusable with dsh-external/Recall), not the deleted legacy name dsh-memory.
dsh-memento is the community rehearsal of the DSH memory protocol — a candidate shape for an official ctx.memory seam. The protocol normalizes this plugin's seam into a cross-plugin contract:
-
Entry spec — two tracks × two layers × per-agent key, plus short
tags(≤16 × ≤32 chars) and a per-entryversionthat increments on everyreplace. -
Write semantics — idempotent unique-substring conditional writes; approve-what-you-see payloads (
replace/remove/consolidatecarry the full text they change). -
Audit contract — every write reconstructable from
approval/asked+approval/decided+ the provider ledger. -
Budget model —
BUDGET_EXCEEDED/AMBIGUOUS_MATCHsemantics. -
Schema versioning — migration rules with loud version checks.
-
Spec — docs/protocol-v1.md (中文: protocol-v1.zh.md); normative JSON Schema at docs/schemas/dsh-memory-protocol-v1.schema.json.
Adapter registry — ctx.memoryAdapters (register / list / adapt / export) lets third-party memory plugins speak the protocol by registering a pure data converter (reversible register(); import rides the approval-gated seed, export is read-only). Onboarding: docs/adapters-guide.md (中文: adapters-guide.zh.md).
| Built-in adapter | External format | Notes |
|---|---|---|
mem0 |
mem0 fact collections ({facts: [{memory, metadata?}]}) |
metadata.category / metadata.tags become tags; raw messages arrays are rejected — adapters convert, never extract |
hermes-memory-md |
Hermes memory.md (## section + bullets) |
section names become tags; non-bullet prose fails loudly |
claude-code-memory-md |
CLAUDE.md-style markdown (headings, bullets, paragraphs) |
bullets and paragraphs become entries; section names become tags |
Conformance suite — test/protocol-conformance/: a distributable case set any provider claiming compatibility runs (node test/protocol-conformance/run.mjs --provider ./your-factory.mjs); this repo's CI runs it against its own provider as the golden reference (npm run test:conformance).
- Upstream proposal — docs/upstream-proposal.md (中文: upstream-proposal.zh.md): why the official
ctx.memoryseam should adopt the protocol, the differences, and the migration path.
- Permissions: declares
harness:tool,filesystem:read,filesystem:write, andnetwork:none/subprocess:none/shell:none/python:none/credentials:nonein its workshop manifest. Write approval rides the official approval seam. - Data: local SQLite database (
0600), zero network, zero credentials. - Session log: audit completeness comes from the approval pair (
approval/asked+approval/decided) plus the plugin's own audit table.
- Public services only. Consumes
tools,systemPrompt, and the approval seam; no engine / agent-loop / apiproxy / official-UI changes. - Zero network, zero credentials. Local database with POSIX file mode
0600. - Fail loud. Corrupt DB, newer schema, or invalid config fails at load; full budgets and ambiguous substring matches fail with structured errors.
- One process, one store. Multiple sessions share the SQLite store; two processes sharing one
$DSH_HOMEwrite the same file (last-writer-wins under SQLite locking).
- Session events are declared, not yet emitted (rc.6).
memory/added|updated|removed|recalled|snapshotare merge-declared, but rc.6 has no registration surface for out-of-repo event types; emission turns on once a harness build registers them. askpolicy needs an answerer. With no UI/ACP answerer composed, writes fail closed.- No FTS5 indexing. Substring search runs on case-insensitive
instr(correct for CJK).
dsh-memento is not a port of Claude Code, Codex, or Hermes — but its design deliberately absorbed the parts each got right, and refused the parts that hurt:
| Terminal memory | What it got right | What dsh-memento adopted |
|---|---|---|
Claude Code — CLAUDE.md |
hierarchical plain-text memory files (user-level → project-level), human-readable and human-editable, merged automatically into every session | plain-text entries; user-global / workspace layers merged per session; a store you can browse, export, and audit — transparency as a feature |
Codex — AGENTS.md |
per-directory scoped instructions auto-discovered and injected with zero model friction | the workspace layer keyed by the session cwd (Windows case-insensitive); the frozen snapshot injected automatically at session start |
Hermes — memory.md |
proactive memory saves and the security lesson that a gate enforced only in the tool layer is bypassable by late tool injection | the memory tool with Save/Skip guidance + approval-gated auto-capture proposals; the gate lives inside ctx.memory's write methods, not in the tool layer |
Sources: Claude Code memory · Codex AGENTS.md · Hermes memory · Hermes #48181.
And the parts deliberately refused: hidden auto-summarization into model-private state (compaction summaries here become pending proposals that wait for a human approve/dismiss), warehouse/vector-store ambitions, and any write that lacks a human-visible approval or audit trail. Also adopted: Hermes's documented caveat that two processes sharing one home directory write the same memory file — see Security boundaries.
npm install # node ^22.19 || >=24
npm test # node --test: 133 tests
npm run test:conformance # dsh-memory-protocol v1 conformance suite
npm run typecheck # tsc --checkJs gate
npm run check:coverage # line-coverage gate
npm run check:readmes # five-language README consistency gatelib/ is zero-DSH-dependency (node: builtins only); DSH imports exist only in index.mjs.
dsh, dsh-plugin, deepseek-harness, memory, agent-memory, approval, audit, sqlite, cordis, llm
- @Niuniu-Sir — the boot-crash report in issue #1 that led to the
~/.dshfallback shipped in 0.3.1.
This project is one of the 15 DeepSeek Harness plugins maintained by PerryLink. If this one helps you, the others likely will too:
| Plugin | One-liner |
|---|---|
| dsh-mcp-panel | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors |
| dsh-doublecheck | Engineering-discipline guard: requirements grill, test gates, adversary review |
| dsh-background-agents | Durable background child agents with a Web UI sidebar, messaging and interrupt |
| dsh-lsp-actions | LSP diagnostics, formatting, completion, code actions and rename over language servers |
| dsh-output-styles | Claude Code outputStyles-equivalent runtime style switching |
| dsh-checkpoint-rewind | Claude Code /rewind-equivalent: snapshots, session forks, one-shot restore |
| dsh-permission-rules | Claude Code-style declarative allow/deny/ask permission rules with audit |
| dsh-auto-review | Second-model auto-review on the approval chain, fail-closed by default |
| dsh-memento | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool |
| dsh-skill-pack-security | Security-audit skill pack: secret scan, dependency and supply-chain review |
| dsh-session-pin | Pin sessions in the Web sidebar with durable ordering |
| dsh-composer-history | Terminal-style input history for the web composer: arrows, Ctrl+R search |
| dsh-github | GitHub PR/issues integration for DSH, every write gated by approval |
| dsh-plugin-guide | Plugin-development knowledge base as an on-demand agent skill |
| dsh-claude-move | Migrate Claude Code sessions, memory, skills and CLAUDE.md into DSH |
Apache License 2.0 © 2026 dsh-memento contributors