A /remember command that writes facts into the AGENTS.md instruction hierarchy dsh already loads, plus a Memory tab showing which instructions the loader kept within its byte budget.
Install
# from npm (prebuilt)
dsh plugin --profile web add @dennisrongo/dsh-memory
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:dennisrongo/dsh-plugins#path:/plugins/dsh-memory
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
A /remember command that writes a fact into the instruction hierarchy dsh already reads, and a Memory tab that shows which of those files the loader actually kept.
Why this is small
dsh already has the read half of a memory system, and it is more capable than it looks. @deepseek-ai/dsh-agent-instructions — its own manifest calls it a "Workspace context loader for AGENTS.md/CLAUDE.md instruction files" — loads the user-global $DSH_HOME/AGENTS.md, then every AGENTS.md and CLAUDE.md from the project root down to the session's directory, plus AGENTS.local.md / CLAUDE.local.md overlays, deduplicated per directory, budgeted by bytes, and it pulls in nested files as the agent touches them. Sessions are already bound to workspaces by canonical path through workspaceRegistry.
Two things were missing:
Nothing writes. There is no #-style capture and no /remember, so a fact learned mid-session is a fact you retype into a file by hand, later, if you remember to.
Nothing shows what loaded. The byte budget silently omits files. A file that exists, is discovered, and is dropped for budget looks exactly like a file the agent is ignoring for no reason — and the shipped code preset's budget is 64 KiB, which a real monorepo reaches.
So this plugin is those two things and deliberately nothing else. There is no parallel fact database: a second store beside the instruction files would mean two things to keep in sync, two precedence orders, and a place for facts to hide from a loader that already works.
Capture
/remember the build needs pnpm 11 — package.json pnpm blocks are ignored
/remember --local the staging token lives in ~/.config/acme
/remember --user I prefer conventional commits with no Claude co-author trailer
| Flag | File | Reach |
|---|---|---|
(default) --project |
<projectRoot>/AGENTS.md |
travels with the repository |
--local |
<projectRoot>/AGENTS.local.md |
this checkout only, usually gitignored |
--user |
$DSH_HOME/AGENTS.md |
every project on this machine |
The reply always names the exact path it wrote. "Saved" would leave you guessing which of four candidate files in the hierarchy it landed in.
Facts are filed under a ## Memories heading rather than appended to the end of the file, and a second fact joins the existing list instead of starting a new one. Nothing a human wrote is ever moved: a file with no memories section gets one appended (with the blank line guarded, so the heading cannot end up glued to the last line of prose), and a file with one gets the new item at the end of that section, not after whatever heading happens to be last.
The Memory tab has the same capture box, with a scope chooser; Enter saves, Shift+Enter is a newline.
Inspection
The tab lists every instruction file discovered for the workspace, in model precedence order, with its size and whether the budget kept it:
AGENTS.md 5.1 KB not loaded
packages/app/AGENTS.md cut to 96 B 5.1 KB
Click a row to read the file. not loaded and cut to … are the two facts you cannot get anywhere else, and they are the reason the tab exists.
Both come from the loader's own exports — discoverBaselineInstructionFiles for the candidate list and loadBaselineInstructions for the omitted / truncated accounting. Nothing here reimplements the walk. An inspector that reimplemented it would eventually disagree with the loader, and an inspector you cannot trust when it disagrees is worse than none: the entire point is to answer "is the agent reading this file?" authoritatively.
read serves a path only when the loader discovered it for that workspace. Without that check the endpoint reads any file on the host.
Configuration
- id: dsh-memory
config:
maxBytes: 65536
maxBytes must match the agent-instructions row's own maxBytes, or the inspector reports omissions against the wrong budget. The shipped code preset uses 65536, which is this plugin's default; a plugin cannot read another plugin's entry config, so if you change one, change both.
Endpoints
| Method | Takes | Returns |
|---|---|---|
dshMemory/inspect |
{ workspaceId } |
{ report } — every discovered file, sized, with included / truncatedTo |
dshMemory/remember |
{ workspaceId, fact, scope } |
{ ok, path, line } or { ok: false, reason } |
dshMemory/read |
{ workspaceId, absolutePath } |
{ text? } — discovered files only |
All take a single parameter named request.
Install
dsh plugin add @dennisrongo/dsh-memory
Restart the profile afterwards — the Typert loader caches its per-package verdict for the process lifetime, so a newly added service is not picked up by a browser refresh.
Requires
ctx.workspaceRegistry and @deepseek-ai/dsh-agent-instructions, both composed by the shipped presets. ctx.commands is picked up through a child fiber rather than injected, so a deployment that composes no command registry still gets the tab and the endpoints — it just has no /remember.
About the author
Plugins and walkthroughs on YouTube @codingmenace — I build AI coding tools in public, including DeepSeek Harness itself. More at dennisrongo.com.
Links
More in this category
vectorize-io/hindsight#coding-agents★ 51291
Hindsight, agent memory that learns: long-term project memory with auto recall and retain, knowledge pages, deep reflection, and per-repo memory banks.
volcengine/OpenViking#examples/dsh-memory-plugin★ 40273
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.
agentscope-ai/ReMe#dsh★ 3646
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★ 2759
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★ 1244
Reads the session files thirty-three 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★ 655
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.