Skip to content

feat(tui): show current git branch in status bar#23

Closed
Dinduks wants to merge 2 commits into
nmelo:mainfrom
Hypefury:feat/git-branch-status
Closed

feat(tui): show current git branch in status bar#23
Dinduks wants to merge 2 commits into
nmelo:mainfrom
Hypefury:feat/git-branch-status

Conversation

@Dinduks
Copy link
Copy Markdown
Contributor

@Dinduks Dinduks commented May 12, 2026

Summary

Adds the current git branch to the right side of the TUI status bar (e.g. git:main).

Design notes

Why parse .git/HEAD directly instead of shelling out to git?

The obvious alternative is exec.Command("git", "branch", "--show-current"). We didn't go that route:

  • No fork+exec on the render tick. Branch is polled every 2s. Spawning a git subprocess that often is wasteful on a hot path, and it'd pull in git as a runtime dependency for what is, fundamentally, reading a small text file.
  • Hermetic, fast tests. The parser is exercised with plain os.WriteFile fixtures — no git init, no temp repos, no git binary needed in CI. The test file covers worktree indirection (absolute + relative gitdir:), detached HEAD, non-branch refs, subdirs, malformed inputs, and missing HEAD with zero subprocess overhead.

Behavior

  • Reads .git/HEAD on a 2s poll.
  • Handles worktree indirection (.git as a file containing gitdir: <path>, relative paths resolved from the directory containing the .git file).
  • Walks upward from projectRoot so a config root inside a subdirectory still resolves the enclosing repo.
  • Only branch checkouts render. Detached HEAD, tag/remote refs, or anything else → nothing shown. Showing a partial SHA was tempting but turned the indicator into "ambiguous text", so it's branches-only.
  • Branch name truncated to 25 runes with an ellipsis so a long name can't push the rightmost status-bar items (clock) off screen.

Test plan

  • initech up from a normal repo shows git:<branch>
  • initech up from a git worktree shows the worktree's branch
  • Detached HEAD / tag checkout: nothing rendered (no panic)
  • Outside a git repo: nothing rendered (no panic)
  • Very long branch name: rendered as git:<first-24-chars>…, clock still visible

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Display current Git branch in the TUI status bar as git:<branch>.
    • Long branch names are truncated with an ellipsis to preserve layout.
    • Branch info refreshes periodically during active rendering.
  • Tests

    • Added tests for branch detection (including worktrees, nested dirs, detached HEAD and malformed cases) and truncation behavior.

Review Change Stack

Copilot AI review requested due to automatic review settings May 12, 2026 01:54
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1030fa27-da54-4ac7-995f-3d8c324264fb

📥 Commits

Reviewing files that changed from the base of the PR and between f464076 and ef13531.

📒 Files selected for processing (4)
  • internal/tui/branch.go
  • internal/tui/branch_test.go
  • internal/tui/render.go
  • internal/tui/render_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/tui/render_test.go
  • internal/tui/render.go
  • internal/tui/branch_test.go

📝 Walkthrough

Walkthrough

Adds filesystem-based git branch detection and polling to the TUI, reads/parses .git/HEAD (including worktree gitdir:), caches and periodically refreshes the branch in TUI, displays git:<branch> (rune-truncated) in the right status bar, and adds unit and render tests.

Changes

Git Branch Detection and Display

Layer / File(s) Summary
Branch detection core implementation
internal/tui/branch.go
Adds branchPollInterval, findGitDir, readBranch (handles .git dirs and worktree gitdir: files), (*TUI).pollBranch, and truncateRunes (rune-aware truncation).
Branch detection unit tests
internal/tui/branch_test.go
Adds tests covering missing/non-repo paths, empty input, normal HEAD branch resolution, nested-subdir resolution, detached HEAD (returns empty), non-branch refs, absolute and relative worktree gitdir resolution, malformed .git contents, missing HEAD, and truncateRunes edge cases.
TUI state and event loop integration
internal/tui/tui.go
Adds branch string and branchPollAt time.Time fields to TUI and calls t.pollBranch() from the ticker housekeeping in Run.
Status bar rendering and tests
internal/tui/render.go, internal/tui/render_test.go
renderHints conditionally appends a right-aligned git:<branch> item when t.branch is non-empty (truncated to fit); tests verify short and truncated rendering behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I sniff the .git files on the ground,
Following HEAD where refs are found,
A tiny poll, a cached delight,
The status shows the branch just right,
Rune-safe cuts keep the tail in sight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.05% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main feature being added: displaying the current git branch in the TUI status bar.
Description check ✅ Passed The description provides comprehensive coverage including summary, design rationale, detailed behavior, and test plan, though the template's Type section checkbox and regression test section are not explicitly marked.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds lightweight Git branch detection to the TUI so the current repo branch (or detached SHA) is shown in the status bar without invoking git, polling .git/HEAD every ~2s and supporting worktrees and nested config roots.

Changes:

  • Adds branch state to TUI and refreshes it on the main loop’s periodic housekeeping tick.
  • Renders git:<branch> on the right side of the status bar when available.
  • Introduces readBranch/findGitDir implementation plus unit tests covering normal repos, nested dirs, detached HEAD, and worktrees.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
internal/tui/tui.go Stores branch state on TUI and polls it during the periodic housekeeping tick.
internal/tui/render.go Renders git:<branch> on the right side of the status bar when non-empty.
internal/tui/branch.go Implements repo discovery + HEAD parsing (including worktree indirection) and polling throttling.
internal/tui/branch_test.go Adds unit tests validating branch resolution across repo/worktree scenarios.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/tui/branch.go Outdated
Comment thread internal/tui/render.go Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment thread internal/tui/branch.go Outdated
Comment thread internal/tui/branch.go
Comment thread internal/tui/branch_test.go
Reads HEAD directly from .git (handling worktree indirection) on a 2s
poll, displayed as "git:<name>" between battery and keyboard shortcuts.
Walks upward from projectRoot so a config root inside a subdirectory
still resolves the enclosing repo.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Dinduks Dinduks force-pushed the feat/git-branch-status branch from d648d33 to b798cb1 Compare May 12, 2026 02:26
@Dinduks Dinduks requested a review from Copilot May 12, 2026 02:26
@Dinduks Dinduks force-pushed the feat/git-branch-status branch from b798cb1 to 1b743a0 Compare May 12, 2026 02:27
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment thread internal/tui/branch.go
Comment thread internal/tui/branch_test.go
Comment thread internal/tui/branch.go
@Dinduks Dinduks force-pushed the feat/git-branch-status branch from 1b743a0 to 123330d Compare May 12, 2026 02:46
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tui/render_test.go`:
- Around line 486-504: The test TestRenderHints_BranchTruncated should also
assert the clock remains visible: after building `line` (the rendered bottom row
produced by TUI.renderHints with `branch` set to `long`), compute the current
clock string with `time.Now().Format("15:04")` and assert that `line` contains
that clock string (similar to the existing branch truncation check) so the test
verifies both truncation and clock visibility.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8708beaa-48c7-4ec1-9054-a6dddb4bec31

📥 Commits

Reviewing files that changed from the base of the PR and between 514db86 and 123330d.

📒 Files selected for processing (5)
  • internal/tui/branch.go
  • internal/tui/branch_test.go
  • internal/tui/render.go
  • internal/tui/render_test.go
  • internal/tui/tui.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/tui/render.go
  • internal/tui/tui.go
  • internal/tui/branch.go

Comment thread internal/tui/render_test.go
@Dinduks Dinduks force-pushed the feat/git-branch-status branch from 123330d to f464076 Compare May 12, 2026 02:51
readBranch previously fell back to "first 7 chars of HEAD" whenever the
file didn't start with "ref: refs/heads/". That meant non-branch refs
(tags, remotes) and malformed HEADs leaked partial text like "ref: re"
into the status bar. We only ever wanted to show *branch* names, so
drop the SHA fallback entirely and return empty for anything that isn't
on a branch.

Also cap the rendered branch at 25 runes with an ellipsis so a long
branch name can't push the rightmost status-bar items (clock) off
screen.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment thread internal/tui/tui.go
Comment on lines 993 to 998
if t.welcome.active && time.Now().After(t.welcome.expiresAt) {
t.welcome.active = false
}
t.rotateTip()
t.pollBranch()
t.fireTimers()
Comment thread internal/tui/tui.go
branch string
branchPollAt time.Time


Comment on lines +508 to +513
// Core reason for truncating: the clock (rightmost item) must stay
// visible even when the branch is long.
now := time.Now().Format("15:04")
if !containsStr(line, now) {
t.Errorf("clock %q should remain visible alongside long branch, got: %q", now, line)
}
@nmelo
Copy link
Copy Markdown
Owner

nmelo commented May 12, 2026

Superseded by #25, which was merged with the same branch detection plus the status bar cleanup. Thanks for the PR — the rebased-stacked version is what ultimately landed.

@nmelo nmelo closed this May 12, 2026
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.

3 participants