--- name: usage description: Track and report model usage across sessions allowed-tools: - Bash - Read --- # Usage Tracking Skill Query session history and report usage statistics. ## Data Sources | Source | Status | Data Available | |--------|--------|----------------| | `history/index.json` | Available | Session IDs, start times | | `history/*.jsonl` | Future | Session content, commands, tokens | | `usage/config.json` | Available | Log level, preferences | ## Command Routing | Command | Action | |---------|--------| | `/usage` | Show last 7 days summary | | `/usage today` | Today's sessions | | `/usage week` | Last 7 days | | `/usage month` | Last 30 days | | `/usage all` | All time stats | | `/usage --by agent` | Group by agent | | `/usage --by skill` | Group by skill | | `/usage --by model` | Group by model tier | | `/usage --set-level ` | Set log level | | `/usage --show-config` | Show current config | ## Log Levels | Level | Data Captured | |-------|---------------| | `minimal` | Session ID, time, model | | `standard` | + agents, skills, tokens (default) | | `detailed` | + commands, delegations, errors | ## Implementation ### Query Sessions ```python import json from datetime import datetime, timedelta from pathlib import Path from zoneinfo import ZoneInfo LOCAL_TZ = ZoneInfo('America/Los_Angeles') HISTORY_DIR = Path.home() / ".claude/state/personal-assistant/history" CONFIG_PATH = Path.home() / ".claude/state/usage/config.json" def load_sessions(): index_path = HISTORY_DIR / "index.json" if not index_path.exists(): return [] with open(index_path) as f: data = json.load(f) return data.get("sessions", []) def filter_sessions(sessions, range_type="week"): now = datetime.now(LOCAL_TZ) if range_type == "today": cutoff = now.replace(hour=0, minute=0, second=0, microsecond=0) elif range_type == "week": cutoff = now - timedelta(days=7) elif range_type == "month": cutoff = now - timedelta(days=30) else: # all return sessions filtered = [] for s in sessions: started = datetime.fromisoformat(s["started"]) if started >= cutoff: filtered.append(s) return filtered def estimate_duration(sessions): """Estimate session duration from consecutive start times.""" if not sessions: return [] sorted_sessions = sorted(sessions, key=lambda s: s["started"]) for i, session in enumerate(sorted_sessions): if i + 1 < len(sorted_sessions): start = datetime.fromisoformat(session["started"]) next_start = datetime.fromisoformat(sorted_sessions[i + 1]["started"]) duration = (next_start - start).total_seconds() / 60 # Cap at 2 hours (likely session gap) session["duration_mins"] = min(duration, 120) else: # Current/last session: estimate 30 mins session["duration_mins"] = 30 return sorted_sessions ``` ### Generate Report ```python def generate_report(sessions, range_type="week"): total_mins = sum(s.get("duration_mins", 0) for s in sessions) hours = int(total_mins // 60) mins = int(total_mins % 60) report = f""" 📊 Usage Summary — {range_type.title()} Sessions: {len(sessions)} Total time: {hours}h {mins}m Model: opus (primary) """ return report ``` ## Output Format ``` 📊 Usage Summary — Last 7 Days Sessions: 12 Total time: 8h 32m Model: opus (primary) ┌─────────────┬──────────┬────────┐ │ Agent │ Sessions │ Time │ ├─────────────┼──────────┼────────┤ │ PA │ 12 │ 8h 32m │ └─────────────┴──────────┴────────┘ Note: Detailed metrics available when session content logging is enabled. ``` ## Future Enhancements When `history/*.jsonl` files are available: - Parse actual commands used - Detect skill invocations - Count delegations (sonnet/haiku) - Estimate token usage - Track errors ## Policy - Read-only operations - No external API calls - Local data only