cass: A Local Index Over Eleven-Plus Coding Agent Session Logs
Unified TUI and CLI to index and search your local coding agent session history across 11+ providers (Codex, Claude, Gemini, Cursor, Aider, etc.)
At a glance
- What is it?
- coding_agent_session_search (cass) is a Rust TUI and CLI that indexes session history from Codex, Claude Code, Gemini CLI, Cursor, Aider and other harnesses into one searchable SQLite-backed store. The design is careful about derived state; the licence is not a standard OSI identifier and the project labels itself alpha, so adoption needs a look at both.
- Who is it for?
- Adopt cass if you already run several coding agents on one machine and want a single local, scriptable index over their session logs. Do not adopt it if you need a stable, non-alpha interface, a standard OSI licence, or a tool that never writes to a shared model cache.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem: session history spread across incompatible harnesses
Every coding agent writes its own transcript format to its own directory. Codex, Claude Code, Gemini CLI, Cline, OpenCode, Amp, Cursor, ChatGPT, Aider, Pi-Agent, Oh My Pi, GitHub Copilot Chat, Copilot CLI, OpenClaw, Clawdbot, Vibe, Crush, Goose, Hermes, Kimi Code, Muse Code, Qwen Code, Factory (Droid), Antigravity, OpenHands and Grok Build are all named in the README as sources. The README's own framing is a single searchable timeline over that pile. The audience is narrow but real: developers who run two or more of these tools on the same machine and have lost the thread of what they asked months ago. The tool is not a replacement for any of them. It is an indexer and a reader, and the README is explicit that SQLite is the source of truth for indexed conversations and messages. The problem it removes is the manual grep across a dozen dot-directories with different JSON shapes, which is the state most multi-agent users are in by default.
How indexing works: SQLite as the only authoritative store
The architecture is stated as a contract rather than described as a pipeline. SQLite holds indexed conversations and messages. Everything else (the lexical index, semantic vectors, analytics rollups, retention backups) is derived and rebuildable from SQLite, and the README says no derived asset is authoritative. That single sentence drives most of the operational behaviour. If a lexical index is missing, stale or incompatible, the documented response is a rebuild from SQLite, not a manual repair procedure. The lexical index is the required fast path for search; semantic vectors are opportunistic background enrichment. Hybrid is the default search intent, and `--robot --robot-meta` reports the requested mode, the realized mode, semantic refinement status, and any lexical fallback reason. During first indexing, semantic catch-up, or when semantic policy is disabled, lexical-only results are documented as expected rather than an error. That is a defensible ordering: a search tool that returns nothing because a 90 MB model has not downloaded yet would be worse than one that returns lexical hits and says so.
Atomic lexical publish and the retention knob
The most concrete engineering detail in the README is how a new lexical generation replaces the old one. On Linux the publish is an atomic renameat2(RENAME_EXCHANGE); elsewhere it is described as a parked-rename with restore-on-failure. Readers see either the old generation or the new one, never a mix. The prior live generation is kept under `<data_dir>/index/.lexical-publish-backups/<dated>/` for a bounded window, default cap 1, meaning one-step rollback. The cap is controlled by the `CASS_LEXICAL_PUBLISH_BACKUP_RETENTION` environment variable, where 0 disables retention and higher values keep deeper history. Pruning runs after each successful publish and emits structured tracing events carrying `freed_bytes` and `retention_limit`. Crash recovery is handled on next startup by a function the README names as `recover_or_finalize_interrupted_lexical_publish_backup`, which moves an orphaned `.<name>.publish-in-progress.bak` sidecar into the backups directory before the next publish. The README points at `src/indexer/mod.rs::publish_staged_lexical_index` for the implementation. This is the part of the project that reads as production-minded rather than prototype-minded.
Running it: install paths and the robot-mode command set
Installation is a curl-piped shell script with `--easy-mode --verify`, a PowerShell equivalent with `-EasyMode -Verify`, or package managers: `brew install dicklesworthstone/tap/cass` and a Scoop bucket on Windows. The README notes the Homebrew tap ships prebuilt release tarballs rather than bottles, and that Intel macOS users should use the install script with `--from-source`. The Rust badge says pinned nightly. The command surface splits into a TUI and a robot mode. The README warns in bold terms never to run bare `cass` in an agent context because it launches the interactive TUI; use `--robot` or `--json`. `cass triage --json` is described as the safest first command, combining readiness, `next_command`, `recommended_commands[]`, docs and schema pointers, starter workflows and accepted recoveries. From zero context, `cass --json` and `cass --robot` also resolve to triage. Search is `cass search "authentication error" --robot --limit 5 --fields minimal`. Session lookup uses `cass sessions --current --json` or `cass sessions --workspace "$(pwd)" --json --limit 5`. Hits are read with `cass view /path/to/session.jsonl -n 42 --json` and `cass expand /path/to/session.jsonl -n 42 -C 3 --json`. `cass capabilities --json`, `cass robot-docs guide` and `cass robot-docs schemas` expose the machine API. Sources can be excluded with `cass sources agents exclude openclaw`. Output conventions are stated plainly: stdout is data, stderr is diagnostics, exit 0 is success.
Semantic search is opt-in and can stay absent indefinitely
Nothing downloads a model unless asked. `cass models install` fetches the default `all-minilm-l6-v2` (alias `minilm`, roughly 90 MB); `--model multilingual-minilm` selects the larger multilingual MiniLM L12 model (roughly 480 MB) for CJK or mixed-language archives. The README states that cass never auto-downloads or auto-selects the multilingual space, and that air-gapped installs use `--from-file <dir>`. While the selected model is absent, hybrid search runs lexical-only and reports `fallback_mode="lexical"` in health and status. That is an honest failure mode rather than a silent one, but it means a user who expects semantic recall will get lexical results with a flag they may never read. The practical consequence: if you never run `cass models install`, cass is a fast lexical indexer with a hybrid label, and the multilingual path is a manual decision you have to make before you need it.
Quarantine, doctor, and the advisory nature of safe_to_gc
Corrupt or failed-validation assets are quarantined, not 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 README is direct that `safe_to_gc` is advisory: it reflects retention policy and 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 each diagnostic, and without `--fix` it is read-only. Two things follow. First, disk usage from quarantined generations is a manual cleanup job, and the default retention cap of 1 keeps that bounded but not zero. Second, `cass selftest --json` verifies a newly installed executable without opening the configured archive, while `health --binary-only` still probes archive readiness, which is a distinction worth knowing before you conclude a bad install from a health failure.
Where it is the wrong tool, and what to compare against
The README labels the project alpha, and the release cadence supports that reading: v0.6.25, v0.6.26 and v0.7.1 landed within roughly four weeks of each other in August 2026. Fast patch releases on a young CLI mean flag and schema churn, and `cass robot-docs schemas` exists precisely because the machine surface moves. If you need a frozen interface for a long-lived integration, this is the wrong moment. The licence is the second boundary. The repository reports NOASSERTION, while the README badge claims MIT plus an OpenAI/Anthropic rider. Those two statements do not match, and a rider attached to an otherwise permissive licence can carry conditions a plain MIT grant does not. Anyone embedding cass in a distributed product should read the LICENSE file itself rather than the badge. For a comparison: ripgrep over the raw session directories needs no index, no SQLite database, no daemon and no model download, and it will never go stale. The difference in approach is that ripgrep matches bytes on disk and returns file paths, while cass normalizes heterogeneous transcripts into conversations and messages in SQLite, then publishes a generation-swapped lexical index and layers optional vector search on top. If your question is "which file contains this string", ripgrep wins on setup cost. If your question is "what did I ask the agent about auth last month, across three different tools", the normalization is the whole product.
Maintenance cost and what to check before adopting
Ongoing cost has three components visible in the material. Rebuilds: derived assets are rebuilt from SQLite by design, so a corrupted lexical generation is a rebuild, not a repair, and the retention cap of 1 means rollback depth is one step unless you raise `CASS_LEXICAL_PUBLISH_BACKUP_RETENTION`. Disk: quarantined artifacts accumulate and are never auto-deleted, so `cass diag --json --quarantine` is the surface to inspect when the data directory grows. Model management: `cass models install` is a manual step, and the multilingual model is a separate manual selection at roughly 480 MB. Upgrade cost tracks the alpha cadence; pinning via `--version <tag>` on the install script or `-Version <tag>` on PowerShell is the documented way to avoid surprise flag changes. On licence, the mismatch between the NOASSERTION metadata and the MIT-plus-rider badge is the item to resolve before any redistribution, and that is a question for your own legal review, not something the README settles.
Editorial conclusion
Adopt cass if you already run several coding agents on one machine and want a single local, scriptable index over their session logs. Do not adopt it if you need a stable, non-alpha interface, a standard OSI licence, or a tool that never writes to a shared model cache. Verify first: run `cass selftest --json`, then `cass triage --json` to see readiness and next_command, and read the LICENSE file rather than the badge, because the repository is marked NOASSERTION while the README claims MIT plus an OpenAI/Anthropic rider.
Community notes