跳到正文

Memmy

一个本地记忆中枢:机器上的一个服务保存着轨迹、策略、场域认知与技能,Claude Code、Codex、Cursor、DeepSeek Harness、OpenClaw、Hermes 与 OpenCode 都在读写它,于是上下文能在工具之间跟着人走,而不是留在当时打开的那一个里面。

Screenshot of Memmy
编辑截图, 1 Oct 2026Memmy ↗

这是什么

一个本地记忆中枢,若干个编码 agent 都在读写它。机器上的一个服务——http://127.0.0.1:18960,数据放在 ~/.memmy/memory-service/memory.sqlite——持有记忆,Hook、插件、memmy-memory CLI 与桌面端都走它,于是 Claude Code、Codex、Cursor、DeepSeek Harness、OpenClaw、Hermes、OpenCode、WorkBuddy 与 Pi 可以共用同一份存储。每个宿主靠三条路之一接进来:写进它自己目录的钩子与工作区桥接文件、按它自己格式写的插件,或者一个只读的适配器,去扫这个宿主本来就留在磁盘上的会话文件。记忆是分层的——L1 轨迹、L2 策略、L3 场域认知与技能——层与层之间按测得的收益晋升,奖励在 30 秒反馈窗口之后沿 episode 反向传播。MemTensor 组织用 76 天做出来:1,279 次提交、20 个 release、2,439 个文件、2,000 个星。

谁做的这是一个组织账号而不是个人账号:MemTensor 把 Memmy 当产品在做,提交里有 memtensor.cn 与 memtensor.com 的公司邮箱,项目有 memmy.bot 官网、Discord 服务器与 X 账号。1,279 次提交来自 25 位贡献者,贡献者账号里有一个叫 Memtensor-AI。单人提交最多的是 Wang-Daoji,223 次;其后是 hijzy 的 163 次、syzsunshine219 的 130 次与 ZongYue99 的 118 次。1,279 次提交里有 921 次关联了账号,375 次没有。组织并不是主要的写作者:153 次提交带共同作者尾注,其中 54 条只写 Cursor,64 条写的是某个 Claude 模型,另有 35 条署的是账号名,其中几个也出现在贡献者列表里。

它是怎么搭起来的

组成 · 6

一个本地优先的记忆服务,外面套一层按宿主接入的适配层,再上面是桌面应用。中心是环回地址上的一个 HTTP 服务——Memory/src/server/index.ts,默认端口 18960,存储与向量都用 SQLite 加 sqlite-vec——它拥有四层记忆模型和在各层之间做晋升的后台任务,于是召回不依赖站在它前面的是哪个 agent。服务周围有三类适配器:把钩子与工作区桥接文件写进宿主自己目录的安装目标、按宿主原生格式写的插件,以及只读、用来导入宿主已经写在磁盘上的历史的扫描器。桌面端是 Electron 外壳加 React 前端,本地后端用 Fastify 并把应用状态放在 SQLite 里;agent 运行时是另一个工作区,有自己的模型 provider、CLI 与 TUI。把服务放在中间的后果是:难题都落在适配层而不是记忆本身——每个宿主给文件起名、组织会话、把关钩子的方式都不同,这正是那一个目录里要放十个目标、每个宿主的文件都不小的原因,也是桌面后端与记忆服务共用的读取代码必须自成一个工作区、而不是两边各抄一份的原因。

Memory/
记忆服务本体:228 个源文件、3037 KB,旁边是 122 个测试文件、1765 KB。src/service/ 里最大的几个文件是 151 KB 的 session-turn-service.ts、116 KB 的 feedback-experience.ts、115 KB 的 memory-service.ts、103 KB 的 retrieval-service.ts、68 KB 的 skill-pipeline.ts 与 64 KB 的 span-pipeline.ts。仓库里最大的单个文件也在这棵树里:263 KB 的 src/algorithm/plugin-algorithms.ts,旁边是 58 KB 的 agent-source 运行时。它旁边还有 Memory/adapters/(给 DeepSeek Harness 的 Cordis patch、OpenClaw 插件清单、给 Hermes 的 Python provider)、Memory/agent-contract/(一个 26 KB 的 DTO 模块加事件与 episode 状态类型)、shell 与 PowerShell 两份安装脚本,以及一个有 71 个文件的查看器。
App/
四个工作区、共 1,695 个文件。frontend 是 Electron 界面,480 个文件、15.7 MB,仅中英文文案表就有 217 KB,agent 的 API 客户端有 105 KB;memmy-agent 是运行时、CLI 与 TUI,733 个文件、8.2 MB,含各家模型 provider、一个 OpenAI 兼容服务与终端界面;shell 是桌面主进程,97 个文件、5.8 MB,其中 main.ts 204 KB、runtime-services.ts 93 KB,还有一个 127 KB 的打包运行时边界测试;backend 是本地 API,385 个文件、2.8 MB,装的是 Fastify 路由、SQLite 应用状态、来源扫描与 Skill 写入。
AgentSourceCore/
20 个源文件,由桌面后端与记忆服务共用而不是各写一份:每个 agent 一个 <host>-source-turn.ts,覆盖 Claude Code、Codex、Cursor、DeepSeek、Hermes、OpenClaw 与 OpenCode,另有 JSONL 切行、密钥脱敏与记忆 token 预算。它的测试里有一个 22 KB 的 source-turn 契约审查测试,七种会话格式就是靠它被约束成同一个形状的。
docs/
文档,两棵树平行:39 个中文页 117 KB 与 38 个英文页 76 KB,12 个架构文档,以及 38 个资源文件共 60.6 MB——按体积算是仓库里最大的目录。记忆总览英文 17,032 字符、中文 15,391 字符,讲记忆来源的那一页英文到 20,262 字符。
Knowledge/、Migrations/ 与 scripts/
三个辅助工作区:一个知识库,它唯一的界面页就有 112 KB;18 个迁移源文件与旁边 14 个测试文件,分别 152 KB 与 136 KB;13 个顶层脚本,加上 scripts/internal 下的 31 个,管着开发启动、打包与发版管道。
.github/
六个工作流加一个 CODEOWNERS:50.5 KB 的 draft release 工作流、Linux CLI 安装器、Windows 记忆校验、记忆发布任务,以及云效到 GitHub 的同步;旁边是 17 个 release note 文件,从 455 字节到 4.7 KB。

取舍,以及它替代了什么

  • 用本地的一个服务当记忆存储 替代 每个 agent 各存一份记忆

    文档明说 Hook、插件、memmy-memory CLI 与桌面端读写的都是 127.0.0.1:18960 这同一个服务,而这正是不同 agent 能共享一份记忆的原因。它同时也让服务能从所有接入里拆出来:install --service-only 只注册服务并校验它的健康,不往任何 agent 里装 Skill 或适配器。

  • 装记忆服务时不去配置它发现的那些 agent 替代 在安装阶段就把检测到的 agent 全部接上

    README 写明安装器初始化记忆时不会改动 Codex、Claude Code、Cursor 或其他 agent,装 Skill 与对应钩子/插件是一个单独的显式命令,要么对所有检测到的 agent、要么对指定的一个。于是记忆核心可以独立使用,侵入性的那一半是自愿开启的。

  • 按测得的收益晋升的分层记忆,连归档阈值都是负数 替代 一份不分层的过往回合堆栈

    L1 轨迹要在收益过 0.02 之后才成为 L2 策略,低于 -0.05 就被归档;L2 聚成 L3 场域认知后,置信度到 0.2 才允许被召回;技能在 eta 到 0.1 时从策略里结晶。晋升是阈值而不是编辑动作,降级也有数字,这才是四层不会被塞满的原因。

  • 召回结果被渲染成历史上下文,当前请求始终优先 替代 把召回文本当作指令的一部分

    命中的条目按固定顺序渲染,文档说当前用户请求始终优先,注入的 Markdown 自己也会写明这些只是历史记忆,需要与当前请求和当前仓库状态核对。同一种直觉还把当前会话自己的 L1 排除在召回之外,于是刚发生的回合不会从长期记忆那条路回声式地回来。

  • 机械排序之后的模型过滤,带一个确定性的兜底 替代 让过滤模型单独决定

    最终的语义过滤默认开启,也允许它丢掉全部候选;但输出无效或调用失败时会保留机械排序的前六条,而诊断信息会说明过滤是跑了、跳过了还是回退了。过滤能改善结果,却不至于成为召回的单点故障。

依据docs/en/memory/overview.mdx(17,032 字符)与 docs/en/concepts/architecture.mdx,以及同样两页的中文副本、README.md(9,833 字符)、Memory/src/agent-source/integration/ 与 Memory/adapters/ 两棵树、Memory/readme.md,还有完整的 2,439 个文件清单及其体积与两级目录汇总。

制作过程

6 个阶段
  1. 01

    一个本地存储、十个宿主,十一周二十个版本

    仓库建于 2026-07-16,第一次提交在 2026-07-17:memmy-agent: Let every AI remember the same you。同一天就发了 v1.0.1,到 2026-09-30 版本线走到 v1.2.0——十一周二十个版本,最长的一段安静是 2026-08-26 的 v1.1.1 到 2026-09-04 的 v1.1.2 之间那九天。提交曲线是七月剩下的日子里 240 次、八月 450 次、九月 589 次,76 天共 1,279 次。周围是 2,000 个星、194 个 fork、5 个 watcher、37 个未关的 issue 与 25 位贡献者,README 上还挂着一枚 Product Hunt 日榜 top-post 徽章。项目给自己立的主张写在仓库描述里——用它的原话说,是「all AI remember the same you」——而实现方式是一个服务而不是每个工具一份存储:地址是 http://127.0.0.1:18960,数据在 ~/.memmy/memory-service/memory.sqlite,文档明说 Hook、插件、memmy-memory CLI 与桌面端最终都读写这一个服务,这正是不同 Agent 能共享同一套记忆的原因。

  2. 02

    接进一个宿主有三条路,因为两个宿主没有一处是一样的

    记忆中枢只有能进出别的工具才有用,而这个仓库给出了三条彼此不同的路。第一条是按宿主安装的目标:Memory/src/agent-source/integration/ 下每个宿主一个目录——claude-code 13.6 KB、codex 12.4 KB 外加 9.6 KB 的 hook-trust.ts、cursor 9.0 KB、deepseek-harness 7.9 KB、opencode 7.5 KB,而 hermes 到 78.8 KB、openclaw 到 64.3 KB,pi 与 qwenwork 都不到 600 字节——旁边还有负责生成写入内容的模板:43.8 KB 的恢复钩子、39.0 KB 的 OpenCode 插件与 25.2 KB 的 DeepSeek Harness 插件。第二条是宿主自己格式的插件:Memory/adapters/openclaw/openclaw.plugin.json、给 DeepSeek Harness 的 Cordis patch 文件,以及给 Hermes 的 Python memmy_provider 包。第三条只读:每个宿主一个适配器,去扫那个工具本来就留在磁盘上的会话文件。它们之间有多不统一,看那些适配器就知道——Cursor 的工作区状态是一个 SQLite 文件,Codex 留的是 rollout,OpenClaw 与 OpenCode 各有自己的数据库,而 DeepSeek Harness 写的是压缩过的 session.jsonl.zstd。

  3. 03

    「完全可控」与「本地优先」在代码里是什么样

    这个服务可以不碰任何 agent 就装上:memmy-memory install --service-only 会下载钉住版本的运行时、注册一个用户级服务、把它启动起来并检查 /api/v1/health,README 说这一整套都不往任何 agent 里装 Skill 或适配器。Linux 安装脚本只把记忆初始化好,Codex、Claude Code、Cursor 与其余工具都原样不动,直到用户自己跑 memmy-memory init,或者 memmy-memory init --agent <agent>。两个开关可以分别关掉记忆的读与写——enableMemorySearch 与 enableMemoryAdd——文档还特意说明二者互不强制。配置是一个文件 ~/.memmy/config.yaml,召回、演化与模型参数可以用 memmy-memory reload-config 热加载;改存储则返回 requiresRestart: true,而不是假装已经生效。想查这台机器到底知道什么,入口很小也能看清:memmy-memory search "..." --verbose 会打印各通道汇总出的原始候选、融合与阈值之后剩下的命中、真正渲染进 agent 上下文的那些记忆,以及模型过滤是跑成功了、被跳过还是回退了。

  4. 04

    四个层、六条通道,以及「一段对话」的两小时定义

    记忆是分层的,而每一层之间的晋升都挂着一个数字。turn.complete 写一条原始回合,并给每个被捕获的步骤写一条 L1 轨迹,文本最多留 4,000 字符、每个工具输出最多 2,000;连续的追问合并成同一个 episode,最大间隔两小时;episode 关闭后服务先给反思打分,等一个 30 秒的反馈窗口,算出任务奖励,再以 0.9 的 gamma 与 30 天的衰减半衰期把它反向传播回这个 episode 的轨迹。价值高于 0.005、相似度到 0.65 的 L1 在收益过 0.02 时成为 L2 策略,低于 -0.05 则被归档;相似度 0.3 的 L2 聚成 L3 场域认知,要被召回还得达到 0.2 的置信度;技能在 eta 到 0.1 时从策略里结晶。召回有四类通道——向量、SQLite FTS5、专为中文二字片段与短 ASCII 词做的短模式通道、以及匹配错误签名与路径的结构化片段——分三档、规模是 3、5、2,这也正是默认十条结果的由来;之后是 0.7 相关度对 0.3 冗余度的 MMR,再是可选的模型过滤,最多留八条,失败时回退到六条。向量检索只在最近 2,000 行里建窗口,文档明说这个数字是固定常量,不是配置项。

  5. 05

    把边界写进 pull request 的发版流程

    对一个这么年轻的项目来说,发版流程写得异常明确。活儿先进版本分支,而切版本的 pull request 会写明它不做什么:九月的一个 v1.1.9 候选里有一节叫「Release boundaries」——只开 draft pull request、不推版本 tag、不发 GitHub Release、不上传安装包。有两个候选在一天之内就被作废并取代,其中一个的原因是它指向版本分支而不是 main。v1.2.0 的合并 pull request 上挂着三条评审交接标记,每条都是带哈希与时间戳的 HTML 注释,并注明只有严格在该时间戳之后提交的评审才算数。任务系统不是 GitHub:需求以 MEMMY-491、MEMMY-487、MEMMY-607、MEMMY-623 这样的编号到达,pull request 里把它们写成云效上的任务,再由一条以云效命名的工作流同步到 GitHub,于是需求记在一处、代码落在另一处。Release notes 就放在仓库里,而且随着节奏加快越来越短——九月初 v1.1.2 有 4,731 字符,到 v1.1.8 只剩 455、v1.2.0 是 695——其中一个候选 PR 顺手修了两条过期的回归断言:根版本已经到 1.1.8,后端测试却还钉着 1.1.7。

  6. 06

    一份编号的 bug 清单、合成样例,以及这些修复的代价

    多数贡献者来自组织之外,他们照着一份编号的已知问题清单干活;这些 pull request 会引用其中的第 2 条、第 5 条、第 39 条与第 60 条,而这些修复大多还开着、没合入。埋点曾经把查询词、记忆正文与记忆 ID 当作「action」发到云端统计接口,而这个项目装进 agent 的 Skill 教的正是这几种命令写法,修完只上报已知的子命令,否则什么也不报。关闭会话时,只有当返回结果里恰好带着一个被关掉的 episode,后台 worker 才会被唤醒,于是刚冻结的 L3 任务一直躺着——那条 pull request 把这个等待量了出来:2 分 41 秒——修法换成一行无条件的调用。read_file 把末尾换行当成多出来的一行,apply_patch 却不这么算,于是一个模型去改只有一行的文件时写出了打不上的补丁。回合捕获原本排除所有被关系模型判为「结束话题」的回合,只要用户把反馈和告别放在同一句里,反馈就一起被丢掉;现在只排除纯粹一句结束口令。这些 pull request 里的样例都是合成的,作者自己会写明;测到哪儿停下也照说——那个把订阅套餐加进 provider 的改动,还没用真实套餐 key 调过一次。还有一份把托管命名空间放到本地中枢背后的提议,以第 547 号 issue 提交,至今没有回复。

相关档案

全部档案 →