Historical migration documentationThis document describes the PM2 to Bun migration that occurred in v7.1.0 (December 2025). If you are installing Claude Mem for the first time, this migration has already been completed and you can use the current Bun-based system documented in the main guides.This documentation is preserved for users upgrading from versions older than v7.1.0.
PM2 to Bun migration
Version: 7.1.0 Date: December 2025 Migration type: Process management (PM2 → Bun) and database driver (better-sqlite3 → bun:sqlite)
Summary
Version 7.1.0 introduces two major architectural migrations:- Process management: PM2 → custom Bun-based
ProcessManager - Database driver:
better-sqlite3npm package →bun:sqliteruntime module
Simplified dependencies
Removes PM2 and better-sqlite3 npm packages. No native module compilation required.
Better Windows support
Bun abstracts platform differences. No more PATH-related ENOENT errors on Windows.
No user action needed
Migration runs automatically on the first hook trigger after update. Takes 2–5 seconds.
Data preserved
User data, settings, and the SQLite database file are completely unchanged.
Why replace PM2?
PM2 pain points
Process management (PM2)
Process management (PM2)
Component: PM2 (Process Manager 2) —
pm2 npm dependency- Daemon required: PM2 runs a persistent background daemon that must be alive for process management to work
- Dependency conflicts: Other tools on the system may also use PM2, leading to unexpected interactions with
pm2 listandpm2 save - Windows issues: PM2’s PATH resolution caused
ENOENTerrors — the PM2 binary could not be found even when installed (v5.1.1) - Overkill: PM2 is a full process manager designed for production Node.js servers; Claude Mem just needs to keep one background worker running
Database driver (better-sqlite3)
Database driver (better-sqlite3)
Component:
better-sqlite3 — native Node.js addon- Native compilation: Requires
node-gypduringnpm install, which needs a C++ compiler - Windows: Visual Studio Build Tools + Python required — the most common installation failure on Windows
- Mac/Linux: Compiler toolchain still required (Xcode CLT or build-essential)
- Bun incompatibility:
better-sqlite3is a Node.js native addon and does not work directly in Bun
What Bun provides instead
Custom ProcessManager (Bun)
Custom ProcessManager (Bun)
Component:
src/services/process/ProcessManager.ts- No external dependency: Uses
Bun.spawn()with detached mode — built into the Bun runtime - Direct control: PID file + process existence check + HTTP health check — no daemon required
- Cross-platform: Bun handles signal and path differences across macOS, Linux, and Windows
- Simpler codebase: Direct process management is easier to reason about and debug
- Does
~/.claude-mem/.worker.pidexist? - Is the process with that PID alive? (
kill(pid, 0)) - Does
GET http://127.0.0.1:37777/healthreturn 200?
bun:sqlite
bun:sqlite
Component:
bun:sqlite — built into the Bun runtime- No installation: Ships with Bun ≥ 1.0, no npm install, no compilation
- Same API: Synchronous interface similar to
better-sqlite3 - Same database file:
~/.claude-mem/claude-mem.dbis unchanged — only the driver changed - Same SQL: All queries are standard SQLite SQL
Architecture comparison
Old system (PM2)
New system (Bun)
How the migration works
The marker-based approach
The migration system uses a single marker file to ensure PM2 cleanup runs exactly once per machine. Implementation (src/shared/worker-utils.ts):
catch block runs and the marker is created anyway — no error surfaces to the user.
Migration trigger points
Hook fires
Any hook — SessionStart, UserPromptSubmit, or PostToolUse — runs using the new v7.1.0 code.
Worker status check
ensureWorkerRunning() checks ~/.claude-mem/.worker.pid. On first run after update, this file does not exist.PM2 cleanup
Marker absent → run
pm2 delete claude-mem-worker (errors ignored), create marker file with current timestamp.The marker file
Location:~/.claude-mem/.pm2-migrated
Content: ISO 8601 timestamp
- Created on the first hook trigger after updating to v7.1.0+ (all platforms)
- Never updated after creation
- Never automatically deleted
- Delete manually to force re-migration (for testing or troubleshooting only)
User experience timeline
First session after update
This is the critical migration moment. The process takes approximately 2–5 seconds.
- Hook fires (SessionStart is most common)
- Worker status check: no PID file → worker not running
- Migration check: no marker file → run PM2 cleanup
- PM2 cleanup:
pm2 delete claude-mem-worker(old worker terminated) - Marker creation:
~/.claude-mem/.pm2-migratedwith timestamp - New worker start: Bun process spawned, PID and port files created
- Verification: process check + HTTP health check
- Hook completes: Claude Code session starts normally
- Slight delay on first startup (~2–5 seconds)
- No error messages (cleanup failures are silently handled)
- Worker appears running via
npm run worker:status - Old PM2 worker no longer in
pm2 list
All subsequent sessions
After migration completes, every hook trigger follows the fast path:Platform behavior
Platform comparison
| Feature | macOS | Linux | Windows |
|---|---|---|---|
| PM2 cleanup | Attempted | Attempted | Attempted |
| Marker file created | Yes | Yes | Yes |
| Process signals | POSIX (native) | POSIX (native) | Bun abstraction |
| Bun support | Full | Full | Full |
| PID file | Yes | Yes | Yes |
| Port file | Yes | Yes | Yes |
| Health check | HTTP | HTTP | HTTP |
| Migration delay | ~2–5s | ~2–5s | ~2–5s |
- macOS
- Linux
- Windows
POSIX signal handling works natively. Bun fully supported. No platform-specific workarounds needed.
Command changes
Worker management commands
| Old (PM2) | New (Bun) |
|---|---|
pm2 start <script> | npm run worker:start |
pm2 stop claude-mem-worker | npm run worker:stop |
pm2 restart claude-mem-worker | npm run worker:restart |
pm2 delete claude-mem-worker | npm run worker:stop |
pm2 logs claude-mem-worker | npm run worker:logs |
pm2 list | npm run worker:status |
pm2 describe claude-mem-worker | npm run worker:status |
pm2 monit | No equivalent (PM2-specific) |
What the output looks like
Before update:File system changes
State directory before migration (PM2 system)
State directory after migration (Bun system)
Cleaning up orphaned PM2 files (optional)
Troubleshooting
Scenario 1: PM2 worker still running after migration
Symptoms:pm2 liststill showsclaude-mem-worker- Port conflict errors in worker logs
- Worker fails to start
Scenario 2: Stale PID file (process dead)
Symptoms:npm run worker:statusreports “not running”~/.claude-mem/.worker.pidexists- The PID it contains does not correspond to a running process
Scenario 3: Port already in use
Error:EADDRINUSE: address already in use :::37777
Resolution:
Common error messages
| Error | Cause | Resolution |
|---|---|---|
EADDRINUSE | Port 37777 already in use | lsof -i :37777 then kill conflicting process |
No such process | Stale PID file | Automatic cleanup on next hook trigger |
pm2: command not found | PM2 not installed | None needed — error is caught and ignored |
Invalid port X | Port validation failed | Update CLAUDE_MEM_WORKER_PORT in settings |
Architecture decisions
Why a custom ProcessManager instead of PM2?
- Simplicity: Direct process control with no external daemon
- No npm dependency: PM2 package removed entirely
- Cross-platform: Bun handles platform differences uniformly
- Bundle size: Reduced plugin package size
- Fine-grained control: Better error handling and validation than PM2’s generic process management
Why a one-time marker file instead of always running pm2 delete?
- Performance: Avoids spawning a
pm2process on every hook trigger - Idempotency: Migration runs exactly once per machine
- Debuggability: Timestamp in the marker shows exactly when migration occurred
- Clarity: Migration state is explicit and inspectable
Why run PM2 cleanup on all platforms (not just macOS/Linux)?
- Quality migration: Orphaned processes should be cleaned up on all platforms
- Consistency: Same migration path everywhere
- Safety:
try/catchmeans if PM2 is not installed, the error is swallowed and the marker is written anyway - No downside: If PM2 was never installed, the migration is a no-op
Testing the migration (developer notes)
Summary
The migration from PM2 to Bun-basedProcessManager is a one-time, automatic, transparent transition that:
- Removes external dependencies (PM2,
better-sqlite3) - Simplifies architecture with direct process control
- Improves cross-platform support, especially on Windows
- Preserves all user data (database, settings, logs unchanged)
- Requires no user action (automatic on first hook trigger after update)