Changes
What changed in the tab's checkout, live, with the reason each file changed read from Claude's own transcripts.
The ± badge in the tab strip counts the selected tab’s checkout. Clicking it, or pressing ⌥⌘D, opens the changes pane on the right with the files, their diffs, and — where there is something to say — why each file changed.
“The tab’s checkout” is worked out in this order: a checkout attached to
the tab (Worktrees ▸ Attach to This Tab), else where the tab’s agent is
working (polled every two seconds from the agent process’s own directory, so
it follows Claude into a worktree), else the shell’s directory. Whichever
it is, the checkout is the nearest ancestor with a .git, and it is never
promoted up to your home directory.
The badge
The ± badge shows in any git repository, so the pane is always one click away. What it counts:
- the uncommitted totals while there are any;
- else the branch’s totals — so an agent’s work stays in sight after it commits;
- else a plain ±.
A click opens the pane in the scope the badge is counting. ⌥⌘D toggles it on whichever scope you used last, and the View ▸ Changes item is ticked while it shows.
Two scopes
A switch under the pane’s header picks what it lists, and the choice is remembered.
| Scope | Compared against | What it includes |
|---|---|---|
| Uncommitted | HEAD |
Working tree and index. Stage, discard and commit act here only. |
| Branch | merge-base(HEAD, base) |
Everything since the branch left its base — committed, staged and unstaged, with renames paired and untracked files from status. Above the cards, the branch’s commits, newest first. |
The base is origin/HEAD, else the main worktree’s branch — the same base
merged worktrees are judged by. Where that is missing or is the branch
itself (a repository pushed from a local git init has no origin/HEAD,
and a main checkout may itself be on a feature branch), the first of
origin/main, origin/master, main, master that exists and is not the
current branch is used instead.
When there is nothing to compare with — no HEAD, no base, HEAD on the base branch itself, or unrelated history with no merge base — the pane says why (“On main — nothing to compare with”) and lists Uncommitted.
In Branch scope the commit list above the cards gives each commit’s subject and short SHA; clicking one shows its date, message and files.
Both scopes’ counts are always live. Diff text is loaded only while the pane is open, and only for the scope being shown. Before the first commit there is no HEAD, and the diff is taken against the empty tree, so the pane works in a fresh repository.
Staying current
The pane refreshes on file system events under the checkout and, for a
linked worktree, under its git directory and the repository’s refs/ — a
commit made there writes nothing inside the checkout, so watching the
checkout alone would miss it. A burst of events is one refresh, and the
window becoming key refreshes too.
How a diff reads
As in the Claude Code desktop app: the editor’s syntax colours, with the part that changed inside an edited line marked more strongly than the line’s own tint.
The intra-line marks are worked out by pairing, in order, a run of removed lines with the run of added lines straight after it — which is how git writes an edit. A pair’s changed part is what lies between their common prefix and suffix, counted in characters so that an emoji, a flag or a letter with an accent is never split in half. Two lines sharing less than 40% of the longer were replaced rather than edited, and get no marks at all; nor do lines over ten thousand units long.
Syntax colouring runs over each hunk’s two sides as whole texts, so a string or block comment spanning several lines is one token. Context lines take the new side’s colours, because that is how the file now reads. A language the highlighter does not know stays plain.
Why each file changed
Under each card’s header, quietly: what Claude said when it edited that
file — the two newest lines and when, with +N for the rest; clicking shows
every one in full. In Branch scope it also lists the commits that touched
the file. Where there is nothing to say, nothing is shown.
This is read from Claude Code’s own session transcripts on this Mac. Nothing is sent anywhere and no API is involved. Concretely:
- Which transcripts. The sessions started in the checkout or below it, found by folder name the same way the Sessions panel finds them. In a linked worktree, also the sessions started in the main checkout — a session keeps its transcript where it started, even after Claude moves into a worktree. Each session’s subagent transcripts count as the session’s own.
- How far back. Only transcripts written since the branch left its base (the merge base, or the branch’s oldest commit, whichever is older — a rebase moves the merge base, not the work), else a week; the newest 60.
- What counts as a change. An
Edit,Write,MultiEditorNotebookEditcall paired with its result. An error, or no result at all, and it changed nothing. - What counts as the reason. The nearest assistant text before the edit since the last prompt you typed — one message often covers several edits — else that prompt, else the session’s title. Thinking is never used as a reason. Up to three reasons per file, newest first.
- What it costs. Reading is incremental and off the main thread: each transcript’s byte offset and parser state are kept, so a refresh parses only what was appended, and a byte search picks out the lines worth parsing at all. 200 MB of transcripts takes about 0.3 s the first time and a millisecond after.
Without Claude Code’s session files the pane shows the diff and no explanation. See Privacy.
Cards, and folding
With more than 8 files the cards start folded, so the pane reads as a
list of files with their +N −M and a click opens one.
A card starts as it is when it is first shown with the pane open; after that only you change it, by clicking its header or using Collapse All / Expand All in the pane’s header, which also applies to cards that appear later. So a refresh never folds or opens a card under you: a list growing past eight folds only the cards that arrive then, not the one you are reading. The folds belong to the checkout, in either scope; another checkout, or coming back later, starts afresh.
Related
- Overgit for history, branches and a commit’s own diff.
- Worktrees and tasks for the branch this is all measured against.