chat-history
Search, inspect, and export Claude Code, Cursor, and Codex conversation history. The short alias ch works identically. If the command is not found: cargo install chat-history.
When to use
- User asks about past conversations or sessions
- User wants to find something they discussed before
- User needs a summary of recent work / accomplishments
- User wants to resume or export a previous session
Process
Keyword question ("find that conversation where I..."):
chat-history search "<query>" --deep --json — always --deep --json from agents. BM25 searches metadata and transcripts together by default (--deep is a no-op for that engine); --deep still forces transcript search if the legacy engine is selected; --json returns structured results (session_id, score, snippet, tools, files, additional_matches). Note --json exists only on search.
- Shortlist by snippet, not by raw score (see "Choosing the best hit").
chat-history inspect <partial-uuid> on the top 2–3 candidates to confirm before answering.
view / export only if the user needs the actual content.
Temporal question ("what did I work on yesterday?") — list, don't search:
chat-history --from yesterday --to yesterday — every row shows a short session ID; -s groups by day for multi-day overviews.
--from X alone means X through today. Always pair with --to when the user means a specific day.
- Short IDs work everywhere a session ID is accepted (
inspect, view, export, find); -v adds full IDs and file paths. resume works for claude / codex rows and for Cursor Agent CLI chats; Cursor rows whose id has no ~/.cursor/chats store (whatever their tag) print the title and DIR: — tell the user to open that folder in Cursor and pick the chat in the sidebar.
chat-history inspect <id> for accomplishments, tools, files touched.
Choosing the best hit
- Scores rank lexical relevance (BM25 by default), not intent. They are not confidence values or comparable across queries or engines. Use scores only to shortlist; decide from snippets and
inspect.
- BM25 groups matches by conversation:
--limit counts conversations, snippet follows the strongest matching passage, and additional_matches contains up to two more excerpts. Read these before inspecting the session. Use --group-by message if individual matching messages are needed; legacy and --scope similar retain their previous message-row default.
- The conversation you are currently in can match its own query and score highest. Ignore hits whose session is the current one.
- When candidates are close,
inspect each before picking — don't answer from the top score alone.
Common mistakes
- Only
search accepts --json; the session list and inspect reject it.
- The subcommands are
search, inspect, view, export, resume, find, install-skill, completions, and the optional cursor-hook receiver. Do not guess others; run chat-history --help when unsure. cursor-hook is for configured Cursor hooks, not normal history queries.
- Cursor CLI rows labeled
[metadata only] support find, resume, and title search when Cursor recorded a title (print-mode chats usually have none); their internal store.db cannot be viewed or exported as a transcript. Do not claim that metadata-only search covers message content.
- Cursor message timestamps may be unavailable.
search --timeframe excludes unknown message times and untimed first-prompt previews. Titles use session activity times. With --engine legacy, add --deep to bypass its metadata shortcut; use session --from / --to filters for activity-date questions. File modification times are not message timestamps.
- A stderr line starting
Note: about the cache directory not being writable means the sandbox blocked ~/.chat-history; results are still complete and later searches stay fast. Mention it only if the user asks why; the README section "Running inside agent sandboxes" has the one-line setting per tool.
- Don't dump raw JSON or full transcripts at the user — summarize, cite the session ID and date (or title + directory for
cursor-ide).
cursor-ide rows (and --json items with "also_ide": true) resume only when the Agent CLI has a ~/.cursor/chats store for the id; otherwise resume prints a sidebar hint instead of launching the Agent CLI. Run resume and follow its output rather than assuming.
- Some Cursor sessions have thin metadata (
(no summary), duration: 0min, raw first-message titles). If inspect is thin, fall back to chat-history view <id> --plain.
Commands
# List sessions
chat-history # newest first; short IDs on every row (-v for full IDs + paths)
chat-history --from yesterday --to yesterday -s # a specific day, grouped
chat-history --from "3 days ago" # natural-language dates
chat-history --source claude # claude | cursor | cursor-agent | cursor-ide | codex
chat-history -L # current workspace only
chat-history --branch feature-xyz -k "auth" -v # branch / keyword filters
# Search (always --deep --json from agents)
chat-history search "auth error" --deep --json
chat-history search "fix" --scope errors --deep --json # only messages with error patterns
chat-history search <full-uuid> # direct session lookup (with --timeframe: only if active in the window)
chat-history search "q" --deep --json --limit 30 # default limit is 15
chat-history search "auth error" --engine legacy --deep --json # compare previous ranking
# Inspect / View / Export / Resume / Find
chat-history inspect --last # accomplishments, tools, model, tokens, files
chat-history inspect <partial-uuid>
chat-history view <id> --plain # transcript, pipe-friendly (--tools for tool names)
chat-history export <id> -o session.md
chat-history resume <id> # Claude Code, Codex, or any Cursor chat with a CLI store
chat-history find <id> # print transcript file path for scripting
chat-history completions zsh # shell completions (bash/zsh/fish/elvish/powershell)
--scope values: all (default), errors (messages with error patterns or the word "error"), similar (user messages only — similar past queries), tools (messages with tool calls), files (messages referencing files). Any scope other than all always searches full transcripts.
- Shared filters on every subcommand:
--from/--to, --source, --project, --branch, -k, --sidechains (include hidden subagent sessions).
Interpreting output
- Display tags:
claude = Claude Code, cursor-ide = Cursor IDE sidebar (SQLite; IDE Agent also writes jsonl with the same id — still listed once as cursor-ide), cursor-agent = Agent CLI / jsonl-only, codex = Codex; ★ N.N = relevance score. --source cursor / cursor-agent = Agent transcripts plus CLI chat metadata and hook-registered paths; --source cursor-ide = SQLite.
- Header line has
DIR: (spawn directory) and, for legacy metadata search, INDEX_FIELD: (summary / first_prompt / branch). Title is on the next line. Pass the short ID to find for any row and to inspect / view / export for rows with a transcript ([metadata only] rows refuse those three), and to resume for claude / codex rows and any Cursor row whose id has a ~/.cursor/chats store. Cursor rows without one are found in the sidebar by title + DIR:.
COPIES: N means the same Cursor Agent session id exists in more than one project folder; inspect/resume/find pick one copy (cwd match, else newest) and print the others.
- Accepted dates:
YYYY-MM-DD, today, yesterday, "3 days ago", "last week", "last month".
1---2name: chat-history3description: Search, inspect, and export Claude Code, Cursor, and Codex conversation history. Use when the user asks about past conversations, wants to find a previous session, needs to search chat history, wants a summary of what they worked on, or asks to resume a session. Also use when the user says "what did I work on", "find that conversation where I...", "show me my recent sessions", or "search my history for...".4---56# chat-history78Search, inspect, and export Claude Code, Cursor, and Codex conversation history. The short alias `ch` works identically. If the command is not found: `cargo install chat-history`.910## When to use1112- User asks about past conversations or sessions13- User wants to find something they discussed before14- User needs a summary of recent work / accomplishments15- User wants to resume or export a previous session1617## Process1819**Keyword question** ("find that conversation where I..."):20211. `chat-history search "<query>" --deep --json` — always `--deep --json` from agents. BM25 searches metadata and transcripts together by default (`--deep` is a no-op for that engine); `--deep` still forces transcript search if the legacy engine is selected; `--json` returns structured results (`session_id`, `score`, `snippet`, `tools`, `files`, `additional_matches`). Note `--json` exists only on `search`.222. Shortlist by snippet, not by raw score (see "Choosing the best hit").233. `chat-history inspect <partial-uuid>` on the top 2–3 candidates to confirm before answering.244. `view` / `export` only if the user needs the actual content.2526**Temporal question** ("what did I work on yesterday?") — list, don't search:27281. `chat-history --from yesterday --to yesterday` — every row shows a short session ID; `-s` groups by day for multi-day overviews.29 - `--from X` alone means **X through today**. Always pair with `--to` when the user means a specific day.30 - Short IDs work everywhere a session ID is accepted (`inspect`, `view`, `export`, `find`); `-v` adds full IDs and file paths. `resume` works for `claude` / `codex` rows and for Cursor Agent CLI chats; Cursor rows whose id has no `~/.cursor/chats` store (whatever their tag) print the **title** and `DIR:` — tell the user to open that folder in Cursor and pick the chat in the sidebar.312. `chat-history inspect <id>` for accomplishments, tools, files touched.3233## Choosing the best hit3435- Scores rank lexical relevance (BM25 by default), not intent. They are not confidence values or comparable across queries or engines. Use scores only to shortlist; decide from snippets and `inspect`.36- BM25 groups matches by conversation: `--limit` counts conversations, `snippet` follows the strongest matching passage, and `additional_matches` contains up to two more excerpts. Read these before inspecting the session. Use `--group-by message` if individual matching messages are needed; legacy and `--scope similar` retain their previous message-row default.37- The conversation you are currently in can match its own query and score highest. Ignore hits whose session is the current one.38- When candidates are close, `inspect` each before picking — don't answer from the top score alone.3940## Common mistakes4142- Only `search` accepts `--json`; the session list and `inspect` reject it.43- The subcommands are `search`, `inspect`, `view`, `export`, `resume`, `find`, `install-skill`, `completions`, and the optional `cursor-hook` receiver. Do not guess others; run `chat-history --help` when unsure. `cursor-hook` is for configured Cursor hooks, not normal history queries.44- Cursor CLI rows labeled `[metadata only]` support `find`, `resume`, and title search when Cursor recorded a title (print-mode chats usually have none); their internal `store.db` cannot be viewed or exported as a transcript. Do not claim that metadata-only search covers message content.45- Cursor message timestamps may be unavailable. `search --timeframe` excludes unknown message times and untimed first-prompt previews. Titles use session activity times. With `--engine legacy`, add `--deep` to bypass its metadata shortcut; use session `--from` / `--to` filters for activity-date questions. File modification times are not message timestamps.46- A stderr line starting `Note:` about the cache directory not being writable means the sandbox blocked `~/.chat-history`; results are still complete and later searches stay fast. Mention it only if the user asks why; the README section "Running inside agent sandboxes" has the one-line setting per tool.47- Don't dump raw JSON or full transcripts at the user — summarize, cite the session ID and date (or title + directory for `cursor-ide`).48- `cursor-ide` rows (and `--json` items with `"also_ide": true`) resume only when the Agent CLI has a `~/.cursor/chats` store for the id; otherwise `resume` prints a sidebar hint instead of launching the Agent CLI. Run `resume` and follow its output rather than assuming.49- Some Cursor sessions have thin metadata (`(no summary)`, `duration: 0min`, raw first-message titles). If `inspect` is thin, fall back to `chat-history view <id> --plain`.5051## Commands5253```bash54# List sessions55chat-history # newest first; short IDs on every row (-v for full IDs + paths)56chat-history --from yesterday --to yesterday -s # a specific day, grouped57chat-history --from "3 days ago" # natural-language dates58chat-history --source claude # claude | cursor | cursor-agent | cursor-ide | codex59chat-history -L # current workspace only60chat-history --branch feature-xyz -k "auth" -v # branch / keyword filters6162# Search (always --deep --json from agents)63chat-history search "auth error" --deep --json64chat-history search "fix" --scope errors --deep --json # only messages with error patterns65chat-history search <full-uuid> # direct session lookup (with --timeframe: only if active in the window)66chat-history search "q" --deep --json --limit 30 # default limit is 1567chat-history search "auth error" --engine legacy --deep --json # compare previous ranking6869# Inspect / View / Export / Resume / Find70chat-history inspect --last # accomplishments, tools, model, tokens, files71chat-history inspect <partial-uuid>72chat-history view <id> --plain # transcript, pipe-friendly (--tools for tool names)73chat-history export <id> -o session.md74chat-history resume <id> # Claude Code, Codex, or any Cursor chat with a CLI store75chat-history find <id> # print transcript file path for scripting76chat-history completions zsh # shell completions (bash/zsh/fish/elvish/powershell)77```7879- `--scope` values: `all` (default), `errors` (messages with error patterns or the word "error"), `similar` (user messages only — similar past queries), `tools` (messages with tool calls), `files` (messages referencing files). Any scope other than `all` always searches full transcripts.80- Shared filters on every subcommand: `--from`/`--to`, `--source`, `--project`, `--branch`, `-k`, `--sidechains` (include hidden subagent sessions).8182## Interpreting output8384- Display tags: `claude` = Claude Code, `cursor-ide` = Cursor IDE sidebar (SQLite; IDE Agent also writes jsonl with the same id — still listed once as `cursor-ide`), `cursor-agent` = Agent CLI / jsonl-only, `codex` = Codex; `★ N.N` = relevance score. `--source cursor` / `cursor-agent` = Agent transcripts plus CLI chat metadata and hook-registered paths; `--source cursor-ide` = SQLite.85- Header line has `DIR:` (spawn directory) and, for legacy metadata search, `INDEX_FIELD:` (`summary` / `first_prompt` / `branch`). Title is on the next line. Pass the short ID to `find` for any row and to `inspect` / `view` / `export` for rows with a transcript (`[metadata only]` rows refuse those three), and to `resume` for `claude` / `codex` rows and any Cursor row whose id has a `~/.cursor/chats` store. Cursor rows without one are found in the sidebar by title + `DIR:`.86- `COPIES: N` means the same Cursor Agent session id exists in more than one project folder; `inspect`/`resume`/`find` pick one copy (cwd match, else newest) and print the others.87- Accepted dates: `YYYY-MM-DD`, `today`, `yesterday`, `"3 days ago"`, `"last week"`, `"last month"`.