Skip to main content
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-sqlite3bun:sqlite)

Summary

Version 7.1.0 introduces two major architectural migrations:
  1. Process management: PM2 → custom Bun-based ProcessManager
  2. Database driver: better-sqlite3 npm package → bun:sqlite runtime module
Both migrations are automatic and transparent. The first time any hook fires after updating to 7.1.0+, the system performs a one-time cleanup of legacy PM2 processes and transitions to the new architecture.

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

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 list and pm2 save
  • Windows issues: PM2’s PATH resolution caused ENOENT errors — 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
Component: better-sqlite3 — native Node.js addon
  • Native compilation: Requires node-gyp during npm 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-sqlite3 is a Node.js native addon and does not work directly in Bun

What Bun provides instead

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
Health check layers:
  1. Does ~/.claude-mem/.worker.pid exist?
  2. Is the process with that PID alive? (kill(pid, 0))
  3. Does GET http://127.0.0.1:37777/health return 200?
All three must pass for the worker to be considered healthy.
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.db is 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):
If PM2 is not installed, the catch block runs and the marker is created anyway — no error surfaces to the user.

Migration trigger points

1

Hook fires

Any hook — SessionStart, UserPromptSubmit, or PostToolUse — runs using the new v7.1.0 code.
2

Worker status check

ensureWorkerRunning() checks ~/.claude-mem/.worker.pid. On first run after update, this file does not exist.
3

Start worker decision

Worker not running → call startWorker().
4

Migration check

startWorker() checks whether ~/.claude-mem/.pm2-migrated exists.
5

PM2 cleanup

Marker absent → run pm2 delete claude-mem-worker (errors ignored), create marker file with current timestamp.
6

New worker start

Spawn new Bun-managed worker process. Write ~/.claude-mem/.worker.pid and ~/.claude-mem/.worker.port.

The marker file

Location: ~/.claude-mem/.pm2-migrated Content: ISO 8601 timestamp
Lifecycle:
  • 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.
What happens step by step:
  1. Hook fires (SessionStart is most common)
  2. Worker status check: no PID file → worker not running
  3. Migration check: no marker file → run PM2 cleanup
  4. PM2 cleanup: pm2 delete claude-mem-worker (old worker terminated)
  5. Marker creation: ~/.claude-mem/.pm2-migrated with timestamp
  6. New worker start: Bun process spawned, PID and port files created
  7. Verification: process check + HTTP health check
  8. Hook completes: Claude Code session starts normally
User-observable behavior:
  • 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:
No migration logic executes on subsequent sessions.

Platform behavior

Platform comparison

POSIX signal handling works natively. Bun fully supported. No platform-specific workarounds needed.

Command changes

Worker management commands

What the output looks like

Before update:
After 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

This is rare but can happen if PM2 has watch mode enabled, or the process is manually restarted between the migration marker being created and the cleanup command running.
Symptoms:
  • pm2 list still shows claude-mem-worker
  • Port conflict errors in worker logs
  • Worker fails to start
Resolution:

Scenario 2: Stale PID file (process dead)

Symptoms:
  • npm run worker:status reports “not running”
  • ~/.claude-mem/.worker.pid exists
  • The PID it contains does not correspond to a running process
Automatic recovery: The next hook trigger detects the dead process and spawns a fresh worker. Manual resolution:

Scenario 3: Port already in use

Error: EADDRINUSE: address already in use :::37777 Resolution:

Common error messages


Architecture decisions

Why a custom ProcessManager instead of PM2?

  1. Simplicity: Direct process control with no external daemon
  2. No npm dependency: PM2 package removed entirely
  3. Cross-platform: Bun handles platform differences uniformly
  4. Bundle size: Reduced plugin package size
  5. 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?

  1. Performance: Avoids spawning a pm2 process on every hook trigger
  2. Idempotency: Migration runs exactly once per machine
  3. Debuggability: Timestamp in the marker shows exactly when migration occurred
  4. Clarity: Migration state is explicit and inspectable

Why run PM2 cleanup on all platforms (not just macOS/Linux)?

  1. Quality migration: Orphaned processes should be cleaned up on all platforms
  2. Consistency: Same migration path everywhere
  3. Safety: try/catch means if PM2 is not installed, the error is swallowed and the marker is written anyway
  4. 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-based ProcessManager is a one-time, automatic, transparent transition that:
  1. Removes external dependencies (PM2, better-sqlite3)
  2. Simplifies architecture with direct process control
  3. Improves cross-platform support, especially on Windows
  4. Preserves all user data (database, settings, logs unchanged)
  5. Requires no user action (automatic on first hook trigger after update)
Key migration moment: First hook trigger after updating to v7.1.0+ Duration: ~2–5 seconds (one-time) Impact: Seamless — users see no errors, no data loss, improved reliability going forward