Memmy:在 VPS 上为 AI 智能体搭建本地共享记忆中心
Memmy 是一个基于 SQLite 的本地记忆中心,支持 Claude Code、Cursor 和 Codex 等工具共享上下文。通过在 VPS 部署并监听 18960 端口,您可以将碎片化的智能体记忆统一管理,减少重复指令消耗并避免因信息孤岛导致的错误决策。
Memmy 的作用及其存储内容
Memmy 是一个运行在您自己的 VPS(虚拟专用服务器)上的 AI 代理本地记忆中心。它使用一个 SQLite 数据库存储代理学习到的内容,同一台服务器上的所有代理都读写这个共享存储。该项目由 MemTensor memmy-agent,采用 MIT 许可证;截至 2026 年 11 月 1 日,版本为 1.2.401。Memory 独立使用 2.1.7 版本。
在服务器上,只有其中一部分组件 relevant。Memmy 提供一个监听 http://127.0.0.1:18960 的记忆服务、一个与该服务通信的 memmy-memory 命令行界面(CLI),以及一个桌面工作台。工作台仅提供 macOS 和 Windows 安装包,因此在 Linux VPS 上运行服务和 CLI 即可。这样,Claude Code、Codex 和 Cursor 就能共享同一套记忆。
Memmy 将存储内容分为四层。Capture 首先单独存储一个 Raw Turn,然后为每个捕获步骤写入一个 L1 Trace 条目,其中包括请求、响应、工具调用和结果。L2 Policy 是从已证明有用的 trace 中归纳出的过程。L3 World Model 是关于项目或环境的稳定知识。Skill 是从 policy 中固化而成的可调用过程。Capture 创建 L1 trace,后台任务逐步完善更高层,显式写入则可以指定层级。如果这些区别比较抽象,可以将 memory 看作学习构建代理的分阶段路径中的后续阶段。等您亲自编写一个简单的代理循环,并观察它在每次运行之间忘记所有内容后,这些层次会更容易理解。
共享记忆中心与各工具独立记忆的区别
如今,每个代理都有自己的记忆机制。Claude Code 将指令文件保存在代码仓库中。Cursor 将规则保存在其工作区数据库中。Codex 将会话日志保存在 ~/.codex 下。每个存储都只属于一个工具,因此,您周一在某个工具中教会它的事实,周二在另一个工具中仍然未知。您会为此付出两次代价:一次是反复解释同一个项目所消耗的令牌,另一次是代理基于您已经在其他地方纠正过的假设执行错误操作。
中心会将存储从工具中移出。Memmy 还会读取现有存储,因此您不必从空数据库开始。其扫描器内置支持 10 个来源:~/.claude/projects/**/*.jsonl 中的 Claude Code、~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl 中的 Codex、~/.local/share/opencode/opencode.db 中的 OpenCode、Cursor 的 state.vscdb 文件、~/.openclaw 下 OpenClaw 的 SQLite 数据库、~/.hermes 下的 Hermes、~/.dsh/sessions 下的 DeepSeek Harness、~/.workbuddy/projects 下的 WorkBuddy、~/.pi/agent/sessions 下的 Pi,以及 ~/.qwenworkcn/projects 下的 QwenWork。桌面工作台可以按名称添加其他代理;只有在无法自行找到该代理时,才会要求您提供其历史记录路径。服务器端扫描器不支持自定义来源,因此在无桌面环境的 VPS 上只能使用内置来源。
导入计数不会完全一致,这是正常现象。扫描器按来源和会话对消息分组,然后为每个完整轮次写入一条 L1 记忆。一个轮次必须同时满足以下条件才算完整:用户内容非空,并且以一条非空的代理消息结束。因此,不完整的轮次不会产生任何内容,直到后续同步完成该轮次。扫描器通过会话检查点和稳定的轮次 ID 去重。同一次运行中,扫描消息数、导入消息数和新增记忆数都会不同。
这一部分与Claude Code 如何在单个会话中管理上下文相互配合。上下文管理决定单个窗口能容纳哪些内容。记忆中心决定窗口关闭后哪些内容仍会保留。
VPS 上的准备条件
- Node.js 22 或更高版本。Memmy 文档要求此版本,而 Ubuntu 24.04 自带 Node 18。
git和构建工具链,因为better-sqlite3是原生模块,安装期间可能需要编译。- 用于安装根工作区及其前端构建链的 RAM。
- 用于
node_modules和数据库的可用磁盘空间。
sudo apt update
sudo apt install -y git build-essential python3 curl ca-certificates sqlite3
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node --version对于文档中的源代码构建,node --version 应输出 v22 或更高版本。此处出现 v18,表示 NodeSource 步骤未生效。npm 的 engine-strict 默认为 false,因此不兼容的引擎声明通常只会产生警告,不会自动导致安装失败。
在 Ubuntu 24.04 上从源代码安装 Memmy
git clone https://github.com/MemTensor/memmy-agent.git
cd memmy-agent
cp .env.example .env
npm install
npm run memory:buildnpm run memory:build 将 @memmy/memory 工作区编译为 Memory/dist。它还会构建 AgentSourceCore、内存查看器,以及该工作区所需的集成资源。确认原生模块已加载:
node -e "const Database = require('better-sqlite3'); const db = new Database(':memory:'); db.close(); console.log('better-sqlite3 loads')"如果该行抛出错误而不是输出结果,请阅读错误信息,确定是模块加载失败还是数据库初始化失败。如果是原生模块不匹配,请运行 npm rebuild better-sqlite3。项目自己的启动脚本在启动任何内容前也会准确执行此命令。
README 将 bash scripts/dev-start.sh 记载为一条命令启动方式。不要在无图形界面的 VPS 上运行它。它会启动 Electron 桌面外壳和 Vite 开发服务器,并在内存服务旁监听 19000 端口。Electron 需要显示环境,因此在没有图形会话的服务器上,该脚本会卡住或退出。
近期版本还提供适用于 Linux x64 和 arm64 的 memmy-agent-linux-cli.tar.gz 及 install.sh。安装程序要求使用 22.x 中的 Node.js 22.23.4+、24.x 中的 24.22.1+,或 26.x 中的 26.12.1+,并要求存在 systemd 用户会话;其他主版本会被拒绝。它会将 memmy 和 memmy-memory 启动器放入 ~/.local/bin,并以用户单元的形式在 127.0.0.1:18960 上启动内存服务。本指南继续采用源代码构建方式,因为这种方式可以在运行前查看每个脚本。
启动 memory 服务并检查其响应
npm run memory:serve:dev这是从源代码运行 memory 服务的文档方式。它监听 127.0.0.1:18960,将数据库保存在 ~/.memmy/memory-service/memory.sqlite,并从 ~/.memmy/config.yaml 读取配置。需要明确指定时,服务器也接受相同的参数作为选项:
npm run memory:serve:dev -- \
--host 127.0.0.1 --port 18960 \
--db ~/.memmy/memory-service/memory.sqlite \
--config ~/.memmy/config.yaml在第二个 shell 中,询问服务是否正在运行:
curl -sS http://127.0.0.1:18960/api/v1/health健康检查不需要令牌,因此适合作为探测请求。如果 curl 以代码 7 退出并显示 Failed to connect to 127.0.0.1 port 18960 消息,表示连接失败;但这本身无法确定是否存在监听器。检查地址、端口和本地防火墙,并查看运行该服务的终端中是否有启动错误。服务启动后,ss -lntp | grep 18960 可确认套接字已建立。
其余 HTTP API(应用程序编程接口)位于 /api/v1 下。
POST /api/v1/memory/add写入一条记忆,POST /api/v1/memory/search执行查询。GET /api/v1/memory/:id和DELETE /api/v1/memory/:id读取并删除一条记录。POST /api/v1/sessions/open和POST /api/v1/sessions/:sessionId/close标记一个代理会话的开始和结束。POST /api/v1/turns/start和POST /api/v1/turns/:turnId/complete记录一轮交互。GET /api/v1/panel/overview、/api/v1/panel/analysis和/api/v1/panel/items为仪表板提供数据。
Memmy 预留了一组端口。无头运行时只使用其中的前几个:18960 用于 memory,18970 用于网关健康检查,18980 用于 Web UI 和管理 HTTP,18990 用于由 memmy serve 启动的 OpenAI 兼容 API,19000 用于桌面前端的 Vite 开发服务器,19001 用于其热重载套接字。项目的端口页面仍将 19010 列为热重载端口,但 Vite 配置使用 19001。如果其中某个端口已被本机上的其他程序占用,应从该端口列表开始排查。
memmy-memory 命令的实际来源
首次安装通常会在这里出错,因此请直接从软件包中确认,不要猜测。命令名称与仓库名称无关。它来自定义该命令的 workspace 的 bin 字段:
node -p "JSON.stringify(require('./Memory/package.json').bin)"该命令会输出 {"memmy-memory":"./dist/src/cli/index.js"}。因此,构建后的入口点是 Memory/dist/src/cli/index.js。只有执行 npm run memory:build 后该入口点才会存在,因为构建过程会创建 dist 并将其标记为可执行文件。直接运行它:
node Memory/dist/src/cli/index.js health如果希望通过 PATH 使用短名称,请链接到同一个文件:
sudo ln -s "$PWD/Memory/dist/src/cli/index.js" /usr/local/bin/memmy-memory
memmy-memory healthCLI 默认使用 http://127.0.0.1:18960,并接受 --url、--token、--config、--source 和 --user-id。它的子命令包括 init、health、search、add、get 和 delete;此外还包括供 agent 而非用户使用的 session 和 turn 调用,以及用于管理服务本身的 install、upgrade、service 和 stop。memmy-memory search "deploy steps" 和 memmy-memory add "staging migrates on deploy" 是 agent 最常运行的两个命令。
如何将 Claude Code 连接到 Memmy?
Memmy 不会在 Claude Code 内部将自己注册为服务器。它通过 Claude Code 已经会读取的文件建立连接,具体能做到什么取决于你运行的 memmy-memory。从源码检出目录运行时,memmy-memory init --agent claude 会将一个 memmy-memory Skill 写入 ~/.claude/skills/,并将带标记的记忆块写入 ~/.claude/CLAUDE.md;之后,当这些指令要求 Claude Code 执行 memmy-memory 时,Claude Code 会将其作为普通 shell 命令运行。Linux 安装程序写入 ~/.local/bin 的启动器功能更完整:同一命令还会在 ~/.claude/settings.json 中为 SessionStart、UserPromptSubmit、Stop、PostCompact 和 SessionEnd 注册钩子。这些钩子会注入相关记忆,并保存每次完成的交互轮次,无需模型自行决定是否执行。
手动编写一次该指令。这样可以确切知道代理收到的指令内容。Claude Code 会在每次会话开始时从项目根目录读取 CLAUDE.md,因此在源码路径下,类似下面的代码块就是完整的集成配置:
## Memory
Before starting a task, run `memmy-memory search "<topic>"` and read what comes back.
When a task is done, run `memmy-memory add "<what you learned>"` for anything that will matter next session.请明确这能带来什么。没有钩子时,这是指令级集成,因此只有模型决定运行该命令时才会生效。没有任何机制强制执行该调用。如果会话结束时没有执行 add,指令本身不会保存任何内容;之后扫描历史记录仍可导入已完成的交互轮次。这与 Claude Code 自带的记忆文件具有相同的取舍,但有一个区别:存储是共享的,因此同一台机器上的 Codex 和 Cursor 也能读取该笔记。钩子可以弥补这一缺口,而不是请求模型主动执行。这也是为什么持久记忆会与预算上限和权限规则一起,列在值得安装的 DeepSeek Harness 插件中。
反向操作无需任何配置。Memmy 的扫描器已经会读取 ~/.claude/projects/**/*.jsonl,Claude Code 会将会话记录写入该目录。在运行 tmux 会话中的 Claude Code 的同一台服务器上运行 Memmy,昨天的工作就会自动成为记忆,无需手动配置。
Memmy 能否作为 Claude Code 的 MCP 服务器使用?
不能。明确这一点可以避免浪费时间。MCP(模型上下文协议)包含客户端和服务器。Memmy 是一个客户端。它连接到 MCP 服务器,并将其工具提供给自身的代理运行时。它不会发布可供 claude mcp add 指向的 MCP 端点。存储库中唯一的 MCP 桥接属于桌面本地 API 内的 Composio 集成,该 API 在 127.0.0.1 上绑定了一个随机端口,并使用其自身的 x-memmy-mcp-token 标头。
客户端配置位于 ~/.memmy/config.yaml 中,即 MEMMY_CONFIG 指向的文件,位于 tools.mcpServers 下:
tools:
mcpServers:
example:
type: stdio
command: npx
args:
- "-y"
- "your-mcp-server"
toolTimeout: 30
enabledTools:
- "*"type 接受 stdio、sse 和 streamableHttp。stdio 服务器作为 Memmy 的子进程运行,这意味着其命令必须存在于同一台机器上,并以相同的用户身份运行。如果您已经在 VPS 上运行 MCP 服务器,则应在此处列出这些服务器。
保持记忆存储为私有
Memmy 的所有数据都位于 ~/.memmy 下:config.yaml、工作区、memory-service/memory.sqlite 和运行时文件。扫描和摄取都在本地进行,记忆也会写入本地 SQLite 文件,因此默认确实是本地存储。
云连接是需要重点检查的一条路径。MEMMY_CLOUD_SERVICE 指定云端来源。代码不会为它设置默认值,但安装步骤会将 .env.example 复制到 .env,其中将其设置为 https://api.memmy.cn。该设置会使用试用令牌启用账户模式。只要设置了该值,Memmy 的分析代码也会向该地址发送使用事件,即使使用 API key 模式也是如此:包括事件和命令名称、版本以及安装 ID。CLI 只会报告固定的命令词,不会发送搜索查询或记忆文本。如果该值未设置,分析代码不会发送任何内容。因此,在只使用 API key 的服务器上,启动任何服务前,请清空 .env 中的这一行。记忆改进计划是隐私设置中的独立开关。
模型调用是另一条路径。如果配置了托管嵌入提供商,正在生成嵌入的记忆文本会发送给该提供商,以便转换为向量。本地存储无法阻止这一点。使用内置的本地嵌入提供商,或使用自行托管的嵌入端点,即可关闭这条路径。托管的摘要、演化和相关性过滤模型在执行这些任务时也会接收记忆内容,因此也应检查这些模型设置。
将端口 18960 保持绑定在回环地址上。无需为它配置防火墙规则,因为绑定到 127.0.0.1 的服务完全无法从本机外部访问。请改用 SSH 从笔记本电脑访问:
ssh -N -L 18960:127.0.0.1:18960 you@your-vps当前的记忆服务会拒绝非回环绑定地址。在配置中设置 storage.token,或设置 MEMMY_MEMORY_TOKEN 或 MEMORY_SERVICE_TOKEN 环境变量,可使用 bearer token 保护普通记忆 API 调用;健康检查仍不需要身份验证,浏览器查看器也会对本地请求执行独立检查。配置值支持 ${ENV_NAME} 引用,因此令牌和模型 API key 无需直接写入文件。这与其他场景中避免将密钥交给 AI 代理的做法相同;如果未来版本更改默认绑定地址,默认拒绝的 ufw 策略可作为最后一道防线。
信任前先备份 ~/.memmy
memory.sqlite 是完整的数据存储文件。向量通过 sqlite-vec 扩展存储在同一个文件中,因此备份这一个文件即可。服务写入期间使用 cp 复制文件,可能会得到不完整的数据库。请使用 SQLite 自带的备份命令:
mkdir -p ~/memmy-backup
sqlite3 ~/.memmy/memory-service/memory.sqlite ".backup '$HOME/memmy-backup/memory.sqlite'"该命令会在服务继续运行时生成一致的副本。按计划将副本传输到服务器之外,这正是 使用 restic 备份到异地存储 的用途。丢失 config.yaml 只会丢失可以重新输入的提供商设置。丢失 memory.sqlite 则会丢失上次可用备份之后记录的记忆;服务还会在架构迁移前创建本地备份,但这不是最新的异地副本。
在 systemd 下运行内存服务
npm run memory:serve:dev 在 shell 中运行时,会随 shell 退出。unit 文件可让服务在重启后继续运行。该服务以 memmy 用户身份运行,使用 /opt/memmy 中的检出代码,并将配置存放在该用户的主目录中。先停止 shell 中运行的副本,然后迁移检出代码和配置,并重新指向 memmy-memory 链接:
sudo useradd -m -s /bin/bash memmy
sudo mkdir -p /opt/memmy
sudo mv ~/memmy-agent /opt/memmy/memmy-agent
sudo chown -R memmy:memmy /opt/memmy
sudo ln -sfn /opt/memmy/memmy-agent/Memory/dist/src/cli/index.js /usr/local/bin/memmy-memory
sudo install -d -o memmy -g memmy -m 700 /home/memmy/.memmy
sudo install -o memmy -g memmy -m 600 ~/.memmy/config.yaml /home/memmy/.memmy/config.yaml
sudo install -d -m 755 /etc/memmy该服务将数据库存放在 /home/memmy/.memmy 中,因此启动时会使用空存储。
[Unit]
Description=Memmy memory service
After=network-online.target
[Service]
Type=simple
User=memmy
WorkingDirectory=/opt/memmy/memmy-agent
EnvironmentFile=/etc/memmy/memory.env
ExecStart=/usr/bin/npm run memory:serve:dev
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target不要将令牌放入 unit 文件。将其写入 /etc/memmy/memory.env,所有者设为 root,权限设为 600:
MEMMY_CONFIG=/home/memmy/.memmy/config.yaml
MEMMY_MEMORY_TOKEN=replace-this-with-a-long-random-stringsudo systemctl daemon-reload
sudo systemctl enable --now memmy-memory
systemctl status memmy-memory --no-pager
curl -sS http://127.0.0.1:18960/api/v1/health状态输出中的 status=203/EXEC 表示 systemd 根本无法运行 ExecStart,因此请检查 which npm:在 NodeSource 安装中,它位于 /usr/bin/npm;使用 nvm 时,它位于用户主目录下的某个路径,而 systemd 无法找到该路径。服务启动后立即退出时,需要检查其退出状态和 journal:代码 0 表示正常退出,其他结果包括非零退出、收到信号和超时。运行 journalctl -u memmy-memory -n 50 查看该服务的输出。具体操作与VPS 上的其他 systemd 服务相同。
该项目现在提供两种用户级替代方案。README 中针对源码构建的方案是 memmy-memory install --service-only,它会下载固定版本的 Memory runtime 并注册用户服务;Linux 安装程序会将 memmy-memory.service 设置为 systemd --user unit。两种方案都不会启用 linger,因此请运行 sudo loginctl enable-linger <user>,让该用户的 service manager 在注销后继续运行,并在启动时启动。
Memmy 尚未实现的功能
- 目前没有 Linux 桌面版。打包脚本覆盖 macOS 和 Windows,因此工作台及其引导向导无法在服务器本身上使用。记忆服务现在在
http://127.0.0.1:18960/viewer/提供浏览器查看器,可通过上面的 SSH 隧道访问。Linux 则提供 CLI tarball 和install.sh。 memory:serve:dev会通过tsx运行 TypeScript 入口点,这属于开发路径。代码仓库还提供用于编译输出的memory:serve。不带参数运行npm run,查看当前 checkout 实际包含哪些脚本。- 检索会根据最新的 2,000 条向量记录建立搜索窗口,然后在该窗口内执行 Top-K 选择。在非常大的存储中,较旧的记忆可能位于窗口之外。
- 捕获完成后才会生成嵌入;如果失败,任务会进入重试队列,不会阻塞 agent 当前轮次。刚添加的记忆可能暂时还无法通过向量搜索找到。
- 另一台使用独立本地 SQLite 数据库的服务器拥有单独的记忆。
截至 1 November 2026 的 Version 1.2.401 仍显示这是一个快速发展的早期项目。不同 release 之间可能会更改标志、路径和脚本名称。请读取自己 checkout 中的 bin 字段以及 npm run 的输出,不要直接信任从任何地方复制的命令,包括本文中的命令。
FAQ
健康检查为什么返回 connection refused?
curl 返回码 7 以及 Failed to connect to 127.0.0.1 port 18960 表示连接失败,但不能说明 Memmy 是已停止、已崩溃、监听其他地址,还是无法访问。检查地址和端口,运行 ss -lntp | grep 18960,并查看服务启动时所在终端或 journal。如果日志报告原生 SQLite 模块不匹配,运行 npm rebuild better-sqlite3。还要检查 Node 版本:源代码文档要求 Node 22 或更高版本,而 Linux 安装程序仅接受 22.x 中的 Node.js 22.23.4+、24.x 中的 24.22.1+,或 26.x 中的 26.12.1+。
从源代码构建后,memmy-memory 命令来自哪里?
它来自 @memmy/memory 工作区软件包的 bin 字段,而不是仓库名称。在 checkout 目录中运行 node -p "JSON.stringify(require('./Memory/package.json').bin)",它会打印 {"memmy-memory":"./dist/src/cli/index.js"}。该文件只有在 npm run memory:build 后才会存在,因为构建过程会创建 dist 并将该文件标记为可执行文件。使用 node Memory/dist/src/cli/index.js health 运行它,或将其符号链接到 /usr/local/bin,以便使用简短名称。
可以使用 claude mcp add 将 Memmy 添加到 Claude Code 吗?
不可以。Memmy 是 MCP 客户端,不是 MCP 服务器。它连接到 ~/.memmy/config.yaml 中 tools.mcpServers 下列出的服务器,并将这些服务器的工具提供给自身运行时。Claude Code 通过将 memmy-memory CLI 作为 shell 命令运行,以另一种方式访问 Memmy。memmy-memory init --agent claude 会写入一个 Skill 和一个 CLAUDE.md 块,告知 Claude Code 何时使用它;Linux 安装程序中的启动器还会添加 Claude Code hooks,以自动保存各轮对话。
运行 Memmy 会将我的记忆发送到云服务吗?
扫描和摄取过程在本地运行,记忆会写入您自己磁盘上的 ~/.memmy/memory-service/memory.sqlite。.env.example 中的 https://api.memmy.cn 设置为 MEMMY_CLOUD_SERVICE 时,该服务会提供账户模式和试用令牌,并接收使用情况分析,但不会接收记忆文本;如果您只使用 API 密钥,请清空该设置。记忆改进计划有单独的隐私开关。托管的嵌入模型会接收它要转换为向量的记忆文本;如需让处理过程保持在本地,请使用内置本地提供程序,或使用您自行运行的端点。运行托管的摘要、演化和相关性过滤模型时,它们也会接收记忆内容。