Completed
on 5 Jan 2026, 1:30 am

Output

📊 statusline-token-tracker.sh

/konnectvol/bin/statusline-token-tracker.sh

#!/bin/bash
# Status Line hook for capturing token usage from Claude Code CLI
# Posts FULL JSON data to konsole for raw capture and telemetry aggregation
#
# This script runs on every status line update from Claude Code CLI (~300ms).
# It receives rich JSON data on stdin including token usage, costs, and session info.

# Read JSON input from stdin
input=$(cat)

# Extract key fields for display
MODEL=$(echo "$input" | jq -r '.model.display_name // "unknown"')
SESSION_ID=$(echo "$input" | jq -r '.session_id // ""')
CONTEXT_SIZE=$(echo "$input" | jq -r '.context_window.context_window_size // 200000')
CURRENT_INPUT=$(echo "$input" | jq -r '.context_window.current_usage.input_tokens // 0')
CURRENT_OUTPUT=$(echo "$input" | jq -r '.context_window.current_usage.output_tokens // 0')
TOTAL_INPUT=$(echo "$input" | jq -r '.context_window.total_input_tokens // 0')
TOTAL_OUTPUT=$(echo "$input" | jq -r '.context_window.total_output_tokens // 0')
TOTAL_COST=$(echo "$input" | jq -r '.cost.total_cost_usd // 0')

# Calculate usage percentage
PERCENT_USED=0
if [ "$CONTEXT_SIZE" -gt 0 ]; then
  PERCENT_USED=$(( (CURRENT_INPUT + CURRENT_OUTPUT) * 100 / CONTEXT_SIZE ))
fi

# Post FULL JSON to konsole if we have meaningful data (skip if all zeros)
if [ "$CURRENT_INPUT" -gt 0 ] || [ "$CURRENT_OUTPUT" -gt 0 ] || [ "$TOTAL_COST" != "0" ]; then
  # Fire and forget - don't block the status line
  # Add timestamp to the full input and send to konsole
  (echo "$input" | jq -c '. + {receivedAt: "'"$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)"'"}' | \
    curl -s -X POST "http://localhost:8020/statusline" \
      -H "Content-Type: application/json" \
      -d @- > /dev/null 2>&1 &)
fi

# Output status line display
# Format: [Model] Context% | Cost | Tokens
if [ "$TOTAL_COST" != "0" ]; then
  # Show cost if available
  printf "[%s] %d%% | \$%.4f | %dK in/%dK out" \
    "$MODEL" "$PERCENT_USED" "$TOTAL_COST" \
    "$(( TOTAL_INPUT / 1000 ))" "$(( TOTAL_OUTPUT / 1000 ))"
else
  # Show tokens only
  printf "[%s] %d%% | %dK in/%dK out" \
    "$MODEL" "$PERCENT_USED" \
    "$(( TOTAL_INPUT / 1000 ))" "$(( TOTAL_OUTPUT / 1000 ))"
fi

📋 Script Overview

Purpose Claude Code StatusLine hook for token telemetry
Update Rate ~300ms during active turns
Data Posted To http://localhost:8020/statusline
Storage /konnectvol/konsole/data/statusline-raw.jsonl
Display Format [Model] %% | $cost | XK in/YK out

🔧 Key Features

  • Fire-and-forget - Posts to konsole asynchronously, never blocks
  • Full JSON capture - Sends complete StatusLine data for analysis
  • Timestamp injection - Adds receivedAt field
  • Smart filtering - Only posts when there's meaningful data

Quick Actions

Original Request

No layout configured

Details

Type General
Status Completed
Scope vibetools
Tags konsoletelemetrystatusline
Created 5 Jan 2026, 1:29 am
Updated 5 Jan 2026, 1:30 am
Timing
⏱️ 66.2s
2 tools
TTFE 5% Thinking 95% Tools 1%
Created By claude

Raw Data

{
  "id": "2347e1b6-0d4d-4c1f-b98c-f05d3fe8efd5",
  "type": "general",
  "status": "completed",
  "title": "StatusLine Token Tracker Script",
  "description": "Contents of the statusline-token-tracker.sh hook script",
  "context": {
    "output": "<div style=\"background:#1e1e1e;color:#e0e0e0;padding:20px;border-radius:8px;font-family:'Consolas','Monaco',monospace;\">\n<h2 style=\"font-family:sans-serif;color:#fff;margin:0 0 16px 0;\">📊 statusline-token-tracker.sh</h2>\n<p style=\"font-family:sans-serif;color:#9ca3af;margin:0 0 16px 0;\"><code style=\"background:#2d2d2d;padding:2px 6px;border-radius:4px;\">/konnectvol/bin/statusline-token-tracker.sh</code></p>\n\n<pre style=\"background:#2d2d2d;padding:16px;border-radius:6px;overflow-x:auto;line-height:1.6;color:#e0e0e0;font-size:0.9rem;\"><span style=\"color:#7f848e;\">#!/bin/bash</span>\n<span style=\"color:#7f848e;\"># Status Line hook for capturing token usage from Claude Code CLI</span>\n<span style=\"color:#7f848e;\"># Posts FULL JSON data to konsole for raw capture and telemetry aggregation</span>\n<span style=\"color:#7f848e;\">#</span>\n<span style=\"color:#7f848e;\"># This script runs on every status line update from Claude Code CLI (~300ms).</span>\n<span style=\"color:#7f848e;\"># It receives rich JSON data on stdin including token usage, costs, and session info.</span>\n\n<span style=\"color:#7f848e;\"># Read JSON input from stdin</span>\n<span style=\"color:#e5c07b;\">input</span>=<span style=\"color:#98c379;\">$(cat)</span>\n\n<span style=\"color:#7f848e;\"># Extract key fields for display</span>\n<span style=\"color:#e5c07b;\">MODEL</span>=<span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.model.display_name // \"unknown\"')</span>\n<span style=\"color:#e5c07b;\">SESSION_ID</span>=<span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.session_id // \"\"')</span>\n<span style=\"color:#e5c07b;\">CONTEXT_SIZE</span>=<span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.context_window.context_window_size // 200000')</span>\n<span style=\"color:#e5c07b;\">CURRENT_INPUT</span>=<span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.context_window.current_usage.input_tokens // 0')</span>\n<span style=\"color:#e5c07b;\">CURRENT_OUTPUT</span>=<span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.context_window.current_usage.output_tokens // 0')</span>\n<span style=\"color:#e5c07b;\">TOTAL_INPUT</span>=<span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.context_window.total_input_tokens // 0')</span>\n<span style=\"color:#e5c07b;\">TOTAL_OUTPUT</span>=<span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.context_window.total_output_tokens // 0')</span>\n<span style=\"color:#e5c07b;\">TOTAL_COST</span>=<span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.cost.total_cost_usd // 0')</span>\n\n<span style=\"color:#7f848e;\"># Calculate usage percentage</span>\n<span style=\"color:#e5c07b;\">PERCENT_USED</span>=<span style=\"color:#d19a66;\">0</span>\n<span style=\"color:#c678dd;\">if</span> [ <span style=\"color:#98c379;\">\"$CONTEXT_SIZE\"</span> -gt <span style=\"color:#d19a66;\">0</span> ]; <span style=\"color:#c678dd;\">then</span>\n  <span style=\"color:#e5c07b;\">PERCENT_USED</span>=<span style=\"color:#98c379;\">$(( (CURRENT_INPUT + CURRENT_OUTPUT) * 100 / CONTEXT_SIZE ))</span>\n<span style=\"color:#c678dd;\">fi</span>\n\n<span style=\"color:#7f848e;\"># Post FULL JSON to konsole if we have meaningful data (skip if all zeros)</span>\n<span style=\"color:#c678dd;\">if</span> [ <span style=\"color:#98c379;\">\"$CURRENT_INPUT\"</span> -gt <span style=\"color:#d19a66;\">0</span> ] || [ <span style=\"color:#98c379;\">\"$CURRENT_OUTPUT\"</span> -gt <span style=\"color:#d19a66;\">0</span> ] || [ <span style=\"color:#98c379;\">\"$TOTAL_COST\"</span> != <span style=\"color:#98c379;\">\"0\"</span> ]; <span style=\"color:#c678dd;\">then</span>\n  <span style=\"color:#7f848e;\"># Fire and forget - don't block the status line</span>\n  <span style=\"color:#7f848e;\"># Add timestamp to the full input and send to konsole</span>\n  (<span style=\"color:#c678dd;\">echo</span> <span style=\"color:#98c379;\">\"$input\"</span> | jq -c <span style=\"color:#98c379;\">'. + {receivedAt: \"'\"$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ)\"'\"}'</span> | \\\n    curl -s -X POST <span style=\"color:#98c379;\">\"http://localhost:8020/statusline\"</span> \\\n      -H <span style=\"color:#98c379;\">\"Content-Type: application/json\"</span> \\\n      -d @- > /dev/null 2>&1 &)\n<span style=\"color:#c678dd;\">fi</span>\n\n<span style=\"color:#7f848e;\"># Output status line display</span>\n<span style=\"color:#7f848e;\"># Format: [Model] Context% | Cost | Tokens</span>\n<span style=\"color:#c678dd;\">if</span> [ <span style=\"color:#98c379;\">\"$TOTAL_COST\"</span> != <span style=\"color:#98c379;\">\"0\"</span> ]; <span style=\"color:#c678dd;\">then</span>\n  <span style=\"color:#7f848e;\"># Show cost if available</span>\n  printf <span style=\"color:#98c379;\">\"[%s] %d%% | \\$%.4f | %dK in/%dK out\"</span> \\\n    <span style=\"color:#98c379;\">\"$MODEL\"</span> <span style=\"color:#98c379;\">\"$PERCENT_USED\"</span> <span style=\"color:#98c379;\">\"$TOTAL_COST\"</span> \\\n    <span style=\"color:#98c379;\">\"$(( TOTAL_INPUT / 1000 ))\"</span> <span style=\"color:#98c379;\">\"$(( TOTAL_OUTPUT / 1000 ))\"</span>\n<span style=\"color:#c678dd;\">else</span>\n  <span style=\"color:#7f848e;\"># Show tokens only</span>\n  printf <span style=\"color:#98c379;\">\"[%s] %d%% | %dK in/%dK out\"</span> \\\n    <span style=\"color:#98c379;\">\"$MODEL\"</span> <span style=\"color:#98c379;\">\"$PERCENT_USED\"</span> \\\n    <span style=\"color:#98c379;\">\"$(( TOTAL_INPUT / 1000 ))\"</span> <span style=\"color:#98c379;\">\"$(( TOTAL_OUTPUT / 1000 ))\"</span>\n<span style=\"color:#c678dd;\">fi</span></pre>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-top:16px;font-family:sans-serif;\">\n<h4 style=\"margin:0 0 12px 0;color:#fff;\">📋 Script Overview</h4>\n<table style=\"width:100%;border-collapse:collapse;font-size:0.9rem;\">\n<tr style=\"border-bottom:1px solid #444;\">\n  <td style=\"padding:8px 12px;color:#9ca3af;\">Purpose</td>\n  <td style=\"padding:8px 12px;color:#e0e0e0;\">Claude Code StatusLine hook for token telemetry</td>\n</tr>\n<tr style=\"border-bottom:1px solid #444;\">\n  <td style=\"padding:8px 12px;color:#9ca3af;\">Update Rate</td>\n  <td style=\"padding:8px 12px;color:#e0e0e0;\">~300ms during active turns</td>\n</tr>\n<tr style=\"border-bottom:1px solid #444;\">\n  <td style=\"padding:8px 12px;color:#9ca3af;\">Data Posted To</td>\n  <td style=\"padding:8px 12px;color:#61afef;\">http://localhost:8020/statusline</td>\n</tr>\n<tr style=\"border-bottom:1px solid #444;\">\n  <td style=\"padding:8px 12px;color:#9ca3af;\">Storage</td>\n  <td style=\"padding:8px 12px;color:#e0e0e0;\">/konnectvol/konsole/data/statusline-raw.jsonl</td>\n</tr>\n<tr>\n  <td style=\"padding:8px 12px;color:#9ca3af;\">Display Format</td>\n  <td style=\"padding:8px 12px;color:#98c379;font-family:monospace;\">[Model] %% | $cost | XK in/YK out</td>\n</tr>\n</table>\n</div>\n\n<div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-top:16px;font-family:sans-serif;\">\n<h4 style=\"margin:0 0 12px 0;color:#fff;\">🔧 Key Features</h4>\n<ul style=\"margin:0;padding-left:20px;color:#e0e0e0;line-height:1.8;\">\n<li><strong style=\"color:#98c379;\">Fire-and-forget</strong> - Posts to konsole asynchronously, never blocks</li>\n<li><strong style=\"color:#61afef;\">Full JSON capture</strong> - Sends complete StatusLine data for analysis</li>\n<li><strong style=\"color:#e5c07b;\">Timestamp injection</strong> - Adds <code style=\"background:#1e1e1e;padding:2px 4px;border-radius:2px;\">receivedAt</code> field</li>\n<li><strong style=\"color:#c678dd;\">Smart filtering</strong> - Only posts when there's meaningful data</li>\n</ul>\n</div>\n\n</div>",
    "requestedAt": "2026-01-05T12:00:00.000Z",
    "requestId": "c7a4e9f0-e659-4965-8c3d-2399871787da",
    "turnTiming": {
      "totalMs": 66239,
      "ttfeMs": 3193,
      "thinkingMs": 62665,
      "toolExecutionMs": 377,
      "toolCallCount": 2,
      "thinkingPct": 95,
      "toolsPct": 1,
      "ttfePct": 5
    }
  },
  "createdBy": "claude",
  "createdAt": "2026-01-04T15:29:54.037Z",
  "updatedAt": "2026-01-04T15:30:03.968Z",
  "requestId": "c7a4e9f0-e659-4965-8c3d-2399871787da",
  "scope": "vibetools",
  "tags": [
    "konsole",
    "telemetry",
    "statusline"
  ],
  "targetUser": "claude"
}
DashboardReportsKontasksSessionsTelemetryLogs + Go