agentleFS
BryceEWatsonBryceEWatson/claude-global-skills/chat-history-search/SKILL.md

chat-history-search

Skill0 starsChanged 45 days agoMITView on GitHub

Exhaustive search across ALL of Bryce's local Claude chat history, both Cowork and the Claude Code CLI, to find past prompts, recover a conversation, inventory how often a pattern was used, or audit prior work across projects. Knows every log location, every JSONL line shape, and the false-positive gotchas that trip up naive grep.

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use the outputs version's verbatim text

    line 155
  2. Distinctive:

    Use the audit version only when no outputs file exists (older sessions, pre ~April 2026 in observed history)

    line 156
  3. Very specific:

    TodoWrite item content misread as user prompts: When Claude writes a todo list during /loop execution, items like "Final adversarial …

    line 183
  4. Distinctive:

    When reporting findings to the user, group by corpus and present chronologically:

    line 201

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Chat History Search

Exhaustive search across the two separate corpora of local Claude chat history.

Why this skill exists

The first time I tried this, I missed the entire Cowork corpus (1,674 JSONL files at %AppData%\Claude\local-agent-mode-sessions\) because I only searched ~/.claude/projects/. The user had to point me at their blog post documenting both locations. I also produced false positives by reporting TodoWrite items, <task-notification> wrappers, and document content read via tool_results as if they were Bryce's typed prompts. This skill encodes the full corpus map plus the verification rules that catch those false positives — so the next search is right the first time.

When this skill triggers

User intent that maps here:

  • "find all uses of X in my chat history" / "every time I asked Claude to Y"
  • "when did I last Z" / "inventory my prompts about W"
  • "recover that conversation where we talked about V"
  • "audit my sessions for U"
  • "search my local logs for T"

Storage map — search ALL of these

Corpus 1: Claude Code CLI / VS Code (~/.claude/projects/)

%USERPROFILE%\.claude\projects\<encoded-cwd>\<sessionId>.jsonl
%USERPROFILE%\.claude\projects\<encoded-cwd>\<sessionId>\subagents\agent-*.jsonl

<encoded-cwd> is the working dir path with : and / replaced by -, lowercased (e.g. c--Users-Bryce-Projects-brycewatson-com). One project = one directory; one session = one JSONL file. Subagent transcripts live in a sibling directory matching the parent session UUID.

Corpus 2: Cowork / Claude Desktop local-agent-mode (%AppData%\Claude\...)

Two top-level names — the rename is in progress, both may coexist:

%AppData%\Claude\local-agent-mode-sessions\     ← current
%AppData%\Claude\claude-code-sessions\          ← migration target (often empty)

Under each:

<org-uuid>/<user-uuid>/<sessionId>/
├── agent/local_ditto_<sessionId>/audit.jsonl              ← top-level audit log (rare)
├── local_<cwdUuid>/
│   ├── audit.jsonl                                        ← per-cwd audit log (PRIMARY user-prompt source)
│   ├── .claude/projects/
│   │   ├── -sessions-<processName>/<cliSessionId>.jsonl   ← CLI subprocess session
│   │   └── <encoded-output-path>/<sessionId>.jsonl        ← outputs session (with queue-operation events)
│   │       └── subagents/agent-*.jsonl                    ← subagent transcripts
│   └── outputs/                                           ← (sometimes)

There is ONE <sessionId> directory currently per user — all Cowork sessions live under it.

What lives where — quick reference

Looking forBest file to grepWhy
Bryce's typed prompts (CLI)~/.claude/projects/<slug>/*.jsonlDirect
Bryce's typed prompts (Cowork)Cowork outputs/.../*.jsonl then audit.jsonlOutputs has enqueue events with verbatim typed text; audit has same prompts deduped by event type
Subagent task descriptionssubagents/agent-*.jsonl OR <task-notification> blocks inside parentThese are NOT Bryce's prompts
Tool / system eventsCLI subprocess files (-sessions-<processName>/)Mostly tool_results when called from Cowork
Session cost / durationaudit.jsonl lines with total_cost_usd or type:"result"Per-session totals
Skill / hook activityFilter by attributionSkill fieldTags loop/review-loop/etc invocations

JSONL line shapes — what to parse, what to skip

User-message shapes (the GOAL — keep these)

CLI / Cowork CLI-subprocess sessions — content is usually an ARRAY of blocks:

{"type":"user","message":{"role":"user","content":[{"type":"text","text":"<typed prompt>"}]},"timestamp":"..."}

Cowork audit.jsonl — content is usually a STRING:

{"type":"user","session_id":"...","message":{"role":"user","content":"<typed prompt>"},"_audit_timestamp":"..."}

Cowork outputs enqueue events — content is a STRING at top level:

{"type":"queue-operation","operation":"enqueue","timestamp":"...","content":"<typed prompt>"}

Look-alikes you must REJECT (false-positive sources)

These all serialize as "type":"user" or contain the search term but are NOT Bryce typing:

PatternHow to detectWhy it's not a user prompt
tool_resultContent array contains {"tool_use_id":"...","type":"tool_result","content":"..."}This is a tool execution result, not typed input
<task-notification> wrapperContent text starts with <task-notification>\n<task-id>...This is a subagent completion notification — the embedded task description is what THE ASSISTANT told the subagent to do, not what Bryce typed
TodoWrite tool inputmessage.content contains {"type":"tool_use","name":"TodoWrite","input":{"todos":[...]}}These are todo items the assistant wrote — common to find search-term hits inside content/activeForm strings
attachment events"type":"attachment" at top level (todo_reminder, ide_selection, file_contents)System-injected context, not typed input
system events"type":"system"Init events, system prompts
Document content via Read toolThe hit is inside a tool_result string that contains file body textThe user's project has docs that mention the term
isSidechain: trueTop-level fieldBackground operations, not main conversation
isApiErrorMessage: trueTop-level fieldAPI errors, not conversation
Subagent task descriptionsWhole file is under subagents/agent-*.jsonlFirst line is the assistant's instruction to the subagent, subsequent are the subagent's own turns

Search strategy — the order that works

Step 1 — enumerate, don't assume

# All CLI jsonl files
ls ~/.claude/projects/*/*.jsonl

# All Cowork jsonl files (use find — directory is deep)
find "$APPDATA/Claude/"local-agent-mode-sessions/ -name "*.jsonl"

# Also check the rename target (usually empty during migration but verify)
find "$APPDATA/Claude/"claude-code-sessions/ -name "*.jsonl"

Count files containing the search term BEFORE deciding scope:

find <base> -name "*.jsonl" | xargs grep -l "<term>" 2>/dev/null | wc -l

Step 2 — categorize Cowork hits before reading

Cowork files split into 4 buckets — search priority differs:

# Build file list once
find "$APPDATA/Claude/"local-agent-mode-sessions/ -name "*.jsonl" > /tmp/all.txt
grep -l "<term>" $(cat /tmp/all.txt) > /tmp/hits.txt

# Categorize
grep "audit[0-9]*\.jsonl$"        /tmp/hits.txt > /tmp/audit.txt     # PRIMARY user-prompt source
grep "/-sessions-"                 /tmp/hits.txt > /tmp/cli_sub.txt   # mostly tool_results (low value for prompts)
grep "/subagents/agent-"           /tmp/hits.txt > /tmp/subagent.txt  # subagent transcripts (skip for user-prompt search)
grep -v "audit\|/-sessions-\|/subagents/" /tmp/hits.txt > /tmp/output.txt  # outputs/*.jsonl — CLEANEST verbatim

For finding Bryce's typed prompts: scan output.txt first (cleanest), audit.txt second (covers older sessions before output logs existed), skip subagent.txt entirely, skip cli_sub.txt unless you specifically want tool-call patterns.

Step 3 — parallel agent dispatch

For scopes over ~30 files, dispatch parallel Explore agents (NOT general-purpose) with each agent's file list pre-staged as a temp file. Explicitly tell each agent:

  1. The exact files they own (path to a manifest text file)
  2. The line shape they'll see (CLI array vs audit string vs enqueue string)
  3. The false-positive checklist above
  4. To return: file basename, timestamp, verbatim excerpt ≤300 chars, 1-line label
  5. To order results by timestamp

Step 4 — DEDUPE across audit + outputs

The Cowork audit log fires 2–3 events per typed prompt (queue + dispatch + run), so audit counts over-count by ~2-3x. The outputs file's enqueue event is the canonical "what Bryce typed" record. When both report the same prompt:

  • Use the outputs version's verbatim text
  • Use the audit version only when no outputs file exists (older sessions, pre ~April 2026 in observed history)

Step 5 — VERIFY before reporting

Spot-check agent reports against raw grep before trusting them. The two most common agent failures:

  1. Reporting <task-notification> content as user prompts (subagent task descriptions, not typed input)
  2. Reporting TodoWrite item strings as user prompts (assistant-generated)

Quick verifier — extract only direct typed prompts from a single file:

grep -n "<term>" <file> | \
  grep '"type":"user"' | \
  grep -v 'tool_result\|tool_use_id\|task-notification\|TodoWrite' | \
  grep -oE '"(text|content)":"[^"]{0,250}'

Note: if a file uses content-as-array (CLI shape), the verifier needs "text":"..." not "content":"...". If audit shape (string), use "content":"...". Try both.

Issues encountered — explicit gotchas to avoid

These cost me time in the original search; calling them out so future-me skips the wrong turns:

  1. Missing the Cowork corpus entirely. First search only hit ~/.claude/projects/ because I treated that as the only log location. Reality: Cowork writes a completely separate, ~10x larger corpus to AppData. ALWAYS scan both.
  2. <task-notification> blocks misread as user prompts. Cowork wraps subagent-completion notifications inside type:user messages. The embedded task description was what the assistant told the subagent, not what Bryce typed. Five "Run adversarial visual QA with subagents" hits in one file turned out to be a single typed prompt plus four subagent task descriptions.
  3. TodoWrite item content misread as user prompts. When Claude writes a todo list during /loop execution, items like "Final adversarial validation + lint/test/build + push" appear inside type:user events (as tool_result confirmations). Strict tool_use-id filtering catches them.
  4. CLI session files use content-as-array, audit uses content-as-string. grep '"content":"<term>"' misses CLI matches because the user text lives inside "content":[{"type":"text","text":"<term>..."}]. Use a regex that handles both shapes, or run the grep against unpacked text.
  5. Audit duplicates inflate counts. A single typed prompt produces 2–3 audit events (often visible as near-identical timestamps within 100ms). De-dupe by (session_id, message.content, ±1s) or just prefer the outputs file's enqueue event.
  6. Cowork CLI-subprocess sessions are mostly tool_results. The .claude/projects/-sessions-<processName>/<id>.jsonl files contain Cowork→Claude-Code subprocess transcripts. The type:user entries there are almost entirely tool_results being passed back to the assistant — not Bryce typing. A search across 54 such files returned ZERO genuine user prompts in one verified pass.
  7. The 117 subagents/agent-*.jsonl files have no user prompts. First line is the assistant's task description to the subagent; subsequent lines are the subagent's own turns. Skip entirely when searching for Bryce's prompts.
  8. subagents/ lives inside the parent CLI session directory (NOT as a sibling). Path: <encoded-cwd>/<sessionId>/subagents/agent-*.jsonl.
  9. The directory rename is in progress — local-agent-mode-sessions → claude-code-sessions. Check both. As of 2026-05-20 the rename target exists but is empty; all data is still under the old name.
  10. Project names with -validation, -worktree-<adjective>-<noun>-<hash> suffixes are separate session corpora (validation runs, worktree sessions). Include them when sweeping a project's history — they may have unique sessions not in the main project directory.

Output format

When reporting findings to the user, group by corpus and present chronologically:

## Claude Code CLI (~/.claude/projects/)
1. <project>/<session>.jsonl  YYYY-MM-DD  "<verbatim excerpt>"   <use-case label>
2. ...

## Cowork (%AppData%\Claude\local-agent-mode-sessions\)
1. local_<uuid>/.../outputs/<id>.jsonl  YYYY-MM-DD  "<verbatim excerpt>"   <use-case label>
2. ...

## Coverage notes
- Files scanned: <N> CLI + <N> Cowork = <total>
- False positives excluded: <list of categories>
- Anything not covered: <e.g., subagent transcripts skipped because they don't contain user prompts>

End with a sentence confirming whether the search exhaustively covered all available local history (so the user doesn't have to re-ask).

What this skill does NOT do

  • Pattern mining across sessions (use pattern-retrospective for that; the old transcript-analysis skill was retired 2026-09-06)
  • Cross-session summary or retrospective reports
  • Real-time monitoring
  • Searching cloud-side conversation history at claude.ai (not on disk)
  • Recovering deleted sessions (none of these formats retain deletes)

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.