How Claude HUD Git Status Features Work: showDirty, showAheadBehind, and showFileStats Explained
The git status features in Claude HUD—showDirty, showAheadBehind, and showFileStats—render real-time repository state by executing three Git commands in src/git.ts and conditionally formatting the output in the renderers based on user configuration flags.
Claude HUD (jarrodwatts/claude-hud) displays repository state directly in your terminal status line through configurable git status features. These optional visual indicators—controlled by showDirty, showAheadBehind, and showFileStats flags—transform raw Git output into compact symbols that appear next to your project path. The implementation spans Git command execution, configuration management, and terminal rendering pipelines.
Git Data Collection Pipeline
All git status features rely on getGitStatus() in src/git.ts, which executes three Git commands with a 1-second timeout to keep the HUD responsive. The function returns a GitStatus object containing branch, isDirty, ahead, behind, and fileStats properties.
Branch Name Detection
The current branch is retrieved using git rev-parse --abbrev-ref HEAD (lines 41–47 in src/git.ts). This provides the base string that appears before any status indicators.
Dirty State and File Statistics
The dirty indicator and file stats both derive from a single porcelain status command:
git --no-optional-locks status --porcelain
In src/git.ts at line 59, the dirty flag is set by checking if any output exists:
isDirty = statusOut.trim().length > 0;
The detailed file statistics are parsed by parseFileStats() (lines 95–117), which walks each porcelain line and categorizes changes:
- Modified (
M,R,Csymbols): Counted as modified files - Added (
Asymbol): Staged additions - Deleted (
Dsymbol): Removed files - Untracked (
??prefix): New untracked files
Ahead/Behind Count Calculation
When showAheadBehind is enabled, Claude HUD queries the upstream relationship using:
git rev-list --left-right --count @{upstream}...HEAD
The output (format: behind ahead) is split and parsed at lines 76–80 in src/git.ts:
const [behindStr, aheadStr] = revOut.trim().split(/\s+/);
behind = parseInt(behindStr, 10) || 0;
ahead = parseInt(aheadStr, 10) || 0;
Configuration System
User preferences for git status features are defined in src/config.ts. The DEFAULT_CONFIG.gitStatus object (lines 84–88) establishes the following defaults:
gitStatus: {
enabled: true,
showDirty: true,
showAheadBehind: false,
showFileStats: false,
},
During initialization, loadConfig() (lines 35–48) merges user settings from ~/.claude/config.json with these defaults. The resulting configuration is stored as ctx.config.gitStatus and passed to both rendering engines.
Rendering the Git Status Features
The visual output is constructed in two locations depending on HUD layout: src/render/lines/project.ts (expanded mode, lines 30–62) and src/render/session-line.ts (compact mode, lines 66–100). Both files implement identical logic for the three feature flags.
showDirty: The Dirty Indicator
When showDirty is true (the default) and ctx.gitStatus.isDirty is true, the renderer appends an asterisk to the branch name:
if ((gitConfig?.showDirty ?? true) && ctx.gitStatus.isDirty) {
gitParts.push('*');
}
This appears in project.ts at lines 36–38 and session-line.ts at lines 73–76, producing output like main* when uncommitted changes exist.
showAheadBehind: Sync Status Arrows
The showAheadBehind feature renders upward and downward arrows indicating divergence from the upstream branch:
if (gitConfig?.showAheadBehind) {
if (ctx.gitStatus.ahead > 0) gitParts.push(` ↑${ctx.gitStatus.ahead}`);
if (ctx.gitStatus.behind > 0) gitParts.push(` ↓${ctx.gitStatus.behind}`);
}
Found in project.ts lines 40–46 and session-line.ts lines 78–85, this generates ↑2 when two commits ahead or ↓1 when one commit behind.
showFileStats: Detailed Change Counters
The showFileStats feature provides granular visibility into working directory changes using Starship-prompt-style symbols:
if (gitConfig?.showFileStats && ctx.gitStatus.fileStats) {
const { modified, added, deleted, untracked } = ctx.gitStatus.fileStats;
const statParts: string[] = [];
if (modified > 0) statParts.push(`!${modified}`);
if (added > 0) statParts.push(`+${added}`);
if (deleted > 0) statParts.push(`✘${deleted}`);
if (untracked > 0)statParts.push(`?${untracked}`);
if (statParts.length) gitParts.push(` ${statParts.join(' ')}`);
}
This logic appears in project.ts lines 49–58 and session-line.ts lines 88–97, producing strings like !3 +2 ✘1 ?4 representing 3 modified, 2 added, 1 deleted, and 4 untracked files.
Final Status Line Assembly
The assembled gitParts array is wrapped with color helpers to produce the final HUD segment:
gitPart = `${magenta('git:(')}${cyan(gitParts.join(''))}${magenta(')')}`;
This creates the familiar git:(main* ↑2 ↓1 !3 +2 ✘1 ?4) format visible in the terminal.
Configuration Examples
To enable all git status features, create or edit ~/.claude/config.json:
{
"gitStatus": {
"enabled": true,
"showDirty": true,
"showAheadBehind": true,
"showFileStats": true
}
}
With this configuration, an expanded layout line renders as:
[Opus] ▓▓░░░░░░░░ 45% │ project/path git:(main* ↑2 ↓1 !3 +2 ✘1 ?4) ░
Disabling file statistics while retaining dirty and ahead/behind indicators:
{
"gitStatus": {
"enabled": true,
"showDirty": true,
"showAheadBehind": true,
"showFileStats": false
}
}
Produces the simplified output:
git:(main* ↑2 ↓1)
Summary
src/git.tsexecutes three Git commands (rev-parse,status --porcelain,rev-list) to populate theGitStatusobject with branch, dirty state, ahead/behind counts, and file statistics.src/config.tsmanages the three boolean flags (showDirty,showAheadBehind,showFileStats) throughDEFAULT_CONFIGand user configuration merging.src/render/lines/project.tsandsrc/render/session-line.tsconditionally render symbols based on these flags:*for dirty,↑N/↓Nfor sync status, and!M +A ✘D ?Ufor file stats.- All Git commands timeout after 1000ms to prevent HUD freezing on large repositories or network-mounted drives.
Frequently Asked Questions
How does Claude HUD determine if a repository is dirty?
Claude HUD checks the length of git status --porcelain output in src/git.ts at line 59. If the trimmed stdout contains any characters, isDirty becomes true and the renderer appends an asterisk when showDirty is enabled.
What Git command provides the ahead/behind counts for showAheadBehind?
The feature uses git rev-list --left-right --count @{upstream}...HEAD (lines 70–80 in src/git.ts). The command returns two space-separated integers representing commits behind and ahead of the upstream branch, which are parsed and rendered as ↓N and ↑N arrows.
Can I show file statistics without the dirty indicator?
Yes. Set showDirty to false and showFileStats to true in your ~/.claude/config.json. The dirty asterisk will be suppressed while the detailed counters (!M +A ✘D ?U) continue to display specific change counts from the parseFileStats function.
Why does showFileStats default to false?
The showFileStats feature defaults to false in DEFAULT_CONFIG.gitStatus (line 87 of src/config.ts) to maintain a minimal status line by default. Computing file statistics requires parsing every line of porcelain output, and the additional granularity is opt-in for users who want detailed repository state visibility.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →