GitHub-native time ledger

Every hour logged
against the issue that actually happened.

Punchcard resolves each entry against a real repository and issue before it's written — never typed, never guessed. What lands on a client's report is what actually shipped.

meridian / my-week
meridian/orbit-app #412
Fix upload progress stalling at 99%
2h 30m
meridian/orbit-api #88
Add audit log export endpoint
1h 45m
meridian/orbit-app #401
Investigate flaky sign-in on iOS 18
45m
work_date 2026‑09‑09 · status active today 5h 00m
The problem with a timesheet

A spreadsheet doesn't know what #412 is.

Free-text time entries drift the moment someone mistypes an issue number, forgets the repo, or writes "misc." A client report built on that is a report you have to re-verify before you can send it — every week, forever.

orbit — #412 bugfix — 2.5h — "misc / bug"
↓ that's not billable to anyone, as written
meridian/orbit-app #412 — Fix upload progress stalling at 99% — 2h 30m
↑ resolved server-side, before the write is ever accepted
How it works

Three steps, one source of truth.

01

Install the GitHub App

Once, per org. It reads issue titles and repository membership — nothing writes to GitHub, and nothing is logged until it's installed.

02

Log against a real issue

A repo dropdown, an issue autocomplete. No owner/repo#123 ever typed by hand, from the dashboard, an import, or /spend.

03

Export what's billable

Only active, billable entries reach a client, rounded per line at export time — the total is the sum of rounded lines, not a rounded sum.

Built like a ledger, not a form

The rules a billing system can't bend on.

Server-side issue resolution

Issue titles and node IDs are never accepted from a client. An issue that can't be resolved writes nothing and fails loudly.

Append-only, always

An edit inserts a new line pointing at the old one. Nothing is ever overwritten in place — the ledger remembers what a number said last week.

Org-scoped by construction

Every query carries its org as a required argument, so leaking another org's data isn't a bug you can accidentally skip — it's a compile error.

Billable, separated

Internal rework and estimation get logged like anything else, then quietly excluded from anything a client sees.

My Week, on the dashboard

A running total and the days with nothing logged, front and center — the only thing that decides whether a timesheet system actually gets used.

Log time where you work

The extension reads owner/repo and the issue number straight off the GitHub page — nothing to mistype, nothing to switch tabs for.

For teams billing real clients

Stop reconciling a spreadsheet against reality.

Punchcard installs on your GitHub org in a few minutes and starts every entry from an issue that's already real.