Task Stats
A CLAUDE.md example showing automated task cost analysis and performance tracking for Claude Code Task operations.
Author: InventorBlack
# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with this repository. ## Important - ALL instructions within this document MUST BE FOLLOWED, these are not optional unless explicitly stated. - ASK FOR CLARIFICATION If you are uncertain of any of thing within the document. - DO NOT edit more code than you have to. - DO NOT WASTE TOKENS, be succinct and concise. ## Task Cost and Usage Information Retrieval - IMPERATIVE: ANY time the user mentions "task stats", "get task stats", "last task stats", or similar variations, IMMEDIATELY use the automated task stats script without question. ### Task Stats Script Usage: **Primary Command**: `bash "/path/to/project/.claude/functions/task/task_stats.sh"` **Script Options:** - `bash .claude/functions/task/task_stats.sh` - Auto-detects and analyzes most recent Task session - `bash .claude/functions/task/task_stats.sh session_id.jsonl` - Analyzes specific session file ### IMPORTANT RULES: - Execute the task_stats.sh script immediately when task stats are requested - The script auto-detects the most recent Task session or accepts a specific session file
Script Implementation
Customization Required
You must update the CLAUDE_DIR path in the script below to match your project's Claude directory structure.
#!/bin/bash
# Task Stats Script - Extracts Claude Code Task operation breakdowns
# Usage: ./task_stats.sh [session_file.jsonl]
# CUSTOMIZE THIS PATH for your project
CLAUDE_DIR="$HOME/.claude/projects/your-project-name-here"
# Find latest session with Task operations
find_task_session() {
    # Get sessions sorted by modification time (newest first)
    for session in $(ls -t "$CLAUDE_DIR"/*.jsonl 2>/dev/null); do
        # Check if this session has sidechain operations AND recent timestamps
        if grep -q '"isSidechain":true' "$session" 2>/dev/null; then
            # Get the newest timestamp from this session
            local newest_timestamp=$(grep '"isSidechain":true' "$session" | tail -1 | grep -o '"timestamp":"[^"]*"' | cut -d'"' -f4)
            if [[ -n "$newest_timestamp" ]]; then
                # Check if the timestamp is recent (within last hour)
                local timestamp_epoch=$(date -d "$newest_timestamp" +%s 2>/dev/null || echo "0")
                local current_epoch=$(date +%s)
                local time_diff=$((current_epoch - timestamp_epoch))
                # If within last hour (3600 seconds), this is likely the current session
                if [[ $time_diff -lt 3600 ]]; then
                    echo "$session"
                    return 0
                fi
            fi
        fi
    done
    # Fallback: return the most recent session with sidechain operations
    for session in $(ls -t "$CLAUDE_DIR"/*.jsonl 2>/dev/null); do
        if grep -q '"isSidechain":true' "$session" 2>/dev/null; then
            echo "$session"
            return 0
        fi
    done
    return 1
}
# Display task breakdown
show_breakdown() {
    local session="$1"
    local basename_session=$(basename "$session")
    echo "Analyzing: $basename_session"
    echo ""
    # Get task description from the most recent Task call
    local last_task_line=$(grep -n '"name":"Task"' "$session" | tail -1 | cut -d: -f1)
    local task_desc=$(tail -n +$((last_task_line)) "$session" | head -1 | grep -o '"description":"[^"]*"' | sed 's/"description":"\([^"]*\)"/\1/')
    [[ -z "$task_desc" ]] && task_desc="Task Operation"
    # Get tokens and tool count from ALL sidechain operations in this session
    local all_sidechain_ops=$(grep '"isSidechain":true' "$session")
    local input_tokens=$(echo "$all_sidechain_ops" | grep -o '"input_tokens":[0-9]*' | grep -o '[0-9]*' | awk '{sum += $1} END {print sum}')
    local cache_creation_tokens=$(echo "$all_sidechain_ops" | grep -o '"cache_creation_input_tokens":[0-9]*' | grep -o '[0-9]*' | awk '{sum += $1} END {print sum}')
    local cache_read_tokens=$(echo "$all_sidechain_ops" | grep -o '"cache_read_input_tokens":[0-9]*' | grep -o '[0-9]*' | awk '{sum += $1} END {print sum}')
    local output_tokens=$(echo "$all_sidechain_ops" | grep -o '"output_tokens":[0-9]*' | grep -o '[0-9]*' | awk '{sum += $1} END {print sum}')
    local tokens=$((${input_tokens:-0} + ${cache_creation_tokens:-0} + ${cache_read_tokens:-0} + ${output_tokens:-0}))
    local tool_count=$(echo "$all_sidechain_ops" | wc -l)
    # Get the most recent Task operation block by looking for Task tool calls
    local last_task_line=$(grep -n '"name":"Task"' "$session" | tail -1 | cut -d: -f1)
    local recent_operations=$(tail -n +$((last_task_line)) "$session" | grep '"isSidechain":true')
    # Calculate total cost and duration from recent sidechain operations only
    local total_cost=$(echo "$recent_operations" | grep -o '"costUSD":[0-9.]*' | cut -d: -f2 | awk '{sum += $1} END {printf "%.4f", sum}')
    local total_duration_ms=$(echo "$recent_operations" | grep -o '"durationMs":[0-9]*' | cut -d: -f2 | awk '{sum += $1} END {print sum}')
    # Get first and last timestamps for elapsed time calculation from recent operations
    local first_timestamp=$(echo "$recent_operations" | head -1 | grep -o '"timestamp":"[^"]*"' | cut -d'"' -f4)
    local last_timestamp=$(echo "$recent_operations" | tail -1 | grep -o '"timestamp":"[^"]*"' | cut -d'"' -f4)
    # Convert timestamps to epoch and calculate elapsed time
    local first_epoch=$(date -d "$first_timestamp" +%s 2>/dev/null || echo "0")
    local last_epoch=$(date -d "$last_timestamp" +%s 2>/dev/null || echo "0")
    local elapsed_sec=$((last_epoch - first_epoch))
    # Convert durations
    local duration_sec=$(echo "scale=1; ${total_duration_ms:-0} / 1000" | bc -l 2>/dev/null || echo "0.0")
    local efficiency="0.0"
    if [[ $elapsed_sec -gt 0 ]]; then
        efficiency=$(echo "scale=1; ($duration_sec / $elapsed_sec) * 100" | bc -l 2>/dev/null || echo "0.0")
    fi
    echo "=== TASK AGENT INTERNAL BREAKDOWN ==="
    echo "Task: \"$task_desc\""
    echo "Total Cost: \${total_cost:-0.0000} | Sequential Duration: ${duration_sec}s | Actual Elapsed: ${elapsed_sec}s | Agent: claude-sonnet-4-5-20250929"
    echo "Efficiency: ${efficiency}% (${duration_sec}s/${elapsed_sec}s)"
    echo ""
    echo "┌─ OPERATION TIMELINE ──────────────────────────────────────────────────────────┐"
    # Find max duration for relative bar chart scaling
    local max_duration=$(echo "$recent_operations" | grep -o '"durationMs":[0-9]*' | cut -d: -f2 | sort -nr | head -1)
    local max_dur_sec=$(echo "scale=1; ${max_duration:-0} / 1000" | bc -l 2>/dev/null || echo "0.0")
    # Get all sidechain operations from the most recent Task operation
    echo "$recent_operations" | while IFS= read -r line; do
        # Extract fields
        local timestamp=$(echo "$line" | grep -o '"timestamp":"[^"]*"' | cut -d'"' -f4)
        local cost=$(echo "$line" | grep -o '"costUSD":[0-9.]*' | cut -d: -f2)
        local duration=$(echo "$line" | grep -o '"durationMs":[0-9]*' | cut -d: -f2)
        # Format time
        local time_str=$(date -d "$timestamp" '+%H:%M:%S' 2>/dev/null || echo "XX:XX:XX")
        local dur_sec=$(echo "scale=1; ${duration:-0} / 1000" | bc -l 2>/dev/null || echo "0.0")
        # Determine operation
        local operation="Agent Operation"
        if echo "$line" | grep -q '"name":"Write"'; then
            local filepath=$(echo "$line" | grep -o '"file_path":"[^"]*"' | cut -d'"' -f4)
            operation="Write $(basename "$filepath" 2>/dev/null || echo "file")"
        elif echo "$line" | grep -q '"name":"Bash"'; then
            operation="Bash Command"
        elif echo "$line" | grep -q '"name":"LS"'; then
            operation="List Directory"
        elif echo "$line" | grep -q '"name":"Read"'; then
            local filepath=$(echo "$line" | grep -o '"file_path":"[^"]*"' | cut -d'"' -f4)
            operation="Read $(basename "$filepath" 2>/dev/null || echo "file")"
        elif echo "$line" | grep -q '"name":"Edit"'; then
            local filepath=$(echo "$line" | grep -o '"file_path":"[^"]*"' | cut -d'"' -f4)
            operation="Edit $(basename "$filepath" 2>/dev/null || echo "file")"
        elif echo "$line" | grep -q '"name":"MultiEdit"'; then
            local filepath=$(echo "$line" | grep -o '"file_path":"[^"]*"' | cut -d'"' -f4)
            operation="MultiEdit $(basename "$filepath" 2>/dev/null || echo "file")"
        elif echo "$line" | grep -q '"name":"Glob"'; then
            operation="Search Files"
        elif echo "$line" | grep -q '"name":"Grep"'; then
            operation="Search Content"
        elif echo "$line" | grep -q '"name":"Task"'; then
            operation="Task Launch"
        elif echo "$line" | grep -q 'Summary.*Created.*Files'; then
            operation="Task Summary"
        else
            # Try to extract any tool name
            local tool_name=$(echo "$line" | grep -o '"name":"[^"]*"' | cut -d'"' -f4)
            if [[ -n "$tool_name" ]]; then
                operation="$tool_name Tool"
            else
                # Look for text content to infer operation
                if echo "$line" | grep -q '"I'\''ll create"'; then
                    operation="Task Planning"
                elif echo "$line" | grep -q '"Successfully created"'; then
                    operation="Task Summary"
                elif echo "$line" | grep -q '"Now I'\''ll"'; then
                    operation="Task Progress"
                elif echo "$line" | grep -q '"Let me"'; then
                    operation="Task Processing"
                elif echo "$line" | grep -q '"All.*demo files"'; then
                    operation="Task Completion"
                else
                    operation="Task Reasoning"
                fi
            fi
        fi
        # Calculate relative progress bar (14 chars max)
        local bars=1
        if [[ $(echo "${max_dur_sec} > 0" | bc -l 2>/dev/null) -eq 1 ]]; then
            bars=$(echo "scale=1; (${dur_sec:-0} / ${max_dur_sec}) * 14 + 0.5" | bc -l 2>/dev/null)
            bars=$(echo "scale=0; $bars / 1" | bc -l 2>/dev/null)  # Convert to integer
            [[ -z "$bars" || "$bars" -eq 0 ]] && bars=1
            [[ "$bars" -gt 14 ]] && bars=14
        fi
        local progress=$(printf "█%.0s" $(seq 1 $bars))
        if [[ $bars -lt 14 ]]; then
            progress="$progress$(printf ".%.0s" $(seq 1 $((14 - bars))))"
        fi
        # Only show operations with non-zero cost
        if [[ $(echo "${cost:-0} > 0" | bc -l 2>/dev/null) -eq 1 ]]; then
            # Format output with clipped operation name
            printf "│ %s | %-28s | \$%6.4f | %5.1fs | %s\n" \
                "$time_str" "${operation:0:28}" "${cost:-0}" "$dur_sec" "$progress"
        fi
    done
    echo "└───────────────────────────────────────────────────────────────────────────────┘"
    echo ""
    echo "TOTALS: $(printf "%'d" ${tokens:-0} 2>/dev/null || echo ${tokens:-0}) tokens | ${tool_count:-0} tool uses | Sidechain: Yes"
}
# Main execution
if [[ $# -eq 1 ]]; then
    session_file="$CLAUDE_DIR/$1"
    [[ ! -f "$session_file" ]] && { echo "Error: File not found: $1"; exit 1; }
else
    session_file=$(find_task_session)
    [[ $? -ne 0 ]] && { echo "No Task sessions found"; exit 1; }
fi
show_breakdown "$session_file"
See Also: Task Agent Tools|CC Usage|Context Window Depletion
Last updated: June 2, 2025

