-
-
-
setBranchFilter(e.target.value)}
- onKeyDown={(e) => e.stopPropagation()}
- onKeyUp={(e) => e.stopPropagation()}
- onKeyPress={(e) => e.stopPropagation()}
- className="h-7 pl-7 text-xs"
- autoFocus
- />
+ }}>
+
+
+
+
+ Switch Branch
+
+ {/* Search input */}
+
-
-
-
- {isLoadingBranches ? (
-
-
- Loading branches...
-
- ) : (() => {
- const filteredBranches = branches.filter((b) =>
- b.name.toLowerCase().includes(branchFilter.toLowerCase())
- );
- if (filteredBranches.length === 0) {
- return (
-
- {branchFilter ? "No matching branches" : "No branches found"}
-
- );
- }
- return filteredBranches.map((branch) => (
-
handleSwitchBranch(worktree, branch.name)}
- disabled={isSwitching || branch.name === worktree.branch}
- className="text-xs font-mono"
- >
- {branch.name === worktree.branch ? (
-
- ) : (
-
- )}
- {branch.name}
+
+
+ {isLoadingBranches ? (
+
+
+ Loading branches...
- ));
- })()}
-
-
- onCreateBranch(worktree)}
- className="text-xs"
- >
-
- Create New Branch...
-
-
-
+ ) : (() => {
+ const filteredBranches = branches.filter((b) =>
+ b.name.toLowerCase().includes(branchFilter.toLowerCase())
+ );
+ if (filteredBranches.length === 0) {
+ return (
+
+ {branchFilter ? "No matching branches" : "No branches found"}
+
+ );
+ }
+ return filteredBranches.map((branch) => (
+ handleSwitchBranch(worktree, branch.name)}
+ disabled={isSwitching || branch.name === worktree.branch}
+ className="text-xs font-mono"
+ >
+ {branch.name === worktree.branch ? (
+
+ ) : (
+
+ )}
+ {branch.name}
+
+ ));
+ })()}
+
+
+
onCreateBranch(worktree)}
+ className="text-xs"
+ >
+
+ Create New Branch...
+
+
+
+ >
) : (
- // Non-main worktrees - just show branch name (worktrees are tied to branches)
+ // Non-main branches - click to switch to this branch
)}
+ {/* Dev server indicator */}
+ {runningDevServers.has(getWorktreeKey(worktree)) && (
+
+ )}
+
{/* Actions dropdown */}
{
if (open) {
@@ -343,18 +624,54 @@ export function WorktreeSelector({
}}>
+ {/* Dev server controls */}
+ {runningDevServers.has(getWorktreeKey(worktree)) ? (
+ <>
+
+
+ Dev Server Running (:{runningDevServers.get(getWorktreeKey(worktree))?.port})
+
+ handleOpenDevServerUrl(worktree)}
+ className="text-xs"
+ >
+
+ Open in Browser
+
+ handleStopDevServer(worktree)}
+ className="text-xs text-destructive focus:text-destructive"
+ >
+
+ Stop Dev Server
+
+
+ >
+ ) : (
+ <>
+ handleStartDevServer(worktree)}
+ disabled={isStartingDevServer}
+ className="text-xs"
+ >
+
+ {isStartingDevServer ? "Starting..." : "Start Dev Server"}
+
+
+ >
+ )}
{/* Pull option */}
handlePull(worktree)}
@@ -384,6 +701,15 @@ export function WorktreeSelector({
)}
+ {/* Open in editor */}
+ handleOpenInEditor(worktree)}
+ className="text-xs"
+ >
+
+ Open in Editor
+
+
{/* Commit changes */}
{worktree.hasChanges && (
void;
categorySuggestions: string[];
+ branchSuggestions: string[];
defaultSkipTests: boolean;
isMaximized: boolean;
showProfilesOnly: boolean;
@@ -60,6 +63,7 @@ export function AddFeatureDialog({
onOpenChange,
onAdd,
categorySuggestions,
+ branchSuggestions,
defaultSkipTests,
isMaximized,
showProfilesOnly,
@@ -74,6 +78,7 @@ export function AddFeatureDialog({
skipTests: false,
model: "opus" as AgentModel,
thinkingLevel: "none" as ThinkingLevel,
+ branchName: "main",
});
const [newFeaturePreviewMap, setNewFeaturePreviewMap] =
useState(() => new Map());
@@ -111,6 +116,7 @@ export function AddFeatureDialog({
skipTests: newFeature.skipTests,
model: selectedModel,
thinkingLevel: normalizedThinking,
+ branchName: newFeature.branchName,
});
// Reset form
@@ -123,6 +129,7 @@ export function AddFeatureDialog({
skipTests: defaultSkipTests,
model: "opus",
thinkingLevel: "none",
+ branchName: "main",
});
setNewFeaturePreviewMap(new Map());
setShowAdvancedOptions(false);
@@ -237,6 +244,21 @@ export function AddFeatureDialog({
data-testid="feature-category-input"
/>
+