cc-history
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseClaude 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
消息类型
| Type | Description |
|---|---|
| User input messages |
| Model responses (thinking, tool_use, text) |
| System messages |
| Background task notifications (subagent done) |
| 类型 | 描述 |
|---|---|
| 用户输入消息 |
| 模型回复(思考、工具调用、文本) |
| 系统消息 |
| 后台任务通知(子代理完成) |
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:
- - Model thinking (has
type: "thinking"field)thinking - - Tool invocation (has
type: "tool_use",namefields)input - - Text response (has
type: "text"field)text
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
undefinedbash
undefinedList 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
undefinedgrep -l "搜索关键词" "$PROJECT_DIR"/*.jsonl
undefinedExtract Messages
提取消息
bash
undefinedbash
undefinedGet 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
undefinedjq -c 'select(.type=="assistant")' file.jsonl
undefinedTool Call Analysis
工具调用分析
bash
undefinedbash
undefinedList 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
undefinedjq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Bash")' file.jsonl
undefinedSkill Invocation Detection
Skill调用检测
Pattern:
python3 -m skills\.([a-z_]+)\.bash
undefined匹配模式:
python3 -m skills\.([a-z_]+)\.bash
undefinedFind 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
undefinedgrep -l "python3 -m skills.planner." "$PROJECT_DIR"/*.jsonl
undefinedToken Usage
Token用量分析
bash
undefinedbash
undefinedTotal 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
undefinedjq -c 'select(.type=="assistant") | {ts: .timestamp[11:19], inp: .message.usage.input_tokens, out: .message.usage.output_tokens}' file.jsonl
undefinedTaxonomy Aggregation
分类统计
bash
undefinedbash
undefinedCount 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
undefinedjq -s '[.[] | select(.type=="assistant") | .message.content[]? | select(.type=="thinking") | .thinking | length] | add' file.jsonl
undefinedSubagent Analysis
子代理分析
bash
undefinedbash
undefinedList 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
undefinedjq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Task") | .input' file.jsonl
undefinedCorrelation
关联匹配
Subagent files () don't link directly to parent Task calls. To correlate:
agent-{hash}.jsonl- List all subagent files under
{session}/subagents/ - Read first user message of each for task description
- Match description to Task tool_use blocks in parent conversation
子代理文件()不会直接关联到父对话中的Task调用。要进行关联:
agent-{hash}.jsonl- 列出下的所有子代理文件
{session}/subagents/ - 读取每个子代理文件的第一条用户消息以获取任务描述
- 将描述与父对话中的Task工具调用块进行匹配