Add token-stats slash command
This commit is contained in:
76
commands/token-stats.md
Normal file
76
commands/token-stats.md
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
description: Show Claude token usage statistics per user. Usage: /token-stats [username|all]
|
||||
argument-hint: [username|all]
|
||||
allowed-tools: [Bash]
|
||||
---
|
||||
|
||||
Show Claude token usage statistics from local session files.
|
||||
|
||||
## Arguments
|
||||
|
||||
The user invoked this command with: $ARGUMENTS
|
||||
|
||||
## Instructions
|
||||
|
||||
1. Parse the argument:
|
||||
- No argument → use the current system user (`whoami`) as the target
|
||||
- A specific username → use that username
|
||||
- `all` → show stats for all users (including root)
|
||||
|
||||
2. To resolve a user's home directory, use this logic:
|
||||
- `root` → `/root`
|
||||
- anything else → `/home/{user}`
|
||||
|
||||
3. For a **single user**, run this Bash command (substitute `TARGET_USER` and `TARGET_HOME`):
|
||||
|
||||
```bash
|
||||
python3 << 'PYEOF'
|
||||
import glob, json
|
||||
from collections import defaultdict
|
||||
|
||||
user = "TARGET_USER"
|
||||
user_home = "TARGET_HOME"
|
||||
stats = defaultdict(lambda: {'input': 0, 'output': 0, 'cache_write': 0, 'cache_read': 0, 'sessions': set()})
|
||||
|
||||
for f in glob.glob(f'{user_home}/.claude/projects/**/*.jsonl', recursive=True):
|
||||
session_id = f.split('/')[-1].replace('.jsonl', '')
|
||||
for line in open(f, errors='ignore'):
|
||||
try:
|
||||
d = json.loads(line)
|
||||
u = d.get('message', {}).get('usage', {})
|
||||
if not u:
|
||||
continue
|
||||
ts = d.get('timestamp', '')
|
||||
date = ts[:10] if ts else 'unknown'
|
||||
stats[date]['input'] += u.get('input_tokens', 0)
|
||||
stats[date]['output'] += u.get('output_tokens', 0)
|
||||
stats[date]['cache_write'] += u.get('cache_creation_input_tokens', 0)
|
||||
stats[date]['cache_read'] += u.get('cache_read_input_tokens', 0)
|
||||
stats[date]['sessions'].add(session_id)
|
||||
except:
|
||||
pass
|
||||
|
||||
if not stats:
|
||||
print(f"No token data found for user: {user}")
|
||||
else:
|
||||
print(f"\n=== Token Usage: {user} ===\n")
|
||||
print(f"{'Date':<12} {'Input':>12} {'Output':>12} {'Cache Write':>12} {'Cache Read':>12} {'Sessions':>9}")
|
||||
print('-' * 72)
|
||||
total_in = total_out = total_cw = total_cr = 0
|
||||
for date in sorted(stats.keys()):
|
||||
s = stats[date]
|
||||
total_in += s['input']
|
||||
total_out += s['output']
|
||||
total_cw += s['cache_write']
|
||||
total_cr += s['cache_read']
|
||||
print(f"{date:<12} {s['input']:>12,} {s['output']:>12,} {s['cache_write']:>12,} {s['cache_read']:>12,} {len(s['sessions']):>9}")
|
||||
print('-' * 72)
|
||||
print(f"{'Total':<12} {total_in:>12,} {total_out:>12,} {total_cw:>12,} {total_cr:>12,}")
|
||||
print(f"\nActual tokens (input+output): {total_in + total_out:,}")
|
||||
print(f"Cache reads (free on Max plan): {total_cr:,}")
|
||||
PYEOF
|
||||
```
|
||||
|
||||
4. For **all users**, collect home dirs from `/home/*/` plus `/root`, run the same logic for each, then print a grand total.
|
||||
|
||||
5. Present output in a code block.
|
||||
Reference in New Issue
Block a user