
Unified, high-performance TUI to index and search your local coding agent history. Aggregates sessions from Codex, Claude Code, Gemini CLI, Cline, OpenCode, Amp, Cursor, ChatGPT, Aider, Pi-Agent, GitHub Copilot Chat, Copilot CLI, OpenClaw, Clawdbot, Vibe, Crush, Hermes, Kimi Code, Qwen Code, and Factory (Droid) into a single, searchable timeline.
curl -fsSL "https://raw.githubusercontent.com/Dicklesworthstone/coding_agent_session_search/main/install.sh?$(date +%s)" \
| bash -s -- --easy-mode --verify
# Windows (PowerShell)
& ([scriptblock]::Create((irm "https://raw.githubusercontent.com/Dicklesworthstone/coding_agent_session_search/main/install.ps1"))) -EasyMode -Verify
Installs the latest release by default. Pass --version <tag> / -Version <tag> to pin a specific version.
Or via package managers:
# Homebrew (Apple Silicon macOS + Linux)
brew install dicklesworthstone/tap/cass
# Windows (Scoop)
scoop bucket add dicklesworthstone https://github.com/Dicklesworthstone/scoop-bucket
scoop install dicklesworthstone/cass
Homebrew bottles are currently published for Linux and Apple Silicon macOS. On Intel macOS, use the install script with --from-source.
⚠️ Never run bare cass in an agent context — it launches the interactive TUI. Always use --robot or --json.
# 1) One-shot agent triage. Follow next_command when present.
cass triage --json
# From zero context, `cass --json` and `cass --robot` also resolve to triage.
# 2) Search across all agent history. Default search is hybrid-preferred:
# lexical is the fast required path; semantic refinement joins when ready.
cass search "authentication error" --robot --limit 5 --fields minimal
# 3) Find the current or recent session for this workspace
cass sessions --current --json
cass sessions --workspace "$(pwd)" --json --limit 5
# 4) View + expand a hit (use source_path/line_number from search output)
cass view /path/to/session.jsonl -n 42 --json
cass expand /path/to/session.jsonl -n 42 -C 3 --json
# 5) Discover the full machine API
cass capabilities --json
cass robot-docs guide
cass robot-docs schemas
# 6) Exclude a noisy agent harness from future indexing
cass sources agents list --json
cass sources agents exclude openclaw
cass sources agents include openclaw
Output conventions - stdout = data only - stderr = diagnostics - exit 0 = success
Search asset contract
- SQLite is the source of truth for indexed conversations and messages. All derived assets (lexical index, semantic vectors, analytics rollups, retention backups) can be rebuilt from SQLite; no derived asset is authoritative.
- Lexical search is the required fast path. Missing, stale, or incompatible lexical assets are treated as derived-state problems that cass should rebuild from SQLite instead of asking operators to perform routine manual repair.
- Hybrid is the default search intent. Robot metadata (--robot --robot-meta) reports the requested mode, realized mode, semantic refinement status, and any lexical fallback reason when semantic assets are not ready.
- Semantic assets are opportunistic background enrichment. Lexical-only results are expected during first indexing, semantic catch-up, disabled semantic policy, or unavailable local model/vector files.
- Semantic model acquisition is opt-in: cass models install downloads the requested embedder on explicit request; cass never auto-downloads. Three embedders are supported via --model <name>: all-minilm-l6-v2 (alias minilm, ~90 MB; the default), snowflake-arctic-s (~120 MB), and nomic-embed (~270 MB). Air-gapped installs use --from-file <dir>. While the chosen model is absent, search silently uses lexical-only and reports fallback_mode="lexical" in health/status.
- cass triage --json is the safest first command for agents: it combines readiness, next_command, recommended_commands[], docs/schema pointers, starter workflows, and accepted recoveries. cass health --json and cass status --json remain the narrower truth surfaces for readiness, active rebuilds, and recovery.
Lexical publish durability (atomic-swap)
- Every lexical publish is an atomic renameat2(RENAME_EXCHANGE) on Linux, or a parked-rename + restore-on-failure dance elsewhere. Readers never see a half-torn index — they see either the old or the new generation, never a mix. See src/indexer/mod.rs::publish_staged_lexical_index.
- The prior-live generation is retained under <data_dir>/index/.lexical-publish-backups/<dated>/ for a bounded retention window. Default cap is 1 (keep just the most-recent prior generation for one-step rollback); override via the CASS_LEXICAL_PUBLISH_BACKUP_RETENTION env var (0 disables retention entirely, higher N keeps deeper history). Pruning runs after every successful publish and emits structured tracing::info! events with freed_bytes + retention_limit for observability.
- Crash recovery is automatic: a crash between the atomic swap and the retain-rename is handled by recover_or_finalize_interrupted_lexical_publish_backup on the next startup, which moves any orphaned canonical sidecar (.<name>.publish-in-progress.bak) into .lexical-publish-backups/ before the next publish lands.
Quarantine, GC, and the doctor/diag surface
- Corrupt or failed-validation assets are quarantined rather than auto-deleted. cass diag --json --quarantine enumerates every quarantined artifact (failed seed bundles, retained publish backups, quarantined lexical generations) with size_bytes, age_seconds, safe_to_gc, and a human-readable gc_reason. The safe_to_gc flag is advisory — it reflects retention policy + cleanup dry-run eligibility and is not wired to any automatic deletion path.
- cass doctor --json surfaces the same quarantine summary plus checks[] status for every diagnostic the tool runs. Without --fix, doctor is read-only (auto_fix_applied=false, auto_fix_actions=[], issues_fixed=0); with --fix it applies only the repairs whose dry-run plans are proven safe (currently: Track A analytics rebuild, Track B rollup rebuild via rebuild_token_daily_stats when the token_usage ledger is intact).
- Lexical generation cleanup uses a dispositions + inspection-required-first policy. Operators running cass doctor --fix never have a generation reclaimed silently — every quarantine stays on disk until an explicit derived-asset rebuild (cass models backfill or an index refresh recommended by cass health --json) supersedes it.
Schema stability guarantees
- The JSON contract surfaces (triage, capabilities, health, status, diag, models status, models verify, models check-update, introspect, doctor, api-version, stats, sessions, search, pack, swarm status, swarm work-packet, swarm lint) are pinned by golden-file regression tests under tests/golden/robot/. A change to any field name, type, or nullability fails the golden test suite and requires a deliberate regeneration pass (UPDATE_GOLDENS=1 rch exec -- env CARGO_TARGET_DIR=/tmp/cass-golden-target cargo test --test golden_robot_json --test golden_robot_docs).
- cass introspect --json's response_schemas block enumerates every schema in a stable alphabetical order (BTreeMap-backed — see bead coding_agent_session_search-8sl73).
- Error envelopes ({error: {code, kind, message, hint, retryable}}) have a fixed shape. kind values are kebab-case; branch on err.kind, not on the numeric code, for codes ≥ 10 (see the Error Handling section below).
If your runtime does not expose built-in mcp-agent-mail tools (for example, list_mcp_resources is empty), you can still coordinate via direct MCP HTTP calls.
~/.local/pipx/venvs/mcp-agent-mail/bin/python -m mcp_agent_mail.cli serve-http --host 127.0.0.1 --port 8765
/mcp)curl -sS -X POST http://127.0.0.1:8765/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":"health","method":"tools/call","params":{"name":"health_check","arguments":{}}}'
# Ensure project
curl -sS -X POST http://127.0.0.1:8765/mcp -H 'Content-Type: application/json' -d \
'{"jsonrpc":"2.0","id":"ensure","method":"tools/call","params":{"name":"ensure_project","arguments":{"human_key":"/data/projects/coding_agent_session_search"}}}'
# Register agent
curl -sS -X POST http://127.0.0.1:8765/mcp -H 'Content-Type: application/json' -d \
'{"jsonrpc":"2.0","id":"register","method":"tools/call","params":{"name":"register_agent","arguments":{"project_key":"/data/projects/coding_agent_session_search","program":"codex","model":"gpt-5","name":"YourAgentName"}}}'
# Send message
curl -sS -X POST http://127.0.0.1:8765/mcp -H 'Content-Type: application/json' -d \
'{"jsonrpc":"2.0","id":"send","method":"tools/call","params":{"name":"send_message","arguments":{"project_key":"/data/projects/coding_agent_session_search","sender_name":"YourAgentName","to":["PeerAgent"],"subject":"[coord] hello","thread_id":"coord-2026-02-13","ack_required":true,"body_md":"Online and starting work."}}}'
# Fetch inbox
curl -sS -X POST http://127.0.0.1:8765/mcp -H 'Content-Type: application/json' -d \
'{"jsonrpc":"2.0","id":"inbox","method":"tools/call","params":{"name":"fetch_inbox","arguments":{"project_key":"/data/projects/coding_agent_session_search","agent_name":"YourAgentName","limit":50,"include_bodies":true}}}'
# Acknowledge message id 42
curl -sS -X POST http://127.0.0.1:8765/mcp -H 'Content-Type: application/json' -d \
'{"jsonrpc":"2.0","id":"ack","method":"tools/call","params":{"name":"call_extended_tool","arguments":{"tool_name":"acknowledge_message","arguments":{"project_key":"/data/projects/coding_agent_session_search","agent_name":"YourAgentName","message_id":42}}}}'
mcp_agent_mail defaults to sqlite+aiosqlite:///./storage.sqlite3. That means the server working directory determines which mailbox database you are using. To avoid "project not found" confusion, start the server from the same directory your team expects for mailbox state.
Three-pane layout with semantic styling: filter bar with pills, results list with color-coded agents and score tiers, and syntax-highlighted detail preview with tab navigation

Full conversation rendering with markdown formatting, code blocks, headers, and structured content

Built-in help screen (press F1 or ?) with all shortcuts, filters, modes, and navigation tips

AI coding agents are transforming how we write software. Claude Code, Codex, Cursor, Copilot, Aider, Pi-Agent; each creates a trail of conversations, debugging sessions, and problem-solving attempts. But this wealth of knowledge is scattered and unsearchable:
cass treats your coding agent history as a unified knowledge base. It:
snake_case ("my_var" matches "my" and "var"), hyphenated terms, and code symbols (c++, `f$ claude mcp add coding_agent_session_search \
-- python -m otcore.mcp_server <graph>