Smithery Logo
MCPsSkillsDocsPricing
Login
NewFlame, an assistant that learns and improves. Available onTelegramSlack
    solatis

    cc-history

    solatis/cc-history
    Research
    557
    1 installs

    About

    SKILL.md

    Install

    • Telegram
      Telegram
    • Slack
      Slack
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    • Download skill
    ├─
    ├─
    └─
    Smithery Logo

    Give agents more agency

    Resources

    DocumentationPrivacy PolicySystem Status

    Company

    PricingAboutBlog

    Connect

    © 2026 Smithery. All rights reserved.

    About

    Reference documentation for analyzing Claude Code conversation history files

    SKILL.md

    Claude Code History Analysis

    Reference documentation for querying and analyzing Claude Code's conversation history. Use shell commands and jq to extract information from JSONL conversation files.

    Directory Structure

    ~/.claude/projects/{encoded-path}/
      |-- {session-uuid}.jsonl          # Main conversation
      |-- {session-uuid}/
          |-- subagents/
          |   |-- agent-{hash}.jsonl    # Subagent conversations
          |-- tool-results/             # Large tool outputs
    

    Project Path Resolution

    Convert working directory to project directory:

    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

    Message Types

    Type Description
    user User input messages
    assistant Model responses (thinking, tool_use, text)
    system System messages
    queue-operation Background task notifications (subagent done)

    Message Structure

    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)

    Common Queries

    Find Conversations

    # 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
    

    Extract Messages

    # 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
    

    Tool Call Analysis

    # 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
    

    Skill Invocation Detection

    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
    

    Token Usage

    # 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
    

    Taxonomy Aggregation

    # 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
    

    Subagent Analysis

    # 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
    

    Conversation Branching

    Each .jsonl file contains the entire conversation tree (all branches), not separate files per branch. Branching is tracked via parentUuid:

    • When user goes back in history and issues a new command, the new message gets the same parentUuid as where they branched from
    • Multiple messages sharing the same parentUuid = sibling branches (fork point)

    Detecting Branch Points

    # 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
    

    Extracting a Single Branch

    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}'
    

    Workflow: Pinpoint and Explore

    # 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'
    

    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
    Recommended Servers
    Context7
    Context7
    Medical Terminologies MCP
    Medical Terminologies MCP
    Repository
    solatis/claude-config
    Files