A passive time-capture and attribution assistant for Productive.
TidyTime is a native macOS menu bar app that watches how you actually spend your workday — foreground apps and window titles, Chrome (URL, title, visible page text), Google Calendar, Fathom meeting transcripts, and Slack — reconstructs the day into loggable blocks, matches each block to your Productive client → project → task, and hands you ready-to-enter time entries: the task, a duration rounded to 15 minutes, and a one-to-two sentence note with a copy button and a deep link.
It recommends; you enter. v1 is read-only against Productive — nothing is ever written back. It's built for backfill, not stopwatch discipline: capture everything passively, attribute afterward, and at end of day (or first thing the next morning) reconcile a whole day in a few minutes instead of an end-of-week archaeology session.
Status: running in production (one user), signed and validated on a real Mac. All seven phases (0–6) of logic ship as tested SwiftPM targets under
Packages/TidyKit— 401 unit tests, 0 failures — covering capture, the read-only Productive mirror, Fathom/Calendar/Slack ingest, the classification ladder, the suggestion engine, the metered AI router, and the Google OAuth sign-in flow. The macOS app inApp/hosts those modules and has been launched and validated live (2026-07-25→27): signed dmg installed, TCC grants persisting, capture banking real sessions, credentials in the Keychain, and live Slack/Fathom syncs exercised (whose first-run failures were found and fixed exactly this way). Still awaiting first live use: the Google sign-in click and the cloud AI rungs. New here, or scoping the MVP? docs/MVP-HANDOFF.md — what the alpha measurably does today, what is written but dark, and what the MVP still needs. Running it: docs/RUNNING.md · review history in docs/PROJECT-REVIEW.md.
The billable time you forget is the time that never got captured: the 15 client minutes inside an hour-long colleague call, the drive-by Slack DMs, the block you'd have misremembered a week later. TidyTime's job is to surface exactly that, with enough context that logging it is a copy-paste.
CAPTURE (local) INGEST (read-only APIs)
app & window watcher Productive · Fathom
Chrome URL/title/text Google Calendar · Slack
idle / away · meeting state
└──────────────┬─────────────────┘
▼
STORE — SQLite (GRDB) + Keychain
▼
UNDERSTAND — sessionize · resolve entities ·
classification ladder (rules → lexical → on-device
→ economy cloud → escalation) · sensitivity gate
▼
SUGGEST — round · pool micro-work · split meetings ·
gap-analyze vs. what's already logged
▼
SURFACE — menu bar · nudges · end-of-day recap ·
dashboard · settings
Everything runs in one menu bar process. Sensitive content (personnel, comp, legal) never leaves the machine. Every cloud AI call is metered and budget-capped. Full architecture: docs/architecture/overview.md.
| Path | What |
|---|---|
| PLAN.md | The canonical vision & scope (source of truth) |
| CLAUDE.md | Orchestration brief + prime directives (loaded by Claude Code) |
| docs/ | All reference, architecture, phase, and decision docs |
project.yml |
XcodeGen spec for the app target |
App/ |
Thin app shell (@main, Info.plist, entitlements) |
Packages/TidyKit/ |
All logic, as SwiftPM library targets |
config.example.json |
Reference for every non-secret setting. Not the runtime file — the app writes a starter ~/Library/Application Support/TidyTime/config.json on first launch and never overwrites it. |
Prerequisites: macOS 14+ (macOS 26 + Apple Intelligence unlocks the on-device model rung), Xcode 16+, Homebrew. Hardware floor: Apple Silicon (M2 or newer).
make bootstrap # installs XcodeGen, generates TidyTime.xcodeproj
cp Local.xcconfig.example Local.xcconfig # then set DEVELOPMENT_TEAM (a free Apple ID works)
make build # build the app
make run # build + launch (icon appears in the menu bar)
make test # run the TidyKit unit testsImportant — stable signing. macOS ties Accessibility/Automation permission grants to the code signature. Sign with a stable identity (personal team) so grants survive rebuilds; an ad-hoc or rotating signature silently drops them. See docs/build/signing-and-tcc.md. One-time human setup (permissions, tokens, OAuth): docs/permissions-setup.md.
Capture-first and strictly ordered; each phase ends in something usable with a human-verifiable acceptance check.
- Skeleton — menu bar, DB, config, signing
- Capture — watcher, Chrome, idle, sessionization
- Productive mirror — read-only sync
- Meetings & calendar — Fathom, Google
- Slack — DM/channel ingest
- Recap & rules — suggestion engine + recap UI
- Intelligence — gate, on-device, cloud router, ledger, nudges
- Read-only against Productive. No write call exists in v1.
- Sensitivity gate fails closed. Personnel/comp/legal content never reaches a cloud model.
- No Screen Recording permission is requested — window titles come from Accessibility.
- Secrets in Keychain only; local data stays on one Mac, purged on a retention schedule.
Details and enforcement: docs/guardrails.md.
Private / internal (4Site Studios). Not for redistribution.