ワンクリックで
ワンクリックで
Invoke IMMEDIATELY via python script when user requests codebase understanding, architecture comprehension, or repository orientation. Do NOT explore first - the script orchestrates exploration.
Invoke IMMEDIATELY via python script when user requests prompt optimization. Do NOT analyze first - invoke this skill immediately.
Invoke IMMEDIATELY via python script to stress-test decisions and reasoning. Do NOT analyze first - the script orchestrates the critique workflow.
Invoke IMMEDIATELY via python script when user requests structured reasoning for open-ended analytical questions. Do NOT explore first - the script orchestrates the thinking workflow.
Detect and resolve incoherence in documentation, code, specs vs implementation.
Interactive planning and execution for complex tasks. IMMEDIATELY invoke when user asks to use planner.
| name | cc-history |
| description | Reference documentation for analyzing Claude Code conversation history files |
Reference documentation for querying and analyzing Claude Code's conversation history. Use shell commands and jq to extract information from JSONL conversation files.
~/.claude/projects/{encoded-path}/
|-- {session-uuid}.jsonl # Main conversation
|-- {session-uuid}/
|-- subagents/
| |-- agent-{hash}.jsonl # Subagent conversations
|-- tool-results/ # Large tool outputs
Convert working directory to project directory:
PROJECT_DIR="~/.claude/projects/$(echo "$PWD" | sed 's|^/|-|; s|/\.|--|g; s|/|-|g')"
Encoding rules:
/ becomes -/ becomes -/. (hidden directory) becomes --Examples:
/Users/bill/.claude -> -Users-bill--claude/Users/bill/git/myproject -> -Users-bill-git-myproject| Type | Description |
|---|---|
user | User input messages |
assistant | Model responses (thinking, tool_use, text) |
system | System messages |
queue-operation | Background task notifications (subagent done) |
Each line in a JSONL file is a message object:
{
"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)# List by modification time (most recent first)
ls -lt "$PROJECT_DIR"/*.jsonl
# Find by date
ls -la "$PROJECT_DIR"/*.jsonl | grep "Jan 15"
# Find by content
grep -l "search term" "$PROJECT_DIR"/*.jsonl
# Get message by line number (1-indexed)
sed -n '42p' file.jsonl | jq .
# Get message by uuid
jq -c 'select(.uuid=="abc123")' file.jsonl
# All user messages
jq -c 'select(.type=="user")' file.jsonl
# All assistant messages
jq -c 'select(.type=="assistant")' file.jsonl
# List all tool calls
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
# Find specific tool calls
jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Bash")' file.jsonl
Pattern: python3 -m skills\.([a-z_]+)\.
# Find all skill invocations
grep -oE "python3 -m skills\.[a-z_]+" file.jsonl | sort -u
# Find conversations using a specific skill
grep -l "python3 -m skills\.planner\." "$PROJECT_DIR"/*.jsonl
# Total tokens in conversation
jq -s '[.[].message.usage? | select(.) | .input_tokens + .output_tokens] | add' file.jsonl
# Token breakdown
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
jq -c 'select(.type=="assistant") | {ts: .timestamp[11:19], inp: .message.usage.input_tokens, out: .message.usage.output_tokens}' file.jsonl
# Count messages by type
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
# Thinking block character count
jq -s '[.[] | select(.type=="assistant") | .message.content[]? | select(.type=="thinking") | .thinking | length] | add' file.jsonl
# List subagents for a session
ls "${SESSION_DIR}/subagents/"
# Get subagent task description (first user message)
jq -c 'select(.type=="user") | .message.content' agent-*.jsonl | head -1
# Find Task tool calls in parent (these spawn subagents)
jq -c 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use" and .name=="Task") | .input' file.jsonl
Each .jsonl file contains the entire conversation tree (all branches), not separate files per branch. Branching is tracked via parentUuid:
parentUuid as where they branched fromparentUuid = sibling branches (fork point)# Find all fork points (messages with multiple children)
jq -s 'group_by(.parentUuid) | map(select(length > 1)) | .[] | {
parentUuid: .[0].parentUuid,
branches: length,
timestamps: [.[].timestamp]
}' file.jsonl
# Show siblings at a known fork point
FORK_POINT="parent-uuid-here"
jq -c --arg fp "$FORK_POINT" 'select(.parentUuid==$fp) | {uuid, ts: .timestamp, preview: (.message.content | tostring)[:100]}' file.jsonl
To filter for exactly one branch, find a unique identifier in that branch, then walk the ancestor chain back to root.
Step 1: Find target message uuid
# By unique content
TARGET=$(jq -r 'select(.message.content | tostring | contains("unique-identifier")) | .uuid' file.jsonl | tail -1)
# By timestamp prefix
TARGET=$(jq -r 'select(.timestamp | startswith("2026-01-28T11:23")) | .uuid' file.jsonl | head -1)
Step 2: Extract branch as JSONL stream
# Outputs one message per line (JSONL), oldest first
extract_branch() {
jq -c -s --arg target "$1" '
(map({(.uuid): .}) | add) as $lookup |
{chain: [], current: $target} |
until(.current == null or ($lookup[.current] | not);
($lookup[.current]) as $msg |
.chain += [$msg] |
.current = $msg.parentUuid
) |
.chain | reverse | .[]
' "$2"
}
# Usage: extract_branch <target-uuid> <file>
extract_branch "$TARGET" file.jsonl | jq -s 'length'
extract_branch "$TARGET" file.jsonl | jq 'select(.type=="user")'
Step 3: Common branch queries
# Message count
extract_branch "$TARGET" file.jsonl | jq -s 'length'
# User messages only
extract_branch "$TARGET" file.jsonl | jq 'select(.type=="user")'
# Tool calls
extract_branch "$TARGET" file.jsonl | jq 'select(.type=="assistant") | .message.content[]? | select(.type=="tool_use") | {name}'
# First and last messages (verify correct branch)
extract_branch "$TARGET" file.jsonl | jq -s '[.[0], .[-1]] | .[] | {type, ts: .timestamp}'
# 1. Find conversation file
FILE=$(grep -l "unique-identifier" "$PROJECT_DIR"/*.jsonl)
# 2. Find matching messages (may show multiple branches)
jq -c 'select(.message.content | tostring | contains("unique-identifier")) | {uuid, ts: .timestamp, parentUuid}' "$FILE"
# 3. Pick target uuid from desired branch, then query
TARGET="uuid-from-step-2"
extract_branch "$TARGET" "$FILE" | jq 'select(.type=="user") | .message.content'
Subagent files (agent-{hash}.jsonl) don't link directly to parent Task calls. To correlate:
{session}/subagents/