dsh-markdown-memory
symlp/dsh-markdown-memory
Markdown folder long-term memory for DeepSeek Harness: one file per fact, an index line per memory, mounted into every request as a system prompt section
インストール
dsh plugin --profile web add github:symlp/dsh-markdown-memoryREADME
dsh-markdown-memory
Your memory is a folder. Every agent already knows how to read a folder.
Markdown folder long-term memory for DeepSeek Harness.
A memory directory holds one markdown file per durable fact, each with YAML frontmatter (name, description, optional metadata) followed by the fact body. An index file (default MEMORY.md) carries one line per memory. This plugin mounts the index and a file listing into every request as a system prompt section; the model reads individual memory files on demand with its file tools.
Why this one
- Zero infrastructure — no daemon, no database, no account, no embedding pipeline. Point at a folder.
- Agent-agnostic by format, not by bridge — the same folder a Claude Code auto-memory already writes, the same vault Obsidian already manages. dsh joins your memory; nothing migrates, nothing syncs, because there is only one copy.
- Human-owned — read it, edit it,
git diffit, delete a line of it. When the agent is gone, your memory is still yours.
The position is deliberate: cross-agent memory does not need a mechanism. It needs a format every agent can already read, and a markdown folder is that format.
Compared to other memory approaches
| Approach | Where memory lives | Cross-agent | You can edit a memory by hand |
|---|---|---|---|
| Graph / vector memory engines | Engine's own store (binary/DB) | Via that engine everywhere | No — through the engine |
| Hosted memory services | Their cloud | Via their connectors | Through their UI/API |
| Session-distillation plugins | Generated files per harness | Usually single-harness | Yes, but the pipeline rewrites |
| dsh-markdown-memory | A folder you already own | Any agent that reads files | Yes — it's just a file |
Each row is a legitimate trade. Pick an engine when you want automatic extraction and semantic search out of the box; pick a service when you want fleet-wide memory without owning storage. Pick this plugin when you want your memory to outlive every agent that reads it.
Install
dsh plugin --profile <name> add dsh-markdown-memory
Then point path at your memory directory in the profile's cordis.patch.yml:
- id: markdown-memory
name: dsh-markdown-memory
config:
path: /absolute/path/to/your/memory
# indexFile: MEMORY.md
# maxBytes: 32768
# sectionOrder: 120
Configuration
| Field | Default | Meaning |
|---|---|---|
path | (required) | Absolute path of the memory directory. Load fails when it is missing or not a directory. |
indexFile | MEMORY.md | Index file name inside the directory. Injected in full. |
maxBytes | 32768 | Byte bound for the injected section. Longer content is truncated with a notice. |
sectionOrder | 120 | Prompt section order, inside the 100–199 tool-guidance band. |
Misconfiguration fails at load with a message naming the field.
Mount your Obsidian vault
An Obsidian vault is a markdown folder, so it mounts directly:
- id: markdown-memory
name: dsh-markdown-memory
config:
path: /absolute/path/to/YourVault
indexFile: Home.md # or whatever your map-of-content note is
What the model then gets: your map-of-content note verbatim, plus a listing of top-level notes, and it reads any note on demand. [[wikilink]] guidance is already part of the injected section, so vault-style links resolve naturally when the model follows them.
Current constraints for vaults (honest ones): only top-level .md files are listed — notes inside subfolders are reachable when the model explores with file tools, but they do not appear in the injected listing yet (recursive listing with ignore rules such as .obsidian/ is on the roadmap, see below). Vaults with a very large map-of-content note should set maxBytes accordingly.
Refresh semantics
The directory is read once at plugin load, then re-read at each agent/session-start. Edits made while a session is running become visible at the next session start. A failed refresh keeps serving the last good snapshot and logs a warning.
Model Experience
Memory index section
What the model sees
One system prompt section named markdown-memory:index at order 120:
# Long-term memory
A persistent memory directory is mounted at: /home/user/memory
Each memory is one markdown file with YAML frontmatter (`name`, `description`) followed by the fact.
The index below lists one line per memory. When an index line is relevant to the current task,
read that memory file with your file tools before relying on it. `[[name]]` references link to
the memory file whose frontmatter `name` matches.
## Index (MEMORY.md)
- [Project layout](project-layout.md) — where each subsystem lives
- [Deploy ritual](deploy-ritual.md) — the release steps that must not be reordered
## Memory files (2)
project-layout.md, deploy-ritual.md
Token effect
The section costs the index file size plus a fixed header and the file listing, on every request, bounded by maxBytes (default 32 KiB ≈ 8k tokens; a typical index is far smaller). Memory file bodies cost nothing until the model chooses to read one.
KV Cache effect
The section lives in the system prompt and its text is stable across requests within a session, so it extends the reusable request prefix rather than breaking it. When a session-start refresh picks up changed content, the prefix diverges once at the next request and is stable again afterwards.
Known Limitations and Deferred Work
- Top-level files only — the injected listing covers
.mdfiles directly inside the memory directory; subfolder notes are not listed (the model can still reach them with file tools). Recursive listing with ignore rules (.obsidian/,.git/,.trash/) is planned. - Host filesystem only — reads use
node:fsdirectly, not thectx.fsprovider seam; remote or sandboxed filesystem products are not covered. - No live watching — changes are picked up at session start, not mid-session; there is no
fs.watchintegration. - No selective recall — the whole index enters every request; intent- and path-scoped recall of individual memories is the next milestone.
- No write path — the model cannot create or update memories yet; a guarded write tool is planned after recall.
- No Loader smoke test yet — coverage is unit-level against real
Context+SystemPromptcomposition; a full Loader boot test is planned.
License
MIT