to wit: to make clearer or more particular something that you have already said
To Wit is a searchable catalog of your Claude Code conversations, organized by topic.
Claude Code conversations are analyzed, filtered for substance, and stored in a local SQLite database. A CLI lets you search, list, and export conversations. A stop hook keeps the catalog up to date automatically after each session.
towit search hook
/Users/chrisbloom7
ID Title Keywords Date
------------------------------------ --------------------------- ------------ ----------
350fa22f-10b7-48ff-ac9d-bd9f1081c23b Debugging non-firing Stop … stop-hook 2026-03-31
towit resume 350fa22f-10b7-48ff-ac9d-bd9f1081c23b
# => switch to `/Users/chrisbloom7` and call `claude --resume 350fa22f-10b7-48ff-ac9d-bd9f1081c23b`- Claude Code (
brew install claude-code) - Python 3.11+ (
brew install python)
Homebrew tap coming soon. For now, clone and run the install script.
git clone https://github.com/chrisbloom7/to-wit.git ~/path/to/to-wit
~/path/to/to-wit/installBy default, install links into /usr/local/bin. Pass a different directory as the first argument if needed:
~/path/to/to-wit/install ~/.local/bin# Full setup: generate config, initialize database, install stop hook, and index existing conversations
towit setup --full
# Or step by step:
towit setup --config # Generate ~/.towit/config.toml (optional but recommended)
towit setup # Initialize the database
towit install-hook # Add stop hook to Claude Code (auto-indexes future sessions)
towit backfill # Index all existing conversations (~4 sec/session on Apple M4 Pro)towit <subcommand> [options]
Subcommands:
setup [--full | --hook | --config] Initialize database
--full also generates config, installs hook, and runs backfill
--hook also installs the stop hook
--config generate ~/.towit/config.toml (skips if already exists)
search <terms...> Search conversations by keyword (default), topic, summary, or title
[--or] Match any term instead of all (default: AND)
[--topic] Also search conversation topics
[--all] Search keywords, topics, summaries, and titles
[--summary] Also search conversation summaries
[--title] Also search conversation titles
[--format json|csv] Output format (default: table)
[--folder <path>] Scope to a working directory
list List all indexed conversations
[--format json|csv] Output format (default: table)
[--folder <path>] Scope to a working directory
[--topic <name>] Filter by topic
[--keyword <name>] Filter by keyword
resume <session-id> Resume a session in its original working directory
[--force] Recreate the working directory if it no longer exists
prune [--dry-run] Remove entries whose transcripts no longer exist
export <session-id> Export a conversation
[--format md|json] Output format: md (default) or json
[--summarize] AI summary instead of full transcript
export --topic <name> Export all conversations matching a topic
[--format md|json] Output format: md (default) or json
[--summarize] Meta-summary of all matching conversations
backfill Index all existing conversations
[--dry-run] Preview without writing
[--force] Re-index already indexed conversations
[--folder <path>] Scope to one project folder
install-hook Add To Wit stop hook to Claude Code settings
uninstall-hook Remove To Wit stop hook from Claude Code settings
teardown [--yes] Remove hook and delete database
implode [--yes] Full uninstall: remove hook, database, and binary symlink
[--install-dir <dir>] Directory where towit was installed (default: /usr/local/bin)
stats Show catalog statistics
doctor Verify setup: config, database, and hook
help Show this message
Indexing: Each conversation is parsed from Claude Code's JSONL transcript files (~/.claude/projects/). Short or purely operational sessions are filtered out. Substantive conversations are analyzed by Claude, which extracts a title, summary, 15–30 specific keywords (identifiers, method names, error messages, domain terms, filenames, etc.), and broad topic tags. Results are stored in ~/.towit/catalog.db (SQLite, WAL mode).
What gets indexed: Deep explorations, research, TIL moments, technical discoveries, documentation writing, theoretical discussions, estimation with depth. Quick one-shots, command execution sessions, and subagent traces are skipped.
Auto-indexing: The stop hook (towit install-hook) fires after each Claude Code response and indexes the conversation in the background.
To Wit is configured via ~/.towit/config.toml. Generate a starter file with all settings commented out:
towit setup --configThese settings control how To Wit calls the Claude API during indexing and directly affect API spend.
| Key | Default | Description |
|---|---|---|
model |
"haiku" |
Model passed to claude -p. Use "default" to inherit your Claude Code default, or any alias ("sonnet", "opus") or full model ID ("claude-sonnet-4-6"). |
reindex_delta |
2 |
Exchanges (user+assistant pairs) that must occur before a resumed session is re-analyzed. The stop hook fires after every response; this prevents re-indexing on every turn. Set to 1 for original behavior. |
min_topics |
1 |
Minimum topic tags Claude should assign per conversation. |
max_topics |
5 |
Maximum topic tags Claude should assign per conversation. |
min_keywords |
15 |
Minimum keywords Claude should extract per conversation. |
max_keywords |
30 |
Maximum keywords Claude should extract per conversation. |
min_summary_sentences |
3 |
Minimum sentences in the generated summary. |
max_summary_sentences |
6 |
Maximum sentences in the generated summary. |
transcript_max_chars |
8000 |
Character cap on the transcript excerpt sent to Claude. When the transcript exceeds this limit, the middle is dropped and replaced with an omission marker; the budget is split 30% from the start and 70% from the end. |
Example:
[indexing]
model = "haiku"
reindex_delta = 2
min_topics = 1
max_topics = 5
min_keywords = 10
max_keywords = 20
min_summary_sentences = 2
max_summary_sentences = 4
transcript_max_chars = 8000Each indexing call sends roughly 2,000–4,000 input tokens depending on transcript length and content (code-heavy conversations tokenize more densely than prose) plus prompt overhead of ~200 tokens. Output is roughly 300 tokens (title + summary + keywords + topics JSON). The estimates below use a mid-range of ~2,200 input / 300 output tokens.
The stop hook fires after every Claude response. With reindex_delta = 2 (default), a 10-exchange conversation triggers ~5 indexing calls instead of 10.
Estimated cost — 100 conversations, 10 exchanges each:
| Model | reindex_delta = 1 (1,000 calls) |
reindex_delta = 2 (~500 calls) |
|---|---|---|
| Haiku 4.5 | ~$2.96 | ~$1.48 |
| Sonnet 4.6 | ~$11.10 | ~$5.55 |
| Opus 4.6 | ~$55.50 | ~$27.75 |
Pricing based on Anthropic's published rates as of April 2026: Haiku 4.5 at $0.80/$4.00 per million input/output tokens; Sonnet 4.6 at $3.00/$15.00; Opus 4.6 at $15.00/$75.00. Actual costs will vary.
To do a full uninstall in one step — removes the stop hook, database, and binary symlink:
towit implodeOr to remove just the hook and database while leaving the binary in place:
towit teardownThen remove the binary manually (or brew uninstall towit when available).
git clone https://github.com/chrisbloom7/to-wit.git
cd to-wit
# Run tests (requires bats-core: brew install bats-core)
./run-tests
# Run a specific test file
./run-tests tests/bin/towit.bats
./run-tests tests/helpers/towit_db_test.py
./run-tests --filter "search"MIT — see LICENSE.