# How Claude HUD Git Status Features Work: showDirty, showAheadBehind, and showFileStats Explained

> Explore how Claude HUD's git status features like showDirty, showAheadBehind, and showFileStats work. Understand the Git commands and configuration behind real-time repository state.

- Repository: [Jarrod Watts/claude-hud](https://github.com/jarrodwatts/claude-hud)
- Tags: deep-dive
- Published: 2026-03-18

---

**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`](https://github.com/jarrodwatts/claude-hud/blob/main/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`](https://github.com/jarrodwatts/claude-hud/blob/main/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`](https://github.com/jarrodwatts/claude-hud/blob/main/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:

```bash
git --no-optional-locks status --porcelain

```

In [`src/git.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/git.ts) at line 59, the dirty flag is set by checking if any output exists:

```typescript
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`, `C` symbols): Counted as modified files
- **Added** (`A` symbol): Staged additions
- **Deleted** (`D` symbol): Removed files
- **Untracked** (`??` prefix): New untracked files

### Ahead/Behind Count Calculation

When `showAheadBehind` is enabled, Claude HUD queries the upstream relationship using:

```bash
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`](https://github.com/jarrodwatts/claude-hud/blob/main/src/git.ts):

```typescript
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`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config.ts)**. The `DEFAULT_CONFIG.gitStatus` object (lines 84–88) establishes the following defaults:

```typescript
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`](https://github.com/jarrodwatts/claude-hud/blob/main/src/render/lines/project.ts)** (expanded mode, lines 30–62) and **[`src/render/session-line.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/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:

```typescript
if ((gitConfig?.showDirty ?? true) && ctx.gitStatus.isDirty) {
  gitParts.push('*');
}

```

This appears in [`project.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/project.ts) at lines 36–38 and [`session-line.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/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:

```typescript
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`](https://github.com/jarrodwatts/claude-hud/blob/main/project.ts) lines 40–46 and [`session-line.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/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:

```typescript
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`](https://github.com/jarrodwatts/claude-hud/blob/main/project.ts) lines 49–58 and [`session-line.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/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:

```typescript
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`:

```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:

```json
{
  "gitStatus": {
    "enabled": true,
    "showDirty": true,
    "showAheadBehind": true,
    "showFileStats": false
  }
}

```

Produces the simplified output:

```

git:(main* ↑2 ↓1)

```

## Summary

- **[`src/git.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/git.ts)** executes three Git commands (`rev-parse`, `status --porcelain`, `rev-list`) to populate the `GitStatus` object with branch, dirty state, ahead/behind counts, and file statistics.
- **[`src/config.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/config.ts)** manages the three boolean flags (`showDirty`, `showAheadBehind`, `showFileStats`) through `DEFAULT_CONFIG` and user configuration merging.
- **[`src/render/lines/project.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/render/lines/project.ts)** and **[`src/render/session-line.ts`](https://github.com/jarrodwatts/claude-hud/blob/main/src/render/session-line.ts)** conditionally render symbols based on these flags: `*` for dirty, `↑N`/`↓N` for sync status, and `!M +A ✘D ?U` for 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`](https://github.com/jarrodwatts/claude-hud/blob/main/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`](https://github.com/jarrodwatts/claude-hud/blob/main/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`](https://github.com/jarrodwatts/claude-hud/blob/main/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.