Skip to content

Watch git refs, push to store and refresh UI - #18

Merged
recrsn merged 2 commits into
mainfrom
feat/live-branch-list
Apr 30, 2026
Merged

Watch git refs, push to store and refresh UI#18
recrsn merged 2 commits into
mainfrom
feat/live-branch-list

Conversation

@recrsn

@recrsnrecrsn commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Backend: fs.watch on .git/refs/heads/ and .git/packed-refs broadcasts a branches-updated WS event (200 ms debounce) whenever local branches change (new worktree, merge, manual branch creation, etc.)
  • Store: branches: GitBranchInfo[] state + fetchBranches() action added to the Zustand store
  • App: fetchBranches() is called once on startup alongside fetchTickets()
  • useSessionSocket: handles branches-updated events → calls fetchBranches() to refresh
  • AgentDetailPanel / AgentLauncher: read branches from the store instead of each component running its own useEffect + api.remote.listBranches() fetch on every mount

Test plan

  • Open the app; confirm branch dropdown is populated
  • Create a new git branch locally; confirm dropdown updates automatically (within ~200 ms)
  • Merge an agent branch; confirm the branch disappears from the dropdown

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Real-time branch updates: server watches repository branch refs and broadcasts a debounced "branches-updated" event; client refreshes branch list via WebSocket.
    • New store action to fetch and expose branch data to the app.
  • Refactor

    • Centralized branch data in the global store.
    • UI components now read branch options from the store instead of loading them individually on mount.
  • Stability

    • Startup is resilient when branch ref files are absent.

@coderabbitai

coderabbitaiBot commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@recrsn has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 6 minutes and 22 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 41ae6c5a-7885-409c-940b-99976028990a

📥 Commits

Reviewing files that changed from the base of the PR and between 7a7da03 and 677c967.

📒 Files selected for processing (2)
  • src/backend/services/GitWatcher.ts
  • src/frontend/store/store.ts
📝 Walkthrough

Walkthrough

On backend startup the server conditionally registers filesystem watchers for Git refs (.git/refs/heads and .git/packed-refs) under configured remotes. When those paths change the server debounces events (200ms) and broadcasts a WebSocket message { type: "branches-updated" }. The frontend adds branches to the global store with an async fetchBranches action; App calls fetchBranches on mount. Components that previously fetched branches locally now read branches from the store. The session socket handler invokes fetchBranches on "branches-updated" messages.

Sequence Diagram

sequenceDiagram
participant Git as Git Filesystem
participant Server as Backend Server
participant WS as WebSocket Broker
participant Client as Frontend Client
participant Store as Zustand Store
participant UI as UI Components
Note over Server,Client: Startup
Server->>Git: Start watching .git/refs/heads & .git/packed-refs
Client->>Store: Call fetchBranches()
Store->>Server: api.remote.listBranches()
Server-->>Store: Return branch list
Store->>UI: Update branches state
UI->>UI: Render using store branches
Note over Git,Client: On branch change
Git->>Server: File change event
Server->>Server: Debounce (200ms)
Server->>WS: Broadcast { type: "branches-updated" }
WS->>Client: Deliver "branches-updated"
Client->>Store: Invoke fetchBranches()
Store->>Server: api.remote.listBranches()
Server-->>Store: Return updated branch list
Store->>UI: Update branches state
UI->>UI: Re-render with new branches
Loading

Possibly related PRs

Suggested Reviewers

  • roulpriya

Poem

🐇
I nibble on refs in the quiet night,
I watch the branches grow and take flight,
Server hums, websockets sing a tune,
Store fetches carrots beneath the moon,
Hop—now the UI stays fresh by noon.


Review rate limit: 0/3 reviews remaining, refill in 6 minutes and 22 seconds.

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

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/backend/main.ts`:
- Around line 52-69: The branch-watcher is only initialized from the boot
snapshot (using remoteStmts.get.get()), so if localPath is absent at startup or
changes later the watchers never get created; refactor the watcher setup (the
debounce, notify, watch(join(... ".git" "refs" "heads") and watch(join(...
".git" "packed-refs") calls and broadcastNotification({ type: "branches-updated"
})) into a new function startBranchWatchers(config) and call startBranchWatchers
whenever the remote config is created/updated (i.e. in the remoteStmts
creation/update handlers) as well as at boot; ensure you preserve the try/catch
behavior and debounce logic when moving code so watchers are re-established
every time remoteStmts changes.
In `@src/frontend/store/store.ts`:
- Around line 212-219: The fetchBranches action can be made race-safe by
tracking a monotonically incrementing request id (or timestamp) in the store so
out-of-order responses don't overwrite newer data: when fetchBranches starts,
increment and capture a local requestId (store a lastFetchId via get/set), then
after awaiting api.remote.listBranches() compare the captured id to the current
lastFetchId and only call set({ branches }) if they match; reference
fetchBranches, api.remote.listBranches, set and get to implement this check and
update the lastFetchId atomically around the request start.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: abeac59e-3362-4ef6-811d-fba6718dd3ec

📥 Commits

Reviewing files that changed from the base of the PR and between 3b1b190 and af6e244.

📒 Files selected for processing (6)
  • src/backend/main.ts
  • src/frontend/App.tsx
  • src/frontend/components/AgentDetailPanel.tsx
  • src/frontend/components/AgentLauncher.tsx
  • src/frontend/hooks/useSessionSocket.tsx
  • src/frontend/store/store.ts

Comment threadsrc/backend/main.ts Outdated
Comment threadsrc/frontend/store/store.ts
@recrsnrecrsn changed the title feat: live branch list — watch git refs, push to store, auto-refresh UIWatch git refs, push to store and refresh UIApr 30, 2026
Branches are fetched once on startup and kept fresh automatically:
- Backend: watch .git/refs/heads/ and packed-refs with fs.watch; broadcast
branches-updated over the notification WS channel on any change (200ms debounce)
- Frontend store: add branches[] state and fetchBranches() action
- App: call fetchBranches() on mount alongside fetchTickets()
- useSessionSocket: handle branches-updated → fetchBranches()
- AgentDetailPanel/AgentLauncher: read branches from store instead of
local effects that fetched on every component mount
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@recrsn
recrsnforce-pushed the feat/live-branch-list branch from af6e244 to 7a7da03CompareApril 30, 2026 18:17
GitWatcher already watches refs/heads/ and the .git/ root (which covers
packed-refs) and gitWatcher.start() is already called from routes/remote.ts
on every config change. Extend handleGitChange to broadcast branches-updated
on ref and packed-refs changes, then remove the redundant boot-only inline
watcher block from main.ts (and its now-unused fs/path imports).
fetchBranches: guard with a monotonic counter so out-of-order responses
from concurrent calls don't overwrite newer data.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@recrsn
recrsn merged commit 3253856 into mainApr 30, 2026
2 checks passed
@recrsn
recrsn deleted the feat/live-branch-list branch April 30, 2026 18:22
Sign up for freeto 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

@recrsn