# I had 1,063 Claude Code conversations and couldn't find anything — so I built claude-grep

> Source: <https://dev.to/coolcorexix/i-had-1063-claude-code-conversations-and-couldnt-find-anything-so-i-built-claude-grep-45k2>
> Published: 2026-06-04 14:24:13+00:00

I use Claude Code a *lot*. Enough that when I finally counted, I had **1,063 conversations** sitting in `~/.claude/projects/`

— around 256 MB of JSONL transcripts.

And I could never find the one I needed.

You know the feeling: *"I definitely solved this exact bug a few weeks ago… in some conversation… somewhere."* But Claude Code's built-in `--resume`

picker only matches on a session's **title** (its first prompt). It has no idea what was actually *said* inside. So the conversation where I'd figured out the gnarly thing was, in practice, gone.

So I built ** claude-grep**: live full-text search across your entire Claude Code history, with one keypress to jump back into any conversation.

You type, and results stream in as you go. Each row shows the matched snippet with your phrase highlighted, the conversation's working directory, and when it happened. Hit `Enter`

and it `cd`

s into that project and runs `claude --resume`

on the right session — you're back exactly where you left off.

Under the hood it's deliberately boring and fast:

`--disabled`

+ `change:reload`

trick — fzf re-runs the search on every keystroke instead of fuzzy-filtering what's already on screen.No index to build, nothing running in the background. It just reads the files Claude Code already writes.

When I first wired up "press Enter to resume," a bunch of conversations simply wouldn't open.

It turns out **940 of my 1,063 transcript files were sub-agent sessions** — the side conversations Claude Code spawns to handle sub-tasks. They live here:

```
~/.claude/projects/<project>/<PARENT-UUID>/subagents/agent-*.jsonl
```

…and they are **not resumable** on their own. `claude --resume agent-abc123`

does nothing.

But the path gives it away: the parent session's UUID is *literally the directory name above* `subagents/`

. (It's also stored in the file's `sessionId`

field, alongside `isSidechain: true`

.) So when a match lands inside a sub-agent transcript, claude-grep resolves it to the parent and resumes **that** — using the parent's working directory, so it even survives sub-agents that ran in a since-deleted git worktree.

``` python
def resumable_session(path):
    parent_dir = os.path.dirname(path)
    if os.path.basename(parent_dir) == "subagents":
        # sub-agent transcript → resume the parent session instead
        return os.path.basename(os.path.dirname(parent_dir)), True
    base = os.path.basename(path)
    return (base[:-6] if base.endswith(".jsonl") else base), False
```

Results then get de-duplicated by resumable session, so you never see two rows that open the same conversation.

You'll need `fzf`

, `ripgrep`

, Python 3, and the `claude`

CLI on your `PATH`

.

```
git clone https://github.com/coolcorexix/claude-grep.git
ln -sf "$PWD/claude-grep/ccfind" ~/.local/bin/ccfind   # ~/.local/bin must be on PATH
ccfind
```

It's MIT-licensed and a single Python script — read it, fork it, rip out the parts you like.

👉 [github.com/coolcorexix/claude-grep](https://github.com/coolcorexix/claude-grep)

If you live in Claude Code as much as I do, I'd love to hear what you search for first — and if you hit a transcript shape it chokes on, open an issue. There are a *lot* of edge cases hiding in those JSONL files.
