Client Time Tracker

Sign in with your work Google account to see your clients, hours, and reports.

Sign in with Google

Dev sign-in

Dev only — used when Google SSO isn't configured.

Client Time Tracker
Customer work
Internal
Analytics & admin

Dashboard

Your home base — hours, clients that need attention, time off, and connected accounts.

Getting started

  1. Connect your accounts below so the tracker can read your calendar, email and meetings.
  2. Open a client in Clients to review your time and manage its living context.
  3. Time is fetched automatically each night; you can review and exclude entries before they're billed.

Your hours

Realized hours per client for the selected window. Forecast = upcoming scheduled meetings, never billed.

Engagement budgets

Desktop capture

Where your desktop time went

Runs on personal machines too — only the categories you enable are counted, and unrecognised/personal activity stays out. Browser capture is limited to your work account.

Billable time to recover from your desktop

Suggestions only — matched from your desktop capture. Review and log what's actually billable; nothing here bills automatically or touches your untracked hours.

Top apps & sites

Apps ·
Sites ·

Focus & deep work

DayWhenActiveLongest DeepSwitches/h

Active vs at-desk

Your ongoing projects

You vs the team

Your customers

Needs attention

Open items waiting on your clients — ordered by urgency.

Your connected accounts

Connect the sources the tracker reads on your behalf. Tokens are encrypted; nobody else can see them.

This computer

Connect this computer so your browser history & ActivityWatch time are counted. Data is uploaded only under your own account.

Clients

Open a client to review your time, manage its living context, or generate a client update.

Time off

Request paid time off, unpaid leave, or log sick leave. Rest is productive — use your allowance.

Your balance

PTO accrues over the year based on your capacity (FTE × 26 days).

Loading…

Request time off

Team time off

Awaiting your approval

Time off from people who report to you.

Your requests

Team time off

Everyone's balance, in days. Remaining is what they can still plan against this year; accrued is what they've earned so far. Set someone's employment profile to change entitlement + half-day eligibility.

Employment profile —

Fraction + working days set the daily norm (fraction × 8h) / working-days, entitlement ceil(FTE × 26), and half-day eligibility (only on 8-hour days). A change versions the profile and converts the balance downward from the 1st of the effective month.

Working days

Requests

Company card, purchase, expense, access, or equipment — one form, routed to your manager.

New request

Awaiting your approval

Requests from people who report to you.

Your requests

Reviews

Feedback rounds — give the reviews assigned to you, and see your own summary.

Reviews to give

Loading…

My feedback

Review cycles

Assigning always adds a self-review and the subject's manager, plus any peers you pick.

Contracts

Signed engagements, renewal dates, and links to the paperwork.

Add contract

Registry

Loading…

Capacity planner

Who's planned on what over the next few months — by % of capacity.

gap <80% over >100%

Loading…

0% removes it.

People P&L

Revenue vs. fully-loaded cost per person, plus utilization and who's on the bench. Realized billable hours only — never forecast.

Overhead ×— ·

Return multiple = revenue ÷ fully-loaded cost. ≥ 2× healthy ≥ 3× great < 1× underwater · set a person's cost to compute it.

Loading…

Monthly cost —

What we pay this person per month (base comp, pre-overhead). Versioned — a new value applies from its effective date; past periods keep the old cost. Sensitive; admin-only.

For retainer / book-of-business / outcome-based people. Enter the revenue attributed to them for a month; the P&L prorates it across the window.

Assets

Laptops, phones, monitors and licences — who holds what, and what's in stock.

Add asset

Register

Loading…

Skills & benefits

The skills matrix, L&D expiries, and benefits — the people-development backbone.

Skills matrix

Loading…

Learning & certifications

Add records something already done; Assign gives someone a course to complete. Expiring within 60 days are flagged.

Benefits

Everyone's benefits — enrolment, cost, and renewals.

Benefits

Renewing within 60 days are flagged. Costs are informational.

Hiring

A candidate pipeline for your open roles. Hiring a candidate creates their employee record.

Connect careers@
Add candidate:

Settings

Enable or hide sections for the team. Changes apply to everyone.

Sections

Toggle a feature to show or hide its section across the team. Experimental features are off by default.

Loading…

Cost model

The overhead multiplier grosses each person's base cost up to a fully-loaded cost (salary + taxes, tooling, space…). The rule of thirds ≈ 1.3. It drives return multiples in People P&L and the scorecard.

Analytics

How the whole book of business is doing — revenue concentration, risk flags, and per-client hours and revenue.

Overview

Revenue concentration

Risk flags

All clients

Internal / overhead time

Loading…

Call sentiment experimental

Team

Add consultants so they can sign in, then assign them to clients from the Clients tab.

Add a consultant

Their work email must match the Google account they'll sign in with.

Companion agents

Daily health check for the machine-local uploaders.

Unclassified

Activity fetches couldn't attribute to a client. Assign each to a client — or ignore it — and it's remembered for future fetches.

Sales time to verify

Meetings with people who aren't a client yet — grouped by company. Confirm sales, or dismiss the noise (dismissing a company is remembered).

Activity log

Who did what, and when — logins, rate changes, invoices, deliveries, context edits, and deletions.

Approvals

Proposed changes waiting on you — assign unclassified activity, or add a client's ID / domain / keyword. Nothing takes effect until you approve.

Rules & Categories

Where time is attributed across all clients — by category and by source. Rename categories or toggle billability here.

Categories

Time attributed to each bucket. Click a label to rename it; toggle to change whether it bills.

Sources

Which integrations the tracked time came from.

How it works

A plain-language reference for the whole system — what runs when and why, what triggers it, who does what, and the decisions behind it. Use it to validate the current design.

Roles & access

Two roles. A consultant only ever sees their own clients and never sees rates or revenue.

RoleCan seeCan do
AdminAll clients, rates, revenue, analytics, audit log, approvals, the whole team. Everything a consultant can, plus: edit any client config, manage employees & assignments, set segments, rename/toggle categories, approve or reject change requests, resolve unclassified activity, generate & approve invoices, run GDPR erasure.
ConsultantOnly clients they're assigned to. Rates & amounts are stripped from everything they see. Connect their own Google/Slack/Fathom, connect their computer (agent), run fetch / AI sync / compose / deliver for their clients, add manual entries, exclude their own time before billing, and propose config edits or unclassified assignments (which an admin approves).

Admin is granted by the is_admin flag on the employee or membership of the ADMIN_EMAILS env list — the env list is a failsafe so you can never lock yourself out of admin.

Where time comes from

A “fetch” turns raw activity into classified time entries. Two families of sources:

  • Cloud sources — Google Calendar, Gmail & Drive (one Google grant), Slack, Fathom, HubSpot. Each consultant connects their own accounts; the tokens are encrypted per-consultant and only decrypted in-memory during a fetch under that person.
  • Machine-local sources — the companion agent a consultant installs on their computer uploads Chrome/Edge history (only the browser profile signed into their work account) and ActivityWatch, once a day, under a personal agent token scoped to just them.

Each source's events become time Intervals, classified into categories using that client's config — email domains, keywords, HubSpot/Miro/Drive IDs, and tool URL patterns. Anything a fetch can't confidently attribute to a client is set aside as Unclassified rather than guessed.

What runs automatically, and when

Scheduled jobs run on the server (systemd timers), not in the browser. Each is stateless and safe to re-run.

Nightly · 02:00
Fetch every assigned (client × consultant) pair whose consultant has Google connected → a fresh Run per consultant.
Why: keep data current without anyone lifting a finger. Each pair runs in its own transaction, so one failure never blocks the rest; Google access tokens are refreshed and re-stored during the run.
Daily · 03:00
AI context sync — fold each new day of activity into every client's living context, one day at a time. Days already synced or with no activity are skipped, so a quiet client costs nothing.
Why after the fetch: it needs the day's data. Day-by-day keeps the timeline granular. A client with no sync yet is backfilled over the last 14 days.
Weekly · Mon 06:00
AI config suggestions — propose additive config changes (add a domain/ID/keyword, or assign recurring unclassified activity) into the Approvals queue as pending items.
Why weekly: config drifts slowly; suggestions are cheap and never applied without an admin approving.
Weekly · Mondays
“Update due” flag (no AI) — the Dashboard briefing marks any active client whose last client-update was ≥7 days ago.
Why not auto-compose: client-facing output is never generated-and-forgotten — this just nudges you to open the client and Compose when ready.

All AI jobs need the org ANTHROPIC_API_KEY; without it they simply no-op (and on-demand AI actions return a clear “AI not configured”).

What people trigger on demand

ActionWhoWhat happens
Run fetchAdmin or assigned consultantPulls a client's activity now (optionally for a specific date range, which becomes its working period) under your account, instead of waiting for tonight.
Sync from activityAdmin or assigned consultantThe same granular day-by-day AI sync as the daily job, on demand. Backfills 14 days the first time; does nothing if there's nothing new.
Compose updateAdmin or assigned consultantDrafts a client-facing update over the last 7 or 14 days (your choice) — never the whole project. Draft only.
AI suggestAdmin or assigned consultantOn-demand version of the weekly suggester → drops proposals into Approvals.
DeliverAdmin or assigned consultantCreates a Gmail draft / Slack preview by default; a second explicit “Send” actually delivers.
Propose a changeConsultantSuggests a config edit or an unclassified→client assignment → goes to Approvals for an admin.
Approve / rejectAdminApplies (or discards) a proposed change. Approving runs the exact same code as a direct admin edit.

The AI layer & its guardrails

  • Living context per client = a human-editable Current State plus running log, decisions, changes, open questions and action items. The Sync extracts these from activity; Compose turns them into a client update.
  • Scoped, never the whole project — sync and compose only ever look at a recent window, so a 12-month engagement isn't re-read every time.
  • Skips when nothing's new — the daily sync tracks which days it has processed and won't spend a cent on a quiet client.
  • Backfill is cheap-by-design — it extracts items for each day but re-writes the Current-State summary only once at the end.
  • Human edits win — if you hand-edit a Current State, the AI never overwrites it.
  • Draft-first — composed updates are drafts; nothing reaches a client without an explicit send. Every AI action shows its cost.

Classifying & billing time

  • Categories (meetings, HubSpot dev, documentation, research, internal coordination, …). Admins can rename a category or toggle whether it's billable org-wide on the Rules tab — a billable change reflows into every report and invoice.
  • Unclassified activity is surfaced for review; assigning it to a client is remembered (a “learned mapping”) and applied automatically on the next fetch. Consultants propose; admins apply.
  • Manual entries — anyone can log time on their assigned clients; manual time survives future fetches.
  • Review — before billing, exclude any of your own entries.
  • Rates — a client base rate plus optional dated rate-schedule overrides; per-consultant rates come from the employee table. Cross-client revenue is FX-converted to one base currency.

Invoicing

Invoices are combined per client: a single consultant's overlapping entries are de-duplicated, but hours from different consultants are summed (parallel work is real, not double-counting). Generate snapshots the current billable time so the invoice stays stable even if later fetches change the runs; Approve freezes it.

Segments

Each client can be mapped to a lifecycle stage: Pipeline (Scoping, Pre-Signature) → Active (Kick-off, Account Management) → Inactive (Dormant, Churned). Admins set it on the Clients tab; you can filter to one segment or stack them under group headers. Inactive clients are excluded from the weekly “update due” nudge.

Security & privacy

  • Credential vault — every OAuth token is encrypted at rest (Fernet, one VAULT_KEY the operator holds) and only decrypted in memory during a fetch. The key can be rotated in place without anyone reconnecting.
  • Sessions expire (signed cookie, 7-day max age). Google login no longer forces a re-consent every time, and never loses your long-term (refresh) token.
  • Audit log — an append-only record of every security- and billing-relevant action (on the Activity tab), never edited.
  • GDPR — deleting an employee or client cascades to their tokens, runs, context and invoices; an optional retention window purges old raw runs (billing survives in invoice snapshots).
  • Companion agent — browser history is read only from the work-account profile (personal profiles are skipped), and everything uploads under the individual's own token.
  • Rates are never exposed to consultants, in any view or export.

Key decisions & why

DecisionWhy
Hosted web app + central Postgres, Google Workspace SSOOne place the whole team uses; an internal OAuth app sidesteps Google's sensitive-scope verification.
Reuse the existing engine; store clients as a few columns + a config blobThe engine's rich client profile round-trips losslessly, so no rewrite and the config can keep evolving.
Per-consultant encrypted token vault; combine per clientEach person's data is accessed under their own grant; the client's invoice pools everyone's hours.
External timers, not an in-process schedulerStateless and idempotent — safe across restarts and retries.
Draft-first delivery · additive-only config proposals · admin approvalA human always signs off on anything client-facing or anything that changes billing/classification.
Windowed AI · skip-if-nothing-new · extract-daily/summarize-onceGranular history without re-reading (and re-paying for) the whole project.
Weekly “flag it's due” instead of auto-composingAI output is never sent — or even generated on a schedule — without review.
Self-contained companion agent (one file, work-profile-only)Easy for non-technical teammates to install; private by construction.

This page is a living summary of the current version — tell me what to add or correct as the design evolves.

Loading…

View report ↗
Report segment: –

Open questions

Action items (client-owed)

Recent decisions

Recent changes

Client update draft

Write your own update, or use Compose update above to draft one with AI — then create a draft (safe) or send it to the client.

Recipient comes from the client's configured email/Slack channel — you can't mis-address it.

Newest first. Uncheck an entry to exclude it from reports & invoices; changes save immediately. Forecast rows are future scheduled meetings that haven't happened yet — shown for planning, never billed.

By consultant

A draft snapshots the current billable time; approving locks it so later fetches can't change it.

–

Client configuration

Basics

Resource links — quick links shown in the Clients list

Rate schedule — optional; the rate above is the default. Add date ranges where a different rate applies.

Keywords — text matched across Slack/email/browser to attribute activity (one per line)

Contacts & domains

Tech-stack IDs — identify the client's tools by the IDs in their URLs, so activity in them is attributed here

HubSpot
Google Drive
Boards & calendars
Other SaaS tools

ClickUp — see this client's tasks and push time to them (each consultant connects their own ClickUp)

Slack channels — one per line, C0ID | channel-name

Delivery & AI

Advanced — everything else (tuning, rate overrides, projects, SOW, branding…) as raw JSON. Edit carefully.