A fast, keyboard‑driven terminal UI for exploring your local Claude Code session history.
It reads session logs from ~/.claude/projects/**/<sessionId>.jsonl, presents a sortable conversation list (Time | CWD | First Message), and lets you open a chat to read with search and code‑aware formatting. You can export any conversation to a clean HTML file.
-
Conversation list
- Columns: Time, CWD (home shortened to
~), First Message (first non‑empty User message) - Lazy previews: first message is populated only for rows on screen (keeps startup snappy)
- Global search across all conversations (
/)- Filters the list to conversations with at least one match
- Runs in the background; title shows
[search: '…' searching…]while running - On completion, title shows
[search: '…' — N matches — x to clear]
- Live updates (watch mode):
- The list auto‑refreshes when files in
~/.claude/projectschange - Toggle on/off with
w; title shows[watch:on]/[watch:off] - Preference persists to
~/.config/cc-history/config.json - Title shows
updating…while a refresh is in progress
- The list auto‑refreshes when files in
- Preferences that persist in
~/.config/cc-history/config.json:- Watcher on/off (
watcher) - Sort key/order (
sort_key,sort_desc) - Current CWD filter (
filter_path) - Claude command (
claude_command)
- Watcher on/off (
- Filter by CWD (
f), clear filter/search (x) - Sorting (async, non‑blocking):
- Default sort: newest session first (created desc)
- Cycle sort key (
s): created → path → last‑message → created - Toggle order (
o): asc/desc - Title shows current sort and a “sorting…” indicator while resorting
- Columns: Time, CWD (home shortened to
-
Chat view
- Simple Markdown‑ish rendering, inline code styling
- Code fences preserved; tool invocation/output rendered clearly
- Search with
/(type → Enter), navigate results withn(next) /N(prev) - Current match line highlighted (yellow background + black text)
-
Tool result handling
- Empty tool results omitted (no stray headers)
- Edit tool (name
Edit) parsed specially: shows unified diff betweenold_stringandnew_stringwithdiffcode fence
-
Session info modal
- Press
ito view detailed information about the selected conversation - Shows session ID, project path, file path, creation date, last message date, and message count
- Modal appears as an overlay and can be closed with
Esc
- Press
-
Settings modal
- Press
,(comma) to open settings configuration - Configure Claude command (defaults to "claude")
- Configure quit-after-launch behavior (defaults to "Yes")
- Use ↑/↓ to navigate between fields, type directly to edit
- Press
Enterto save all changes,Escto cancel and restore original values - Settings persist to
~/.config/cc-history/config.json
- Press
-
Session resumption
- Press
rto resume the selected session in Claude Code - Executes the configured Claude command with
--resume <session_id>in the session's project directory - Supports command switches (e.g.,
claude --verbosebecomesclaude --verbose --resume <session_id>) - Behavior after Claude exits depends on "Quit after launch" setting:
- "Yes": Application exits (does not return to browser)
- "No": Returns to cc-history TUI for continued browsing (terminal state fully restored)
- Terminal state is properly restored for the launched session
- Displays informational message showing the command executed and directory used
- Press
-
Export
- Export current conversation to
exports/conversation-<id>.html(e) and open in default browser - Tool results are collapsed in
<details>sections to keep pages readable
- Export current conversation to
Pre-built binaries are available on the Releases page.
Note for macOS users: The macOS builds are currently not notarized. You may need to right-click the binary and select "Open" the first time, or run xattr -d com.apple.quarantine cc-history to remove the quarantine flag.
Requirements:
- Rust (stable) with
cargo - macOS or Linux terminal (TrueColor/TMUX compatible works best)
Build and run:
cd cc-history-rs
cargo build
cargo run
The app will look for Claude session logs under ~/.claude/projects. If none are found you’ll see an empty list.
Using a custom projects directory:
- Run with
--projects-dir <path>to point at a different projects folder. - Example with included demo data:
cargo run -- --projects-dir cc-history-rs/demo_data/projects - Demo data uses
cwdunder/Users/js/...so~abbreviation appears on that system.
List view:
- Up/Down: move selection
- PgUp/PgDn: page
- Home / g: go to top
- End / G: go to bottom
- Enter: open selected conversation
- f: filter to selected CWD
- x: clear filter and search
- /: global search across all conversations (type → Enter to run; Esc cancels input)
- w: toggle file watcher (live updates)
- s: cycle sort key (created → path → last‑message)
- o: toggle sort order (asc/desc)
- i: show session info modal
- , (comma): open settings modal
- r: resume session in Claude Code
- e: export to HTML and open
- q: quit (only when not typing a search)
Chat view:
- Up/Down: scroll one line
- PgUp/PgDn: page scroll
- Home / g: go to top
- End / G: go to bottom
/: start a search (type → Enter to confirm; Esc cancels input)- n / N: next / previous match
- e: export to HTML and open
- Esc / q: back to list (when not typing a search)
- Source:
~/.claude/projects/**/<sessionId>.jsonl ChatReaderprovides:list_conversations()→ id, cwd path (if present), approximate creation timeget_messages_by_id(id)→ flattened sequence of{role, content}messagesearliest_message_time_ms(file),latest_message_time_ms(file)for sorting
- First message preview logic prefers the first non‑empty User message; falls back to first non‑empty of any role.
- List header is aligned to column widths calculated for the current terminal size.
- CWD column is truncated/padded safely and replaces your home directory with
~. - Chat messages are rendered with minimal styling that preserves content and line breaks.
- Tool events:
Edittool shows a unified diff with adiffcode fence- Tool results with no content are omitted
e in list or chat view writes exports/conversation-<id>.html and opens it in your default browser.
- Markdown is rendered to HTML (headings/lists/inline code/quotes/code blocks)
- Tool results are collapsed using
<details><summary>Tool Result (N lines)</summary>…</details> - Uses simple, readable CSS that works in light/dark mode
- Lazy loading of message previews avoids scanning the entire history on startup
- Sorting runs asynchronously; the UI remains responsive and shows a “sorting…” badge in the title while results compute
- Chat search works on a plain‑text mirror of the view to avoid ANSI/style complexity
- “No conversations found”: ensure
~/.claude/projectsexists and contains*.jsonlsession files - Slow resorting on large histories: sorting is done in the background; a temporary “sorting…” indicator will be shown until complete
- Terminal issues (colors/borders): try a 24‑bit color‑capable terminal, or check tmux config for truecolor support
cc-history-rs/
├─ src/
│ ├─ main.rs # TUI, keybindings, search, sorting, export, layout
│ └─ chat_reader.rs # Log discovery, JSONL parsing, message flattening, time helpers
├─ Cargo.toml # Dependencies: ratatui, crossterm, chrono, pulldown-cmark, similar, open, etc.
└─ README.md # This file
- Inline substring highlighting (not just full‑line) for search matches
- Configurable column widths and visible columns
- Persist sort/filter preferences between runs
- Richer syntax highlighting via
syntect(optional feature)
This tool reads your local Claude logs under ~/.claude/projects. No data is sent anywhere. Exported HTML files are written under ./exports/ in your current working directory.
MIT License
