Implement /usage command for session tracking (fc-005)
Components: - commands/usage.md: Slash command with aliases (stats) - skills/usage/SKILL.md: Query logic and report generation - state/usage/config.json: Log level and preferences Features: - Parse history/index.json for session metadata - Estimate duration from consecutive session starts - Group by date, show summary stats - Configurable log levels (minimal/standard/detailed) - Extensible for future session content parsing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
66
commands/usage.md
Normal file
66
commands/usage.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
name: usage
|
||||||
|
description: View model usage statistics and session history
|
||||||
|
aliases: [stats]
|
||||||
|
invokes: skill:usage
|
||||||
|
---
|
||||||
|
|
||||||
|
# /usage Command
|
||||||
|
|
||||||
|
View usage statistics across Claude Code sessions.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
/usage # Summary (last 7 days)
|
||||||
|
/usage today # Today's sessions
|
||||||
|
/usage week # Last 7 days (default)
|
||||||
|
/usage month # Last 30 days
|
||||||
|
/usage all # All time
|
||||||
|
```
|
||||||
|
|
||||||
|
## Grouping
|
||||||
|
|
||||||
|
```
|
||||||
|
/usage --by agent # Group by agent
|
||||||
|
/usage --by skill # Group by skill
|
||||||
|
/usage --by model # Group by model tier
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
```
|
||||||
|
/usage --set-level minimal|standard|detailed
|
||||||
|
/usage --show-config
|
||||||
|
```
|
||||||
|
|
||||||
|
## Log Levels
|
||||||
|
|
||||||
|
| Level | Data Captured |
|
||||||
|
|-------|---------------|
|
||||||
|
| `minimal` | Session ID, time, model |
|
||||||
|
| `standard` | + agents, skills, tokens (default) |
|
||||||
|
| `detailed` | + commands, delegations, errors |
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
```
|
||||||
|
📊 Usage Summary — Last 7 Days
|
||||||
|
|
||||||
|
Sessions: 12
|
||||||
|
Total time: 8h 32m
|
||||||
|
Model: opus (primary)
|
||||||
|
|
||||||
|
┌─────────────┬──────────┬────────┐
|
||||||
|
│ Agent │ Sessions │ Time │
|
||||||
|
├─────────────┼──────────┼────────┤
|
||||||
|
│ PA │ 12 │ 8h 32m │
|
||||||
|
│ sysadmin │ 4 │ 1h 15m │
|
||||||
|
└─────────────┴──────────┴────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Data Sources
|
||||||
|
|
||||||
|
- Session metadata from `~/.claude/state/personal-assistant/history/index.json`
|
||||||
|
- Configuration from `~/.claude/state/usage/config.json`
|
||||||
|
- Session content from `history/*.jsonl` (when available)
|
||||||
153
skills/usage/SKILL.md
Normal file
153
skills/usage/SKILL.md
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
---
|
||||||
|
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 <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
|
||||||
8
state/usage/config.json
Normal file
8
state/usage/config.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0",
|
||||||
|
"log_level": "standard",
|
||||||
|
"default_range": "week",
|
||||||
|
"track_tokens": true,
|
||||||
|
"model": "opus",
|
||||||
|
"notes": "Session content parsing available when history/*.jsonl files exist"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user