The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Passbaton listing page.
Session continuity for AI coding agents. Your agent picks up where it left off — never re-explain your project again. Persistent memory for Claude Code, OpenAI Codex CLI & Google Gemini CLI, sharing one local db: auto context injection, compaction handover, semantic search, and error→solution recall. Zero config, zero API cost, 100% local.
⚡ One install → context auto-loads every session · 🧩 survives compaction (0 re-explaining) · 🔒 100% local, $0 API

Renamed (v2.0.0): this project was previously
claude-session-continuity-mcp. The old name suggested it was Claude-only — it never was. Claude Code, Codex CLI, and Gemini CLI are all first-class and share one local memory. Existing installs keep working: the oldclaude-hook-*commands still ship as aliases. See Migrating from v1.
Every new session — whether you're in Claude Code, Codex CLI, or Gemini CLI:
5 minutes of context-setting. Every. Single. Time.
Fully automatic. Lifecycle hooks handle everything without manual calls — on Claude Code, OpenAI Codex CLI, and Google Gemini CLI, sharing one local memory so context carries across all three:
Zero manual work. Context follows you.
Most Claude memory tools rely on explicit tool calls ("remember this"), a cloud API, or a background AI worker. This one is deliberately different:
| passbaton | Typical cloud/AI-memory MCP | |
|---|---|---|
| Setup | npm i -g → hooks auto-install | Manual server + API key |
| Trigger | 5 automatic hooks (no commands) | You call a remember tool |
| Storage | 100% local SQLite | Cloud / external service |
| API cost | $0 — local embeddings | Per-token / subscription |
| Latency | < 5ms (on-device) | Network round-trip |
| Privacy | Never leaves your machine | Sent to a provider |
| Search | FTS5 + local semantic, KO/EN/JA cross-lingual | Varies |
If you want zero-config, offline, no-cost memory that just happens while you work — this is it.
There's also a great class of local search tools (e.g. ctx) that index your agent history so you can query it (search "failed migration"). That's complementary, not the same job:
| passbaton | Local-search tools (ctx, etc.) | |
|---|---|---|
| How you use it | Automatic — context appears on session start, no command | You (or the agent) run a search query |
| Compaction | PreCompact hook re-injects a handover → 0 context re-explained after a compact | Not its job (it's a search index) |
| Best at | Never losing your thread across sessions & compacts, hands-off | Finding a specific past decision/command on demand |
| Coverage | Claude Code + Codex CLI + Gemini CLI (where auto-injection is possible) | Often 30+ agents indexed for search |
Use search when you want to look something up. Use this when you want your context to follow you without asking.
Beyond Claude Code, this also supports OpenAI Codex CLI. If ~/.codex exists,
the installer registers the same hooks in ~/.codex/hooks.json (SessionStart,
UserPromptSubmit, PreCompact, Stop), and the hooks auto-detect the host and emit
the right output format (Codex's hookSpecificOutput.additionalContext).
The same local sessions.db is shared, so context carries across both agents:
what you did in Codex is available in Claude Code and vice versa.
Scope: session save + context injection work on both. Codex file-change
tracking (PostToolUse) isn't wired yet — session save already covers most of it
via transcript parsing. Codex's transcript_path is treated as an unstable
interface (it can be null at startup), so host detection uses an installer-injected
--codex marker rather than relying on the path.
Also supports Google Gemini CLI. If ~/.gemini exists, the installer registers
the hooks in ~/.gemini/settings.json (SessionStart, BeforeAgent, PreCompress,
SessionEnd — Gemini's event names), preserving your other settings. Same shared
local sessions.db, so context carries across all three agents.
Gemini's transcript format was verified against real ~/.gemini/tmp/.../chats/*.jsonl
files — it uses two shapes (a flat {type, content} line and an older
{"$set":{"messages":[…]}} diff line); the parser handles both. Like Codex,
transcript_path can be null at startup, so host detection uses a --gemini marker.
Honest scope note: session save (SessionEnd) and context output are verified working.
Gemini's SessionStart context injection is documented as advisory-only upstream
(gemini-cli#15413) — if your
Gemini build doesn't render the injected context on startup, that's an upstream limit,
not this tool. Session continuity still works via the saved history.
If you installed this as claude-session-continuity-mcp (v1.x), nothing breaks — the v1 claude-hook-* commands still ship as aliases in v2.
To move to the new name:
The installer rewrites your hook entries to passbaton-hook-* and removes the old claude-hook-* lines — it matches on both names, so you won't end up with duplicates. Your existing sessions.db is untouched: all past sessions, memories, and solutions carry over.
Nothing else changes — same hooks, same database, same behavior.
Requires Node.js 22+. The native
better-sqlite3dependency only ships prebuilt binaries for Node 22, 24, and 26 (the currently supported lines — Node 18 and 20 are both end-of-life). On older Node it falls back to compiling from source, which fails without build tools. Node 22 and up install cleanly with no compiler needed.
That's it! The postinstall script automatically:
~/.claude.json~/.claude/settings.json-g)?This tool is designed to track all your Claude Code projects in a single unified database. Global installation is strongly recommended because:
| Reason | Detail |
|---|---|
| Single source of truth | One binary serves every project — no version drift between projects |
| Hooks are user-scoped | ~/.claude/settings.json lives in your home directory, not per-project |
| Cross-project context | Sessions from app-a and app-b share the same DB and search index |
| One update = everything refreshed | npm install -g <latest> updates all projects at once; no per-project reinstall |
| Hooks resolve by bin name | The installer writes the bare bin name (passbaton-hook-*) when it resolves on PATH — the normal case for npm i -g. Measured 135 ms per fire vs 1,367 ms for npm exec -- … (10×), and PostToolUse fires on every edit. If the name does not resolve (local install), it falls back to npm exec -- … |
Add the database to your project's .gitignore. Since 2.4.0 passbaton creates
<project>/.claude/sessions.db on the first session in any project it recognises as a
workspace root, so a project that had no database before will get one:
Do not ignore all of .claude/ — settings.json there is meant to be committed.
Important: Even with global install, you can still disable the hook for specific projects (see below). Global ≠ forced on every project.
Global install does not mean "always on everywhere". You have three layers of control:
| Layer | File | Scope |
|---|---|---|
| 1. Global ON (default) | ~/.claude/settings.json | All projects |
| 2. Project-wide OFF | <project>/.claude/settings.json | Whole team (committed) |
| 3. Personal-only OFF | <project>/.claude/settings.local.json | Just you (gitignored) |
To disable hooks in a specific project, create the override file with empty hook arrays:
Empty arrays override the global setting → that project's sessions are no longer tracked.
That's the only step — all projects pick up the new binary on next Claude Code restart. No need to reinstall in each project.
If you really want per-project install (e.g., locked version for one project):
Drawback: you must install separately in every project, npm exec may not find the local copy reliably from hook context (cwd-dependent), and you pay the npm exec startup cost (~1.4 s) on every hook fire instead of ~135 ms. Stick with -g unless you have a specific reason.
MCP Server (in ~/.claude.json):
Claude Hooks (in ~/.claude/settings.json):
Note (v2.2.1+): Full lifecycle coverage with 5 hooks. The installer probes whether passbaton-hook-* resolves on PATH and writes the bare name if so (≈10× faster per fire); otherwise it writes npm exec -- …, which also finds a local node_modules/.bin.
| Hook | Command | Function |
|---|---|---|
SessionStart | passbaton-hook-session-start | Auto-loads project context on session start |
UserPromptSubmit | passbaton-hook-user-prompt | Auto-injects relevant memories + past reference search |
PostToolUse | passbaton-hook-post-tool | Tracks active files (Edit, Write) + auto-injects error solutions (Bash) |
PreCompact | passbaton-hook-pre-compact | Structured handover context before compression |
Stop | passbaton-hook-session-end | Extracts commits, decisions, error-fix pairs from transcript |
After installation, restart Claude Code to activate the hooks.
| Feature | Description |
|---|---|
| 🤖 Zero Manual Work | Claude Hooks automate all context capture/load |
| 🎯 Quality Memory Only | (v1.10.0) Only decisions, learnings, errors — no file-change noise |
| 🧠 Semantic Search | multilingual-e5-small embedding (94+ languages, 384d) |
| 🌍 Multilingual | Korean/English/Japanese + cross-language search (EN→KR, KR→EN) |
| 🔗 Git Integration | Commit messages auto-extracted from transcripts |
| 🕸️ Knowledge Graph | Memory relations (solves, causes, extends...) |
| 📊 Memory Classification | 5 types: observation, decision, learning, error, pattern |
| ✅ Integrated Verification | One-click build/test/lint execution |
| 📋 Task Management | Priority-based task management |
| 🔧 Auto Error→Solution | (v1.12.0) Bash errors auto-detect → inject past solutions; session-end auto-records error-fix pairs |
| 💰 Token Efficiency | (v1.11.0) Removed loadContext from UserPromptSubmit (saves 24-60K tokens/session) |
| 📑 Progressive Disclosure | (v1.11.0) memory_search returns index first, memory_get for full content |
| ⏳ Temporal Decay | (v1.11.0) Memory scoring with type-specific half-lives for relevance |
| 📝 Structured Handover | (v1.10.0) PreCompact saves work summary, active files, pending actions |
| 🚪 Smart Session End | (v1.10.0) Extracts commits, decisions, error-fix pairs from transcript |
| 🗑️ Auto Noise Cleanup | (v1.10.0) Auto-deletes stale observation memories (3d+) |
| 🔍 Past Reference Detection | (v1.8.0) "저번에 X 어떻게 했어?" auto-searches DB |
| 📝 User Directive Extraction | (v1.8.0) Auto-extracts "always/never" rules from prompts |
(v2.1.0+) Six behaviours are individually toggleable; the rest are shown for
transparency but are always on (a hook's mere existence is controlled by your
settings.json, not by config) or not yet wired. Config lives in a plain,
hand-editable JSON file (~/.claude/passbaton.config.json) — separate from your data,
so it survives a db reset. No file = today's defaults (nothing changes for existing users).
Trying to set an always-on / not-yet-wired feature is rejected with a clear message.
Each toggleable feature also has an env override for one-off/CI use:
PASSBATON_<FEATURE>=0 (e.g. PASSBATON_SOLUTIONCAPTURE=0) wins over the config file.
On-by-default rule: a feature ships on only if it's silent, safe, and universally useful. Anything that speaks unprompted, guesses, or writes speculative rows ships off.
Legend: ●/○ = toggleable (on/off) · · = always on, not a config toggle · ⋯ = not yet wired.
| Feature | Key | Toggle | What it does |
|---|---|---|---|
| Session start injection | sessionStart | · always on | Restore prior context on start |
| Compaction handover+ | compactionHandover | ● toggleable | Before a compaction, carry over your working state plus hot files and last build status — the one gap platform auto-memory structurally can't cover |
| Session persist | sessionEnd | · always on | Save session state on exit |
| Auto memory surfacing | autoInject | · always on | Auto-surface relevant past memories on start |
| Task tracking | taskTracking | · always on | Read/write the task list via MCP + hooks |
| Hot-path pre-warm | hotPathPrewarm | ● toggleable | On start, surface the files you edit most in this project, ranked by real access count |
| Verification ledger | verificationLedger | ● toggleable | Warn on start if a recent session left the build red or issues open |
sessionStart/sessionEndare "always on" because a hook either runs or it doesn't — that's controlled by the hook registration in~/.claude/settings.json, not by config. To disable them, remove the hook there.
| Feature | Key | Toggle | What it does |
|---|---|---|---|
| Cross-agent share | crossAgentSync | · inherent | One local db shared across Claude Code / Codex / Gemini (not a toggle — it's how storage works) |
| Tool-use capture | postToolCapture | · always on | Observe tool use to build hot-paths (low-noise) |
| Solution capture | solutionCapture | ● toggleable | Auto-record error→fix pairs to a solution archive. Set off to skip it entirely (session save is unaffected) |
| Feature | Key | Toggle | What it does |
|---|---|---|---|
| Strict solution gate | strictSolutionGate | ○ opt-in | Stricter error→fix capture filter — fewer noise entries, but may drop some real ones |
| Trigger matching | triggerMatching | ⋯ not yet wired | (planned) Match prompt keywords to auto-inject solutions |
| Pattern mining | patternMining | ⋯ not yet wired | (planned) Mine work patterns and suggest workflows |
| Memory auto-store | memoryAutoStore | ⋯ not yet wired | (planned) Auto-write observation memories from prompts |
| Status line | statusLineInject | ⋯ not yet wired | (planned) Append a passbaton status line to session-start output |
| Hook trace | hookTrace | ○ opt-in | Diagnostics: one line per SessionStart / PostToolUse fire into <workspace>/.claude/hook-trace.log, with pid and the resolved ws_root. Off by default because PostToolUse fires on every edit. Capped at 5 MB (one generation kept). Logs absolute file paths in plaintext — add .claude/hook-trace.log to .gitignore if your repo tracks .claude/ |
The only genuinely user-flippable flags today are compactionHandover, hotPathPrewarm,
verificationLedger, solutionCapture (on) and strictSolutionGate, hookTrace (opt-in).
Turning on
hookTraceon Windows: edit~/.claude/passbaton.config.json(or runpassbaton config set hookTrace on). ThePASSBATON_HOOKTRACE=1env override works too, but hooks are launched fromsettings.jsonthroughcmd.exe, where aVAR=1 commandprefix is a syntax error — so the config file is the practical path.
SessionStart Hook (npx passbaton-hook-session-start):
apps/project-name/) or single project (package.json root folder name).claude/sessions.dbUserPromptSubmit Hook (npx passbaton-hook-user-prompt):
PostToolUse Hook (npx passbaton-hook-post-tool):
active_context.recent_files[File Change] noise)PreCompact Hook (npx passbaton-hook-pre-compact):
Stop Hook (npx passbaton-hook-session-end):
git commit -m patterns)sessions.issues column as JSONWhen you ask about past work, the UserPromptSubmit hook automatically searches the database:
Supported patterns (Korean & English):
| Pattern | Example |
|---|---|
| 저번에/전에/이전에 ... 어떻게 | "저번에 CORS 에러 어떻게 해결했지?" |
| ~했던/만들었던/해결했던 | "수정했던 로그인 로직" |
| 지난 세션/작업에서 | "지난 세션에서 결제 구현" |
| last time/before/previously | "How did we handle auth last time?" |
| did we/did I ... before | "Did we fix the database migration before?" |
| remember when/recall when | "Remember when we set up CI?" |
Output example:
Previous versions used absolute paths or npx:
Now we use npm exec --:
npm exec -- finds local node_modules/.bin first, then falls back to global. Works with both local and global installation without hitting npm registry.
| Type | Description | Use Case |
|---|---|---|
observation | Patterns, structures found in codebase | "All screens are separated in features/ folder" |
decision | Architecture, library choices | "Decided to use SharedPreferences for caching" |
learning | New knowledge, best practices | "Riverpod is better for testing" |
error | Occurred errors and solutions | "Provider.read() doesn't rebuild → use watch()" |
pattern | Recurring code patterns, conventions | "Avoid late keyword abuse" |
| Relation | Description | Example |
|---|---|---|
related_to | General relation | A and B are related |
causes | A causes B | Caching decision → folder structure change |
solves | A solves B | Riverpod learning → Provider bug fix |
depends_on | A depends on B | Folder structure → Caching decision |
contradicts | A conflicts with B | Two design decisions conflict |
extends | A extends B | late pattern → Extended to Riverpod learning |
example_of | A is example of B | Specific code is example of pattern |
SQLite database at ~/.claude/sessions.db:
| Table | Purpose |
|---|---|
memories | Classified memories (observation, decision, learning, error, pattern) |
memories_fts | Full-text search index (FTS5) |
memory_relations | Knowledge graph relations |
embeddings_v4 | Semantic search vectors (multilingual-e5-small, 384d) |
project_context | Fixed project info (tech stack, decisions) |
active_context | Current work state |
tasks | Task backlog |
solutions | Error solution archive |
sessions | Session history |
| Variable | Default | Description |
|---|---|---|
WORKSPACE_ROOT | - | Workspace root path (required) |
MCP_HOOKS_DISABLED | false | Disable Claude Hooks |
LOG_LEVEL | info | Log level (debug/info/warn/error) |
LOG_FILE | - | Optional file logging path |
| Metric | Value |
|---|---|
| Context load (cached) | <5ms |
| Memory search (FTS) | ~10ms |
| Semantic search | ~50ms |
| Build verification | Project-dependent |
[File Change] noise (v1.10.0)PRs welcome! Please:
npm test passesMIT © Byeongchang Lee
If this saves you from re-explaining your project, consider giving it a ⭐ — it genuinely helps others find it.