Skip to content

历史迁徙记录

本文档描述了发生在 v7.1.0(2025 年 12 月)的 PM2 到 Bun 的迁移。如果您是第一次安装 claude-mem,这次迁移已经完成,您可以使用主指南中记录的当前基于 Bun 的系统。

此文档为从 v7.1.0 之前版本升级的用户保留。

PM2到Bun的迁移:完整技术文档

版本: 7.1.0 日期:2025年12月 迁移类型:流程管理(PM2 → Bun) 数据库驱动(better-sqlite3 → bun:sqlite)

执行摘要

Claude-mem 版本 7.1.0 引入了两个主要的架构迁移:

  1. 进程管理:PM2 → 基于自定义 Bun 的进程管理器
  2. 数据库驱动:better-sqlite3 npm 包 → bun:sqlite 运行时模块

这两次迁移对最终用户来说都是自动透明的。在更新到 7.1.0 后第一次触发钩子时,系统会对旧的 PM2 进程执行一次性清理,并过渡到新的架构。

主要好处

  • 简化的依赖:移除 PM2 和 better-sqlite3 npm 包
  • 改进的跨平台支持:更好的 Windows 兼容性
  • 更快的安装:无需本地模块编译
  • 内置运行时:利用 Bun 的内置进程管理和 SQLite
  • 降低复杂性:自定义 ProcessManager 比 PM2 集成更简单

迁移影响

  • 数据保留:用户数据、设置和数据库保持不变
  • 自动清理:旧的 PM2 进程自动终止(所有平台)
  • 无需用户操作:迁移将在第一次触发挂钩时自动进行
  • 向后兼容:SQLite 数据库格式保持不变(仅驱动更改)

架构比较

旧系统(基于 PM2)

组件:PM2(进程管理器 2)

  • 软件包: pm2 npm 依赖
  • 进程名称: claude-mem-worker
  • 管理:外部 PM2 守护进程管理生命周期
  • 发现: pm2 listpm2 describe 命令
  • 自动重启:PM2 在崩溃时会自动重启
  • 日志: ~/.pm2/logs/claude-mem-worker-*.log
  • PID 文件: ~/.pm2/pids/claude-mem-worker.pid

生命周期命令

bash
pm2 start <script>           # Start worker
pm2 stop claude-mem-worker   # Stop worker
pm2 restart claude-mem-worker # Restart worker
pm2 delete claude-mem-worker  # Remove from PM2
pm2 logs claude-mem-worker    # View logs

痛点:

  • 需要额外的 npm 依赖
  • PM2 守护进程必须正在运行
  • 可能与其他 PM2 进程冲突
  • Windows 兼容性问题
  • 用于简单用例的复杂配置

组件:better-sqlite3

  • better-sqlite3 npm 包(本地模块)
  • 安装:需要本地编译(node-gyp)
  • Windows:需要 Visual Studio 构建工具 Python
  • 导入: import Database from 'better-sqlite3'

安装要求

  • Node.js 开发头文件
  • C 编译器(Mac/Linux 上的 gcc/clang,Windows 上的 MSVC)
  • Python(用于 node-gyp)
  • Windows:Visual Studio 构建工具

新系统(基于 Bun)

组件:自定义 ProcessManager (src/services/process/ProcessManager.ts)

  • :内置 Bun API(无需外部依赖)
  • 进程生成Bun.spawn() 使用分离模式
  • 管理:通过 PID 文件直接控制进程
  • 发现:PID 文件 进程存在检查 HTTP 健康检查
  • 自动重启:在检测到故障时触发钩子重启
  • 日志: ~/.claude-mem/logs/worker-YYYY-MM-DD.log
  • PID 文件: ~/.claude-mem/.worker.pid
  • 端口文件~/.claude-mem/.worker.port(新建)

生命周期命令

bash
npm run worker:start    # Start worker
npm run worker:stop     # Stop worker
npm run worker:restart  # Restart worker
npm run worker:status   # Check status
npm run worker:logs     # View logs

核心机制

  1. PID 文件管理

    • 文件:~/.claude-mem/.worker.pid
    • 内容:进程 ID(例如,“35557”)
    • 验证:通过 kill(pid, 0) 信号检测进程存在
  2. 端口文件管理

    • 文件:~/.claude-mem/.worker.port
    • 内容:两行(端口号,进程ID)
    • 目的:跟踪端口绑定并验证 PID 匹配
  3. 健康检查:

    • 第1层:PID 文件存在吗?
    • 第2层:进程存活吗?(kill(pid, 0)
    • 第3层:HTTP 健康检查 (GET /health)
    • 三项都必须通过才能获得“健康”状态

优势

  • 无外部依赖
  • 更简单的代码库(直接控制)
  • 更好的错误处理和验证
  • 平台无关(Bun 处理平台差异)

组件: bun:sqlite

  • 软件包:内置于 Bun 运行时(无需 npm 软件包)
  • 安装:无需安装(随 Bun ≥1.0 提供)
  • 平台:在 Bun 可运行的任何地方均可使用
  • 导入: import { Database } from 'bun:sqlite'
  • API:类似于 better-sqlite3(同步)

安装要求

  • Bun ≥1.0(如果缺失会自动安装)
  • 不需要本地编译
  • 无需特定平台的构建工具

兼容性:

  • SQLite 数据库格式:未改变
  • 数据库文件:~/.claude-mem/claude-mem.db(相同位置)
  • 查询语法:相同(两者都使用 SQLite SQL)

迁移机制

一次性PM2清理

迁移系统使用基于标记的方法来确保 PM2 清理仅执行一次。

实施: src/shared/worker-utils.ts:73-86

typescript
// Clean up legacy PM2 (one-time migration)
const pm2MigratedMarker = join(DATA_DIR, '.pm2-migrated');

if (!existsSync(pm2MigratedMarker)) {
  try {
    spawnSync('pm2', ['delete', 'claude-mem-worker'], { stdio: 'ignore' });
    // Mark migration as complete
    writeFileSync(pm2MigratedMarker, new Date().toISOString(), 'utf-8');
    logger.debug('SYSTEM', 'PM2 cleanup completed and marked');
  } catch {
    // PM2 not installed or process doesn't exist - still mark as migrated
    writeFileSync(pm2MigratedMarker, new Date().toISOString(), 'utf-8');
  }
}

迁移触发点

SessionStart、UserPromptSubmit 或 PostToolUse 钩子使用新的 7.1.0 代码执行

ensureWorkerRunning() 检查 ~/.claude-mem/.worker.pid 是否存在(在更新后的第一次运行中不存在)

Worker 进程未运行 → 调用 startWorker()

检查 ~/.claude-mem/.pm2-migrated 是否存在

执行 pm2 delete claude-mem-worker(忽略错误),创建标记文件

生成新的由 Bun 管理的工作进程,并创建 PID 和端口文件

标记文件

地点: ~/.claude-mem/.pm2-migrated

内容:ISO 8601 时间戳

2025-12-13T00:18:39.673Z

目的

  • 一次性迁移标志
  • 防止每次启动时重复清理 PM2
  • 在重启和重新启动后仍然存在

生命周期

  • 创建:更新到 7.1.0 后的第一个钩子触发(所有平台)
  • 更新:从未
  • 已删除:从不(用户可以手动删除以强制重新迁移)

用户体验时间线

更新后的第一次会话

这是关键的迁移时刻。该过程大约需要2到5秒。

逐步执行

  1. 钩子触发(SessionStart 最常见)
  2. 工作进程状态检查:没有 PID 文件 → 工作进程未运行
  3. 迁移检查:没有标记文件 → 运行 PM2 清理
  4. PM2 清理pm2 delete claude-mem-worker(旧工作进程已终止)
  5. 标记创建:带有时间戳的~/.claude-mem/.pm2-migrated
  6. 新员工开始:Bun 进程已启动,已创建 PID/端口 文件
  7. 验证:流程检查 HTTP 健康检查
  8. 钩子完成:Claude Code 会话正常开始

用户可观察行为

  • 首次启动略有延迟(PM2 清理 新工作进程生成)
  • 没有错误信息(清理失败将被静默处理)
  • Worker 似乎正在通过 npm run worker:status 跑动
  • 旧的 PM2 工作进程不再在 pm2 list

后续会议

迁移完成后,每个钩子触发都会遵循快速路径:

  1. PID 文件存在吗?
  2. 进程还活着吗?
  3. HTTP 健康检查?成功
  4. 结果:工作进程已在运行,完成(约50毫秒)

后续会话中不会运行迁移逻辑。

特定平台行为

平台比较

功能macOSLinuxWindows
PM2 清理已尝试已尝试已尝试
标记文件创建创建创建
进程信号POSIX(本地)POSIX(本地)Bun 抽象
臀部支撑全部全部全部
PID 文件
端口文件
健康检查HTTPHTTPHTTP
迁移延迟首次约2-5秒首次约2-5秒首次约2-5秒

平台说明

  • POSIX 信号处理本地支持

  • Bun 完全支持

  • 不需要特定平台的解决方法

  • 与 macOS 完全相同的行为

  • POSIX 信号处理

  • 适用于 Ubuntu、Debian、RHEL、CentOS、Arch

  • Alpine 可能需要 glibc(而不是 musl)

  • PM2 清理现在运行(由于 try/catch,安全)

  • Bun 抽象信号处理的差异

  • Path 模块处理 Windows 分隔符

  • 由 SQLite 处理的文件锁定

可观察到的变化

命令更改

旧的 (PM2)新的 (Bun)备注
pm2 listnpm run worker:status显示 Worker 状态
pm2 start <script>npm run worker:start启动 Worker
pm2 stop claude-mem-workernpm run worker:stop停止 Worker
pm2 restart claude-mem-workernpm run worker:restart重启工作进程
pm2 delete claude-mem-workernpm run worker:stop移除 Worker
pm2 logs claude-mem-workernpm run worker:logs查看日志
pm2 describe claude-mem-workernpm run worker:status详细状态
pm2 monit无对应项PM2特定监控

文件位置更改

日志:

Old: ~/.pm2/logs/claude-mem-worker-out.log
     ~/.pm2/logs/claude-mem-worker-error.log

New: ~/.claude-mem/logs/worker-YYYY-MM-DD.log

PID 文件:

Old: ~/.pm2/pids/claude-mem-worker.pid

New: ~/.claude-mem/.worker.pid

进程状态

Old: PM2 daemon memory (pm2 save)

New: ~/.claude-mem/.worker.pid
     ~/.claude-mem/.worker.port
     ~/.claude-mem/.pm2-migrated (all platforms)

数据库(不变):

Same: ~/.claude-mem/claude-mem.db

用户可见的更改

更新前

bash
$ pm2 list
┌────┬────────────────────┬─────────┬─────────┬──────────┐
 id name status restart uptime
├────┼────────────────────┼─────────┼─────────┼──────────┤
 0 claude-mem-worker online 0 2d 5h
└────┴────────────────────┴─────────┴─────────┴──────────┘

更新后

bash
$ pm2 list
# Empty - worker no longer managed by PM2

$ npm run worker:status
Worker is running
PID: 35557
Port: 37777
Uptime: 2h 15m

孤立文件

迁移后,这些 PM2 文件可能仍然存在(可以安全删除):

~/.pm2/                    # Entire PM2 directory
~/.pm2/logs/               # Old logs
~/.pm2/pids/               # Old PID files
~/.pm2/pm2.log             # PM2 daemon log
~/.pm2/dump.pm2            # PM2 process dump

清理(可选)

bash
# Remove PM2 entirely (if not used for other processes)
pm2 kill
rm -rf ~/.pm2

# Or just remove claude-mem logs
rm -f ~/.pm2/logs/claude-mem-worker-*.log
rm -f ~/.pm2/pids/claude-mem-worker.pid

文件系统状态

州目录结构

迁移前(PM2 系统):

~/.claude-mem/
├── claude-mem.db          # Database (unchanged)
├── chroma/                # Vector embeddings (unchanged)
├── logs/                  # Application logs (unchanged)
└── settings.json          # User settings (unchanged)

~/.pm2/
├── logs/
│   ├── claude-mem-worker-out.log
│   └── claude-mem-worker-error.log
├── pids/
│   └── claude-mem-worker.pid
└── pm2.log

迁移后(Bun 系统):

~/.claude-mem/
├── claude-mem.db          # Database (same file)
├── chroma/                # Vector embeddings (unchanged)
├── logs/
│   └── worker-2025-12-13.log  # New log format
├── settings.json          # User settings (unchanged)
├── .worker.pid            # NEW: Process ID
├── .worker.port           # NEW: Port + PID
└── .pm2-migrated          # NEW: Migration marker (all platforms)

~/.pm2/                    # Orphaned (safe to delete)
├── logs/                  # Old logs (no longer written)
├── pids/                  # Old PID (no longer updated)
└── pm2.log                # PM2 daemon log (not used)

边缘情况与故障排除

场景1:迁移失败(PM2仍在运行)

这很少见,但如果 PM2 启用了监视模式或进程被手动重启,就有可能发生。

症状

  • pm2 list 仍然显示 claude-mem-worker
  • 日志中的端口冲突错误
  • Worker 进程无法启动

解析度:

bash
# Manual cleanup
pm2 delete claude-mem-worker
pm2 save  # Persist the deletion

# Force re-migration (optional)
rm ~/.claude-mem/.pm2-migrated

# Restart worker
npm run worker:restart

场景 2:陈旧的 PID 文件(进程已死)

症状

  • npm run worker:status 显示“未运行”
  • .worker.pid 文件存在
  • 进程ID不存在

自动恢复:下一个钩子触发器检测到已终止的进程并启动一个新的工作进程。

手动解决

bash
rm ~/.claude-mem/.worker.pid
rm ~/.claude-mem/.worker.port
npm run worker:start

场景 3:端口已被占用

错误: EADDRINUSE: address already in use

解析度

bash
# Check what's using the port
lsof -i :37777

# Kill the process
kill -9 <PID>

# Restart worker
npm run worker:restart

常见错误信息

错误原因解决方法
EADDRINUSE端口已被占用lsof -i :37777 然后终止冲突的进程
No such process过期的 PID 文件下次钩子触发时自动清理
pm2: command not foundPM2 未安装不需要(错误会被捕获并忽略)
Invalid port X端口验证失败在设置中更新 CLAUDE_MEM_WORKER_PORT

开发者笔记

测试迁移

bash
# 1. Install old version (with PM2)
git checkout <pre-7.1.0-tag>
npm install && npm run build && npm run sync-marketplace

# 2. Start PM2 worker
pm2 start plugin/scripts/worker-cli.js --name claude-mem-worker

# 3. Update to new version
git checkout main
npm install && npm run build && npm run sync-marketplace

# 4. Trigger hook
node plugin/scripts/session-start-hook.js

# 5. Verify migration
pm2 list  # Should NOT show claude-mem-worker
cat ~/.claude-mem/.pm2-migrated  # Should exist
npm run worker:status  # Should show Bun worker running

架构决策

为什么使用自定义 ProcessManager 而不是 PM2?

  1. 简洁:直接控制,无需外部守护进程
  2. 依赖项:移除 npm 依赖
  3. 跨平台:Bun 处理平台差异
  4. 包大小:减少插件包的大小
  5. 控制:细粒度的错误处理和验证

为什么使用一次性标记而不是一直运行 PM2 删除?

  1. 性能:避免不必要的进程生成
  2. 幂等性:迁移只运行一次
  3. 调试:时间戳显示迁移发生的时间
  4. 简洁:清晰的迁移状态

为什么在所有平台上运行 PM2 清理?

  1. 质量迁移:清理孤立的进程
  2. 一致性:在所有平台上的行为相同
  3. 安全性:错误处理已到位(try/catch)
  4. 没有负面影响:如果未安装 PM2,错误会被捕获并忽略

摘要

从 PM2 迁移到基于 Bun 的进程管理器是一次一次性、自动、透明的过渡,其特点是:

  1. 移除外部依赖(PM2、better-sqlite3)
  2. 简化架构(直接过程控制)
  3. 改善跨平台支持(尤其是 Windows)
  4. 保留用户数据(数据库、设置、日志保持不变)
  5. 无需用户操作(首次挂钩触发时自动执行)

关键迁移时刻:更新到 7.1.0 后的首次钩子触发 持续时间:约2-5秒(一次性延迟) 影响:无缝过渡,对用户不可见 回滚:不需要(迁移仅向前,安全)

对于大多数用户来说,迁移将是完全透明的——他们不会看到任何错误,也不会有数据丢失,并且将体验到更高的可靠性和更简单的故障排除。