- 1024 store channel:
npm i -g dsh1024once, thendsh1024 plugin --profile web add dsh-memento(counts toward the deepseek1024.com install ranking).
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 an audit trail you can rebuild — from the approval pair plus the plugin's own audit table, with the session-log gap named out loud.
| Surface | Status |
|---|---|
| Harness | DeepSeek Harness dsh-v0.1.7-alpha.1 (adapted 2026-09-22): the 0.1.7 line replaced the whole settings registration surface (installSettingsSection / SettingsProvider.installSection / SettingsNamespace / SettingsScope) with live Config forms, so both halves follow the new contract — a form's namespace is the profile entry id (memento), its editable fields are the .volatile() ones, and an accepted edit is committed into the running plugin instead of remounting it. The browser half reads that form through ctx.configForms.get(entryId) (the ctx.settingsScope service is gone). Both halves keep their installSection / settingsScope branches for the 0.1.2-rc.1, 0.1.5-alpha.1 and 0.1.6-0 lines the peer range still advertises, and the new >=0.1.7-0 <0.2.0 clause is what makes the target host itself installable (the old range excluded it by semver's prerelease rule). Still no plugin event-registration surface — KNOWN_SESSION_EVENT_TYPES does not carry memory/*, and Session.append's third argument only carries a SurfaceIntent for surface-eligible types, so the audit gate stays adaptive and skips as before (it says so once per process and in /memory audit). Type evidence comes from three faces: the local checkout's built types, the pinned published line in node_modules, and the browser half under a DOM lib. |
| 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
system/message; 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.
- The audit gap is visible.
/memory auditlists the plugin audit table and appends one line when the session-log side is not written: this harness does not know thememory/*session event types, and appending unknown types would make the session unloadable, so writes are audited throughapproval/asked+approval/decidedand the plugin's table instead. The gate is adaptive — the line disappears on its own once the host knows those types.
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.
Settings panel. On the 0.1.7 line the plugin's own Config is its settings page: the form's namespace is the profile entry id (memento — the id: of this bundle's row), the editable fields are exactly the ones the plugin declares .volatile() (every key below except enabled), and an accepted edit is merged into the profile's plugin row and committed into the running plugin — no file editing, no restart. Nearly everything applies live (write policies, language, budgets, limits, proposals, panel, dbPath / auditRetentionDays via a store reopen, retrieval.vector via a retriever swap); what a plugin registers at load time (snapshotOrder, tool descriptions) is re-read on reload, and the page marks those fields. Numeric bounds are declared in the schema as well, so an out-of-range edit is refused at write time instead of leaving an unusable config behind. On the older lines (0.1.2-rc.1, 0.1.5-alpha.1, 0.1.6-0) the same card edits the dsh-memento settings namespace exactly as before; with no settings service at all, everything falls back to the composed cordis config. The floating panel button can be hidden from the same page (panel.enabled).
| Key | Default | Meaning |
|---|---|---|
enabled |
true |
Master switch; false removes the service, tools, snapshot, command, panel, and answerer (not editable from the settings page — a disabled plugin has no settings entry) |
panel.enabled |
true |
Show the web panel's floating button; saving false from the settings page hides the 🧠 entry immediately, no reload needed (the settings page itself stays reachable) |
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 |
retrieval.vector |
false |
Semantic recall switch: true enables memory_recall vector recall (fake hash embedding) when an embedding provider is available; otherwise degrades to substring |
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; the floating entry button can be hidden (panel.enabled) |
| settings section | DSH settings sidebar → dsh-memento |
Edit every config field except enabled without touching files (namespace = the memento profile entry on the 0.1.7 line, the dsh-memento settings namespace before it); live vs reload-required timing is marked on the page |
dsh-memento ships a read-only stdio MCP server (dsh-memento-mcp) so external MCP clients (Claude, Codex, …) can search the memory store without a harness. It speaks JSON-RPC 2.0 over newline-delimited JSON (NDJSON) — one JSON object per line, no Content-Length framing.
Read-only. The database is opened with node:sqlite readOnly: true (no migrations, no WAL writes, no recall-count bump); a missing database returns empty results instead of crashing.
| Tool | Purpose |
|---|---|
memory_search |
{query, limit?} → ranked entries (case-insensitive substring via the retrieval Provider seam) |
memory_stats |
{} → {total, namespaces} entry count + per-track/scope overview |
Run it directly:
node bin/mcp-server.mjs
# or, after npm install: npx dsh-memento-mcpThe database path is $DSH_MEMENTO_DB_PATH (absolute, or relative to $DSH_HOME); it defaults to $DSH_HOME/dsh-memento/memory.db.
Claude Desktop (claude_desktop_config.json) example:
{
"mcpServers": {
"dsh-memento": {
"command": "npx",
"args": ["-y", "dsh-memento-mcp"],
"env": {
"DSH_MEMENTO_DB_PATH": "/home/you/.dsh/dsh-memento/memory.db"
}
}
}
}The server is read-only: no network, no writes, no approval gate — search and stats only.
| 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; the session-log side of that gap is declared in/memory auditand disappears once the host registersmemory/*.
- 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.2).
memory/added|updated|removed|recalled|snapshotare merge-declared, but rc.2 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: 187 tests
npm run lint # oxlint
npm run test:conformance # dsh-memory-protocol v1 conformance suite
npm run typecheck # host face vs a local D:\deepseek-harness checkout (prints "not verifiable" and exits 0 without one)
npm run typecheck:ci # host face vs the pinned published line in node_modules
npm run check:client # browser half (DOM lib) type gate
npm run check:coverage # line-coverage gate
npm run check:readmes # five-language README consistency gate
npm run verify:self-contained # reject out-of-repo dependency specs
npm run verify:artifacts # artifact presence + syntax + importlib/ 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 45 DeepSeek Harness plugins maintained by PerryLink. If this one helps you, the others likely will too:
| Plugin | One-liner |
|---|---|
| dsh-auto-review | Second-model auto-review on the approval chain, fail-closed by default |
| dsh-autotier | Automatic strong/cheap model-tier routing with deterministic risk guards and a /tier command |
| dsh-background-agents | Durable background child agents with a Web UI sidebar, messaging and interrupt |
| dsh-budget | Cost governance for DeepSeek Harness: budgets, carbon, and latency in one panel. |
| dsh-catalog | DSH Desktop Market standard catalog source for the PerryLink family |
| dsh-cert-mcp | Read-only MCP server exposing the certification registry: grades, snapshots and five-dimension evidence |
| dsh-checkpoint-rewind | Claude Code /rewind-equivalent: snapshots, session forks, one-shot restore |
| dsh-claude-move | Migrate Claude Code sessions, memory, skills and CLAUDE.md into DSH |
| dsh-click | Cross-platform native desktop control for DeepSeek Harness — Windows first. |
| dsh-composer-history | Terminal-style input history for the web composer: arrows, Ctrl+R search |
| dsh-data-quality | Dataset quality checks and citation cross-checks (the optional numeric bridge consumed here) |
| dsh-defend | Prompt-injection, jailbreak, and secret-leak defense for DeepSeek Harness. |
| dsh-doublecheck | Engineering-discipline guard: requirements grill, test gates, adversary review |
| dsh-draw | Unified static-image generation routing for DeepSeek Harness. |
| dsh-fast | Read-only performance diagnostics for DeepSeek Harness. |
| dsh-fund-research | Deterministic research reports for Chinese public mutual funds |
| dsh-github | GitHub PR/issues integration for DSH, every write gated by approval |
| dsh-industry-research | Industry research orchestration that seals its deliverables through this plugin's ctx.researchReport.assemble |
| dsh-laya | Laya typed decisions (noul/choice/score) as a first-class Cordis service and model-visible tools |
| dsh-library | Local document knowledge base for DeepSeek Harness. |
| dsh-local-ai | Local-model (Ollama) integration for DeepSeek Harness. |
| dsh-lsp-actions | LSP diagnostics, formatting, completion, code actions and rename over language servers |
| dsh-mask | PII masking middleware: anonymize at the model boundary, restore at the display layer |
| dsh-mcp-panel | Read-only MCP runtime panel: /mcp command + Settings tab with status, tools and errors |
| dsh-memento | Approval-gated cross-session memory: ctx.memory seam + SQLite + memory tool |
| dsh-observe | OpenTelemetry and Langfuse observability exporter for DeepSeek Harness. |
| dsh-output-styles | Claude Code outputStyles-equivalent runtime style switching |
| dsh-permission-rules | Claude Code-style declarative allow/deny/ask permission rules with audit |
| dsh-plugin-certification | Community certification registry with repro-checkable grades and badges |
| dsh-plugin-doctor | Zero-dependency static + sandbox smoke detector for DSH plugins |
| dsh-plugin-guide | Plugin-development knowledge base as an on-demand agent skill |
| dsh-plugin-kit | Shared zero-runtime-dependency toolkit for the PerryLink DSH plugins |
| dsh-plugin-upgrade | One-package, one-corridor-index plugin upgrade skill: routes a repository to the matching closed corridor card |
| dsh-plugin-upgrade-015 | Merged 0.1.3-alpha.1 → 0.1.5-rc.1 upgrade corridor card plus a zero-dependency seam scanner |
| dsh-reach | Multi-channel approval/question bridge: WeChat/Telegram/Feishu, session console |
| dsh-research-report | Verifiable research-report engine: content-addressed evidence ledger and sealed versions |
| dsh-score | Multi-dimensional quality scoring for DeepSeek Harness plugins. |
| dsh-session-pin | Pin sessions in the Web sidebar with durable ordering |
| dsh-session-sync | Cross-device session sync for DeepSeek Harness — a dedicated git mirror of your session store. |
| dsh-skill-pack-security | Security-audit skill pack: secret scan, dependency and supply-chain review |
| dsh-talk | Voice-first session loop for DeepSeek Harness: talk to it, hear it answer. |
| dsh-team-rooms | Cross-session team rooms: shared message bus, task board and timeline |
| dsh-test-drive | Isolated install-and-smoke test drives for DeepSeek Harness plugins. |
| dsh-ticktick | TickTick/Dida365 task bridge: session-header panel + 11 tools |
| dsh-translate | Vendor parameter translation and deterministic JSON repair for DeepSeek Harness. |
All PerryLink plugins are browsable in the built-in DSH Desktop Market: Market → Sources → add source → paste https://perrylink-dsh-catalog.perrylink.workers.dev/catalog-source.json → select it. Installation still goes through the Market's npm-identity verification and your confirmation.
Apache License 2.0 © 2026 dsh-memento contributors