Pass context between Claude Code sessions like a baton.
Claude Code sessions are isolated. Every time you start a new one:
- You re-explain everything. "We're building an auth system. We chose JWT over sessions because..." — for the third time this week.
- You lose decisions. Yesterday Claude helped you evaluate three caching strategies. You picked one. Today, neither of you remembers why.
- Project switching is manual. You're deep in a backend refactor, need to fix a quick frontend bug, and now you're copy-pasting context between windows.
- Your history is gone. Two weeks ago Claude wrote a brilliant database migration pattern. It's buried in a JSONL transcript file somewhere. Good luck finding it.
relay gives Claude Code persistent state that survives across sessions, a way to switch between projects without losing your place, and full-text search across every conversation you've ever had.
Your workstream loads automatically. When you start a session, relay injects your active workstream's state — what you were working on, decisions made, next steps. Claude picks up where you left off without being told.
Project switching takes one command. /relay:switch database-refactor saves your current workstream, loads the other project's state, and you're working in seconds. Both workstreams stay active — run them in parallel across multiple Claude instances if you want.
Nothing gets lost. Every conversation is indexed and searchable. Find that auth pattern from last week, that deployment fix from two weeks ago, or every UX review you've ever done — across all your projects.
Starting a session — your workstream state is already loaded:
relay: Active workstream 'api-refactor'
---
# api-refactor — REST API Modernization
## Current Status
Completed endpoint migration for /users and /teams. 47 tests passing.
## Key Decisions
- Using Express middleware for auth (not per-route)
- Pagination via cursor, not offset
## Next Steps
1. Migrate /projects endpoints
2. Add rate limiting middleware
---
Switching projects mid-session:
> /relay:switch frontend-redesign
Saved api-refactor state. Switched to frontend-redesign.
# frontend-redesign — Dashboard Overhaul
## Current Status
Navigation component complete. Working on data tables...
Finding something from weeks ago:
> "How did we handle the database connection pooling issue?"
[Claude searches your history and finds the exact session]
Saving before you go:
> /relay:save
Saved workstream state, backup created, session hint written.
relay introduces one new concept — workstreams — and builds on two that Claude Code already has:
| Concept | What it is | Lifespan |
|---|---|---|
| Session | A single Claude Code conversation (start to exit). Has a UUID and a slug. When you "continue" a conversation, that's a new session in the same slug chain. | One conversation |
| Context window | Everything Claude can currently see — system prompt, conversation history, tool results, injected state. Gets compressed (compacted) when it fills up. Gone when the session ends. | During a session |
| Workstream | A named project or task with a persistent state file (state.md). relay loads it into the context window at session start, and saves it back to disk when you're done. This is what survives across sessions. |
Until you complete or delete it |
The relationship:
workstream (persistent — lives on disk)
└── loaded into context window (ephemeral — lives during a session)
└── inside a session (one conversation, has a UUID)
relay bridges the gap between the ephemeral context window and persistent workstream state. When a session ends or context gets compacted, your workstream state has already been saved to disk. The next session loads it back in automatically.
- Auto-loaded workstream — every session starts with your workstream state already in the context window
- One-command switching — save current workstream, load another, keep both active
- Multi-instance support — run parallel Claude instances on different workstreams without conflicts
- Compaction protection — warnings as the context window fills up, with a prompt to save before compression
- Full conversation search — every transcript indexed into searchable SQLite FTS5 across all projects
- Auto-tagging — messages classified by type (UX reviews, architecture decisions, plans, debugging) for easy filtering
- Activity summaries —
/relay:summarize 7dfor standup prep, brag books, or catching up after time away - Idea capture —
/relay:ideato jot down future work without losing your flow
- Claude Code v2.1.0+ (plugin system support)
jq— JSON parser, required for hook scripts# Ubuntu/Debian sudo apt install jq # macOS brew install jq # Other: https://jqlang.github.io/jq/download/
- Python 3.10+ and
uv— Required for the MCP conversation search server
# Add the marketplace
claude plugin marketplace add mattpollak/relay
# Install the plugin
claude plugin install relay@relayTo verify it's installed:
claude plugin listStart a new Claude Code session — you should see the SessionStart hook fire. If no workstreams exist yet, it will prompt you to create one.
Core workstream operations (save, create, park, switch, list, ideas) are handled by MCP tools — no bash permission prompts needed. Hooks (session start, context monitor, pre-compact) still run as bash scripts and are automatically approved by a bundled PreToolUse hook (scripts/approve-scripts.sh).
# Pull latest from the marketplace
claude plugin marketplace update relay
# Update the plugin
claude plugin update relay@relayRestart Claude Code after updating to apply changes.
claude --plugin-dir /path/to/relay| Command | What it does |
|---|---|
/relay:status |
Show active workstream, other workstreams, and available commands |
/relay:new api-refactor Modernizing the REST API |
Create a new workstream |
/relay:list |
List all workstreams grouped by status |
/relay:save |
Save current workstream state to disk |
/relay:switch database-refactor |
Save current, load a different workstream |
/relay:park |
Save and deactivate the current workstream |
/relay:idea use websockets for real-time |
Capture an idea for future work (shown in /relay:list) |
/relay:idea promote 2 |
Promote an idea to a full workstream |
/relay:summarize 48h |
Summarize recent activity grouped by workstream (standup prep, brag books) |
/relay:backfill 7d |
Generate session hints for older sessions (one-time cost for efficient future summaries) |
The skills also respond to natural language:
- "new workstream", "start workstream", "create workstream"
- "switch to X", "resume workstream", "work on X"
- "save state", "save workstream", "save session"
- "park this", "park workstream", "pause workstream"
- "list workstreams", "show workstreams"
- "relay status", "workstream status", "what am I working on"
- "add idea", "jot down", "remember this idea"
- "summarize activity", "what did I work on", "standup summary", "brag book"
- "backfill hints", "generate summaries", "backfill sessions"
The MCP server provides tools that Claude uses directly during your session — both for conversation search and workstream management:
Workstream management:
| Tool | What it does |
|---|---|
save_workstream |
Atomically save state file (with backup), update registry, write session hint + marker to DB — all in one call |
create_workstream |
Create a new workstream: add to registry, write initial state file |
park_workstream |
Save state and set workstream status to parked |
switch_workstream |
Save current workstream, activate target, write session marker, return target state |
list_workstreams |
List all workstreams grouped by status (active, parked, completed) plus ideas |
manage_idea |
Add, remove, or list ideas for future work |
summarize_activity |
Summarize recent activity grouped by workstream — writes markdown to file, returns path + overview |
Conversation search:
| Tool | What it does |
|---|---|
search_history |
Full-text search across all conversations (FTS5: AND, OR, NOT, "phrases"). Results include session_number showing position in slug chain. |
get_conversation |
Retrieve messages from a session by UUID or slug. Slug chains (via "continue") return all sessions combined chronologically. Use session param to filter to specific sessions (e.g. "4", "2-3", "1,4"). |
list_sessions |
List recent sessions with metadata, filterable by project, date, and tags. Use slug param to get a session index with session_number fields. |
tag_message |
Manually tag a message for future discoverability |
tag_session |
Manually tag a session (e.g., associate with a workstream) |
list_tags |
List all tags with counts — see what's been auto-detected |
get_session_summaries |
Get pre-written session summaries (hint segments with bullets and decisions) |
reindex |
Force a complete re-index from scratch |
Session-level addressing: When a conversation spans multiple sessions (via "continue"), you can address specific sessions:
list_sessions(slug="my-conversation")— returns a session index withsession_numberfor each sessionget_conversation("my-conversation", session="4-5")— retrieves only sessions 4 and 5search_history("ledger")— results includesession_numberso you know which session each hit is in
Tag filtering: Both search_history and list_sessions accept an optional tags parameter to narrow results. For example, searching for "splash page" with tags: ["review:ux"] returns only UX review messages that mention splash page.
Auto-tags applied during indexing:
| Tag | What it detects |
|---|---|
review:ux |
Substantial UX/usability review content |
review:architecture |
Architecture or system design reviews |
review:code |
Code quality reviews |
review:security |
Security reviews or audits |
plan |
Implementation plans (plan-mode messages or structured phase/implementation docs) |
decision |
Architectural or approach decisions |
investigation |
Root cause analysis and debugging findings |
insight |
Messages with ★ Insight markers |
has:browser |
Session used browser/Playwright tools |
has:tests |
Session ran tests (pytest, vitest, etc.) |
has:deploy |
Session involved deployment (ssh, docker, etc.) |
has:planning |
Session used Claude Code's plan mode |
Configuration lives at ${XDG_CONFIG_HOME:-$HOME/.config}/relay/:
~/.config/relay/
├── relay.json # Server-level config (optional — see below)
├── workstreams.json # Central registry
├── ideas.json # Pre-workstream ideas (shown in /relay:list)
├── session-markers/ # Links session IDs to workstreams (written by hooks; also stored in DB by MCP tools)
│ └── <session-id>.json
├── session-hints/ # Pre-written session summaries (legacy file path; MCP tools write directly to DB)
│ └── <timestamp>-<session-id>.json
└── workstreams/
├── api-refactor/
│ ├── state.md # ~80 lines, auto-loaded on session start
│ ├── state.md.bak # One-deep backup (previous version)
│ ├── plan.md # Optional, loaded on /switch
│ └── architecture.md # Optional, loaded on /switch
└── ...
The conversation search index lives at ~/.local/share/relay/index.db (SQLite, WAL mode).
Activity summaries are written to ~/.local/share/relay/summaries/ by default (configurable — see below).
Optional server-level settings in ~/.config/relay/relay.json:
{
"summary_dir": "~/Documents/relay-summaries"
}| Key | What it does | Default |
|---|---|---|
summary_dir |
Directory for /relay:summarize output files |
~/.local/share/relay/summaries |
The file is optional — relay works fine without it. Missing or malformed files are silently ignored. The output_dir parameter on summarize_activity overrides the config value.
| Hook | Event | What it does |
|---|---|---|
session-start.sh |
SessionStart | Reads registry, injects workstream state into the context window. Auto-attaches if one active workstream; prompts for choice if multiple are active. Writes session marker. |
context-monitor.sh |
PostToolUse | Counts tool calls, warns at 80 and 100 that the context window is filling up |
pre-compact-save.sh |
PreCompact | Prompts Claude to save workstream state before context compression |
session-end.sh |
SessionEnd | Cleans up temp files, updates last_touched timestamp |
approve-scripts.sh |
PreToolUse | Auto-approves Bash commands targeting plugin scripts (no user prompt) |
State files (state.md) are kept under 80 lines and contain:
- Current status
- Key decisions
- Next steps
- Recent session summaries (if space permits)
Saves are handled by the save_workstream MCP tool, which atomically writes the state file (with .bak backup), updates the registry, and writes session hints and markers to the database — all in one call.
The MCP server handles both workstream management and conversation search. Workstream operations (save, create, park, switch, list, ideas) use atomic file writes and SQLite transactions — each skill invocation is a single MCP call instead of multiple bash scripts.
On startup, the server scans ~/.claude/projects/ for JSONL transcript files and incrementally indexes them into SQLite FTS5. First run takes 3-5 seconds; subsequent runs process only new/modified files (~0.01s). Auto-tagging runs during indexing — keyword heuristics classify messages by content type (reviews, plans, decisions, etc.) and sessions by activity (testing, deployment, browser usage).
Cross-project indexing — The search index covers every Claude Code conversation across all your projects, not just the current one. Search for that auth pattern you figured out in project A while working in project B. Use the project parameter on search_history or list_sessions to narrow results to a specific project.
relay handles workstream state (what you're working on, decisions made, next steps). It complements, not replaces, Claude Code's built-in systems:
| System | Purpose | Example |
|---|---|---|
Auto-memory (MEMORY.md) |
Learnings about the codebase | "Use TypeORM migrations for schema changes" |
CLAUDE.md |
Instructions for Claude | "Run tests with npm test before committing" |
| relay | Workstream state + project switching + history search | "Working on auth migration, next: add OAuth" |
If you have - and you almost certainly don't, unless you're me - an existing manual workstream system with a WORKSTREAMS.md registry:
# Preview what the migration will do
bash /path/to/relay/scripts/migrate-from-workstreams.sh --dry-run
# Run the migration
bash /path/to/relay/scripts/migrate-from-workstreams.shThe migration is non-destructive — it copies files to the new location without deleting originals.
- Episodic Memory — conversation archival and search
- Get Shit Done — context monitoring and lean state files
- CASS Memory System — structured knowledge accumulation
See ATTRIBUTION.md for details.
MIT — see LICENSE.
