Stop guessing your billable hours: build automatic time tracking on your Mac
If you forget to start and stop timers, your invoices become guesses. Here is how we built a Mac tracker that logs the work for you and keeps the data on your own computer.
the quick answer
Automatic time tracking on a Mac works when a small background program asks AppleScript for the front app and window title every 30 seconds, and treats two quiet minutes as idle3. Rules then tag each block to a client. You approve it in Privacy & Security, under Accessibility and Automation1. Keep the data on your own disk.
Safe to try? Medium risk Window titles can show email subjects and bank pages, so keep the data on an encrypted disk, and never open the tracker to a network.
Why do my billable hours end up as guesses?
You did nothing wrong. Timers ask you to remember something at the exact moment you are busy thinking about something else. People keep asking how to skip that step, and it makes sense: you forget to start, you forget to stop, and on Friday you rebuild the week from memory.
Many off-the-shelf trackers fix this by watching your screen, but some send that activity to a cloud service. Others still need you to press a button. If you want something that runs quietly, matches work to the right client and stays on your Mac, building a small one with an AI coding assistant is a fair choice.
We built one for our own time and have run it since. This article tells what we did and what went wrong, so you can skip our detours.
What a good solution does: automatic time tracking on a Mac
A good tracker does five things, in this order.
It notices what you are doing without being asked: the front app and the window title. AppleScript can control scriptable apps and parts of macOS itself, which is how a script reads that information3.
It knows when you walked away. We read the seconds since the last keyboard or mouse input from the system, and call two minutes without input "idle".
It turns raw activity into billing. Rules say "this app, this website or this window title means this client."
It asks you before it guesses. Anything it is unsure about stays a suggestion.
It keeps everything on your Mac.
What you need before you start
- A Mac, and Node.js installed from the official site.
- Claude Code or Codex, started in an empty folder. Our start-here page explains how.
- Patience to go one step at a time. Nothing here needs to be fast.
- Permission for the program that runs AppleScript. macOS shows an alert, and you must grant access in Privacy & Security settings2. The Accessibility list covers apps that run scripts and system commands to control your Mac, and the Automation list covers apps that control other apps1.
Grant access only to apps you know and trust2. When you review the list later, turn permission on or off for any app2.
The playbook: ten steps to build it
Ask your AI to do each step with you, and to explain every command before it runs.
Check the prerequisites.
Confirm Node.js works and the permissions above are on. If the tracker later reads blank window titles, this is the first place to look.
Create the database.
We used SQLite through the better-sqlite3 library, in one local file. Tables: clients, projects, tags, tag rules, activities, time entries, invoices and settings. The library's own page says to set the WAL pragma,
db.pragma('journal_mode = WAL'), for performance6. WAL lets readers and writers work at the same time4.Build the tracker.
Every 30 seconds, ask for the front app and window title, and read the idle seconds. Write one row per unbroken stretch in the same window.
Add safety limits.
Cap any one row at 2 hours. Ignore anything under 5 seconds, because quick app flickers are not work. After a restart, restore saved state only if it is under about 10 minutes old.
Add the rules engine.
A rule matches an app, a website domain, part of a URL, a window title or a browser profile, and assigns a tag, a client and a project. Run the highest priority first.
Sync browser history.
Read copies of the browsers' history files every 5 minutes, never the live ones.
Sync your calendar.
Every 15 minutes, match events to clients. Log automatically only when the match is very sure (we use 0.9 or higher), and leave the rest as suggestions.
Add invoicing.
Pick one clear order for rates: an override first, then the project rate, then the client rate. Treat your client records as the source of truth.
Back up the data.
Export the database once a day to a place you control. Check that the export opens.
Run it at login.
A launchd user agent runs only while you are logged in, which suits this job5. Bind the web page to localhost only.
Apple's own launchd example shows a job that runs on a timer, every five minutes (300 seconds)5. Our 5 minute browser sync uses the same idea.
Did this fix work?
One tap tells the next reader what to expect. No sign-up.
What we got wrong the first time
- Giant rows. Restarts and sleep produced multi-hour entries. That is why the code now caps each row at 2 hours and refuses stale saved state.
- Too much trust. Auto-matching needs a confidence threshold. We only trust high-confidence rules, and calendar matches at 0.9 or better.
- A Mac that was off. A Mac powered off overnight never ran its scheduled jobs, and launchd did not catch up afterward. If daily totals matter for billing, run a catch-up check at login.
- One fault, many alarms. When a network tunnel to a database was down, the daily export failed along with every other job. Check the shared dependency before you debug each job.
- No version control at first. Our tracker went a while with no git repository. Start one on day one.
- What we do not know. We have not measured how accurate the client matching is, or how many hours it saves. Treat it as a good draft you check before you bill.
What it costs to run
The software is free and runs on your Mac. If you use an AI model through an API for suggestions or to learn new rules, that costs per use. We did not record the amounts, so check your provider's pricing page.
Keep it safe
- Encrypt the disk. On a Mac with Apple silicon or a T2 chip, data is encrypted automatically7. Turning on FileVault adds an extra layer by requiring your login password to get at the data7.
- Keep the web page local. Our tracker has no login on purpose, because it is single user and local. So it must never be reachable from a network.
- Strip before you send. If an AI model sees window titles or URLs, those leave your Mac. Remove or hash them first, or use a local model.
- Track only your own time. Tracking employees without consent is illegal in many places.
- Be careful with backups. Keep the database out of backups you do not control.
Common questions
How does time tracking software work?
It watches a signal, such as the front app or a timer you press, and stores the start and end of each stretch. Rules or you then label the stretch with a client. A tracker like ours reads the front app and window title with AppleScript3.
Does automatic tracking need special Mac permissions?
Can a local tracker keep working while I use two apps at once?
It records the front window, so it logs one app at a time. Rules can group related apps under one client.
Is SQLite fine for a one-person tool?
Yes. WAL mode works when all processes are on the same computer, but not over a network filesystem4. That fits a tracker on your own Mac.
Nice work if you got this far. A tracker that runs itself means Friday evening is yours again. Spend it with someone you love.
James
Made with care: researched from 7 official sources and checked step by step against them on November 12, 2026. Written with AI, security-scanned before publishing.
This is general help, not professional support. For account recovery, the company that runs the account is the only real authority.
Back up anything you can't replace before you start.
Sources
- Apple Support. "Change Privacy & Security settings on Mac." Official docs, read November 12, 2026. support.apple.com
- Apple Support. "Allow accessibility apps to access your Mac." Official docs, read November 12, 2026. support.apple.com
- Apple Developer Documentation Archive. "Introduction to AppleScript Language Guide." Official docs, read November 12, 2026. developer.apple.com
- SQLite. "Write-Ahead Logging." Official docs, read November 12, 2026. sqlite.org
- Apple Developer Documentation Archive. "Creating Launch Daemons and Agents." Official docs, read November 12, 2026. developer.apple.com
- better-sqlite3 project (GitHub). "better-sqlite3: The fastest and simplest library for SQLite3 in Node.js." Official docs, read November 12, 2026. github.com
- Apple Support. "Protect data on your Mac with FileVault." Official docs, read November 12, 2026. support.apple.com
Spotted a mistake? Tell us. We fix it in place and note the change.
Notes from readers
Found a better way, or did a step change? Tell me. Every note is read by a person before it goes up, and the best ones make the guide better.