Skip to content

Feat/custom worktree branch name - #6428

Open
MrSimmmons wants to merge 6 commits into
pingdotgg:mainfrom
MrSimmmons:feat/custom-worktree-branch-name
Open

Feat/custom worktree branch name#6428
MrSimmmons wants to merge 6 commits into
pingdotgg:mainfrom
MrSimmmons:feat/custom-worktree-branch-name

Conversation

@MrSimmmons

@MrSimmmons MrSimmmons commented Aug 13, 2026

Copy link
Copy Markdown

What Changed

Allows the setting of a custom branch name when creating a new worktree from a new thread

Why

Fixes #6421, also adds a workflow / fixes a potential bug for #3044, #5359 #5734 and #967

Was initially developed on top of #6427 to round out some worktree features I found missing when comparing to other apps like VS Code, but its a pretty good stand alone feature addition so this gets its own PR

UI Changes

Before:
Screenshot 2026-08-13 at 4 03 25 PM

After:
Screenshot 2026-08-13 at 2 33 01 PM
Screenshot 2026-08-13 at 2 33 26 PM

Happy to make changes to the UI if the idea seems sound :D

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes

Note

Medium Risk
Touches first-message worktree creation and send gating; mistakes could block sends or create branches with wrong names, but scope is limited to draft worktree flows with explicit validation.

Overview
Adds an optional custom branch name when starting a new worktree from a draft (before the first send), instead of always using a temporary generated name.

The branch toolbar shows BranchToolbarWorktreeNameInput only for draft + worktree mode with no existing worktree path. Names are sanitized/normalized via new shared helpers (sanitizeWorktreeBranchNameInput, normalizeWorktreeBranchName), persisted on the draft as worktreeBranchName, and checked against local refs through listRefs (with GIT_LIST_BRANCHES_MAX_LIMIT exported for a full local page). Send is blocked while validation is in flight or on conflict; a validated custom name is passed in prepareWorktree.branch and skips server LLM rename behavior for temporary branches.

Minor toolbar layout tweaks (shrink / flex-auto) accommodate the new control on mobile and desktop.

Reviewed by Cursor Bugbot for commit 0eadfa0. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add custom branch name input for new worktree creation in chat

  • Adds a new BranchToolbarWorktreeNameInput component that lets users type a custom branch name before sending the first message in new-worktree mode; input is sanitized per-keystroke via sanitizeWorktreeBranchNameInput and normalized via normalizeWorktreeBranchName.
  • Validates the typed name against existing local branches asynchronously using vcsEnvironment.listRefs; conflicts are shown inline and block sending.
  • Persists the custom branch name in the draft store (worktreeBranchName field) so it survives navigation; on send, uses the validated name instead of a random hex fallback.
  • Introduces sanitizeWorktreeBranchNameInput and normalizeWorktreeBranchName helpers in packages/shared/src/git.ts, with full test coverage.
  • Exports GIT_LIST_BRANCHES_MAX_LIMIT from packages/contracts/src/git.ts for use in the new component.

Macroscope summarized 0eadfa0.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c200e80b-12fe-44a8-8198-0e70556f60ce

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 13, 2026
Comment thread apps/web/src/composerDraftStore.ts Outdated
Comment thread apps/web/src/components/BranchToolbar.tsx Outdated
// A custom name skips the server's LLM branch naming:
// only temporary-pattern branches get renamed.
branch:
customWorktreeBranchName ?? buildTemporaryWorktreeBranchName(randomHex),

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.

🟠 High components/ChatView.tsx:5248

customWorktreeBranchName can pass Git-invalid names such as feature.lock or foo.lock/bar to prepareWorktree.branch, so the conflict check passes and the first send fails during worktree creation. Validate the final branch name against Git's full ref-format rules, including slash-separated components ending in .lock, before dispatching it.

Also found in 1 other location(s)

packages/shared/src/git.ts:133

normalizeWorktreeBranchName can return names Git rejects because it never removes or rejects a slash-separated component ending in .lock (for example, feature.lock or team.lock/topic). Git's ref-format rules explicitly forbid such components. The conflict query will not flag a nonexistent invalid ref, so send proceeds with this custom name and worktree/branch creation fails instead of creating the new thread.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/ChatView.tsx around line 5248:

`customWorktreeBranchName` can pass Git-invalid names such as `feature.lock` or `foo.lock/bar` to `prepareWorktree.branch`, so the conflict check passes and the first send fails during worktree creation. Validate the final branch name against Git's full ref-format rules, including slash-separated components ending in `.lock`, before dispatching it.

Also found in 1 other location(s):
- packages/shared/src/git.ts:133 -- `normalizeWorktreeBranchName` can return names Git rejects because it never removes or rejects a slash-separated component ending in `.lock` (for example, `feature.lock` or `team.lock/topic`). Git's ref-format rules explicitly forbid such components. The conflict query will not flag a nonexistent invalid ref, so send proceeds with this custom name and worktree/branch creation fails instead of creating the new thread.

Comment thread apps/web/src/components/BranchToolbar.tsx Outdated
Comment thread apps/web/src/composerDraftStore.ts Outdated
Comment thread apps/web/src/components/BranchToolbarWorktreeNameInput.tsx Outdated
Comment thread packages/shared/src/git.ts
@macroscopeapp

macroscopeapp Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Needs human review

3 blocking correctness issues found. This PR introduces a new user-facing feature for custom worktree branch naming with new UI components, state management, and send-flow integration. New features with this scope warrant human review. Additionally, there are High-severity findings about edge cases in branch conflict detection.

You can customize Macroscope's approvability policy. Learn more.

@MrSimmmons
MrSimmmons force-pushed the feat/custom-worktree-branch-name branch from 85e8859 to efd6128 Compare August 18, 2026 02:42

@macroscopeapp macroscopeapp Bot 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.

Three consistency issues in the new BranchToolbarWorktreeNameInput control, all within the composer context strip it joins.

Posted via Macroscope — UI Consistency

Comment thread apps/web/src/components/BranchToolbarWorktreeNameInput.tsx Outdated
Comment thread apps/web/src/components/BranchToolbarWorktreeNameInput.tsx
Comment thread apps/web/src/components/BranchToolbarWorktreeNameInput.tsx Outdated

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit efd6128. Configure here.

Comment thread apps/web/src/components/BranchToolbarWorktreeNameInput.tsx
listRefs matches the query as a substring and pages the result, so an
exact branch could fall off a 20-ref page and the gate would report the
name as available. Ask for local refs only at the schema's max page size,
and export that ceiling so the two stay in step.
// result, so an exact match can fall off a short page. Locals
// only (remotes can't collide) at the max page size.
refKind: "local",
limit: GIT_LIST_BRANCHES_MAX_LIMIT,

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.

🟠 High components/BranchToolbarWorktreeNameInput.tsx:55

When more than 200 local refs contain the typed text, an exact duplicate after the first page is omitted and the input is marked available; sending then fails when Git rejects creation of the existing branch. listRefs paginates the substring-filtered results, so use nextCursor to inspect all pages or perform a server-side exact-match check.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/BranchToolbarWorktreeNameInput.tsx around line 55:

When more than 200 local refs contain the typed text, an exact duplicate after the first page is omitted and the input is marked `available`; sending then fails when Git rejects creation of the existing branch. `listRefs` paginates the substring-filtered results, so use `nextCursor` to inspect all pages or perform a server-side exact-match check.

const conflict =
checked &&
(conflictRefsQuery.data?.refs.some(
(refName) => !refName.isRemote && refName.name === normalizedValue,

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.

🟠 High components/BranchToolbarWorktreeNameInput.tsx:69

Conflict detection marks names as available when they have a /-boundary prefix relationship with an existing local branch, but Git rejects both feature vs feature/foo combinations. Worktree creation therefore fails on send; treat either name being the other name plus / as a conflict.

Suggested change
(refName) => !refName.isRemote && refName.name === normalizedValue,
(refName) =>
!refName.isRemote &&
(refName.name === normalizedValue ||
refName.name.startsWith(`${normalizedValue}/`) ||
normalizedValue.startsWith(`${refName.name}/`)),
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/BranchToolbarWorktreeNameInput.tsx around line 69:

Conflict detection marks names as `available` when they have a `/`-boundary prefix relationship with an existing local branch, but Git rejects both `feature` vs `feature/foo` combinations. Worktree creation therefore fails on send; treat either name being the other name plus `/` as a conflict.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Fully custom branch name when starting a new worktree thread

1 participant