A Claude Code plugin that persists conversation context across sessions, /clear commands, and compaction events — with cross-session search, tagging, cross-session highlight sharing, and observability.
Marketplace Status: Submitted via the official submission form at claude.ai/settings/plugins/submit.
Pre-built Marketplace: claude-recall-marketplace (for easy installation until approved)
- Claude Code 2.0.x or 2.1.x (see breaking change note below for 2.1.x), or Claude Cowork (macOS desktop app)
- Python 3.6+ (for hook and script execution)
As of Claude Code 2.1.x, local plugins no longer persist across sessions. This is an undocumented breaking change from 2.0.x behavior. See issue #17089.
Custom plugins now require a marketplace structure to work reliably with the VSCode extension. The --plugin-dir flag only works with the CLI, not VSCode.
From GitHub:
- Open the Claude Desktop app
- Navigate to the Cowork tab
- Click "Plugins" in the left sidebar
- Click "Add from GitHub"
- Enter:
https://github.com/bledden/claude-recall-plugin
From zip file:
- Download claude-recall-plugin.zip
- In the Cowork Plugins sidebar, click "Upload plugin"
- Select the downloaded
claude-recall-plugin.zipfile
The plugin will appear in your Cowork plugins list. Invoke with /recall during a Cowork session.
This is the only reliable method for the VSCode extension until the plugin is approved in the official marketplace.
claude plugin marketplace add https://github.com/bledden/claude-recall-marketplace
claude plugin install recall@recall-localThe plugin will now persist across sessions in both CLI and VSCode.
Alternative: Build Your Own Marketplace
If you prefer to create your own local marketplace:
Step 1: Clone and set up marketplace structure
# Clone this repo
git clone https://github.com/bledden/claude-recall-plugin.git
# Create a marketplace wrapper
mkdir -p claude-recall-marketplace/.claude-plugin
mkdir -p claude-recall-marketplace/plugins
cp -R claude-recall-plugin claude-recall-marketplace/plugins/recallStep 2: Create the marketplace manifest
Create claude-recall-marketplace/.claude-plugin/marketplace.json:
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "recall-local",
"version": "1.0.0",
"description": "Local marketplace for the recall plugin",
"owner": {
"name": "your-name",
"email": "your-email@example.com"
},
"plugins": [
{
"name": "recall",
"description": "Recover conversation context when Claude loses track",
"source": "./plugins/recall",
"category": "productivity"
}
]
}Step 3: Register and install
claude plugin marketplace add /path/to/claude-recall-marketplace
claude plugin install recall@recall-localThis method works for the terminal but does not work with the VSCode extension.
git clone https://github.com/bledden/claude-recall-plugin.gitFor Zsh (default on macOS):
echo "alias claude='claude --plugin-dir /path/to/claude-recall-plugin'" >> ~/.zshrc
source ~/.zshrcFor Bash:
echo "alias claude='claude --plugin-dir /path/to/claude-recall-plugin'" >> ~/.bashrc
source ~/.bashrcclaude plugins install https://github.com/bledden/claude-recall-pluginWarning: This method does not reliably persist in Claude Code 2.1.x. The plugin may disappear after restarting. Use Option 1 instead.
Migration is automatic. On the first prompt after upgrading to v2.0.0, the hook migrates your existing index.json into SQLite and renames the file to index.json.migrated. No manual steps required.
Rollback: If you need to go back to v1.0.1, rename index.json.migrated to index.json. v1.0.1 ignores recall.db.
When Claude seems to have lost context, run:
/recall:recall
This will:
- Show you a timestamped index of all exchanges in your session
- Present a menu asking what you'd like to recall
- Fetch and display the exchanges you select
- Summarize where you left off
/recall Interactive menu (index + options)
/recall last5 Last 5 exchanges, current session
/recall around 2pm Exchanges around a time
/recall search <keyword> Search current session
/recall search <keyword> --all Search all sessions, current project
/recall search <keyword> --global Search across ALL projects
/recall search <keyword> --project <name> Search a specific project by name
/recall sessions List all sessions (current project)
/recall sessions --all List sessions across all projects
/recall session <id> last10 Browse a specific past session
/recall tag <name> Tag the current session
/recall tag <name> #<exchange> Tag a specific exchange by number
/recall tags Show all tags
/recall search --tag <name> Find sessions and exchanges by tag
/recall highlight "summary" Flag a finding for connected sessions
/recall connect <session-id> "topic" Watch another session for highlights
/recall connect --latest "topic" Watch most recent active session (same project)
/recall disconnect <session-id> Stop watching a session
/recall inbox View new highlights from connected sessions
/recall config check_mode decay Enable decay-based polling (default: explicit)
/recall config delivery_mode inject Auto-inject highlights as system messages (default: silent)
/recall config auto_highlight true Enable heuristic highlight detection (default: false)
/recall config skill_enabled true Enable the recall-assistant skill (default: false)
/recall config detection_signals explicit,behavioral,temporal Configure context-loss detection signals
/recall config auto_run_highlight true Auto-flag findings without asking (default: false)
/recall stats Storage statistics
/recall prune --session <id> Delete a specific session
/recall prune --before 2026-01-01 Delete all sessions before a date
/recall export --session <id> --json Export a session to JSON
The plugin understands various time formats:
| Format | Example |
|---|---|
| 12-hour | 2pm, 2:30pm, 2:30 pm |
| 24-hour | 14:30, 14:00 |
| With date (month day) | jan 5 2pm, dec 25 10am |
| With date (numeric) | 1/5 2pm, 12/25 10:30am |
| Relative | yesterday 2pm, today 10am |
Context is persisted to SQLite before /clear executes. After clearing, your full exchange history is still searchable and retrievable. Clearing the context window no longer means losing the record of what happened.
Search across all sessions in a project with --all, or across every project you've worked in with --global. Results include session ID, project, timestamp, and a content preview.
/recall search "auth flow" --all
/recall search "triton kernel" --global
After Claude Code compacts the conversation, the plugin automatically injects a brief context-recovery hint: a prompt reminding Claude to re-anchor on what was happening. No manual /recall needed after compaction.
Technical terms are extracted automatically from each exchange — function names, file paths, identifiers, command names. These feed into FTS5 search so you can find exchanges without remembering the exact wording.
Apply your own tags to sessions or individual exchanges for cross-project discovery:
/recall tag auth-refactor
/recall tag metal-backend #42
Tags are queryable across all sessions and projects.
Share findings between parallel sessions working on related problems. Highlights are lightweight tag-pointers, not full context — checks are token-efficient. Full context is pulled on demand via /recall search.
Two highlight creation paths:
- Explicit (default): Claude proactively runs
/recall highlight "summary"when it produces a finding worth sharing — a bug fix, performance technique, architectural insight, or config that solved a problem. - Auto-detect (opt-in): Enable with
/recall config auto_highlight true. The hook scans assistant responses for solution signals (e.g., "the fix is", "the solution", "resolved by"). If 2+ signals appear in one exchange and the response is 25+ words, a highlight is created automatically withsource='auto'.
Check frequency:
By default, connections are check_mode=explicit — highlights only appear when you run /recall inbox. Enable decay polling with /recall config check_mode decay: starts checking every 7th prompt, grows by 3 each time, caps at every 30th prompt.
Delivery modes:
silent(default): highlights queue silently, view with/recall inboxinject: highlights are injected as system messages automatically
Natural language support: Claude translates "watch session abc123 for kernel work" into /recall connect abc123 "kernel work" automatically.
/recall connect abc123 "CUDA reduction kernels"
/recall connect --latest "Blackwell dispatch work"
/recall inbox
An optional skill that teaches Claude to proactively use the recall plugin. Enable with /recall config skill_enabled true.
When enabled, Claude will:
- Detect context loss — recognizes when it's lost earlier conversation context (explicit signals like "didn't we already...", behavioral signals like contradicting itself, temporal signals like post-compaction)
- Suggest highlighting — when Claude produces a transferable finding, it suggests
/recall highlight(or auto-runs it ifauto_run_highlightis enabled) - Translate natural language — "keep an eye on session abc123" becomes
/recall connect abc123 "..." - Suggest inbox checks — when working on topics that overlap with connected sessions
The skill is fully opt-in and respects all existing opt-in gates. It never auto-runs connect, disconnect, or inbox commands.
Multiple Claude sessions in the same project write to the same database without conflicts. SQLite WAL mode allows concurrent reads and serializes writes safely.
All context is stored in a single SQLite database (recall.db) with FTS5 for full-text search. No JSON files, no external dependencies beyond Python's built-in sqlite3 module.
Every exchange is indexed with its timestamp:
Session started: Jan 5, 2026 at 9:00 AM (Jan 5 - Jan 7)
Total exchanges: 117
Showing page 1 of 6 (most recent first):
Jan 7:
#117 [5:13 pm] "root@dendritic-distillation:~/dendritic# ls..."
#116 [2:49 pm] "Yes, give me the command to kick that off"
Jan 6:
#115 [1:33 pm] "It looks like the experiment is complete..."
Search looks in both user prompts and assistant responses, not just preview text. Multi-word queries use AND logic — both terms must appear anywhere in the exchange. Force exact phrase matching by quoting: search "the fix is".
/recall search dimension
/recall search "auth flow"
Results show up to 10 most recent matches, grouped by date.
Every /recall invocation is logged:
~/.claude/recall-events.log
Log format:
2026-01-05T16:45:00+00:00 | session=abc123 | exchanges=72 | CONTEXT_RECALL_TRIGGERED
Long sessions are paginated (20 exchanges per page):
Showing page 1 of 6 (most recent first)
Navigation:
- Show newer: page 1
- Show older: page 2
/recall last5
/recall search "API endpoint"
/recall search "gradient checkpointing" --all
/recall search "WAL mode" --global
/recall around "yesterday 3pm"
/recall tag metal-backend
/recall sessions
/recall session abc123 last10
/recall prune --before 2026-01-01
/recall highlight "threadgroup size 512 optimal for Blackwell dispatch"
/recall connect abc123 "CUDA reduction kernel work"
# or connect to the most recent active session in this project:
/recall connect --latest "Metal backend optimizations"
/recall inbox
Three hooks are registered:
- UserPromptSubmit — Incrementally indexes each exchange into SQLite on every prompt. Handles
/clearsurvival by committing before the clear executes. Also runs connection checks (decay mode) and auto-highlight detection (if enabled). - PostCompact — After compaction, injects a context-recovery nudge so Claude re-anchors on the session state.
- SessionEnd — Finalizes the session record in the database.
SQLite with FTS5 for full-text search and WAL mode for concurrent session safety. All data lives in a single file — no external services, no dependencies beyond Python's standard library.
A hybrid approach: auto-tags are extracted from exchange content at index time; manual tags are applied via /recall tag. Both are searchable via FTS5.
Highlights are created via two paths: explicit (Claude runs /recall highlight) or auto-detection (heuristic scan of assistant responses, opt-in). Connections are opt-in links between sessions stored in the connections table. The UserPromptSubmit hook checks connections on each prompt when check_mode=decay is set. Delivery is either silent (queue for /recall inbox) or injected as a system message.
~/.claude/context-recall/recall.db Single SQLite database (WAL mode, FTS5)
~/.claude/recall-events.log Recall event log (unchanged from v1)
The database contains five tables:
sessions— one row per session, with project, timestamps, and metadata (including per-session config likeauto_highlight)exchanges— one row per exchange, with full user/assistant texttags— session and exchange-level tagshighlights— findings flagged for sharing, linked to a session and exchange;sourcefield distinguishes explicit vs auto-detectedconnections— opt-in links between sessions; storescheck_mode,check_interval,delivery_mode, andlast_checked_at
FTS5 virtual tables index exchange content for fast keyword search across any scope.
# View recent recall events
tail -20 ~/.claude/recall-events.log
# Count recalls per day
cut -dT -f1 ~/.claude/recall-events.log | uniq -c
# Find sessions with frequent recalls
grep -oP 'session=\K[^ ]+' ~/.claude/recall-events.log | sort | uniq -c | sort -rn
# Count total recalls
wc -l ~/.claude/recall-events.logclaude-recall-plugin/
├── .claude-plugin/
│ └── plugin.json # Plugin metadata (v2.2.0)
├── commands/
│ └── recall.md # The /recall command definition
├── skills/
│ └── recall-assistant/
│ └── SKILL.md # Proactive recall assistant skill
├── hooks/
│ ├── hooks.json # Hook config (UserPromptSubmit, PostCompact, SessionEnd)
│ ├── prompt_submit.py # Incremental indexer + auto-tagging + connection checks
│ ├── post_compact.py # Context recovery nudge
│ └── session_end.py # Session finalization
├── scripts/
│ ├── db.py # SQLite layer (FTS5, WAL, all CRUD)
│ ├── utils.py # Shared formatting and parsing utilities
│ ├── auto_tagger.py # TF-based keyword extraction
│ ├── highlight.py # Highlight creation (explicit + auto-detect)
│ ├── manage_connections.py # Connect, disconnect, inbox, config
│ ├── manage_tags.py # Tag CRUD, search by tag
│ ├── manage_sessions.py # Session list, prune, export, stats
│ ├── fetch_exchanges.py # Fetch exchanges by query
│ └── show_index.py # Paginated index display
├── tests/
│ ├── test_db.py # Schema, CRUD, FTS5, maintenance (43 tests)
│ ├── test_auto_tagger.py # TF extraction, heuristic (13 tests)
│ ├── test_prompt_submit.py # Hook behavior, migration (13 tests)
│ ├── test_post_compact.py # Nudge generation (7 tests)
│ ├── test_session_end.py # Session finalization (3 tests)
│ ├── test_fetch_exchanges.py # Query scripts (25 tests)
│ ├── test_show_index.py # Pagination, search (26 tests)
│ ├── test_manage_tags.py # Tag management (14 tests)
│ ├── test_manage_sessions.py # Session management (16 tests)
│ ├── test_manage_connections.py # Connection management (15 tests)
│ ├── test_highlight.py # Highlight creation (19 tests)
│ ├── integration_test.py # Full lifecycle, migration, cross-project (4 tests)
│ ├── eval_skill_defaults.py # Skill config and SKILL.md verification (50 tests)
│ ├── stress_test_scale.py # Scale: 5000 exchanges, FTS5 timing (22 tests)
│ ├── stress_test_concurrent.py # Concurrent: 5 threads, WAL validation (6 tests)
│ ├── stress_test_clear.py # /clear cycles: 20 rapid clears (22 tests)
│ └── stress_test_sharing.py # Sharing: highlights, decay, inbox (22 tests)
├── docs/
│ └── superpowers/
│ ├── specs/ # Design specifications
│ └── plans/ # Implementation plans
├── README.md
├── LICENSE
└── .gitignore
cd claude-recall-plugin
# Unit and integration tests (226 tests)
python3 -m pytest tests/ -v
# Stress tests (72 tests)
python3 -m pytest tests/stress_test_*.py -v
# All tests (298 total)
python3 -m pytest tests/ tests/stress_test_*.py -v- Fork the repository
- Make your changes
- Run tests:
python3 -m pytest tests/ -v - Submit a pull request
All data is stored locally on your machine in ~/.claude/context-recall/. The plugin makes no network requests, includes no telemetry, and shares no data with any external service.
For full details on what data is stored, how to delete it, and your control options, see PRIVACY.md.
To report a security vulnerability, please open an issue at github.com/bledden/claude-recall-plugin/issues or contact the author directly via GitHub.
- All SQL queries use parameterized statements
- No dynamic code execution of any kind
- No external network requests or downloads
- Error messages do not leak file paths or internal state
- Transcript reads are bounded (10MB / 5000 messages per invocation)
- Database directory created with restricted permissions (0o700)
- Hook stdin reads bounded to 1MB
- Claude Cowork requires zip upload — Cowork does not yet support marketplace installation; upload the plugin zip file manually via the Plugins sidebar
- VSCode extension requires marketplace — Due to a breaking change in 2.1.x, the VSCode extension requires the marketplace installation method
- No semantic/embedding search — Search is keyword-based via SQLite FTS5; embedding/vector search is not supported yet
- Cross-session sharing is polling-based — No real-time push; highlights appear on the next check interval or via
/recall inbox
If installed via marketplace:
claude plugin uninstall recall@recall-local
claude plugin marketplace remove recall-localIf using shell alias:
Remove the alias line from your ~/.zshrc or ~/.bashrc, then run source ~/.zshrc or source ~/.bashrc.
Removing stored data:
rm -rf ~/.claude/context-recall/See CHANGELOG.md for the full version history.
MIT License - see LICENSE file for details.