Skip to content

Group agent spend by Git branch - #146

Merged
bhavsarpratik merged 4 commits into
mainfrom
feat/branch-spend
Nov 11, 2026
Merged

bhavsarpratik merged 4 commits into
mainfrom
feat/branch-spend

Conversation

@bhavsarpratik

Copy link
Copy Markdown
Member

Summary

Token Meter now groups spend by the Git branch each session ran on, using only local data: agent session files and this Mac's Git reflogs. Nothing calls GitHub, GitLab, or an issue tracker.

  • Sessions › By branch (#sessions-branches): spend per branch with search (branch or issue key such as ENG-142), app, project, time range, push status, and a show-main toggle. Rows sort and expand to their sessions. All five Sessions tabs sit on one row.
  • Branch chip: one shared :where(.branchChip) component on session cards, All sessions rows, the session header, and both branch tables. It opens the branch in By branch.
  • Git › Branches: four metrics that should go down, each compared with the prior period: cost to ship a branch (median), unshipped spend, rework after the first push (session-level estimate), and hard-to-finish branches (3× or more your median spend per commit). Below them is a searchable, sortable table that shows five rows at a time and scrolls.

Privacy and data

  • Branch names come from Claude gitBranch and Codex session_meta.git.branch. They are stored internally as _branch. Only /logs exposes branch and a path-free repo label.
  • /state, /menubar, notifications, and every MCP tool, including git_stats, carry no branch. Tests check for both the key and a sample branch name.
  • Git ledger schema 2 is additive: three new tables, and the v1 history is kept. It stores salted branch keys and each branch's own non-merge commits by you that were not already on the default branch. A test confirms the database file contains no ref names.
  • Project totals on the Git page are unchanged. A test compares them with branch recording on and off.

Rule changes

  • specs/ARCHITECTURE.md: branch names may appear on the local dashboard only, never in MCP, the menu bar, notifications, or logs.
  • specs/DESIGN.md: the four branch metrics are scored lower-is-better; pushed-code volume and ratios stay neutral.
  • specs/AGENTS.md: Sessions gains By branch. Root AGENTS.md was regenerated through the tested transform, because scripts/setup-agent-tools is absent on main.

Validation

  • Full suite: 2,661 tests passed and 21 were skipped. Design contract, scripts/check-page, and py_compile pass.
  • Headless Chrome at 1440 and 1024 px, zero console errors: tab row, filters, sort, expand, chip navigation, and Git table search, sort, and five-row scroll.
  • Installed locally: /health OK and /menubar has no branch. Source and runtime match. Branch spend agrees for all 37 live branches between both pages.
  • An independent tester and one privacy reviewer are running on 180b0df. The owner waived the second reviewer.

Known limits

  • Apps that do not record a branch (Cursor, OpenCode, Kiro) show as "No branch recorded".
  • Rework is a session-level estimate.
  • A branch pushed under a different remote name, or to a remote whose name contains a slash, shows as not pushed.

🤖 Generated with Claude Code

bhavsarpratik and others added 4 commits November 11, 2026 16:51
Read the branch each session ran on from agent traces (Claude gitBranch,
Codex session_meta) and add:

- Sessions > By branch: spend per branch with search, app, project, time,
  status, and show-main filters, sorting, and expandable session lists.
- A shared branch chip on session cards, All sessions rows, and the
  session header that opens the branch in By branch.
- Git > Branches: cost to ship, unshipped spend, rework after first push,
  and hard-to-finish branches, scored lower-is-better, plus a searchable,
  sortable table showing five rows at a time.

Branch names stay on the local dashboard. MCP, the menu bar, /state, and
notifications never carry them. The Git ledger (schema 2, additive) stores
salted branch keys and each branch's own non-merge commits, never ref
names. No GitHub or GitLab access.

Co-Authored-By: Claude Code <noreply@anthropic.com>
- Store a push as incomplete when no trunk reflog entry predates it, and
  wait for a later scan when a trunk ref exists but was not read, so
  commit counts are never a measured zero by accident.
- Keep /git-delivery working if the branch rollup fails.
- Ask Git for all history when By branch shows all history.
- Visible keyboard focus on branch sessions; aria-controls only while
  expanded; the count label includes listed main rows; Branch sort
  follows the displayed name.
- Describe branch keys as salted pseudonymous keys; note the one default
  branch per repository limit.

Co-Authored-By: Claude Code <noreply@anthropic.com>
A trunk ref outside the selected refs (over the remote-ref cap or in
another rotation batch) is now read on demand for branch evidence only.
If it cannot be read, the push waits at most three passes and is then
stored incomplete, never reported as not pushed. packed-refs is parsed
once per repository scan.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
@bhavsarpratik
bhavsarpratik merged commit a34b140 into main Nov 11, 2026
10 checks passed
@bhavsarpratik
bhavsarpratik deleted the feat/branch-spend branch November 11, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant