Skip to content

feat(statusline): draw the project path, version control status and changed files - #536

Merged
Mearman merged 2 commits into
mainfrom
feat/statusline-project
Oct 19, 2026
Merged

Mearman merged 2 commits into
mainfrom
feat/statusline-project

Conversation

@Mearman

@Mearman Mearman commented Oct 19, 2026

Copy link
Copy Markdown
Member

Adds the project and version control elements of claude-hud to the built-in statusline: a project header segment (the working directory's last directories or its full path, with the directories added to the session inline), a vcs header segment (git:(main* ↑2 ↓1 [+10 -3]), or the bookmark of a Jujutsu repository), an addedDirs row and a gitFiles row. None of them is in the default layout, so the default output is unchanged. Their settings sit in new project, git and jj groups, with project, git and gitBranch colour roles, and the parity map and document account for each claude-hud key the group covers.

claude-hud's project line is one segment holding the path, the added directories and the branch, and showProject, showAddedDirs and gitStatus.enabled are booleans. Here visibility is membership of layout.header or layout.rows, so the line is two segments, and git.branchOverflow keeps its meaning: under truncate a vcs segment listed straight after project is joined to it into one unit the client cuts off at the terminal's edge, and under wrap the two are separate segments the layout may break between. claude-hud's showFileStats switches on both the changed-files line and the total line counts in the branch block; those are now the gitFiles row and git.showLineDiff. Added directories riding on the project segment need that segment listed, so the row layout is how to show them with no project path. pathLevels is written as text ("1", "2", "3", "full") because choice settings are closed sets of strings.

Git is run through ports.run and asked for the fewest things the settings need. The branch alone is one rev-parse; anything that needs the tree is a single status --porcelain=v2 --branch -z, which carries the branch, the upstream's ahead and behind counts, dirtiness and every changed file; the line counts are a diff --numstat only for a dirty tree and only when something drawn uses them; the repository root is read only to order changed files by modification time, since git prints their paths relative to it, not to the working directory (claude-hud resolves them against the working directory, which misorders them from a subdirectory). A detached HEAD costs a tag lookup and a short commit. claude-hud also looks up the remote to build a branch link; terminal hyperlinks are not reproduced, and the parity document says so. The segment and the row share one read per render through a memo keyed on the render's context. Jujutsu keeps claude-hud's rules: opt in, found by walking up for a real .jj directory without following links, stopped by a .git entry, and one read-only jj log. Because those checks need the file system, the ports gain entryKind, realPath and modifiedAtMs, and the renderer's context gains the terminal's width for the files row. Names read from the machine are passed through a sanitiser that removes escape sequences, control characters and bidirectional controls.

Booleans become a setting kind, so agent-shim statusline keys, profile set --statusline git.showDirty=false and the typed API handle them like every other key.

Run against a scratch repository with a modified, a staged-new and a deleted file, one untracked file and a commit ahead of its upstream, the default statusline prints the model line alone, and with the elements listed it prints demo2/src git:(main* ↑1 [+3 -2]), an Added dirs: sparkle, lib-foo line and +b2.ts(+1) ~a.ts(+2 -1) -gone.ts(-1) ?1.

…usted text

Elements that name a directory, a branch or a file need to ask what lies at a path, where a link
leads and when a file last changed, and each of those goes through the statusline's ports so an
element stays a pure function of its context and a test hands it fakes. The real run port also
hides the console window a Windows host would otherwise flash for each program.

Names read from the machine or the client (a path, a branch, a file) are untrusted, so a
sanitiser removes escape sequences, control characters and bidirectional controls before one is
drawn.
…hanged files

Four elements join the statusline, none of them in the default layout. The project segment names
the working directory by its last directories (or all of it) and carries the directories added to
the session inline; the addedDirs row draws them on a line of their own instead. The vcs segment
draws the branch of a git repository, or the bookmark of a Jujutsu one when jj is enabled and the
directory is inside one, never both, with the dirty, ahead and behind, line count and conflict
markers each behind a setting. The gitFiles row lists the changed tracked files, most recently
modified first.

Git is asked for the fewest things the settings need: one command for the branch alone, one that
reads the branch, upstream counts, dirtiness and changed files together, and further ones only for
the line counts, the repository root to order files by, and a detached HEAD's name. The vcs segment
and the gitFiles row share one read per render. Under branchOverflow truncate a vcs segment listed
straight after the project segment joins it into one unit, and under wrap the two stay separate.

Settings are in the project, git and jj groups plus the project, git and gitBranch colour roles.
Booleans become a setting kind, so they are listable, settable from the command line and validated
like every other key, and the renderer is handed the terminal's width for the files row. The parity
map and document account for the claude-hud keys these cover.
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ⚠️ Failed 2026-10-19T21:36:04.013840Z 101a694 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

This security review couldn’t start because the paying account has exhausted its Codex allowance and has insufficient available credits. The payer can check their balance and add credits in the Codex usage dashboard, then try again. If you do not manage the paying account, contact this repository's admins.

@Mearman
Mearman merged commit 8e7f5ee into main Oct 19, 2026
32 checks passed
@Mearman
Mearman deleted the feat/statusline-project branch October 19, 2026 21:42
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