Skip to content

Releases: thedotmack/claude-mem

v12.3.9

22 Apr 23:12

Choose a tag to compare

Highlights

🔐 Security observation types + Telegram notifier

  • New observation types: security_alert 🚨 (high-priority, triggers notifications) and security_note 🔐 (low-priority).
  • Fire-and-forget Telegram notifier — MarkdownV2 formatting, per-observation error isolation, no token logging.
  • Five env vars control behavior. CLAUDE_MEM_TELEGRAM_ENABLED master toggle defaults on (no-op without bot token + chat ID).

⚡ Stop hook: fire-and-forget summarize

  • Eliminated the ~110s terminal block when a session ended. Summarize handler now enqueues and returns immediately.
  • Server-side SessionCompletionHandler finalizes off the hook's critical path (generator + HTTP fallback), with singleton sharing across the worker.

🐛 Hooks: worker-port precedence + Windows (#2086 / PR #2084)

  • Hooks now resolve endpoint with the same precedence as the worker: env (CLAUDE_MEM_WORKER_PORT, CLAUDE_MEM_WORKER_HOST) > settings.json > defaults.
  • Looser sed regex handles both quoted and unquoted JSON port values.
  • Windows fallback to 37777 when per-uid formula doesn't apply.

🔧 Bug fixes (reviewer rounds on PR #2084)

  • Don't remove in-memory session after a failed finalize; preserve crash-recovery state at 3 sites.
  • Eliminate double-broadcast of session_completed on fallback path.
  • Sync DatabaseManager.getSessionById return type.
  • TelegramNotifier now respects settings.json (not just env).
  • Hardcoded 🚨 emoji replaced with per-type mapping.

📝 Docs

  • version-bump skill now covers npm publish + all 6 manifest paths so npx claude-mem@<version> always resolves. Adds git grep pre-flight for new manifests.

⚙️ Chores

Full Changelog: v12.3.8...v12.3.9

v12.3.8

21 Apr 02:51

Choose a tag to compare

🔧 Fix

Detect PID reuse in the worker start-guard so containers can restart cleanly. (#2082)

The kill(pid, 0) liveness check false-positived when the worker's PID file outlived its PID namespace — most commonly after docker stop / docker start with a bind-mounted ~/.claude-mem. The new worker would boot as the same low PID (often 11) as the old one, kill(0) would report "alive," and the worker would refuse to start against its own prior incarnation. Symptom: container appeared to start, immediately exited cleanly with no user-visible error, worker never came up.

What changed

  • Capture an opaque process-start identity token alongside the PID and verify identity, not just liveness:
    • Linux: /proc/<pid>/stat field 22 (starttime in jiffies) — cheap, no exec, same signal pgrep/systemd use.
    • macOS / POSIX: ps -p <pid> -o lstart= with LC_ALL=C pinned so the emitted timestamp is locale-independent across environments.
    • Windows: unchanged — falls back to liveness-only. The PID-reuse scenario doesn't affect Windows deployments the way containers do.
  • verifyPidFileOwnership emits a DEBUG log when liveness passes but the token mismatches, so the "PID reused" case is distinguishable from "process dead" in production logs.
  • PID files written by older versions are token-less; verifyPidFileOwnership falls back to the existing liveness-only behavior for backwards compatibility. No migration required.

Surface

Shared helpers (PidInfo, captureProcessStartToken, verifyPidFileOwnership) live in src/supervisor/process-registry.ts and are re-exported from ProcessManager.ts to preserve the existing public surface. Both entry points updated: worker-service.ts GUARD 1 and supervisor/index.ts validateWorkerPidFile.

Tests

+14 new tests covering token capture, ownership verification, backwards compatibility for tokenless PID files, and the container-restart regression scenario. Zero regressions.

v12.3.7

20 Apr 20:32

Choose a tag to compare

What's Changed

Refactor: remove bearer auth and platform_source context filter (#2081)

  • Drop bearer-token auth from the worker API. Worker binds localhost-only and CORS restricts origins to localhost — the token added friction for every internal client (hooks, CLI, viewer, sync script) with no real security benefit for single-user local deployments.
  • Drop the unused platform_source query-time filter from the /api/context/inject pipeline (ContextBuilder, ObservationCompiler, SearchRoutes, context handler, transcripts processor). The DB column stays — only the WHERE-clause filter and its plumbing are removed.
  • Replace the removed auth with a simple in-memory rate limiter (300 req/min) as a lightweight compensating control. Limiter normalises IPv4-mapped IPv6, emits Retry-After on 429, and has a size-guarded prune that never runs on localhost.

Cleanup

  • Deleted src/shared/auth-token.ts and all its dependents (worker-utils.ts Authorization header, ViewerRoutes.ts token injection, CORS allowedHeaders: ['Authorization'], sync-marketplace.cjs admin restart header).
  • Stopped tracking .docker-blowout-data/claude-mem.db and added the directory to .gitignore.

Full Changelog

v12.3.6...v12.3.7

v12.3.6

20 Apr 19:36

Choose a tag to compare

Viewer fix: drop the rate limiter

v12.3.5 kept the 300 req/min rate limiter from v12.3.3's "security hardening" bundle. That tripped the live viewer within seconds (it polls logs and stats) and served it "Rate limit exceeded" errors.

Fix: remove the rate limiter entirely. The worker is localhost-only (enforced via CORS), so there's no abuse surface to protect. Rate-limiting a single-user local process is security theater.

Still kept from v12.3.3 hardening

  • 5 MB JSON body limit
  • Path traversal protection
  • Localhost-only CORS
  • Everything else from v12.3.5

No upgrade action required.

v12.3.5

20 Apr 19:23

Choose a tag to compare

Restored v12.3.3 fixes minus bearer auth

v12.3.3 shipped 25 bug fixes under "Issue Blowout 2026" but also introduced bearer-token auth that broke SessionStart context injection for everyone. v12.3.4 rolled everything back to v12.3.2 to unblock users.

v12.3.5 restores all 25 fixes, with the bearer-auth mechanism surgically removed.

Kept hardening from v12.3.3

  • 5 MB JSON body limit
  • In-memory rate limiter (300 req/min/IP)
  • Path traversal protection on watch.context.path
  • RestartGuard (time-windowed restart counter)
  • Idle session eviction on pool slot allocation
  • WAL checkpoint + journal_size_limit
  • Periodic clearFailed() for pending_messages
  • FTS5 keyword-search fallback when ChromaDB is unavailable
  • ResponseProcessor marks non-XML responses as failed (with retry) instead of confirming
  • /health reports activeSessions
  • Summarize hook wraps workerHttpRequest in try/catch (no more blocking exit code 2)
  • UserPromptSubmit session-init waits for worker health on Linux/WSL
  • MCP loopback self-check uses process.execPath instead of bare node
  • Nounset-safe TTY_ARGS in docker/claude-mem/run.sh

Removed from v12.3.3

  • src/shared/auth-token.ts (deleted)
  • requireAuth middleware and its wiring in Server.ts/Middleware.ts
  • Authorization: Bearer injection in worker-utils.ts (hook client), ViewerRoutes.ts (browser token injection), viewer authFetch, and the OpenCode plugin

Upgrade notes

  • ~/.claude-mem/worker-auth-token from a previous 12.3.3 install is harmless and can be deleted.
  • If your Claude Code session kept the 12.3.3 daemon alive, restart Claude Code once so the fresh 12.3.5 daemon takes over.

v12.3.4

20 Apr 18:59

Choose a tag to compare

Rollback of v12.3.3

v12.3.3 (Issue Blowout 2026, PR #2080) broke SessionStart context injection — new sessions received no memory context from claude-mem. This release reverts to the v12.3.2 tree state while the regression is investigated.

Reverted

  • #2080 — Issue Blowout 2026 (25 bugs across worker, hooks, security, and search)

Notes

No functional changes from v12.3.2. A follow-up release will re-land the v12.3.3 fixes individually once the context regression is identified and resolved.

v12.3.3

20 Apr 18:44

Choose a tag to compare

Issue Blowout 2026 — 25 bugs across worker, hooks, security, and search

Security Hardening

  • Bearer token authentication for all worker API endpoints with auto-generated tokens
  • Path traversal protection on context write paths
  • Per-user worker port derivation (37700 + uid%100) to prevent cross-user data leakage
  • Rate limiting (300 req/min/IP) and reduced JSON body limit (50MB → 5MB)
  • Caller headers can no longer override the bearer auth token

Worker Stability

  • Time-windowed RestartGuard replaces flat counter — prevents stranding pending messages on long sessions
  • Idle session eviction prevents pool slot deadlock when all slots are full
  • MCP loopback self-check uses process.execPath instead of bare 'node'
  • Age-scoped failed message purge (1h retention) instead of clearing all
  • RestartGuard decay anchored to real successes, not object creation time

Search & Chroma

  • FTS5 keyword fallback when ChromaDB is unavailable for all search handlers
  • doc_type:'observation' filter on Chroma queries feeding observation hydration
  • Project filtering passed to Chroma queries and SQLite hydration in all endpoints
  • Bounded post-import Chroma sync with concurrency limit of 8
  • FTS5 MATCH input escaped as quoted literal phrases to prevent syntax errors
  • LIKE metacharacters escaped in prompt text search
  • date_desc ordering respected in FTS session search

Hooks Reliability

  • Summarize hook wrapped in try/catch to prevent exit code 2 on network failures
  • Session-init gated on health check success — no longer runs when worker unreachable
  • Health-check wait loop added to UserPromptSubmit for Linux/WSL startup race

Database & Performance

  • Periodic WAL checkpoint and journal_size_limit to prevent unbounded WAL growth
  • FTS5 availability cached at construction time (no DDL probe per query)
  • _fts5Available downgraded when FTS table creation fails

Viewer UI

  • response.ok check added to settings save and initial load flows
  • Auth failure handling in saveSettings

v12.3.2

20 Apr 05:20

Choose a tag to compare

Bug Fixes

  • Search: Fix concept/concepts parameter mismatch in /api/search/by-concept (#1916)
  • Search: Add FTS5 keyword fallback when ChromaDB is unavailable (#1913, #2048)
  • Database: Add periodic clearFailed() to purge stale pending messages (#1957)
  • Database: Add WAL checkpoint schedule and journal_size_limit to prevent unbounded growth (#1956)
  • Worker: Mark messages as failed (with retry) instead of confirming on non-XML responses (#1874)
  • Worker: Include activeSessions in /health endpoint for queue liveness monitoring (#1867)
  • Docker: Fix nounset-safe TTY_ARGS expansion in run.sh
  • Search: Cache isFts5Available() at construction time (Greptile review)

Closed Issues

#1908, #1953, #1916, #1913, #2048, #1957, #1956, #1874, #1867

v12.3.1

20 Apr 03:35

Choose a tag to compare

Error Handling & Code Quality

This patch release resolves error handling anti-patterns across the entire codebase (91 files), improving resilience and correctness.

Bug Fixes

  • OpenRouterAgent: Restored assistant replies to conversationHistory — multi-turn context was lost after method extraction (#2078)
  • ChromaSync: Fixed cross-type dedup collision where observation#N, session_summary#N, and user_prompt#N could silently drop results
  • Timeline queries: Fixed logger calls wrapping Error inside an object instead of passing directly
  • FTS migrations: Preserved non-Error failure details instead of silently dropping them

Error Handling Improvements

  • Replaced 301 error handling anti-patterns across 91 files:
    • Narrowed overly broad try-catch blocks into focused error boundaries
    • Replaced unsafe error as Error casts with instanceof checks
    • Added structured error logging where catches were previously empty
    • Extracted large try blocks into dedicated helper methods
  • Installer resilience: Moved filesystem operations (mkdirSync) inside try/catch in Cursor, Gemini CLI, Goose MCP, and OpenClaw installers to maintain numeric return-code contracts
  • GeminiCliHooksInstaller: Install/uninstall paths now catch readGeminiSettings() failures instead of throwing past the 0/1 return contract
  • OpenClawInstaller: Malformed openclaw.json now throws instead of silently returning {} and potentially wiping user config
  • WindsurfHooksInstaller: Added null-safe parsing of hooks.json with optional chaining
  • McpIntegrations: Goose YAML updater now throws when claude-mem markers exist but regex replacement fails
  • EnvManager: Directory setup and existing-file reads are now wrapped in structured error logging
  • WorktreeAdoption: adoptedSqliteIds mutation delayed until SQL update succeeds
  • Import script: Guard against malformed timestamps before toISOString()
  • Runtime CLI: Guard response.json() parsing with controlled error output

Documentation

  • Added README for Docker claude-mem harness

v12.3.0

20 Apr 00:36

Choose a tag to compare

New features

Basic claude-mem Docker container (docker/claude-mem/)

A ready-to-run container for ad-hoc claude-mem testing with zero local setup beyond Docker.

  • FROM node:20; layers pinned Bun (1.3.12) + uv (0.11.7) + the built plugin
  • Non-root node user so --permission-mode bypassPermissions works headlessly
  • build.sh, run.sh (auto-extracts OAuth from macOS Keychain or ~/.claude/.credentials.json, falls back to ANTHROPIC_API_KEY), entrypoint.sh
  • Persistent .claude-mem/ mount so the observations DB survives container exit

Validated end-to-end: PostToolUse hook → queue → worker SDK call under subscription OAuth → <observation> XML → observations table → Chroma sync.

SWE-bench evaluation harness (evals/swebench/)

Two-container split (our agent image + the upstream SWE-bench harness) for measuring claude-mem's effect on resolve rate.

  • Dockerfile.agentclaude-mem/swebench-agent:latest (same non-root, version-pinned approach)
  • run-instance.sh — two-turn ingest/fix protocol per instance; shallow clone at base_commit with full-clone fallback
  • run-batch.py — parallel orchestrator with OAuth extraction, per-container naming, timeout enforcement + force-cleanup, --overwrite guard against silent truncation of partial results
  • eval.sh — wraps python -m swebench.harness.run_evaluation
  • summarize.py — aggregates per-instance reports
  • smoke-test.sh — one-instance smoke test

Fixes / hardening (from PR review)

  • chmod 600 on extracted OAuth creds files
  • Grouped { chmod || true; } so bash precedence can't mask failed curl|sh installs
  • macOS creds: Keychain-first with file fallback for migrated / older setups
  • smoke-test.sh TIMEOUT now actually enforced via timeout/gtimeout plus docker rm -f on exit 124
  • Container naming + force-cleanup in run-batch.py timeout handler prevents orphan containers
  • Fixed stdin-redirection collision in the consolidated smoke-test.sh JSON parser
  • Drop exec in run.sh so the EXIT trap fires and cleans the temp creds file

PR: #2076