Open source · macOS menu bar

Your own freelance
back office.
Log, bill, report, forecast.

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 $425.00
Acme Corp $300 (2.4h)
Moonlight Labs $125 (1.0h)
THIS MONTH $6,840.00
Acme Corp Retainer: 28.5h / 30.0h (95%)
Almost there
Moonlight Labs: 22.0h / 40.0h (55%)
Behind — ramp up to stay on track
Month Projection: $9,200 · 14/20 workable days
2 days off excluded (from calendar)
01 Log
Use Toggl as the time-tracking backend, but log in plain English. Or log straight from Claude Code sessions, based on your message timestamps.
02 Bill
Invoice through Stripe, export CSVs, push hours to Gusto, open your Upwork work diary, and set reminders to send invoices out on schedule.scheduled
03 Report
See your billable hours and money for today, this week, and this month. Keep up with retainers and stay ahead of hour caps on time-based contracts. Revenue shares and flat-rate projects supported.
04 Forecast
Intelligently pace hours and project your revenue for the month. Vacation days and OOO events on your calendar are taken into account.
+ Agent
Includes an MCP server so your coding agent can log time directly, based on its session timestamps. Lifesaver!
Features

Built for freelancers who
juggle multiple clients

9:41 AM 💰 $425

Always in your menu bar

Today's earnings are one glance away. Click for today, this week, and this month by project. Settings live in the same popover.

Acme Retainer: 28.5h / 30.0h
Almost there
Moonlight Labs: 22.0h / 40.0h
Behind — ramp up to stay on track

Pacing that tells you where you stand

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.

2h of Acme design review at 9am mon and tue
☑Mon Oct 19 · 9:00–11:002.00h
☐Tue Oct 20 · 9:00–11:00overlaps

Log time by typing it

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.

Month Projection: $9,200
14/20 workable days · $460/day avg
2 days off excluded (from calendar)
$1,500 rev share (this month)

See your month shaping up

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 CSVAcme Corp · last month
Create Stripe Invoicedraft
Open Upwork Diarytoday
Push to Gusto● due Mon

Invoicing from the same popover

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.

Fri 14:00invoice Acme Corp
Last day of month 10:00invoice Moonlight Labs

Billing reminders

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.

Connect the services you already bill through

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.

⏱

Toggl

Time tracking

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.

Connects to: Toggl API. Every call is written to a local audit log.
💳

Stripe

Billing & invoicing

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.

Connects to: Stripe API. 2 writes per draft, plus 1 read when linking a customer.
🔗

Upwork

Billing & invoicing

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.

Connects to: nothing. It opens a link in your browser.
💵

Gusto

Billing & invoicing · for contractors paid through Gusto

Pushes one project's Toggl hours into your Gusto contractor timesheet as shifts, on the days you worked them, with each entry's note.

Mon 09:00Pushes last Monday–Sunday
Day before cutoffPushes the month so far, as a backup
Cutoff dayPushes from 1 PM and retries every 20 min until the 3 PM deadline
Any timeExport/Invoice → Push to Gusto
Export/Invoice Hours due Fri Oct 30 by 3 PM · payday Mon Nov 2
  • Only ever adds shifts. Each Toggl entry is pushed once and recorded in a local ledger. A shift that already matches is adopted, not duplicated.
  • Edit or delete a pushed entry in Toggl and it gets flagged for you. Gusto is never edited behind your back.
  • Hours are fetched fresh from Toggl for every push, never from the cache, so payroll isn't short.
  • Runs in a visible Chrome window. You approve the login with your passkey. The app never types a password and never tries to get past a bot check.
  • An orange dot on Export/Invoice means Gusto is behind or something needs you.
Connects to: Gusto's web app, through the internal API its own pages use. Gusto can change it without notice, and if it does, the push fails with an error instead of guessing. Each run makes 1 Toggl call.
📅

Google Calendar

Planning

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.

Connects to: your iCal feed, fetched at most every 6 hours.
✦

OpenAI

Assistant

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.

Connects to: OpenAI, on your account. It sends what you type and your Toggl project names. Nothing else.
🤖

Agents (MCP)

Agents

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.

Connects to: nothing. Your agent sends what it reads to its own model. You can anonymize client names and amounts.
⚙

One settings pane

Settings → Integrations
Toggl✓ Active
Stripe✓ Active
Gusto✓ Active
Google CalendarConfigure integration
Agents (MCP)✓ Active

See which integrations are active at a glance, and click one to open its setup pane.

Ask your agent how the month is going

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.

claude · read

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:

1. Moonlight Labs is behind: 18.0h to go over 7 business days, about 2.6h/day.
2. Agency Y is over target. Hours past 10.0h won't bill this cycle.

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

claude · write access on

log 90 min on Acme this morning from 9, sprint planning

freelance-tracker · log_time (preview)

Log Thu Oct 22 9:00am–10:30am (1.50h) to Acme Corp — sprint planning
Nothing has been written yet. confirm=3f9a2b71

That's the entry I'd add. Log it?

yes

freelance-tracker · log_time (confirm=3f9a2b71)

Logged. The menu bar total is already updated.

Off by default

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.

One entry per call

Log, edit, or delete exactly one time entry. No lists, no date ranges. Two changes mean two previews and two confirmations.

Preview, then confirm

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.

Guide: Log your hours from Claude Code →

Billing Models

Works however you bill

Hourly

Uses your hourly rate from Toggl. This is the default if you don't configure a project.

Config

  • Rate pulled from Toggl project settings
  • No additional configuration needed

Display

  • Daily, weekly, monthly earnings
  • Hours and dollar amounts per project
  • Included in month projection
Acme Corp — hourly @ $125/hr
Today: 3.5h = $437.50

Hourly with Cap

Billed hourly up to a maximum number of hours. Works in two modes depending on how your billing cycle works.

Monthly cycle (carryover)

  • Cap resets each calendar month
  • Over/under hours carry forward
  • Progress bar adjusts for carryover

Rolling cycle (last_billed_date)

  • Cap resets from your last invoice date
  • Hours counted since that date, not month start
  • Set last_billed_date after each invoice

Config

  • hourly_rate and cap_hours
  • Optional last_billed_date for rolling cycles

Display

  • Progress bar: hours vs cap
  • Daily earnings show $0 past the cap
Moonlight Labs — 28.5h / 30.0h cap
28.5h × $100/hr = $2,850 (max $3,000/cycle)

Fixed + Required Hours

You get paid a fixed monthly amount for a specific number of hours. Over/under hours carry over to adjust next month's target.

Config

  • monthly_amount and target_hours
  • Effective rate = amount ÷ target
  • Carryover auto-calculated monthly

Display

  • Progress bar: hours vs adjusted target
  • Carryover from prior month
  • Fixed amount included in projection
Startup X — 18.0h / 20.0h target
Fixed $4,000/mo · +2.0h carryover from Feb

Fixed + Soft Target

Fixed monthly amount with a target hour guideline. No carryover — once you hit the target, daily earnings show $0 for additional hours.

Config

  • monthly_amount and target_hours
  • No carryover tracking
  • Effective rate = amount ÷ target

Display

  • Progress bar: hours vs target
  • Monthly earnings capped at amount
  • Daily shows $0 past target hours
Agency Y — 10.0h / 10.0h target
Fixed $2,000/mo · at target, today shows $0

Fixed Flat

A flat monthly payment with no hour tracking at all. Hours are logged in Toggl but don't affect earnings.

Config

  • monthly_amount only
  • No target hours or carryover
  • Rate derived from hours worked

Display

  • Hours shown, no progress bar
  • Earnings based on effective rate
  • Fixed amount in projection
Consulting Co — flat monthly
Fixed $3,000/mo · 6.5h logged this month
Setup

Three minutes to clarity

01
Connect Toggl
Paste your Toggl API token. It's the only credential you need.
~ $
Toggl API Token:
████████████
02
Define your projects
Set billing types and targets. Turn on Stripe, Gusto, Calendar, or agents if you use them.
Acme Corp
Hourly with cap
Moonlight
Fixed retainer
03
Work as usual
Revenue appears in your menu bar, updating every 30 minutes.
Wi-Fi 3:42 PM 💰 $425

Start tracking in minutes

Free 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