cc-history

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Claude Code History Analysis

Claude Code对话历史分析

Reference documentation for querying and analyzing Claude Code's conversation history. Use shell commands and jq to extract information from JSONL conversation files.
用于查询和分析Claude Code对话历史的参考文档。使用Shell命令和jq从JSONL对话文件中提取信息。

Directory Structure

目录结构

~/.claude/projects/{encoded-path}/
  |-- {session-uuid}.jsonl          # Main conversation
  |-- {session-uuid}/
      |-- subagents/
      |   |-- agent-{hash}.jsonl    # Subagent conversations
      |-- tool-results/             # Large tool outputs
~/.claude/projects/{encoded-path}/
  |-- {session-uuid}.jsonl          # 主对话文件
  |-- {session-uuid}/
      |-- subagents/
      |   |-- agent-{hash}.jsonl    # 子代理对话文件
      |-- tool-results/             # 大型工具输出结果

Project Path Resolution

项目路径解析

Convert working directory to project directory:
bash
PROJECT_DIR="~/.claude/projects/$(echo "$PWD" | sed 's|^/|-|; s|/\.|--|g; s|/|-|g')"
Encoding rules:
  • Leading
    /
    becomes
    -
  • Regular
    /
    becomes
    -
  • /.
    (hidden directory) becomes
    --
Examples:
  • /Users/bill/.claude
    ->
    -Users-bill--claude
  • /Users/bill/git/myproject
    ->
    -Users-bill-git-myproject
将工作目录转换为项目目录:
bash
PROJECT_DIR="~/.claude/projects/$(echo "$PWD" | sed 's|^/|-|; s|/\.|--|g; s|/|-|g')"
编码规则:
  • 开头的
    /
    转换为
    -
  • 常规
    /
    转换为
    -
  • /.
    (隐藏目录)转换为
    --
示例:
  • /Users/bill/.claude
    ->
    -Users-bill--claude
  • /Users/bill/git/myproject
    ->
    -Users-bill-git-myproject

Message Types

消息类型

TypeDescription
user
User input messages
assistant
Model responses (thinking, tool_use, text)
system
System messages
queue-operation
Background task notifications (subagent done)
类型描述
user
用户输入消息
assistant
模型回复(思考、工具调用、文本)
system
系统消息
queue-operation
后台任务通知(子代理完成)

Message Structure

消息结构

Each line in a JSONL file is a message object:
json
{
  "type": "assistant",
  "uuid": "abc123",
  "parentUuid": "xyz789",
  "timestamp": "2025-01-15T19:39:16.000Z",
  "sessionId": "session-uuid",
  "message": {
    "role": "assistant",
    "content": [...],
    "usage": {
      "input_tokens": 20000,
      "output_tokens": 500,
      "cache_read_input_tokens": 15000,
      "cache_creation_input_tokens": 5000
    }
  }
}
Assistant message content blocks:
  • type: "thinking"
    - Model thinking (has
    thinking
    field)
  • type: "tool_use"
    - Tool invocation (has
    name
    ,
    input
    fields)
  • type: "text"
    - Text response (has
    text
    field)
JSONL文件中的每一行都是一个消息对象:
json
{
  "type": "assistant",
  "uuid": "abc123",
  "parentUuid": "xyz789",
  "timestamp": "2025-01-15T19:39:16.000Z",
  "sessionId": "session-uuid",
  "message": {
    "role": "assistant",
    "content": [...],
    "usage": {
      "input_tokens": 20000,
      "output_tokens": 500,
      "cache_read_input_tokens": 15000,
      "cache_creation_input_tokens": 5000
    }
  }
}
助手消息内容块:
  • type: "thinking"
    - 模型思考内容(包含
    thinking
    字段)
  • type: "tool_use"
    - 工具调用(包含
    name
    input
    字段)
  • type: "text"
    - 文本回复(包含
    text
    字段)

Common Queries

常见查询

Find Conversations

查找对话

bash
undefined
bash
undefined

List by modification time (most recent first)

按修改时间排序(最新的在前)

ls -lt "$PROJECT_DIR"/*.jsonl
ls -lt "$PROJECT_DIR"/*.jsonl

Find by date

按日期查找

ls -la "$PROJECT_DIR"/*.jsonl | grep "Jan 15"
ls -la "$PROJECT_DIR"/*.jsonl | grep "Jan 15"

Find by content

按内容查找

grep -l "search term" "$PROJECT_DIR"/*.jsonl
undefined
grep -l "搜索关键词" "$PROJECT_DIR"/*.jsonl
undefined

Extract Messages

提取消息

bash
undefined
bash
undefined

Get message by line number (1-indexed)

按行号获取消息(从1开始计数)

sed -n '42p' file.jsonl | jq .
sed -n '42p' file.jsonl | jq .

Get message by uuid

按uuid获取消息

jq -c 'select(.uuid=="abc123")' file.jsonl
jq -c 'select(.uuid=="abc123")' file.jsonl

All user messages

所有用户消息

jq -c 'select(.type=="user")' file.jsonl
jq -c 'select(.type=="user")' file.jsonl

All assistant messages

所有助手消息

jq -c 'select(.type=="assistant")' file.jsonl
undefined
jq -c 'select(.type=="assistant")' file.jsonl
undefined

Tool Call Analysis

工具调用分析

bash
undefined
bash
undefined

List all tool calls

列出所有工具调用

jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | {name, input}' file.jsonl
jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | {name, input}' file.jsonl

Count tool calls by name

按工具名称统计调用次数

jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' file.jsonl | sort | uniq -c | sort -rn
jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | .name' file.jsonl | sort | uniq -c | sort -rn

Find specific tool calls

查找特定工具的调用记录

jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Bash")' file.jsonl
undefined
jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Bash")' file.jsonl
undefined

Skill Invocation Detection

Skill调用检测

Pattern:
python3 -m skills\.([a-z_]+)\.
bash
undefined
匹配模式:
python3 -m skills\.([a-z_]+)\.
bash
undefined

Find all skill invocations

查找所有Skill调用记录

grep -oE "python3 -m skills.[a-z_]+" file.jsonl | sort -u
grep -oE "python3 -m skills.[a-z_]+" file.jsonl | sort -u

Find conversations using a specific skill

查找使用特定Skill的对话

grep -l "python3 -m skills.planner." "$PROJECT_DIR"/*.jsonl
undefined
grep -l "python3 -m skills.planner." "$PROJECT_DIR"/*.jsonl
undefined

Token Usage

Token用量分析

bash
undefined
bash
undefined

Total tokens in conversation

对话中的总Token数

jq -s '[.[].message.usage? | select(.) | .input_tokens + .output_tokens] | add' file.jsonl
jq -s '[.[].message.usage? | select(.) | .input_tokens + .output_tokens] | add' file.jsonl

Token breakdown

Token用量细分

jq -s '[.[].message.usage? | select(.)] | { input: (map(.input_tokens) | add), output: (map(.output_tokens) | add), cached: (map(.cache_read_input_tokens // 0) | add) }' file.jsonl
jq -s '[.[].message.usage? | select(.)] | { input: (map(.input_tokens) | add), output: (map(.output_tokens) | add), cached: (map(.cache_read_input_tokens // 0) | add) }' file.jsonl

Token progression over time

Token用量随时间的变化

jq -c 'select(.type=="assistant") | {ts: .timestamp[11:19], inp: .message.usage.input_tokens, out: .message.usage.output_tokens}' file.jsonl
undefined
jq -c 'select(.type=="assistant") | {ts: .timestamp[11:19], inp: .message.usage.input_tokens, out: .message.usage.output_tokens}' file.jsonl
undefined

Taxonomy Aggregation

分类统计

bash
undefined
bash
undefined

Count messages by type

按消息类型统计数量

jq -s 'group_by(.type) | map({type: .[0].type, count: length})' file.jsonl
jq -s 'group_by(.type) | map({type: .[0].type, count: length})' file.jsonl

Character count in user messages

用户消息的字符总数

jq -s '[.[] | select(.type=="user") | .message.content | length] | add' file.jsonl
jq -s '[.[] | select(.type=="user") | .message.content | length] | add' file.jsonl

Thinking block character count

思考块的字符总数

jq -s '[.[] | select(.type=="assistant") | .message.content[]? | select(.type=="thinking") | .thinking | length] | add' file.jsonl
undefined
jq -s '[.[] | select(.type=="assistant") | .message.content[]? | select(.type=="thinking") | .thinking | length] | add' file.jsonl
undefined

Subagent Analysis

子代理分析

bash
undefined
bash
undefined

List subagents for a session

列出会话的所有子代理

ls "${SESSION_DIR}/subagents/"
ls "${SESSION_DIR}/subagents/"

Get subagent task description (first user message)

获取子代理的任务描述(第一条用户消息)

jq -c 'select(.type=="user") | .message.content' agent-*.jsonl | head -1
jq -c 'select(.type=="user") | .message.content' agent-*.jsonl | head -1

Find Task tool calls in parent (these spawn subagents)

在父对话中查找生成子代理的Task工具调用

jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Task") | .input' file.jsonl
undefined
jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Task") | .input' file.jsonl
undefined

Correlation

关联匹配

Subagent files (
agent-{hash}.jsonl
) don't link directly to parent Task calls. To correlate:
  1. List all subagent files under
    {session}/subagents/
  2. Read first user message of each for task description
  3. Match description to Task tool_use blocks in parent conversation
子代理文件(
agent-{hash}.jsonl
)不会直接关联到父对话中的Task调用。要进行关联:
  1. 列出
    {session}/subagents/
    下的所有子代理文件
  2. 读取每个子代理文件的第一条用户消息以获取任务描述
  3. 将描述与父对话中的Task工具调用块进行匹配