Long-term memory for DeepSeek Harness, read-only as of 0.1.0: a scribe_recall tool that reads a plain-markdown memory room, path rules that refuse directory traversal, Unicode smuggling and NTFS alternate data streams, and a bounded index whose truncation is always reported rather than silent.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:BOWLUNA/dsh-zcode-scribe
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
v1.0.0 · developed and verified against dsh >=0.1.5-rc.2 <0.2.0 || >=0.1.6-alpha.1 <0.2.0.
Long-term memory for DeepSeek Harness whose writer is a narrowed subagent.
Status: early, and read-only. The
scribe_recalltool is registered, executes for real inside a live host, and a real model session on dsh0.1.6-alpha.2used it to answer from a memory room —docs/MEASUREMENTS.mdcarries the raw output behind every claim below. 101 tests pass. What does not exist yet: writes, extraction, and the narrowed writer, which is gated on milestone M0 — proving a subagent's capability set can actually be narrowed through a public seam. Nothing is injected into the prompt yet, so installing this changes what the model can ask for, not what it knows.
The problem this is actually solving
The DSH plugin market lists 190 plugins under memory. Long-term memory is not an
empty niche, and this project is not justified by a missing feature. It is justified by
three missing safety properties, and it only takes the second slot in the table below
because the first is already served by other people's work.
| Property | Existing coverage |
|---|---|
| A local, bounded, inspectable store | Covered. engramory, dsh-memento, dsh-memoir and dozens more do this well. Install one of those. |
| Hard permission narrowing for the component that decides what to remember | None. No plugin removes capabilities from its writer; the closest analog, dsh-memento, gates writes behind human approval — a different and complementary mechanism. |
| Path safety on the write path (root-relative denylist, Unicode bidi/control stripping, NTFS alternate-data-stream truncation, containment) | None. Schemes that store in a database avoid it; every markdown-based option leaves it open. |
This matters more every month. OWASP ASI06 — Memory & Context Poisoning joined the Agentic Top 10 for 2026, and the published numbers are not close:
- 98% injection success for a memory-poisoning payload (GhostWriter), ~60% activation even with polite phrasing, and 0% detection by existing one-turn injection filters.
- 95%+ (MINJA), 80%+ at under 0.1% poison rate (AgentPoison).
Anthropic's own memory-tool documentation says restricting operations to the memory directory "is not optional for any agent with write access to persistent storage", and advises scoping write permission to the sessions that actually add memories.
What makes the problem unavoidable is this: legitimate memory writing and malicious memory injection are the same operation. Same file, same write call — only intent differs, and intent is not observable.
So dsh-zcode-scribe does not try to detect intent. It removes capability, and constrains what
remains:
the writer → cannot see: shell · run_code · every MCP tool · network fetch/search
subagents · present · upload/attachment tools
→ can do: Read/Grep/Glob · Write/Edit only inside the memory room
rm only for a contained, absolute, non-glob, non-recursive .md
Two enforcement layers, because they fail differently:
| Layer | Seam | Effect |
|---|---|---|
| Remove | ctx.tools.restrict({ deny }) on the writer's agent.ctx |
the tool is absent from the writer's tool list — it cannot be talked into reaching for it |
| Constrain | ctx.tools.guard(exec => reason | undefined) on the writer's agent.ctx |
argument-level policy for the tools that must remain, e.g. "read a file, but write only *.md under the memory root" |
Both require a scoped context and both throw rather than silently degrade to global — which is what makes them usable as a security boundary instead of a convention.
What is borrowed
Almost everything. This project's contribution is the combination, not the parts:
- Claude Code — memory is an index, not storage;
MEMORY.mdcapped at the first 200 lines or 25 KB; topic files loaded on demand, never at session start; an over-cap write succeeds and returns an error telling the model to rewrite the index rather than truncating silently; subagent memory in a separate directory. - Anthropic memory tool — client-side storage ownership,
/memoriesas a mapped prefix, mandatory path-traversal rejection. - Anthropic managed memory stores — immutable version per change (audit + rollback), a hard capacity cap where writes fail loudly, and scoping write access.
- Memory-poisoning research (AM-Sentry, memory-risk scoring) — an admission policy before storage, trust tiers per entry, and holding a contradicting memory for a human decision instead of overwriting.
- The DSH ecosystem —
engramoryfor thectx.tools.guard()primitive,dsh-mementofor loud-not-truncating budgets and session-frozen snapshots,dsh-memoirfor prefix-cache-aware injection.
Full tables, sources and line-referenced seam evidence: docs/ARCHITECTURE.md.
Design in one picture
user turn ──▶ agent/post-step
│ skip if the main agent already wrote memory this turn
│ skip if the user turn carried no substantial prose
│ skip if the cursor did not advance
▼ (coalescing: only the newest snapshot survives)
mint the writer ──▶ restrict({deny}) + guard(...) ← the whole point
▼
writer reads the manifest, writes candidates inside the room
▼
admission: path safety · cap (loud) · conflict hold · secret screen
▼
accept → versioned write → index rebuild → audit row
hold → needs a human decision
The main agent sees the index and a manifest of filenames plus descriptions. Topic bodies are never injected automatically — the model reads them on demand.
Install (when it is ready)
dsh plugin --profile web add dsh-zcode-scribe
dsh --profile web --dump-config | grep -A3 'id: scribe' # rows collide ⇒ hard boot failure
Develop
node test/run.mjs # all suites
Requires Node >= 20. No runtime dependencies — the plugin imports node: builtins and the
host's peer packages only.
License
MIT.
Links
More in this category
volcengine/OpenViking#examples/dsh-memory-plugin★ 38348
OpenViking memory and context bundle for DeepSeek Harness: pre-step auto-recall and profile injection, session capture, `viking://` URI guarding, and recall/write memory tools backed by an OpenViking server.
vectorize-io/hindsight#coding-agents★ 24711
Hindsight, agent memory that learns: long-term project memory with auto recall and retain, knowledge pages, deep reflection, and per-repo memory banks.
agentscope-ai/ReMe#dsh★ 3498
Connects DeepSeek Harness to ReMe's local-first, self-evolving personal knowledge base: automatically captures completed main-agent conversations as user-owned Markdown memory, searches conversations and source material through reme_search with BM25, optional embeddings, and wikilink expansion, and schedules daily memory consolidation.
zilliztech/memsearch#MemSearch★ 2630
Shared Markdown memory for DSH and other coding agents, with automatic capture, pre-step context injection, searchable recall, and memory-to-skill self-evolution through a review panel.
vshulcz/deja-vu#extensions/dsh★ 918
Reads the session files twenty-two other coding agents on this machine already wrote — Claude Code, Codex, Cursor, VS Code Copilot Chat, opencode, OpenClaw, Hermes, Kimi, Cline, Zed and more — including sessions from before it was installed: six tools (deja_recall, deja_session, deja_blame, deja_fix, deja_how, deja_remember), a /deja command, and optional automatic recall added to the runtime context. Local BM25 index, no LLM, no embeddings, no network (dsh plugin --profile web add dsh-deja).
adoresever/graph-memory★ 627
Traceable, searchable cross-session memory for DeepSeek Harness — conversation knowledge as typed graph nodes (TASK/SKILL/EVENT) and typed edges.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.