update cc statusline

This commit is contained in:
David Chen 2025-09-09 17:48:34 -07:00
parent 02eea13aa6
commit 0487e8b3ba
4 changed files with 171 additions and 14 deletions

View file

@ -1,14 +1,29 @@
{ {
"version": 3, "version": 3,
"lines": [ "lines": [
[
{
"id": "95e108c1-bf22-4a23-94c8-be096ccaf8c8",
"type": "model"
},
{
"id": "222b40b7-1291-4090-a0ae-bc43637241b3",
"type": "custom-command",
"commandPath": "uv run ~/.config/claude/scripts/context-status.py"
},
{
"id": "64a1187d-65c6-4490-9f30-fa618da8b8ce",
"type": "output-style"
}
],
[ [
{ {
"id": "9fc4ae79-f172-4d4b-b7f8-c2c3e923e7aa", "id": "9fc4ae79-f172-4d4b-b7f8-c2c3e923e7aa",
"type": "current-working-dir", "type": "current-working-dir",
"color": "white",
"commandPath": "pwd | xargs basename", "commandPath": "pwd | xargs basename",
"preserveColors": true, "preserveColors": true,
"timeout": 5000, "timeout": 5000
"color": "white"
}, },
{ {
"id": "4f12f8ba-4728-4590-ac5d-8c2b96ec91e8", "id": "4f12f8ba-4728-4590-ac5d-8c2b96ec91e8",
@ -23,12 +38,33 @@
"type": "version" "type": "version"
} }
], ],
[], [
[] {
"id": "032c2103-52cd-42fd-9e03-325ee4dfc6c7",
"type": "session-cost"
},
{
"id": "e7177c91-ecb8-422d-9496-b380d05d6e6b",
"type": "session-clock"
},
{
"id": "5aef38b5-a24f-40a7-b201-afd3a5870f2d",
"type": "custom-command",
"commandPath": "echo \"$(ccusage daily --json | jq -r 'if type == \\\"array\\\" then .[-1] else . end | if .totalCostUSD then \\\"$\\\" + (.totalCostUSD | tostring) else \\\"$0.00\\\" end') 📅\"",
"timeout": 10000
},
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "custom-command",
"commandPath": "ccusage blocks --active --json | jq -r '.blocks[0] | \"$\" + (.costUSD | . * 100 | round / 100 | tostring) + \" block (\" + (.projection.remainingMinutes / 60 | floor | tostring) + \"h \" + (.projection.remainingMinutes % 60 | tostring) + \"m left)\"'",
"timeout": 10000
}
]
], ],
"flexMode": "full", "flexMode": "full",
"compactThreshold": 60, "compactThreshold": 60,
"colorLevel": 2, "colorLevel": 2,
"defaultPadding": " ",
"inheritSeparatorColors": false, "inheritSeparatorColors": false,
"globalBold": false, "globalBold": false,
"powerline": { "powerline": {
@ -41,8 +77,7 @@
], ],
"startCaps": [], "startCaps": [],
"endCaps": [], "endCaps": [],
"autoAlign": false, "theme": "nord-aurora",
"theme": "nord-aurora" "autoAlign": false
}, }
"defaultPadding": " "
} }

View file

@ -0,0 +1,72 @@
#!/usr/bin/env python3
import json
import sys
# Constant
CONTEXT_LIMIT = int(168000) # CC triggers /compact at ~78% context utilization
# Read JSON from stdin
data = json.load(sys.stdin)
transcript_path = data["transcript_path"]
# Parse transcript file to calculate context usage
context_used_token = 0
try:
with open(transcript_path, "r") as f:
lines = f.readlines()
# Iterate from last line to first line
for line in reversed(lines):
line = line.strip()
if not line:
continue
try:
obj = json.loads(line)
# Check if this line contains the required token usage fields
if (
obj.get("type") == "assistant"
and "message" in obj
and "usage" in obj["message"]
and all(
key in obj["message"]["usage"]
for key in [
"input_tokens",
"cache_creation_input_tokens",
"cache_read_input_tokens",
"output_tokens",
]
)
):
usage = obj["message"]["usage"]
input_tokens = usage["input_tokens"]
cache_creation_input_tokens = usage["cache_creation_input_tokens"]
cache_read_input_tokens = usage["cache_read_input_tokens"]
output_tokens = usage["output_tokens"]
context_used_token = (
input_tokens
+ cache_creation_input_tokens
+ cache_read_input_tokens
+ output_tokens
)
break # Break after finding the first occurrence
except json.JSONDecodeError:
# Skip malformed JSON lines
continue
except FileNotFoundError:
# If transcript file doesn't exist, keep context_used_token as 0
pass
context_used_rate = (context_used_token / CONTEXT_LIMIT) * 100
# Create progress bar
bar_length = 20
filled_length = int(bar_length * context_used_token // CONTEXT_LIMIT)
bar = "" * filled_length + "" * (bar_length - filled_length)
print(f"[{bar}] {context_used_rate:.1f}% ({context_used_token:,})")

50
claude/scripts/usage-line.sh Executable file
View file

@ -0,0 +1,50 @@
#!/bin/bash
# Get current session cost (assuming current working directory as session)
session_data=$(ccusage session --json | jq -r '.sessions[] | select(.sessionId == "'"$(pwd | sed 's|/|-|g')"'") | .totalCost')
session_cost=${session_data:-0}
# Get today's cost
today_cost=$(ccusage daily --json | jq -r '.daily[0].totalCost // 0')
# Get current active block info
block_info=$(ccusage blocks --json | jq -r '
.blocks[] |
select(.isActive == true) |
"\(.costUSD // 0)|\(.startTime)|\(.endTime)"
')
if [[ -n "$block_info" ]]; then
block_cost=$(echo "$block_info" | cut -d'|' -f1)
start_time=$(echo "$block_info" | cut -d'|' -f2)
end_time=$(echo "$block_info" | cut -d'|' -f3)
# Calculate time left in block (5 hours from start)
start_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%S.%fZ" "$start_time" +%s 2>/dev/null || date -d "$start_time" +%s 2>/dev/null || echo "0")
current_epoch=$(date +%s)
elapsed_seconds=$((current_epoch - start_epoch))
remaining_seconds=$((18000 - elapsed_seconds)) # 5 hours = 18000 seconds
if [[ $remaining_seconds -gt 0 ]]; then
hours=$((remaining_seconds / 3600))
minutes=$(((remaining_seconds % 3600) / 60))
time_left="${hours}h ${minutes}m left"
else
time_left="expired"
fi
# Calculate hourly rate
if [[ $elapsed_seconds -gt 0 ]]; then
hourly_rate=$(echo "scale=2; $block_cost * 3600 / $elapsed_seconds" | bc -l 2>/dev/null || echo "0.00")
else
hourly_rate="0.00"
fi
else
block_cost="0.00"
time_left="no active block"
hourly_rate="0.00"
fi
# Format output
printf "💰 \$%.2f session / \$%.2f today / \$%.2f block (%s) | 🔥 \$%.2f/hr\n" \
"$session_cost" "$today_cost" "$block_cost" "$time_left" "$hourly_rate"

View file

@ -1,11 +1,6 @@
{ {
"model": "opusplan",
"includeCoAuthoredBy": false, "includeCoAuthoredBy": false,
"statusLine": { "model": "opusplan",
"type": "command",
"command": "bash ~/.config/claude/scripts/statusline.sh",
"padding": 0
},
"hooks": { "hooks": {
"Stop": [ "Stop": [
{ {
@ -18,5 +13,10 @@
] ]
} }
] ]
"statusLine": {
"type": "command",
"command": "bunx -y ccstatusline@latest",
"padding": 0
},
} }
} }