find-past-conversation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Find a Past Claude Code Conversation

查找过往Claude Code会话

You are helping the user recall a previous Claude Code session. They remember roughly what was discussed, and they want you to find the actual transcript — the session ID, when it happened, a short summary, and (if relevant) what shipped from it.
Claude Code stores every session as a JSON-lines file under
~/.claude/projects/
. This skill tells you how to search those transcripts efficiently without burning context on multi-megabyte log files.
你正在帮助用户回忆之前的Claude Code会话。他们大致记得讨论的内容,希望你找到实际的转录本——会话ID、会话发生时间、简短摘要,以及(如果相关)从中产出的成果。
Claude Code会将会话存储为
~/.claude/projects/
下的JSON行文件。本技能告诉你如何高效搜索这些转录本,无需加载多兆字节的日志文件占用上下文。

When to use this skill

何时使用本技能

Trigger on phrases like:
  • "search your history for [topic]"
  • "find the conversation we had about [topic]"
  • "look through your past sessions for [topic]"
  • "did I ever finish that work on [topic]"
  • "what did we decide about [topic] last week"
  • "remind me what came out of the [topic] session"
Do not use this for searching the current codebase, the current PR's comments, or external systems like Slack/Jira — those have their own skills and tools.
当出现以下短语时触发:
  • "搜索你的历史记录中关于[主题]"
  • "查找我们关于[主题]的对话"
  • "查看你过往会话中关于[主题]的内容"
  • "我有没有完成关于[主题]的工作"
  • "上周我们关于[主题]做出了什么决定"
  • "提醒我那次[主题]会话的结果是什么"
请勿将其用于搜索当前代码库、当前PR的评论或Slack/Jira等外部系统——这些有专门的技能和工具。

How transcripts are organized

转录本的组织方式

~/.claude/projects/
├── -Users-alice-source-acme-api/
│   ├── 06c5c59e-0735-...jsonl          # one session = one file
│   ├── a7e955d8-cf10-...jsonl
│   └── a7e955d8-cf10-.../
│       └── subagents/
│           └── agent-ab42fde6...jsonl  # subagent transcripts
├── -Users-alice-source-acme-worker/
└── ...
Important facts:
  • The project folder is the working directory with
    /
    replaced by
    -
    .
    So a session run in
    /Users/alice/source/acme/api
    lives under
    ~/.claude/projects/-Users-alice-source-acme-api/
    .
  • The session ID is the filename without
    .jsonl
    — e.g.
    a7e955d8-cf10-42ec-a36b-0fe2bcb42d45
    .
  • Each line in the
    .jsonl
    is a single JSON message
    with a
    type
    field (
    user
    ,
    assistant
    ,
    system
    , etc.), a
    timestamp
    , and content. Lines are not pretty-printed and can be tens of KB each.
  • Subagent transcripts live in
    <session-id>/subagents/agent-*.jsonl
    .
    They're noisy and multiply hits without adding much. Skip them by default.
~/.claude/projects/
├── -Users-alice-source-acme-api/
│   ├── 06c5c59e-0735-...jsonl          # one session = one file
│   ├── a7e955d8-cf10-...jsonl
│   └── a7e955d8-cf10-.../
│       └── subagents/
│           └── agent-ab42fde6...jsonl  # subagent transcripts
├── -Users-alice-source-acme-worker/
└── ...
重要信息:
  • 项目文件夹是将工作目录中的
    /
    替换为
    -
    后的路径
    。例如,在
    /Users/alice/source/acme/api
    中运行的会话会存储在
    ~/.claude/projects/-Users-alice-source-acme-api/
    下。
  • 会话ID是不带
    .jsonl
    的文件名
    ——例如
    a7e955d8-cf10-42ec-a36b-0fe2bcb42d45
  • .jsonl
    文件中的每一行是一条单独的JSON消息
    ,包含
    type
    字段(
    user
    assistant
    system
    等)、
    timestamp
    和内容。行未格式化,每行可能达数十KB。
  • 子代理转录本存储在
    <session-id>/subagents/agent-*.jsonl
    。这些文件内容冗余,会增加命中数但价值不大。默认情况下跳过它们。

The search workflow

搜索流程

Step 1 — Pick the right project folder

步骤1 — 选择正确的项目文件夹

If the user is currently working in a repo and the session they remember was in that repo, start there. Compute the project folder from the current working directory:
bash
ENCODED=$(pwd | sed 's|/|-|g')
ls ~/.claude/projects/$ENCODED/*.jsonl 2>/dev/null | wc -l
If the user is fishing across all their work (e.g. "did we ever talk about X anywhere?"), search across every project:
bash
ls -d ~/.claude/projects/*/
When in doubt, ask: "Was that conversation in this repo, or across all your work?" — narrowing the search up front saves time and reduces false positives.
如果用户当前正在某个仓库中工作,且他们记得的会话是在该仓库中进行的,从这里开始。根据当前工作目录计算项目文件夹:
bash
ENCODED=$(pwd | sed 's|/|-|g')
ls ~/.claude/projects/$ENCODED/*.jsonl 2>/dev/null | wc -l
如果用户想要搜索所有工作内容(例如“我们有没有在任何地方讨论过X?”),则搜索所有项目:
bash
ls -d ~/.claude/projects/*/
如有疑问,询问用户:“那次对话是在这个仓库中,还是涉及你所有的工作内容?”——提前缩小搜索范围可以节省时间并减少误判。

Step 2 — Run a targeted ripgrep

步骤2 — 运行定向ripgrep搜索

Use
rg
on the project folder(s). Never
cat
whole
.jsonl
files — they routinely run into the megabytes and contain large model-thinking blocks with cryptographic signatures that blow context.
bash
rg -l -i "<distinctive phrase>" ~/.claude/projects/<project>/*.jsonl
-l
(list-only) is the right first move — you just want the candidate files. Look at content in a second pass once you've narrowed.
Search-string hygiene matters. Common words produce noise:
  • auto-approve
    → hits every CI workflow with
    terraform apply -auto-approve
  • commit
    → hits every git commit message in every session
  • error
    → hits every retried bash command
If the user only has a generic word, ask them for a distinctive phrase before searching: an error string, a function name, a flag, a file path, a UI label, a person's name. One specific phrase beats five generic ones.
Subagent transcripts live one level deeper (
<project>/<session-id>/subagents/agent-*.jsonl
), so a top-level shell glob like
~/.claude/projects/<project>/*.jsonl
skips them automatically — no extra flag needed for the targeted case:
bash
rg -l -i "your phrase" ~/.claude/projects/<project>/*.jsonl
If you instead recurse with ripgrep across everything (e.g. when you don't know the project), exclude the subagent subtree explicitly — otherwise you'll get duplicate hits:
bash
rg -l -i "your phrase" ~/.claude/projects \
   --glob '*.jsonl' --glob '!**/subagents/**'
在项目文件夹上使用
rg
命令。切勿使用
cat
读取整个
.jsonl
文件——这些文件通常达数兆字节,包含大量模型思考块和加密签名,会占用大量上下文。
bash
rg -l -i "<distinctive phrase>" ~/.claude/projects/<project>/*.jsonl
-l
(仅列出文件名)是正确的第一步——你只需要候选文件。缩小范围后再查看内容。
搜索字符串的准确性很重要。常用词会产生大量噪声:
  • auto-approve
    → 会命中所有包含
    terraform apply -auto-approve
    的CI工作流
  • commit
    → 会命中每个会话中的所有git提交消息
  • error
    → 会命中所有重试的bash命令
如果用户只提供了通用词汇,在搜索前请他们提供一个独特的短语:错误字符串、函数名、参数、文件路径、UI标签、人名。一个特定短语胜过五个通用词汇。
子代理转录本存储在更深一级的目录(
<project>/<session-id>/subagents/agent-*.jsonl
),因此顶层shell通配符
~/.claude/projects/<project>/*.jsonl
会自动跳过它们——定向搜索时无需额外参数:
bash
rg -l -i "your phrase" ~/.claude/projects/<project>/*.jsonl
如果你需要递归搜索所有内容(例如不知道项目名称),请明确排除子代理子目录——否则会得到重复命中:
bash
rg -l -i "your phrase" ~/.claude/projects \
   --glob '*.jsonl' --glob '!**/subagents/**'

Step 3 — Triage the candidate list

步骤3 — 筛选候选列表

  • 0 hits → tell the user, ask for a more distinctive phrase. Don't keep guessing at synonyms.
  • 1-3 hits → great, examine each.
  • 4+ hits → ask for a second narrowing term, or sort by recency and look at the most recent first (
    ls -lt
    ).
  • 0个命中结果 → 告知用户,请他们提供更独特的短语。不要继续猜测同义词。
  • 1-3个命中结果 → 很好,逐个检查。
  • 4个及以上命中结果 → 请用户提供第二个筛选词,或按时间排序查看最新的结果(
    ls -lt
    )。

Step 4 — Extract context, JSON-aware

步骤4 — 提取上下文,支持JSON解析

For each candidate file, pull surrounding context with bounded windows. Two patterns work well:
Pattern A — grep with line context (fast, rough):
bash
rg -i -B 2 -A 5 "your phrase" ~/.claude/projects/<project>/<session>.jsonl | head -100
This catches a few hundred lines of raw JSON around each match. Good for a quick visual scan.
Pattern B — JSON-aware extraction (cleaner):
bash
rg -i "your phrase" ~/.claude/projects/<project>/<session>.jsonl | \
  jq -r 'select(.type=="user" or .type=="assistant") |
         "\(.timestamp) [\(.type)] \(.message.content // .content | tostring | .[0:300])"'
This filters to user/assistant turns only and prints the timestamp + first 300 characters. Skip
tool_use
and
tool_result
entries unless they're directly relevant to what the user is searching for — they're voluminous and rarely the answer.
对于每个候选文件,使用有限窗口提取相关上下文。以下两种模式效果良好:
模式A — 带行上下文的grep(快速、粗略):
bash
rg -i -B 2 -A 5 "your phrase" ~/.claude/projects/<project>/<session>.jsonl | head -100
这会捕获匹配内容周围的几百行原始JSON。适合快速视觉扫描。
模式B — 支持JSON解析的提取(更清晰):
bash
rg -i "your phrase" ~/.claude/projects/<project>/<session>.jsonl | \
  jq -r 'select(.type=="user" or .type=="assistant") |
         "\(.timestamp) [\(.type)] \(.message.content // .content | tostring | .[0:300])"'
这会过滤出用户/助手的对话内容,并打印时间戳+前300个字符。除非与用户搜索的内容直接相关,否则跳过
tool_use
tool_result
条目——这些条目内容冗长,很少是答案。

Step 5 — Report the find

步骤5 — 报告搜索结果

For each strong candidate, surface:
  • Session ID (the filename without
    .jsonl
    )
  • Project folder (
    ~/.claude/projects/<encoded>
    )
  • Date / time (use the timestamp on the matching message, or the file's mtime as a fallback)
  • 2-4 sentence summary of what was discussed and decided
If there are multiple candidates, list each briefly and let the user pick which one to dig into. Don't dump 20 KB of raw JSON into chat — they want a recap, not a re-read.
对于每个优质候选结果,展示:
  • 会话ID(不带
    .jsonl
    的文件名)
  • 项目文件夹
    ~/.claude/projects/<encoded>
  • 日期/时间(使用匹配消息的时间戳,或文件的修改时间作为备选)
  • 2-4句话的摘要,说明讨论内容和做出的决定
如果有多个候选结果,简要列出每个结果,让用户选择深入查看的内容。不要将20KB的原始JSON粘贴到聊天中——用户需要的是摘要,而不是重新阅读整个会话。

Reporting the outcome (optional follow-up)

报告成果(可选后续步骤)

Often the user's real question is "did we ever ship that?" Once you've located the session, you can scan the transcript for what was actually done:
bash
undefined
用户真正的问题往往是“我们有没有发布那个功能?”找到会话后,你可以扫描转录本查看实际完成的工作:
bash
undefined

Branches created, commits made, PRs opened

创建的分支、提交的代码、创建的PR

rg -o '"command":"git (commit|push|checkout -b)[^"]' <session>.jsonl rg -o 'gh pr create[^"]' <session>.jsonl rg -o 'https://github.com/[^"]*pull/[0-9]+' <session>.jsonl | sort -u

If you find a PR URL, check the current status:

```bash
gh pr view <N> --repo <owner>/<repo> --json number,title,state,mergedAt,reviewDecision,url
Report back: open / merged / closed, current review decision, and whether CI was last green. That's usually the answer the user actually wanted.
rg -o '"command":"git (commit|push|checkout -b)[^"]' <session>.jsonl rg -o 'gh pr create[^"]' <session>.jsonl rg -o 'https://github.com/[^"]*pull/[0-9]+' <session>.jsonl | sort -u

如果找到PR链接,检查当前状态:

```bash
gh pr view <N> --repo <owner>/<repo> --json number,title,state,mergedAt,reviewDecision,url
报告结果:打开/已合并/已关闭、当前审核状态,以及CI最近是否通过。这通常是用户真正想要的答案。

Anti-patterns to avoid

需要避免的反模式

  • Don't
    cat
    whole
    .jsonl
    files.
    They are huge and contain
    signature
    blocks, base64 thinking traces, and tool-result payloads. Use
    rg
    first to find the matching lines, then
    jq
    or
    grep -B/-A
    to pull a window.
  • Don't grep for common words without a qualifier.
    approve
    ,
    error
    ,
    fix
    ,
    commit
    ,
    pr
    will hit every session. Anchor on something distinctive the user remembers.
  • Don't trust the first match. Sessions can run for hours; the canonical decision is often in a later turn. Scan the timestamps and prefer matches near the end of a session over the start.
  • Don't auto-include subagent transcripts. They duplicate the parent session's content from a different angle and multiply hits. When recursing, exclude with
    --glob '!**/subagents/**'
    ; with a top-level shell glob they're already skipped.
  • Don't paraphrase from memory. If you're reporting what was discussed, ground every claim in an actual line you extracted from the file — model memory of past sessions is unreliable.
  • Don't search across
    ~/.claude/projects/*
    when the user has clearly named the repo.
    Narrow first.
  • 切勿使用
    cat
    读取整个
    .jsonl
    文件
    。这些文件体积庞大,包含
    signature
    块、base64编码的思考轨迹和工具结果负载。先使用
    rg
    找到匹配行,再使用
    jq
    grep -B/-A
    提取窗口内容。
  • 切勿在没有限定条件的情况下搜索常用词
    approve
    error
    fix
    commit
    pr
    会命中每个会话。聚焦于用户记得的独特内容。
  • 切勿轻信第一个匹配结果。会话可能持续数小时;最终决定通常出现在后续对话中。查看时间戳,优先选择会话末尾的匹配结果,而非开头的。
  • 切勿自动包含子代理转录本。它们从不同角度重复父会话的内容,会增加命中数。递归搜索时,使用
    --glob '!**/subagents/**'
    排除;使用顶层shell通配符时会自动跳过。
  • 切勿凭记忆转述。如果要报告讨论内容,每个结论都要基于从文件中提取的实际内容——模型对过往会话的记忆不可靠。
  • 当用户明确指定仓库时,切勿搜索
    ~/.claude/projects/*
    。先缩小范围。

Failure modes and recovery

故障模式与恢复

  • The search returns nothing. Ask the user for a more specific phrase (error message, function name, file path, person's name). If they only remember a topic, try 2-3 synonym variants — but stop after that and ask, don't drift into pattern-matching forever.
  • The matching file is in a project you've never seen. That's fine — the transcript still lives at
    ~/.claude/projects/<encoded-cwd>/
    . The encoded directory name tells you the original cwd; you can
    cd
    there if you need to inspect the repo.
  • You find the session but can't tell what was decided. Read the last few user turns and the last assistant turn before a tool-use chain ended. Decisions usually live in those, not in the middle of long debugging back-and-forth.
  • 搜索无结果。请用户提供更具体的短语(错误消息、函数名、文件路径、人名)。如果他们只记得主题,尝试2-3个同义词变体——但之后停止猜测,询问用户,不要无休止地尝试匹配模式。
  • 匹配文件位于你从未见过的项目中。没关系——转录本仍存储在
    ~/.claude/projects/<encoded-cwd>/
    下。编码后的目录名告诉你原始工作目录;如果需要检查仓库,可以
    cd
    到该目录。
  • 找到会话但无法确定做出的决定。查看最后几条用户对话工具使用链结束前的最后一条助手对话。决定通常出现在这些内容中,而非冗长的调试对话中间。

Worked example

示例操作

User says: "Find the conversation we had about the bot auto-approving a PR when it finds approvals."
bash
undefined
用户说:“找到我们关于机器人在发现审批后自动批准PR的对话。”
bash
undefined

Step 1: across all projects since user didn't name a repo.

Step 1: across all projects since user didn't name a repo.

The shell glob
*/[0-9a-f]*.jsonl
only matches top-level session files,

The shell glob
*/[0-9a-f]*.jsonl
only matches top-level session files,

so subagent transcripts (one dir deeper) are naturally excluded.

so subagent transcripts (one dir deeper) are naturally excluded.

rg -l -i "auto.approv" ~/.claude/projects//[0-9a-f].jsonl
rg -l -i "auto.approv" ~/.claude/projects//[0-9a-f].jsonl

→ too many hits; mostly
terraform apply -auto-approve
. Ask for a distinctive phrase.

→ too many hits; mostly
terraform apply -auto-approve
. Ask for a distinctive phrase.

User: "look for 'request changes'"

User: "look for 'request changes'"

rg -l -i "request changes" ~/.claude/projects//[0-9a-f].jsonl
rg -l -i "request changes" ~/.claude/projects//[0-9a-f].jsonl

→ narrows to ~10 files. Sort by recency.

→ narrows to ~10 files. Sort by recency.

ls -lt $(rg -l -i "request changes" ~/.claude/projects//[0-9a-f].jsonl) | head -5
ls -lt $(rg -l -i "request changes" ~/.claude/projects//[0-9a-f].jsonl) | head -5

Step 4: read context from the most recent candidate

Step 4: read context from the most recent candidate

rg -i -B 2 -A 5 "request changes"
~/.claude/projects/-Users-alice-source-acme-api/a7e955d8-*.jsonl | head -60
rg -i -B 2 -A 5 "request changes"
~/.claude/projects/-Users-alice-source-acme-api/a7e955d8-*.jsonl | head -60

Step 5: report — Session a7e955d8-... in acme-api, 2026-05-14, about the review bot

Step 5: report — Session a7e955d8-... in acme-api, 2026-05-14, about the review bot

posting a plain comment after a REQUEST_CHANGES review (which doesn't clear the

posting a plain comment after a REQUEST_CHANGES review (which doesn't clear the

block) instead of submitting a new opinionated review.

block) instead of submitting a new opinionated review.

Outcome check

Outcome check

rg -o 'https://github.com/[^"]*pull/[0-9]+'
~/.claude/projects/-Users-alice-source-acme-api/a7e955d8-*.jsonl | sort -u
rg -o 'https://github.com/[^"]*pull/[0-9]+'
~/.claude/projects/-Users-alice-source-acme-api/a7e955d8-*.jsonl | sort -u
gh pr view 23 --repo acme/api --json state,mergedAt,reviewDecision
gh pr view 23 --repo acme/api --json state,mergedAt,reviewDecision

→ OPEN, APPROVED, not yet merged

→ OPEN, APPROVED, not yet merged


The user gets one tight answer: session ID, date, summary, and "PR #23 — approved but not merged."

用户会得到一个简洁的答案:会话ID、日期、摘要,以及“PR #23 — 已批准但未合并”。