Native macOS · Open-source privacy proxy

One recording.
The whole billable day.

Press Record when you start and Stop when you're done. Noesa reconstructs the day on your Mac into a reviewable work / leisure / idle timeline, attributes every block to the right client, and carries it through to an invoice.

Open-source proxy (MIT) · No timers, no manual entry · Your screen never leaves your Mac.

It reads your stack, not your screen

VS Code Cursor Ghostty JetBrains Zed Linear Figma Slack

The reality of billing by hand

Time tracking, without the tracking.

0

timers to start, stop, or remember. The session is the only button.

100%

of screen capture is OCR'd and tagged on-device. The pixels never leave your Mac.

1

model call per session, not per minute. Most attribution is deterministic and free.

Record → Invoice

One session, followed all the way to the bill.

Five moves take a day from the first captured signal to a line on an invoice. Every timestamp is computed from real capture times and is never trusted to a model.

01

Record · Capture

Talk to nothing. Just work.

One button starts the session. Noesa notes the foreground app, window title, idle time and active git repo, deduped by an adaptive scheduler and kept entirely on your Mac. Screenshots are change-gated and OCR'd locally.

  • Signals: app, title, idle, active repo, all free and deterministic
  • Screenshots fire on change, never on a blind clock
  • Nothing is captured until you hit Record
Foreground appVS Code
Window titleStore.swift
Active reporepo:noesa
Idle0s · active
02

Synthesis · Timeline

Your day, already written up.

The session is fused into a work / leisure / idle timeline with a plain-language narrative. Offline? A deterministic on-device rollup keeps the breakdown rendering, so the day is never blank.

  • Work / leisure / idle segments, merged where adjacent
  • A narrative you can paste into a status update
  • Timestamps from real capture times, not the model

Deep work on the Noesa store layer through the morning, a short Acme standup, then Linear triage after lunch. Two idle stretches excluded.

09:12 – 11:36 · BuildNoesa2.4h
11:40 – 12:10 · StandupAcme0.5h
13:00 – 14:36 · TriageAcme1.6h
03

Attribution · Projects

Every block, on the right client.

A deterministic cascade maps activity to projects, taking the active repo first, then app and keyword hints. Only the ambiguous remainder goes to one batched model call, threaded with the day's intent.

  • The active git repo is the strongest signal a dev can give
  • Rename or merge a project and it sticks in every future summary
  • Only redacted titles + intent are ever sent
repo:noesadeterministic · repo matchNoesa
jira ACME-214deterministic · keywordAcme Web
Figma · "moodboard"batched model · 1 callAcme Web
04

Review · Approve

Nothing is billable until you say so.

Confirm, edit or exclude each block, then approve. Approving snapshots the rate, so a later rate change never rewrites a period you've already billed. Approved blocks lock, then invoice.

  • Suggested → Confirmed → Approved → Locked → Invoiced
  • Effective-dated rates, snapshotted at approval
  • Per-frame evidence replay behind every block
Suggested Confirmed Approved Locked
Rate (snapshotted)$150 / h
Hours2.4 h
Amount$360.00
05

Billing · Export

Hours in, invoice out.

Hours times the effective-dated rate, reconciled to the cent. Out comes an invoice, a profitability view, an AI client recap and clean CSV, per client and ready to send.

  • Invoice + profitability report per client
  • AI client recap written from the real timeline
  • CSV export that drops straight into your books
Development18.5 h$2,775.00
Meetings4.0 h$600.00
Design triage2.2 h$330.00
Total due$3,705.00

Private by construction

What leaves your Mac is what you'd put on an invoice.

Raw signals, screenshots and work blocks live in a local SQLite store and are never synced. The unsafe thing isn't avoided by discipline. It is made impossible by structure.

On-device OCR Key-custody proxy Titles redacted Local-only storage No analytics Open-source proxy
  • Screen pixels never leave the device

    Every frame is OCR'd and tagged idle/active locally, with no per-frame model. Screenshots stay on-device, used only for OCR and in-app evidence replay.

  • Only derived text egresses, through a key-custody proxy

    A tiny, auditable Cloudflare Worker holds the provider key server-side, so no API key ships in the app and client identity headers can never reach the model.

  • Attribution text is redacted before it's sent

    Emails, key-prefixes and long opaque tokens are stripped from the attribution path. Request bodies are never read, buffered, or logged by the proxy.

  • Local at rest, no analytics, fully local if you want it

    Everything sits in local SQLite and is never synced. Prefer no cloud at all? Point synthesis at your own endpoint. A local Ollama works.

The only thing that syncs

A project, a time range, and the signal that attributed it.

When you approve a block, this is the whole record that leaves your Mac. The evidence field is simply the signal Noesa used to attribute the work to a client, like the active repo name. No screenshots, window titles, or keystrokes ever sync.

// nothing else ever leaves
{
  "projectId": "noesa",
  "start":     "09:12",
  "end":       "11:36",
  "billable":  true,
  "evidence":  ["repo:noesa"]
}
// no screenshots · no titles · no keystrokes

Questions

The honest answers.

How does Noesa know what I worked on?

Two on-device sources. Cheap programmatic signals (the foreground app, window title, idle time and active git repo) plus change-gated screenshots that are OCR'd locally with Apple's Vision framework. Once you stop, those per-frame signals are fused into a single work / leisure / idle timeline.

Do my screenshots or screen contents get uploaded?

No. Screen pixels never leave the device. Every frame is OCR'd and tagged locally with no per-frame model. Only derived text (signals plus short OCR snippets) is sent for whole-session synthesis, and only through the key-custody proxy, never the images themselves.

Do I need an API key?

No. The default provider is the Noesa proxy: keyless, authenticated by a random per-install device id generated on your Mac. Prefer your own account? Bring your own key, or point Noesa at your own OpenAI-compatible endpoint in Setup.

Which apps and platforms does it understand?

Any macOS app. Editors, terminals, browsers, design tools and meetings are all read through the foreground app, window title and active git repo. Noesa is a native macOS app (SwiftUI + AppKit). There is no Windows build today.

What happens if I'm offline?

The timeline still renders. If the cloud model is unreachable, or you flip the per-session Offline switch, Noesa falls back to a deterministic on-device rollup and marks the breakdown as degraded, so nothing is ever blank.

Is it really free?

There's a free tier, no account needed (paid plans aren't live yet). The app itself isn't open source. But the privacy-critical part, the backend proxy that handles your data, is: MIT-licensed, roughly 300 lines you can read in one sitting, with every privacy guarantee mapped to a code path.

Bill what you actually worked.

Install Noesa, name a client and a project, and let the hours attribute themselves.

Requires macOS · Swift 5.10+ · ~300-line open-source proxy