On-demand memory for DeepSeek Harness: session logs are distilled into layered markdown (a summary, an index and per-topic files), and a mem_query tool returns only the matched entries rather than the whole index. Nothing is injected per turn, there are no dependencies, and every entry keeps a source pointer back to the conversation it came from.
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:MiHjy12138/dsh-memory-lite
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
This plugin publishes its README in Chinese only.
记忆插件都在比「记得多」,它只比「查得省」。
你的 agent 不是记性差,是记忆太贵:每轮注入记忆,就是每轮重发计费;读一次索引,就是上万字符全程占位。
这个项目只优化一个数——查一次记忆 11,819 → 738 字符(省 92%)。 为此它刻意不做那些要你每轮付钱、或每轮维护的东西:
不自动注入 · 不建向量库 · 不起后台进程 · 不做知识图谱 · 不做侧栏面板 · 零依赖
留下的只有三样:本地 markdown · 一个查询工具 · 一份能人工核对的溯源。
作者的话: DSH本身的架构极其轻便:
一 · 基线上下文:~\.dsh\AGENTS.md,系统提示中出现 Instructions from: ~/.dsh/AGENTS.md
二 · 引用快照:@deepseek-ai/dsh-session-reference,输入框 @ 可选历史会话
三 · 索引查询:session-query-sqlite + dsh-tool-session-query,搜「记忆」跨会话命中
本插件只是在此基础上做了个小扩展。让记忆和索引更加顺畅,全程DSH自己搞的,我只负责提灵感。所以有什么问题即时反馈,会改的(๑˃ᴗ˂)ﻭ
框架核心:三条不变量
整套设计只为守住这三条。功能可以加,这三条破了就不成立。
| # | 不变量 | 具体含义 |
|---|---|---|
| 1 | 零常驻 | 记忆不进系统提示。要查才查,只回命中片段。(插件版唯一的常驻是一个工具 schema,约 50–100 token) |
| 2 | 零依赖 | 只用 Node 内置模块——没有数据库、没有服务端、没有后台进程、没有 npm install |
| 3 | 可溯源 | 每条记忆都指得回「哪次会话的哪句话」,verify 能把原文拉出来。不可核对的经验不是记忆,是猜测 |
于是有了那句推论,也是它便宜的全部原因:读多少,由调用方决定。 记忆库从不主动往上下文里塞东西,只在你问的时候,递回最近的那几条。
一眼看完
| 卖点 | 数字与事实 |
|---|---|
| 查询省 92% | 查一次记忆 11,819 → 738 字符(12 组真实关键词实测) |
| 不注入记忆 | 不往系统提示里塞记忆内容;要查才查 |
| 两种用法 | 装成 DSH 插件(agent 自己会查)/当 CLI 用(不装任何东西) |
| 零依赖 | 只用 Node 内置模块,没有 npm install,没有后台进程 |
| 700 行 | 五个 .mjs/.js,一小时内能读完并改成你要的样子 |
| 条条可溯源 | 每条记忆带 source,verify 能把它拉回原文逐条核对 |
| 30 秒上手 | 用 examples/ 的合成数据就能跑通全流程 |
记忆就是本地 markdown 文件——随时能读、能改、能 diff、能删。
两种用法,挑一个(也可以都用)
| 方式 A:装成 DSH 插件 | 方式 B:当 CLI 用 | |
|---|---|---|
| 适合 | 想让 agent 自己会查记忆 | 想完全手动,或不使用 DSH |
| 装什么 | 一条命令(不发 npm,直装 GitHub) | 什么都不装,下载即用 |
| agent 怎么用 | 直接调用 mem_query 工具 |
自己敲 node src/mem.mjs query "…" |
| 每轮常驻成本 | 工具 schema 约 50–100 token | 0(连 schema 都没有) |
| 记忆库放哪 | 工作区下的 memory/(或设 MEM_HOME) |
任意目录 |
| 采集 | 仍需跑一次 mem.mjs collect(见下) |
同左 |
两条入口共用
src/lib.mjs—— 一份实现,不会各改各的走偏。
方式 A:装成插件
dsh plugin --profile web add github:MiHjy12138/dsh-memory-lite
装完重启一次后端(新增 bundle 不会热加载——这是 DSH 的装配规则)。
之后 agent 的工具表里会多出 mem_query,它的描述里写着「优先用它,别整份读记忆文件」。于是你不需要在 AGENTS.md 里写任何提示——工具自己会说话。
记忆库放在当前工作区的 memory/ 下即可;也可以设 MEM_HOME 指向别处。
方式 B:当 CLI 用
git clone https://github.com/MiHjy12138/dsh-memory-lite
cd dsh-memory-lite
node src/mem.mjs query "powershell bom" --n 5 # 查
node src/mem.mjs collect # 采集
node src/build.mjs # 汇总
CLI 版跨平台(Windows / macOS / Linux),不依赖 DSH 的任何东西——采集器才需要读 DSH 的会话日志,其余环节与平台无关。
它凭什么便宜
| 常见做法 | 隐含代价 |
|---|---|
| 每轮自动注入记忆 | 注入一次,之后 每轮随上下文重发、每轮计费 |
| 每次全量读记忆文件 | 一份索引动辄上万字符,读一次就永久占位 |
| 上向量库 / 记忆服务 | 引入依赖与运维,而且检索结果难以人工核对 |
第四条路:分层 markdown + 关键词检索——上面三种代价,它一样都不付。
省下的其实不是「存储」(记忆本来也没多大),而是每一轮都要重发的那堆中间量: 索引、总览、你只是为了找一条而读进来的整份文件。查询只在被问到时发生一次, 返回的也只有一小段命中片段。
和市面上的记忆插件比
DSH 插件市场里的记忆类插件,绝大多数属于「自动注入派」:auto-recall、pre-step injection、injected every turn。功能确实全,代价是每一轮都在为它付钱。
| 常见记忆插件 | dsh-memory-lite | |
|---|---|---|
| 每轮注入 | 有(有人实测过约 2.7 KB/轮) | 0 字符(不注入记忆内容) |
| 形态 | 插件进程 + npm 依赖 | 四个 .mjs + 一个 72 行的插件入口(共 700 行) |
| 存储 | SQLite / 服务端 / 自有格式 | markdown + 一个 index.json |
| 查询 | 自动召回(你事先不知道召回了什么) | 显式 mem_query,回了什么一眼看得见 |
| 核对 | 多为「自动捕获后直接入库」 | verify 把每条拉回素材原文 |
| 卸载 | 改多处配置 + 卸依赖 | 删目录 |
所以,什么时候该选别人? 当你需要语义召回(搜「硬盘不认」也得命中「掉盘」)、 跨机器同步、知识图谱、或者一个可视化面板时——这些项目里都有现成的,本项目不做,也不打算做。
它只解决一个很具体的问题:你已经知道自己要查什么,只是不想为了查它而读进一万个字符。
特点
- 零依赖:只用 Node 内置模块(
fs/zlib/path),插件版也只用到宿主自带的dsh-tools - 摘要税只有 0.9%:常驻的只有「一句话摘要」,正文按需加载(实测样本:全文 271,295 字符,摘要合计 2,461 字符)
- 查询省 91–94%:只回命中的 3–5 条(实测 12 组,平均 738 字符/次)
- 每条可溯源:记忆条目带
source标记,verify.mjs能把它拉回素材原文逐条核对 - 分层不膨胀:SUMMARY(提炼句)/ INDEX(条目名)/ topics(正文)三层,每层都有体量上限
- 采集先过滤:按
source.kind只留真人输入与助手回复,实测滤掉约 68% 的注入噪音 - 人工提炼在环:顶层那句话由人或 agent 提炼,不靠自动摘要——质量上限来自这一步,不是来自脚本
- 一份实现两条入口:CLI 与插件共用
src/lib.mjs;插件坏了不影响 CLI,反之亦然
快速开始(CLI 路线)
# 1) 采集:扫会话日志 → 素材文件(.staging/*.md)
node src/mem.mjs collect
# 2) 提炼:读素材,写成 extracts/*.json
# 格式:[{ "kind": "lesson", "topic": "...", "text": "...", "source": "session-xxxxxxxx#123" }]
# 这一步由人或 agent 完成,是整套流程质量的来源
# 3) 汇总:extracts → SUMMARY.md / INDEX.md / topics/*.md / index.json
node src/build.mjs
# 4) 查询:只回命中的那几条
node src/mem.mjs query "powershell bom" --n 5
# 5) 核对:抽出来的条目能否对回原文
node src/verify.mjs examples/extracts-example.json --staging examples/staging
不碰真实日志,先跑一遍 demo
mkdir -p extracts
cp examples/extracts-example.json extracts/00.json
cp examples/memory.config.example.json memory.config.json
node src/build.mjs # 生成 SUMMARY / INDEX / topics / index.json
node src/mem.mjs query "BOM" # 只回命中的那几条
node src/mem.mjs query "单元格" --n 3
node src/verify.mjs examples/extracts-example.json --staging examples/staging
examples/SUMMARY.example.md 就是上面这几步的产物。
架构
会话日志(jsonl + zstd 分帧)
│
│ mem.mjs collect ← 只留真人输入 / 助手回复 / 压缩点,滤掉注入
▼
.staging/*.md ← 素材:一条一行,行尾带 `#seq` 便于溯源
│
│ 人 或 agent 提炼 ← 这一步是质量的来源,不自动化
▼
extracts/*.json ← [{kind, topic, text, source}]
│
│ build.mjs ← 分类归并、生成 id、硬卡顶层规模
▼
┌─────────────────────────────────────────────────┐
│ SUMMARY.md 顶层:一句话提炼 │ ← 定方向用
│ INDEX.md 索引:全库条目名,按主题分家 │ ← 找条目用
│ topics/*.md 明细:按主题分家,文件头写「何时翻它」 │ ← 取正文用
│ index.json 机读索引 │
└─────────────────────────────────────────────────┘
│
├── mem_query 工具(插件入口 index.js) ← agent 自己查
└── mem.mjs query "关键词"(CLI 入口) ← 人手动查
│
▼
约 700 字符命中片段(而不是上万字符)
↑ 两条入口共用 src/lib.mjs
三层记忆模型
| 层 | 文件 | 什么时候读 | 体量约束 |
|---|---|---|---|
| 顶层 | SUMMARY.md |
会话开始定方向、或查询没命中时 | 只有提炼句,条数固定 |
| 索引 | INDEX.md |
找具体条目(推荐用 mem_query 代替) |
一行一条,全库 |
| 明细 | topics/*.md |
只读命中的那一个主题文件 | 按主题分家,各自独立 |
设计意图:越往上越贵,所以越往上越短。顶层是唯一「可能每会话都读」的东西,因此它只装一句话;正文全部下沉到按需层。
命令参考
| 命令 | 作用 | 常用参数 |
|---|---|---|
dsh plugin --profile web add github:MiHjy12138/dsh-memory-lite |
装成插件,得到 mem_query 工具 |
— |
node src/mem.mjs collect |
扫会话日志产出素材 | --all 扫全部工作区|--force 忽略增量判重 |
node src/mem.mjs list |
列出待处理素材 | — |
node src/mem.mjs mark <id> |
把素材标为已处理 | — |
node src/mem.mjs query "词 [词2]" |
按关键词检索,只回命中片段 | --n 8 调整条数(默认 5) |
node src/build.mjs |
extracts → 分层记忆库 | — |
node src/verify.mjs <extract.json> |
条目溯源核对 | --staging <素材目录> |
匹配规则(坦白说明能力边界):
- 子串匹配,不分词、无同义词——搜不到就换词
- 词长加权:
词长 × (1 + log2(命中次数)),多词累加 - 单字词被忽略(噪音太大)
- 多词之间是「或」:谁中算谁,靠得分排序
- 只在
SUMMARY.md与topics/*.md里找,不碰INDEX.md(避免索引与正文重复计分)
Token 账(实测,不是估算)
| 量 | 实测值 |
|---|---|
| 常驻摘要(技能/索引一句话) | 2,461 字符,占全文 0.91% |
| 一次「读索引 + 读主题正文」 | 约 11,819 字符 |
| 一次查询输出 | 约 738 字符(省 92%) |
| 插件版新增常驻 | 工具 schema 约 50–100 token/轮 |
关键在复利:读进上下文的内容会留驻,之后每轮请求都随上下文重发。所以一次查询省下的 11,081 字符,要按「剩余轮数」放大:
| 会话场景 | 旧做法(读索引+正文) | 本方案(查询) |
|---|---|---|
| 30 轮会话,第 5 轮查 1 次 | 307,294 字符累计输入 | 21,798 字符累计输入 |
接入 agent
插件版:不用写任何提示。mem_query 的工具描述里已经写明「优先用它,别整份读记忆文件」,agent 看得到工具表。
CLI 版:在 AGENTS.md(或 CLAUDE.md / 系统提示)里加一行:
- 记忆:有 `memory/` 时**先跑** `node memory/src/mem.mjs query "关键词 [关键词2]"`,
只回命中片段;命中不够再按主题翻 `topics/<主题>.md`。
**SUMMARY.md / INDEX.md 整份不读**。
为什么是「先跑查询」而不是「先读 SUMMARY」:读 SUMMARY 是「先花 2,864 字符买一个方向」,而查询是「直接拿命中结果」。命中就赚,不命中再退回去读导航——只有落空时才付那笔钱。
目录结构
dsh-memory-lite/
├── README.md
├── LICENSE
├── CHANGELOG.md
├── package.json # 同时声明 CLI(bin)与插件(main + dsh.bundle.patch)
├── index.js # 插件入口:注册 mem_query(72 行)
├── cordis.patch.yml # 插件装配 patch(4 行)
├── marketplace-entry.json # 提交到插件市场的条目
├── .gitignore # 默认忽略你本地的记忆数据
├── .gitattributes # 统一换行符(LF)
├── docs/
│ ├── ARCHITECTURE.md # 数据流、文件格式、设计取舍
│ ├── TOKEN-ECONOMY.md # 上下文成本的实测方法与账
│ └── GITHUB-SETUP.md # 仓库描述 / topics / 发布步骤
├── src/
│ ├── lib.mjs # 共享核心:解析 + 打分(CLI 与插件共用)
│ ├── mem.mjs # CLI:采集 + 查询
│ ├── build.mjs # 提炼汇总(分类可配置)
│ └── verify.mjs # 溯源核对
└── examples/
├── staging/
│ └── session-1a2b3c4d.md # 素材长什么样(合成)
├── extracts-example.json # 提炼输入长什么样
├── SUMMARY.example.md # 输出长什么样
├── memory.config.example.json # 分类与顶层场景的配置示例
└── plugin-smoke-test.mjs # 插件冒烟测试:不装进 DSH 也能验 mem_query
设计取舍
为什么要两个入口?
因为「谁来查记忆」有两种真实场景:agent 自己查(插件),和人手动查/脚本里用(CLI)。两者共享同一份核心逻辑,代价是多了一层 lib.mjs——换来的是不必维护两份会走偏的实现。
为什么不用向量库 / embedding? 记忆条目通常是「结论型」的短句,条数在几百量级,关键词检索已经够用;而且检索结果必须能被人一眼核对——向量相似度做不到这一点。当记忆上万条、或必须做语义召回时,这个项目就不合适了。
为什么顶层要人工提炼? 自动摘要会把「能救命的那个细节」压成「一般的经验」。顶层只有二十几条,值得人写——这是整套流程里唯一无法自动化的部分,也是它有价值的部分。
为什么用文件而不是数据库? 可 diff、可读、可直接编辑、坏不了、删得掉。代价是没有事务与并发——对「单人 + 单 agent」的记忆场景不是问题。
为什么采集时要按 source.kind 过滤?
因为日志里大部分是注入内容(系统提示、插件消息、子 agent 回执)。在真实样本里,真人输入只占 32%——不滤掉,素材会被噪音淹掉。
适用边界
- 插件版面向 DSH,安装后需要重启一次后端
- CLI 版跨平台;其中
collect面向 DSH 会话日志(zstd 分帧的 jsonl),换平台需替换lib.mjs里的decodeFrames/filterEvents,其余环节无关平台 - Windows 上写 PowerShell 脚本时注意编码:
.ps1必须带 UTF-8 BOM,否则 PowerShell 5.1 按 GBK 解码会崩(本项目脚本不受影响,但用的人会遇到) - 记忆是本地文件,没有云端同步、没有加密——敏感内容请自行决定是否入库
License
MIT © dsh-memory-lite contributors
Links
More in this category
vectorize-io/hindsight#coding-agents★ 57722
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★ 41317
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.
MemTensor/MemOS#memos-local-plugin★ 12224
Local-first memory plugin for DeepSeek Harness: layered L1/L2/L3 memory with automatic capture, manual memos_* retrieval tools, and a built-in memory viewer.
agentscope-ai/ReMe#dsh★ 3735
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★ 2815
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★ 1352
Reads the session files forty-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).
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.