Topic: how to search chatgpt history
How to Search Your ChatGPT History (the Four Levels)
From sidebar search at chatgpt.com to jq against your full export — four escalating tools, and the moment each one runs out and you should drop down to the next.
TL;DR
Level 1: chatgpt.com sidebar search — fast, lossy, only the last few weeks. Level 2: CMD+F inside chat.html from the export ZIP — every message you've ever sent, but you have to know the keyword. Level 3: jq queries against conversations.json — structured filtering by date, model, role, conversation. Level 4: decision extraction — when you've stopped searching for words and started searching for outcomes.
Why search isn't built-in (well)
OpenAI's product is the chat, not the archive. Sidebar search exists, but it's optimized for "what did we discuss in the last week?", not "give me every time I weighed Postgres against MongoDB across two years." For real retrieval, you have to take the data local and bring your own tools. The good news: the export is complete — every message, every chat, every model. The four levels below escalate from zero-effort to engineering-effort, in that order.
Level 1 — Sidebar search at chatgpt.com
Click the magnifying-glass at the top of the chat list, or type / to focus search. It indexes conversation titles and recent message bodies. Best for: "I had a chat about pricing last week, where is it?" Worst for: anything more than 30 days old or buried in a 200-message thread. Latency is good (<300ms), recall is poor.
If sidebar search returns nothing for a query you're sure you've discussed, that's the signal to drop to level 2. Don't keep refining the query — the index doesn't have it.
Level 2 — CMD+F inside chat.html
The export ZIP includes chat.html, a single HTML page with every conversation rendered inline. Open it in a browser and CMD+F (Ctrl+F on Windows). Pros: zero setup, finds every literal string match across your entire history, jumps you to the conversation in context. Cons: literal-string only (no regex, no fuzzy), and the page can be 50–200 MB so initial load is slow on a low-spec laptop.
Better tool for the same data: ripgrep against chat.html:
rg -i -C 2 'postgres.*mongo' chat.html
Case-insensitive, with two lines of surrounding context. Faster than the browser, and you can use real regex. Most decisions are findable at this level if you know roughly what was said.
Level 3 — jq against conversations.json
When you need structured filtering — by date, by role, by conversation title, by model — drop down to jq. The shape is documented at conversations.json format; the recipes that come up most often:
# every conversation title, sorted by recency
jq -r '.[] | "\(.update_time) \(.title)"' conversations.json | sort -nr
# every user message containing "postgres" (any case)
jq -r '.[] | .mapping | to_entries[]
| select(.value.message.author.role=="user")
| select(.value.message.content.parts[0]|tostring|test("postgres";"i"))
| .value.message.content.parts[0]' conversations.json
# every conversation that used gpt-4o
jq -r '.[] | select(.default_model_slug=="gpt-4o") | .title' conversations.json
# decisions made between two dates (epoch seconds)
jq -r '.[] | select(.create_time > 1735689600 and .create_time < 1738368000) | .title' \
conversations.json
Slow on multi-gigabyte exports — expect 5–30 seconds per query — but precise and composable. Pipe to fzf for interactive narrowing. This is the level where you stop being a chat user and start treating the export as a real dataset.
Level 4 — Decision extraction
Levels 1–3 all answer the same shape of question: "find me text matching X." There's a class of question they can't answer well: "what architecture decisions did I make in Q1?" The answer requires understanding which messages contained a decision, which contained a clarification question, and which contained scratch thinking. No keyword search resolves that — the decision often doesn't contain the word "decision."
This is the level WhyChose's open-source extractor targets. It walks your conversations.json, applies the regex/heuristic patterns documented in patterns.md, and emits a structured decision record per match — chose / rejected / rationale / source-conversation-id. The output is auditable: every record links back to the message it came from. For a quarterly review of "what did we actually decide and why?" extraction is the right tool — search will exhaust you long before you've found everything.
Picking the right level
| Question shape | Right level |
|---|---|
| "That chat from last Tuesday about onboarding…" | Level 1 (sidebar) |
| "Did we ever talk about Pulsar?" | Level 2 (CMD+F or ripgrep on chat.html) |
| "All conversations with gpt-4 from January" | Level 3 (jq) |
| "All architecture decisions I made last quarter, with rationale" | Level 4 (extraction) |
Related questions
Why doesn't ChatGPT's built-in search find things I know I said?
Sidebar search indexes conversation titles and recent message bodies, but coverage thins out for older chats and for messages inside very long threads. It also lags a few hours behind your actual usage. For old chats and long threads, drop down to local search of the export.
Can I grep the export ZIP directly?
You can grep conversations.json, but you'll get raw JSON noise — escaped newlines, the entire mapping object dumped on one line. Use jq instead, or grep chat.html if you just want a quick literal-string match.
What's the smallest dependency for full-text search?
ripgrep against chat.html. ChatGPT's HTML viewer is one big file with all messages inlined, so rg -i 'PATTERN' chat.html gets you fast case-insensitive matches with surrounding context. Takes 30 seconds to set up.
When should I escalate from search to extraction?
When you stop searching for words and start searching for outcomes. "Find every message where I said Postgres" is search; "find every architecture decision I made and why" is extraction. Search returns matches; extraction returns structured records you can audit.
Further reading
- How to export your ChatGPT history — get the ZIP first.
- ChatGPT conversations.json format — the schema that level-3
jqqueries depend on. - How to extract decisions from your ChatGPT chats — the level-4 walkthrough.
- Convert your ChatGPT export to Markdown — once you have
.mdfiles, ripgrep and grep work without a flatten step. - The open-source extractor — runs locally, MIT-licensed.