Add custom branch name feature

Users can now specify a custom branch name when creating a session. If provided, the custom name is used as both the git branch name and the session display name.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Amrit Subramanian 2025-10-05 17:09:48 -04:00
parent 9405824d7b
commit fcd62c27bb
3 changed files with 32 additions and 7 deletions

View file

@ -71,6 +71,12 @@
</select>
</div>
<div class="form-group">
<label class="form-label">Branch Name (optional)</label>
<input type="text" id="branch-name" class="form-input" placeholder="e.g., feature/add-login" />
<span class="text-xs text-gray-400 mt-1 block">Custom branch name (will also be used as session name)</span>
</div>
<div class="form-group">
<label class="form-label">Coding Agent</label>
<select id="coding-agent" class="form-select">

24
main.ts
View file

@ -14,6 +14,7 @@ const execAsync = promisify(exec);
interface SessionConfig {
projectDir: string;
parentBranch: string;
branchName?: string;
codingAgent: string;
skipPermissions: boolean;
setupCommands?: string[];
@ -343,14 +344,21 @@ async function ensureFleetcodeExcluded(projectDir: string) {
}
}
async function createWorktree(projectDir: string, parentBranch: string, sessionNumber: number, sessionUuid: string): Promise<string> {
async function createWorktree(projectDir: string, parentBranch: string, sessionNumber: number, sessionUuid: string, customBranchName?: string): Promise<string> {
const git = simpleGit(projectDir);
const fleetcodeDir = path.join(projectDir, ".fleetcode");
const worktreeName = `session${sessionNumber}`;
const worktreePath = path.join(fleetcodeDir, worktreeName);
// Include short UUID to ensure branch uniqueness across deletes/recreates
const shortUuid = sessionUuid.split('-')[0];
const branchName = `fleetcode/session${sessionNumber}-${shortUuid}`;
// Use custom branch name if provided, otherwise generate default
let branchName: string;
if (customBranchName) {
branchName = customBranchName;
} else {
// Include short UUID to ensure branch uniqueness across deletes/recreates
const shortUuid = sessionUuid.split('-')[0];
branchName = `fleetcode/session${sessionNumber}-${shortUuid}`;
}
// Create .fleetcode directory if it doesn't exist
if (!fs.existsSync(fleetcodeDir)) {
@ -434,7 +442,9 @@ ipcMain.on("create-session", async (event, config: SessionConfig) => {
try {
const sessionNumber = getNextSessionNumber();
const sessionId = `session-${Date.now()}`;
const sessionName = `Session ${sessionNumber}`;
// Use custom branch name as session name if provided, otherwise default
const sessionName = config.branchName || `Session ${sessionNumber}`;
// Generate UUID for this session (before creating worktree)
const sessionUuid = uuidv4();
@ -442,8 +452,8 @@ ipcMain.on("create-session", async (event, config: SessionConfig) => {
// Ensure .fleetcode is excluded (async, don't wait)
ensureFleetcodeExcluded(config.projectDir);
// Create git worktree with unique branch name
const worktreePath = await createWorktree(config.projectDir, config.parentBranch, sessionNumber, sessionUuid);
// Create git worktree with custom or default branch name
const worktreePath = await createWorktree(config.projectDir, config.parentBranch, sessionNumber, sessionUuid, config.branchName);
// Extract and write MCP config
const mcpServers = extractProjectMcpConfig(config.projectDir);

View file

@ -5,6 +5,7 @@ import { FitAddon } from "xterm-addon-fit";
interface SessionConfig {
projectDir: string;
parentBranch: string;
branchName?: string;
codingAgent: string;
skipPermissions: boolean;
setupCommands?: string[];
@ -761,6 +762,7 @@ ipcRenderer.on("session-created", (_event, sessionId: string, persistedSession:
const modal = document.getElementById("config-modal");
const projectDirInput = document.getElementById("project-dir") as HTMLInputElement;
const parentBranchSelect = document.getElementById("parent-branch") as HTMLSelectElement;
const branchNameInput = document.getElementById("branch-name") as HTMLInputElement;
const setupCommandsTextarea = document.getElementById("setup-commands") as HTMLTextAreaElement;
if (createBtn) {
@ -775,6 +777,9 @@ ipcRenderer.on("session-created", (_event, sessionId: string, persistedSession:
projectDirInput.value = "";
selectedDirectory = "";
parentBranchSelect.innerHTML = '<option value="">Loading branches...</option>';
if (branchNameInput) {
branchNameInput.value = "";
}
if (setupCommandsTextarea) {
setupCommandsTextarea.value = "";
}
@ -934,9 +939,13 @@ createBtn?.addEventListener("click", () => {
? setupCommandsText.split("\n").filter(cmd => cmd.trim())
: undefined;
const branchNameInput = document.getElementById("branch-name") as HTMLInputElement;
const branchName = branchNameInput?.value.trim() || undefined;
const config: SessionConfig = {
projectDir: selectedDirectory,
parentBranch: parentBranchSelect.value,
branchName,
codingAgent: codingAgentSelect.value,
skipPermissions: codingAgentSelect.value === "claude" ? skipPermissionsCheckbox.checked : false,
setupCommands,