Output
/konnectvol/bin/statusline-token-tracker.sh
StatusLine hook that captures token telemetry from Claude Code CLI
#!/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 # 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 if [ "$CURRENT_INPUT" -gt 0 ] || [ "$CURRENT_OUTPUT" -gt 0 ]; then # Fire and forget - don't block the status line (echo "$input" | jq -c '. + {receivedAt: ...}' | \ curl -s -X POST "http://localhost:8020/statusline" \ -H "Content-Type: application/json" \ -d @- > /dev/null 2>&1 &) fi # Output status line display printf "[%s] %d%% | $%.4f | %dK in/%dK out" ...
How it works
| Trigger | Runs every ~300ms during active Claude turns |
| Input | Full JSON from Claude Code CLI on stdin |
| Action | POSTs to localhost:8020/statusline (konsole) |
| Output | Formatted status: [Opus] 45% | $0.0234 | 15K in/4K out |
| Storage | Raw JSONL at /konnectvol/konsole/data/statusline-raw.jsonl |
Quick Actions
Original Request
No layout configured
Details
Type
General
Status
Completed
Scope
vibetools
Tags
consoletelemetryconfig
Created
5 Jan 2026, 1:17 am
Updated
5 Jan 2026, 1:17 am
Created By
claude
Raw Data
{
"id": "072bc1e1-bcc2-4b68-84fa-b33d1132c0ad",
"type": "general",
"status": "completed",
"title": "StatusLine Hook Script",
"description": "Token tracker hook script for Claude Code CLI telemetry",
"context": {
"output": "<div style=\"background:#1e1e1e;color:#e0e0e0;padding:20px;border-radius:8px;font-family:'Consolas','Monaco',monospace;\"><h2 style=\"font-family:sans-serif;color:#fff;margin:0 0 16px 0;\">/konnectvol/bin/statusline-token-tracker.sh</h2><p style=\"color:#7f848e;margin:0 0 12px 0;font-family:sans-serif;\">StatusLine hook that captures token telemetry from Claude Code CLI</p><pre style=\"background:#2d2d2d;padding:16px;border-radius:6px;overflow-x:auto;line-height:1.6;margin:0;font-size:0.85rem;\"><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\n<span style=\"color:#7f848e;\"># Read JSON input from stdin</span>\n<span style=\"color:#e5c07b;\">input</span><span style=\"color:#c678dd;\">=</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:#c678dd;\">=</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:#c678dd;\">=</span><span style=\"color:#98c379;\">$(echo \"$input\" | jq -r '.session_id // \"\"')</span>\n<span style=\"color:#e5c07b;\">CONTEXT_SIZE</span><span style=\"color:#c678dd;\">=</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:#c678dd;\">=</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:#c678dd;\">=</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:#c678dd;\">=</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:#c678dd;\">=</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:#c678dd;\">=</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:#c678dd;\">=</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:#c678dd;\">=</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</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:#c678dd;\">then</span>\n <span style=\"color:#7f848e;\"># Fire and forget - don't block the status line</span>\n (echo <span style=\"color:#98c379;\">\"$input\"</span> | jq -c <span style=\"color:#98c379;\">'. + {receivedAt: ...}'</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>\nprintf <span style=\"color:#98c379;\">\"[%s] %d%% | $%.4f | %dK in/%dK out\"</span> ...</pre><div style=\"background:#2d2d2d;padding:16px;border-radius:6px;margin-top:16px;font-family:sans-serif;\"><h4 style=\"margin:0 0 12px 0;color:#fff;\">How it works</h4><table style=\"width:100%;border-collapse:collapse;font-size:0.9rem;\"><tr><td style=\"padding:8px 0;color:#7f848e;vertical-align:top;width:100px;\">Trigger</td><td style=\"padding:8px 0;color:#e0e0e0;\">Runs every ~300ms during active Claude turns</td></tr><tr><td style=\"padding:8px 0;color:#7f848e;vertical-align:top;\">Input</td><td style=\"padding:8px 0;color:#e0e0e0;\">Full JSON from Claude Code CLI on stdin</td></tr><tr><td style=\"padding:8px 0;color:#7f848e;vertical-align:top;\">Action</td><td style=\"padding:8px 0;color:#e0e0e0;\">POSTs to <code style=\"background:#3d3d3d;padding:2px 6px;border-radius:4px;\">localhost:8020/statusline</code> (konsole)</td></tr><tr><td style=\"padding:8px 0;color:#7f848e;vertical-align:top;\">Output</td><td style=\"padding:8px 0;color:#e0e0e0;\">Formatted status: <code style=\"background:#3d3d3d;padding:2px 6px;border-radius:4px;\">[Opus] 45% | $0.0234 | 15K in/4K out</code></td></tr><tr><td style=\"padding:8px 0;color:#7f848e;vertical-align:top;\">Storage</td><td style=\"padding:8px 0;color:#e0e0e0;\">Raw JSONL at <code style=\"background:#3d3d3d;padding:2px 6px;border-radius:4px;\">/konnectvol/konsole/data/statusline-raw.jsonl</code></td></tr></table></div></div>",
"requestedAt": "2026-01-05T14:18:00Z",
"requestId": "ef67fb17-dc17-45a1-b35c-5eb9f9adfe1c",
"choices": [
{
"label": "View raw data",
"value": "Show the last 5 entries from statusline-raw.jsonl",
"primary": true
},
{
"label": "Check konsole",
"value": "Run kon-status to check if konsole is running"
},
{
"label": "View settings",
"value": "Show me the Claude settings.json again"
}
]
},
"createdBy": "claude",
"createdAt": "2026-01-04T15:17:53.228Z",
"updatedAt": "2026-01-04T15:17:53.556Z",
"requestId": "ef67fb17-dc17-45a1-b35c-5eb9f9adfe1c",
"scope": "vibetools",
"tags": [
"console",
"telemetry",
"config"
],
"targetUser": "claude"
}