#!/usr/bin/env python3 """Generate usage statistics from session history.""" import json import sys 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(): """Load sessions from history index.""" 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"): """Filter sessions by time range.""" 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: try: started = datetime.fromisoformat(s["started"]) if started.tzinfo is None: started = started.replace(tzinfo=LOCAL_TZ) if started >= cutoff: filtered.append(s) except (KeyError, ValueError): continue 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 def generate_report(sessions, range_type="week"): """Generate usage report.""" sessions = estimate_duration(sessions) total_mins = sum(s.get("duration_mins", 0) for s in sessions) hours = int(total_mins // 60) mins = int(total_mins % 60) # Group by date by_date = {} for s in sessions: date = s["started"][:10] by_date.setdefault(date, []).append(s) report = f"""šŸ“Š Usage Summary — {range_type.title()} Sessions: {len(sessions)} Total time: {hours}h {mins}m Days active: {len(by_date)} Model: opus (primary) """ if by_date: report += "\nšŸ“… Sessions by Date:\n" for date in sorted(by_date.keys(), reverse=True)[:7]: count = len(by_date[date]) day_mins = sum(s.get("duration_mins", 0) for s in by_date[date]) report += f" {date}: {count} sessions ({int(day_mins)}m)\n" return report def main(): range_type = sys.argv[1] if len(sys.argv) > 1 else "week" sessions = load_sessions() filtered = filter_sessions(sessions, range_type) report = generate_report(filtered, range_type) print(report) if __name__ == "__main__": main()