Runs from your macOS menu bar. Paces Toggl hours against retainers and caps, drafts Stripe invoices, pushes Gusto timesheets on schedule, and answers your agent over MCP.
curl -fsSL https://raw.githubusercontent.com/dennislysenko/freelance-tracker/main/install.sh | bash
Requires macOS, Python 3, Git · view source
Today's earnings are one glance away. Click for today, this week, and this month by project. Settings live in the same popover.
Each bar compares your hours with how far you are into the cycle: ahead, on pace, or behind. Capped projects can pace from your last invoice date instead of the 1st. Near the end of a cycle, a cap you can no longer reach reads “cap out of reach”, not green.
Describe the time in plain English and review the proposed entries before anything is written. Rows that overlap time already in Toggl start unchecked. Ask “how many hours on Acme this month?” and it answers from the cache. Uses your own OpenAI key.
Fixed retainers count as guaranteed. Hourly work is projected from your pace. Vacation and PTO events on your Google Calendar come off the workable days, and you can add this month's rev share on top.
Export a billing-ready CSV, create a Stripe draft invoice, open today's Upwork work diary, or push hours to Gusto. For a capped project, the “Unbilled (under cap)” range stops on the last day that keeps you under the cap.
Local macOS notifications on a weekly or monthly schedule, so you invoice on time. No API calls, nothing sent anywhere.
Toggl tells you what you worked on.
This tells you where you stand.
Everything except Toggl is optional. Each integration has its own pane in Settings with setup steps, and each card below says what it connects to.
Where your hours come from. One API token and a workspace id. Entries are cached by day and past days stay cached, so a background refresh usually costs 0–1 API calls.
Pick a project and a date range and the app creates a draft invoice, with a line per Toggl entry in the footer. Link each project to a Stripe customer by name once. You review and send it in Stripe.
Save a contract id per project and Open Upwork Diary jumps to today's work diary for that contract. Projects without a contract id let you add one inline.
Pushes one project's Toggl hours into your Gusto contractor timesheet as shifts, on the days you worked them, with each entry's note.
Paste your calendar's secret iCal address. Events matching your keywords (vacation, PTO, OOO, holiday, and any you add) come off the month's workable days, including recurring ones.
Powers typed time logging. Bring your own API key; it's checked with a live call when you save it. Without a key, the input box doesn't appear.
A local MCP server for Claude Code, Codex, or any MCP host. Off until you turn it on. Settings shows the command to register it and a button to test it.
See which integrations are active at a glance, and click one to open its setup pane.
Six read tools give Claude Code or Codex the same numbers as the dashboard: totals, projection, pacing per project, billing rules, and time entries. They read the app's cache, so they never call Toggl.
how's my freelance month going?
freelance-tracker · get_month_status
You're at $6,840, projecting $9,200 with 14 of 20 workable days done.
Needs attention:
Acme Retainer is at 28.5 of 30h, so 1.5h more fills it. Shift Agency Y time to Moonlight.
data as of 9:41 AM · 0 Toggl calls
log 90 min on Acme this morning from 9, sprint planning
freelance-tracker · log_time (preview)
That's the entry I'd add. Log it?
yes
freelance-tracker · log_time (confirm=3f9a2b71)
Logged. The menu bar total is already updated.
Writing is a separate switch from reading, and both start off. With anonymization on, writes are refused: an agent that sees “Project A” shouldn't edit billable hours.
Log, edit, or delete exactly one time entry. No lists, no date ranges. Two changes mean two previews and two confirmations.
The first call writes nothing and returns a one-time token tied to that exact change. It expires in 10 minutes and can't confirm a different entry.
claude mcp add --scope user freelance-tracker -- ~/.freelance-tracker/venv/bin/python ~/.freelance-tracker/mcp_server.py
Then enable it in Settings → Integrations → Agents (MCP). Codex setup is in the agent docs.
Uses your hourly rate from Toggl. This is the default if you don't configure a project.
Billed hourly up to a maximum number of hours. Works in two modes depending on how your billing cycle works.
last_billed_date after each invoicehourly_rate and cap_hourslast_billed_date for rolling cyclesYou get paid a fixed monthly amount for a specific number of hours. Over/under hours carry over to adjust next month's target.
monthly_amount and target_hoursFixed monthly amount with a target hour guideline. No carryover — once you hit the target, daily earnings show $0 for additional hours.
monthly_amount and target_hoursA flat monthly payment with no hour tracking at all. Hours are logged in Toggl but don't affect earnings.
monthly_amount onlyFree and open source. Runs on your Mac and talks only to Toggl, plus any integration you turn on.
curl -fsSL https://raw.githubusercontent.com/dennislysenko/freelance-tracker/main/install.sh | bash