I've watched smart, organized people use manual time trackers, and the failure mode is always the same.
Monday morning, they remember to start the timer. By Monday afternoon, they switch contexts six times and forget to switch the timer with it. Tuesday, they catch themselves and update Monday's entries from memory. By Wednesday, the timer is on "Email" for four hours because that's the project that was open when they got distracted.
The data is wrong, and the person tracking it knows it's wrong, which means they trust it less, which means they update it less, which means it gets worse. Manual time tracking is a slow-motion collapse.
I tried for years to be the disciplined exception. I'm not. Nobody I know is. So the question becomes: if manual tracking is a fantasy, what does automatic tracking actually capture, and is it good enough?
What "automatic" actually means
There are roughly three things a Mac can know about what you're doing at any given moment, all without you lifting a finger:
Which app is in the foreground. macOS publishes an
NSWorkspacenotification every time the frontmost application changes. That's a hard signal — it knows whether Slack or Xcode is on top.What the focused window says. Most apps name their windows in useful ways. Xcode says the project. Slack says the channel. Chrome says the tab title. That's a soft signal — useful when titles are descriptive, useless when they aren't (looking at you, Finder).
What the active browser tab is. This requires the browser to expose its tab title to an accessibility client, which on macOS means asking the user for explicit Accessibility permission. Opt-in only.
A good automatic Mac time tracker listens to all three. Timex listens to all three. The thing it stores is a stream of rows that look roughly like this:
2026-05-21 14:32:01 | Xcode | timex/AppDelegate.swift
2026-05-21 14:32:02 | Xcode | timex/AppDelegate.swift
2026-05-21 14:32:03 | Xcode | timex/AppDelegate.swift
2026-05-21 14:32:04 | Slack | #engineering
2026-05-21 14:32:05 | Slack | #engineering
2026-05-21 14:32:06 | Chrome | github.com — pull request #482
That's it. Three columns, one row per second. The strip of color in the Today view is just those rows rolled up into contiguous blocks and rendered along a 24-hour line.
The 1 Hz decision
I get asked why we sample once per second instead of every five seconds, or every minute, or every tenth of a second.
Slower than 1 Hz loses the short context switches. If you check a Slack notification for nine seconds and come back to Xcode, a 60-second sampler will record that minute as either all-Xcode or all-Slack depending on which one was up at the moment of capture. Both are wrong. You want to see the nine-second Slack blip.
Faster than 1 Hz doesn't reveal anything new — humans don't switch focus 10 times per second — and it bloats the SQLite file for no informational gain. A workday at 1 Hz is about 30,000 rows. At 10 Hz it's 300,000 rows for the same insight. We optimized for the lower number.
The other thing 1 Hz buys you is honest idle detection. macOS exposes the time since the last user input. If the gap crosses a threshold (Timex defaults to 90 seconds), the row is marked idle. Two consecutive idle rows become an idle block. Idle blocks don't count toward your break timer, so a deep focus session doesn't get unfairly chopped up by a coffee run.
The browser tab question
This is the part of automatic tracking that gets people nervous, and rightly so.
If a Mac time tracker can see the title of the browser tab you're looking at, it can theoretically see "Bank of America" or "MyChart Patient Portal" sitting in your history. The cleanest response is to ask the user before any of that happens. macOS forces us to. The first time you launch Timex, the browser-tab feature is off. You have to explicitly grant Accessibility permission, and you can revoke it any time in System Settings.
When you do grant it, what gets stored is the window title string the browser publishes for the current tab — nothing more. We don't read the URL. We don't read the page content. We don't read your browsing history. We store the same string that's visible in your browser's title bar at that exact moment.
If you'd rather not, leave the permission off and the tracker still works — you just see the browser as a single block ("Chrome — 41m") instead of the per-tab breakdown.
The data model in SQLite
For anyone curious about the storage layer: Timex uses a single SQLite file with a small set of tables. The shape that matters is the activity log, which is roughly:
CREATE TABLE activity_samples (
ts INTEGER NOT NULL, -- unix seconds
app_bundle TEXT, -- e.g. "com.apple.dt.Xcode"
app_name TEXT, -- e.g. "Xcode"
window_title TEXT, -- e.g. "AppDelegate.swift"
browser_tab TEXT, -- nullable, only when permission granted
is_idle INTEGER NOT NULL -- 0 or 1
);
CREATE INDEX idx_samples_ts ON activity_samples(ts);
That's the entire shape of "what did you do today." Open the file with any SQLite client. Run a query. The answer is a few rows away.
I've shared this schema before in Your data, your file — the deeper argument for why the storage layer is the product. The short version: a tool whose only output is a proprietary cloud dashboard ages badly. A tool whose only output is a SQLite file ages with you.
The questions automatic tracking can answer
These are the queries we actually run on our own data:
Where did the morning go? Drag onto the 09:00–12:00 slice of the strip. The totals filter to that window. Tap the top app. Expand to see which windows ate the slice.
Did I make progress on the right thing this week? Sum the time spent in
Xcoderows that have window titles matching the active project name. If it's smaller than expected, that's a calendar problem, not a tracker problem.When was I last actually thinking deeply? Look for the longest contiguous block of
is_idle=0on a single app. If the longest is 28 minutes, the answer is "never this week" — and that's data you can act on.What did Chrome eat? Filter to rows where
app_name='Google Chrome'. Group bybrowser_tab. Sort by count. The top of the list is, depressingly, often Reddit. Or Hacker News. Or one of the two AI vendors whose names rhyme.
The questions it can't
I want to be upfront about the limits.
It can't tell you what you intended to do. It only sees what your foreground app was. If you spent forty minutes on Hacker News researching something for work, the tracker sees Hacker News. The classifier of "was that worth it" is in your head, not in the data. We don't try to automate that. We don't think you can.
It can't tag projects automatically. Some apps make this easy (Xcode's window title is the file path, which maps to a project). Some don't (Chrome's window title is the page title, which says nothing about the work). The v1 answer is to read the strip yourself and use your eyes. A later version may add rule-based tagging ("if window title contains X, tag as project Y") for people who want lightweight project structure.
It can't reconstruct sessions you didn't have it open for. This is the obvious one. Install it today, you get today onward. There's no magic backfill.
Idle, sleep, and the screen lock
Three edge cases worth saying out loud, because most automatic trackers handle them inconsistently:
Idle — the user input timeout. Default 90 seconds. Marked in the row, used to skip break-timer counts, but the data is still recorded so the strip shows the gap honestly.
Display sleep — when macOS dims the screen because of system idle. We pause the sampler entirely. No rows are written. The strip shows a clean gap.
Screen lock — when you hit Ctrl+Cmd+Q or step away long enough for the lock to engage. Same as display sleep: sampler pauses, no rows, clean gap.
The principle: if you're not at the Mac, the data doesn't get to claim you were.
"What about projects?"
This comes up enough to deserve an explicit answer.
If your job is to bill hours to a client, you genuinely need a project picker. An automatic tracker that doesn't know about your project structure can't generate an invoice. Toggl and Harvest are designed for this. They have the project picker, the start/stop friction, and the export pipeline that your accountant trusts.
If your job is to understand your own week, you don't need a project picker. You need to look at the strip and notice that Tuesday afternoon was four hours of Slack with nothing in Cmd+Tab distance of the codebase. That's the insight. No project label needed.
Most of the people I built this for are in the second camp. They're already inside Claude Code and Cursor and the Octomind agent runs that ate Wednesday morning. They want to see where the hours landed, not bucket them into bill codes.
The Wednesday test
Here's the test I run for any time tracker before I'd consider relying on it.
It's Wednesday morning. The standup asks what you did Monday. You open the tracker.
- If the data was reconstructed from your Tuesday-evening memory, it lies. You misremember Slack as Xcode and Xcode as Slack. The standup answer is confidently wrong.
- If the data is automatic, it's the same boring truth the strip showed you Monday evening. You read it. You say it. You move on.
That's the gap automatic tracking actually closes. Not productivity. Not focus. Not even memory. Just the version of the day your tracker reports matching the version that actually happened.
If you want to see what that looks like on your Mac, grab the 100-hour trial. Three Macs, no account, no cloud. The strip is the same one we use on our own laptops every day.