time-audit
/time-audit — Weekly Time Audit
Run a personal time audit using macOS Screen Time data and Chrome history. Produces an HTML visualization showing where time actually went and how to improve.
Instructions
Step 0: Pre-flight check
Run these in parallel:
- Verify Full Disk Access:
sqlite3 ~/Library/Application\ Support/Knowledge/knowledgeC.db ".tables" 2>&1 - Check system timezone:
date - Find all Chrome History files:
find ~/Library/Application\ Support/Google/Chrome/ -name "History" 2>/dev/null
If knowledgeC.db returns a permissions error, stop and tell the user:
"Terminal needs Full Disk Access to read Screen Time data. Go to System Settings → Privacy & Security → Full Disk Access → enable Terminal. Then re-run /time-audit."
Step 1: Get context (REQUIRED — do not skip)
Before pulling any data, ask the user these questions in a single message:
Quick context before I pull the data:
- What's your role and what does a good week look like for you? (e.g. "GM of Courses — good week = 3+ hours of deep work daily, Slack under control")
- What are you hoping to learn or fix? (e.g. "I think I'm spending too much time reactive", "I want to see if weekends are bleeding into work", "just curious")
- Any apps or sites you already know are time drains you want to flag?
Wait for the user's answers before proceeding. These answers frame all findings.
Step 2: Pull knowledgeC data
Run in parallel:
Query A — Weekly app totals:
SELECT
ZOBJECT.ZVALUESTRING as app,
ROUND(SUM(ZOBJECT.ZENDDATE - ZOBJECT.ZSTARTDATE) / 3600.0, 2) as total_hours,
COUNT(*) as sessions
FROM ZOBJECT
WHERE ZOBJECT.ZSTREAMNAME = '/app/usage'
AND ZOBJECT.ZSTARTDATE > (strftime('%s', 'now') - 978307200 - 7*86400)
AND ZOBJECT.ZVALUESTRING IS NOT NULL
GROUP BY app
ORDER BY total_hours DESC;
Query B — Daily totals with correct day labels:
SELECT
date(ZOBJECT.ZSTARTDATE + 978307200, 'unixepoch', 'localtime') as day,
strftime('%A', ZOBJECT.ZSTARTDATE + 978307200, 'unixepoch', 'localtime') as weekday,
ROUND(SUM(ZOBJECT.ZENDDATE - ZOBJECT.ZSTARTDATE) / 3600.0, 2) as total_hours
FROM ZOBJECT
WHERE ZOBJECT.ZSTREAMNAME = '/app/usage'
AND ZOBJECT.ZSTARTDATE > (strftime('%s', 'now') - 978307200 - 7*86400)
GROUP BY day
ORDER BY day DESC;
Note: knowledgeC timestamps use CoreData epoch (Jan 1, 2001). Add 978307200 to convert to Unix. Use localtime — never hard-code a UTC offset.
Step 3: Pull Chrome history
Find the active profiles: Copy each History file to /tmp, then compare MAX(last_visit_time) across all profiles. Only query profiles with data from the last 7 days.
for profile in "Default" "Profile 1" "Profile 2" "Profile 3" "Profile 4" "Profile 5" "Profile 6"; do
db="/Users/$(whoami)/Library/Application Support/Google/Chrome/$profile/History"
cp "$db" "/tmp/chrome_${profile// /_}.db" 2>/dev/null
result=$(sqlite3 "/tmp/chrome_${profile// /_}.db" "SELECT datetime(MAX(last_visit_time)/1000000 - 11644473600, 'unixepoch', 'localtime') FROM urls;" 2>/dev/null)
name=$(cat "/Users/$(whoami)/Library/Application Support/Google/Chrome/$profile/Preferences" 2>/dev/null | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('account_info',[{}])[0].get('email','unknown'))" 2>/dev/null)
echo "$profile ($name): $result"
done
For each active profile (last visit within 7 days), run the site categorization query. Adapt the CASE statement categories to match the user's role and tools — add/remove categories based on the context gathered in Step 1.
Chrome timestamps: last_visit_time / 1000000 - 11644473600 = Unix timestamp. Chrome has visit counts, not time — treat as activity proxy.
Standard category template:
SELECT
CASE
WHEN url LIKE '%mail.google.com%' THEN 'Gmail'
WHEN url LIKE '%docs.google.com%' THEN 'Google Docs/Sheets'
WHEN url LIKE '%drive.google.com%' THEN 'Google Drive'
WHEN url LIKE '%calendar.google.com%' THEN 'Google Calendar'
WHEN url LIKE '%meet.google.com%' THEN 'Google Meet'
WHEN url LIKE '%notion.so%' OR url LIKE '%notion.com%' THEN 'Notion'
WHEN url LIKE '%slack.com%' THEN 'Slack (web)'
WHEN url LIKE '%linkedin.com%' THEN 'LinkedIn'
WHEN url LIKE '%youtube.com%' THEN 'YouTube'
WHEN url LIKE '%claude.ai%' OR url LIKE '%anthropic.com%' THEN 'Claude.ai'
WHEN url LIKE '%github.com%' THEN 'GitHub'
WHEN url LIKE '%zoom.us%' THEN 'Zoom'
WHEN url LIKE '%localhost%' OR url LIKE '%127.0.0.1%' THEN 'Localhost (dev)'
ELSE 'Other'
END as category,
COUNT(*) as visits,
date(last_visit_time/1000000 - 11644473600, 'unixepoch', 'localtime') as day
FROM urls
WHERE last_visit_time/1000000 - 11644473600 > strftime('%s','now') - 7*86400
GROUP BY category, day
ORDER BY day DESC, visits DESC;
Also pull top domains in "Other" to identify unlabeled sinks.
Step 4: Generate HTML visualization
Save to a sensible path — suggest ~/Desktop/time-audit-{month}{year}.html or wherever the user typically works.
The HTML should include:
- 4 stat cards — Total screen time, Deep work hours (terminal/focused tools), top comms app sessions, weekend hours
- Daily bar chart — Color-coded: work days (dark green), personal days (red), mixed (amber), no data (gray), partial (light green). Use actual day names from data — never assign manually.
- App totals — Horizontal bar chart, all apps from knowledgeC
- Chrome breakdown — Work profile vs personal profile side by side, with visit bars
- Where work time goes — Ranked estimated hours per activity
- Findings — 4–6 cards, color-coded green/yellow/red, framed against the user's stated goals from Step 1
Design: clean, minimal, system font, white cards on light gray background. No dependencies — pure HTML/CSS.
Open the file automatically after writing: open <path>
Step 5: Deliver findings
Frame every finding against what the user said in Step 1. Lead with the most surprising or actionable insight, not a summary of what the data shows.
Structure:
- The one thing that stands out most (1 sentence)
- 3–4 specific findings, each tied to the user's stated goals
- 2–3 concrete recommendations — specific and behavioral, not generic ("batch Slack to top of hour" not "use Slack less")
Notes
- Always derive day-of-week from the date — never assign manually. Use
strftime('%A')in SQL or Python'sdate.strftime('%A'). - Chrome history may be locked if Chrome is open. Always
cpto /tmp first. - knowledgeC session count is often more revealing than total time — flag high session counts (200+/day on a single app) as fragmentation signals.
- If a profile has a personal Google account, label it clearly and call out that personal browsing will be visible — let the user decide how much detail they want.
- The HTML output is self-contained and shareable — mention this to the user.
More from kristenschumann/claude-skills
learn
Post-session retrospective: audits efficiency, proposes skill/memory/CLAUDE.md updates, and generates coaching feedback
55executive-critique
Executive critique with two modes: operational (Nick's lens — execution, timelines, dependencies) and strategic (John's lens — ROI, ambition, customer psychology)
2scope
Declares EXPAND/HOLD/REDUCE mode before planning sessions, monitors for scope drift, and maintains a parked ideas list
1kpi-bot
Builds a daily Slack KPI bot: takes any metric + SQL query, creates an n8n workflow that posts daily updates to a Slack channel
1