workon 3.6.0 → 3.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -283,6 +283,13 @@ var init_project = __esm({
283
283
  }
284
284
  return this._path;
285
285
  }
286
+ /**
287
+ * Override the project path with an absolute path.
288
+ * Used when targeting a worktree instead of the main project directory.
289
+ */
290
+ overridePath(absolutePath) {
291
+ this._path = File.from(absolutePath).absolutify();
292
+ }
286
293
  set branch(branch) {
287
294
  this._branch = branch;
288
295
  }
@@ -1268,7 +1275,7 @@ var init_tmux = __esm({
1268
1275
  getWorktreeSessionName(projectName, worktreeName) {
1269
1276
  const sanitizedProject = sanitizeForShell(projectName);
1270
1277
  const sanitizedWorktree = sanitizeForShell(worktreeName);
1271
- return `${this.sessionPrefix}${sanitizedProject}-${sanitizedWorktree}`;
1278
+ return `${this.sessionPrefix}${sanitizedProject}_wt_${sanitizedWorktree}`;
1272
1279
  }
1273
1280
  async killSession(sessionName) {
1274
1281
  try {
@@ -1421,24 +1428,6 @@ var init_tmux = __esm({
1421
1428
  }
1422
1429
  });
1423
1430
 
1424
- // src/types/constants.ts
1425
- var IDE_CHOICES;
1426
- var init_constants = __esm({
1427
- "src/types/constants.ts"() {
1428
- "use strict";
1429
- IDE_CHOICES = [
1430
- { name: "Cursor", value: "cursor" },
1431
- { name: "Visual Studio Code", value: "vscode" },
1432
- { name: "Visual Studio Code (code)", value: "code" },
1433
- { name: "IntelliJ IDEA", value: "idea" },
1434
- { name: "Atom", value: "atom" },
1435
- { name: "Sublime Text", value: "subl" },
1436
- { name: "Vim", value: "vim" },
1437
- { name: "Emacs", value: "emacs" }
1438
- ];
1439
- }
1440
- });
1441
-
1442
1431
  // src/lib/worktree.ts
1443
1432
  import { exec as execCallback2 } from "child_process";
1444
1433
  import { promisify as promisify2 } from "util";
@@ -1771,6 +1760,24 @@ var init_worktree = __esm({
1771
1760
  }
1772
1761
  });
1773
1762
 
1763
+ // src/types/constants.ts
1764
+ var IDE_CHOICES;
1765
+ var init_constants = __esm({
1766
+ "src/types/constants.ts"() {
1767
+ "use strict";
1768
+ IDE_CHOICES = [
1769
+ { name: "Cursor", value: "cursor" },
1770
+ { name: "Visual Studio Code", value: "vscode" },
1771
+ { name: "Visual Studio Code (code)", value: "code" },
1772
+ { name: "IntelliJ IDEA", value: "idea" },
1773
+ { name: "Atom", value: "atom" },
1774
+ { name: "Sublime Text", value: "subl" },
1775
+ { name: "Vim", value: "vim" },
1776
+ { name: "Emacs", value: "emacs" }
1777
+ ];
1778
+ }
1779
+ });
1780
+
1774
1781
  // src/commands/worktrees/utils.ts
1775
1782
  import File3 from "phylo";
1776
1783
  import path from "path";
@@ -2035,7 +2042,7 @@ import ora from "ora";
2035
2042
  import { select as select2, confirm as confirm4 } from "@inquirer/prompts";
2036
2043
  function createAddCommand(ctx) {
2037
2044
  const { config, log } = ctx;
2038
- return new Command2("add").description("Create a new worktree for a branch").argument("<branch>", "Branch name for the worktree").option("-b, --base <branch>", "Base branch to create new branch from").option("-f, --force", "Overwrite existing worktree").option("-o, --open", "Open the worktree after creation").option("--no-hook", "Skip running the post-setup hook").action(async (branch, options) => {
2045
+ return new Command2("add").description("Create a new worktree for a branch").argument("<branch>", "Branch name for the worktree").option("-b, --base <branch>", "Base branch to create new branch from").option("-f, --force", "Overwrite existing worktree").option("-o, --open", "Open the worktree after creation").option("--no-hook", "Skip running the post-setup hook").option("-y, --yes", "Skip all confirmation prompts (non-interactive mode)").action(async (branch, options) => {
2039
2046
  const projectCtx = await resolveProjectFromCwd(config, log);
2040
2047
  if (!projectCtx) {
2041
2048
  log.error("Not in a git repository. Run this command from within a git project.");
@@ -2045,11 +2052,15 @@ function createAddCommand(ctx) {
2045
2052
  process.exit(1);
2046
2053
  }
2047
2054
  if (!projectCtx.isRegistered) {
2048
- const result = await promptToRegisterProject(projectCtx.projectPath, config, log);
2049
- if (result) {
2050
- projectCtx.projectName = result.projectName;
2051
- projectCtx.projectConfig = result.projectConfig;
2052
- projectCtx.isRegistered = true;
2055
+ if (options.yes) {
2056
+ log.info("Project is not registered. Proceeding without registration.");
2057
+ } else {
2058
+ const result = await promptToRegisterProject(projectCtx.projectPath, config, log);
2059
+ if (result) {
2060
+ projectCtx.projectName = result.projectName;
2061
+ projectCtx.projectConfig = result.projectConfig;
2062
+ projectCtx.isRegistered = true;
2063
+ }
2053
2064
  }
2054
2065
  }
2055
2066
  const { projectPath, projectName } = projectCtx;
@@ -2057,16 +2068,21 @@ function createAddCommand(ctx) {
2057
2068
  const branchExists = await manager.branchExists(branch);
2058
2069
  let baseBranch = options.base;
2059
2070
  if (!branchExists && !baseBranch) {
2060
- const branches = await manager.getBranches();
2061
- const currentBranch = await manager.getCurrentBranch();
2062
- baseBranch = await select2({
2063
- message: `Branch '${branch}' doesn't exist. Create from which branch?`,
2064
- choices: branches.map((b) => ({
2065
- name: b === currentBranch ? `${b} (current)` : b,
2066
- value: b
2067
- })),
2068
- default: currentBranch
2069
- });
2071
+ if (options.yes) {
2072
+ baseBranch = await manager.getCurrentBranch();
2073
+ log.info(`Branch '${branch}' doesn't exist. Creating from '${baseBranch}'.`);
2074
+ } else {
2075
+ const branches = await manager.getBranches();
2076
+ const currentBranch = await manager.getCurrentBranch();
2077
+ baseBranch = await select2({
2078
+ message: `Branch '${branch}' doesn't exist. Create from which branch?`,
2079
+ choices: branches.map((b) => ({
2080
+ name: b === currentBranch ? `${b} (current)` : b,
2081
+ value: b
2082
+ })),
2083
+ default: currentBranch
2084
+ });
2085
+ }
2070
2086
  }
2071
2087
  const spinner = ora(`Creating worktree for branch '${branch}'...`).start();
2072
2088
  try {
@@ -2099,6 +2115,9 @@ ${chalk2.bold("Worktree details:")}`);
2099
2115
  if (projectCtx.isRegistered && projectName) {
2100
2116
  if (options.open) {
2101
2117
  await openWorktreeSession(projectCtx, worktree.name, config, log);
2118
+ } else if (options.yes) {
2119
+ console.log(`
2120
+ To open later: ${chalk2.cyan(`workon worktrees open ${worktree.name}`)}`);
2102
2121
  } else {
2103
2122
  const shouldOpen = await confirm4({
2104
2123
  message: "Open workon session in this worktree?",
@@ -2268,7 +2287,7 @@ import path4 from "path";
2268
2287
  import { select as select3, confirm as confirm6 } from "@inquirer/prompts";
2269
2288
  function createMergeCommand(ctx) {
2270
2289
  const { config, log } = ctx;
2271
- return new Command4("merge").description("Merge a worktree branch and optionally remove the worktree").argument("<name>", "Worktree name").option("-i, --into <branch>", "Target branch to merge into").option("-s, --squash", "Use squash merge").option("-k, --keep", "Keep the worktree after merging").option("-y, --yes", "Skip confirmation prompts").action(async (name, options) => {
2290
+ return new Command4("merge").description("Merge a worktree branch and optionally remove the worktree").argument("<name>", "Worktree name").option("-i, --into <branch>", "Target branch to merge into").option("-s, --squash", "Use squash merge").option("-k, --keep", "Keep the worktree after merging").option("-y, --yes", "Skip confirmation prompts").option("--delete-branch", "Delete the merged branch after merge").action(async (name, options) => {
2272
2291
  const projectCtx = await resolveProjectFromCwd(config, log);
2273
2292
  if (!projectCtx) {
2274
2293
  log.error("Not in a git repository. Run this command from within a git project.");
@@ -2310,14 +2329,19 @@ function createMergeCommand(ctx) {
2310
2329
  }
2311
2330
  const commonTargets = ["main", "master", "develop", "dev"];
2312
2331
  const defaultTarget = commonTargets.find((t) => targetBranches.includes(t)) || targetBranches[0];
2313
- targetBranch = await select3({
2314
- message: `Merge '${worktree.branch}' into which branch?`,
2315
- choices: targetBranches.map((b) => ({
2316
- name: b,
2317
- value: b
2318
- })),
2319
- default: defaultTarget
2320
- });
2332
+ if (options.yes) {
2333
+ targetBranch = defaultTarget;
2334
+ log.info(`Auto-selected target branch: '${targetBranch}'`);
2335
+ } else {
2336
+ targetBranch = await select3({
2337
+ message: `Merge '${worktree.branch}' into which branch?`,
2338
+ choices: targetBranches.map((b) => ({
2339
+ name: b,
2340
+ value: b
2341
+ })),
2342
+ default: defaultTarget
2343
+ });
2344
+ }
2321
2345
  }
2322
2346
  if (!await manager.branchExists(targetBranch)) {
2323
2347
  log.error(`Target branch '${targetBranch}' does not exist.`);
@@ -2359,6 +2383,11 @@ ${chalk4.bold("Merge operation:")}`);
2359
2383
  log.info("You may need to resolve conflicts manually.");
2360
2384
  process.exit(1);
2361
2385
  }
2386
+ if (options.keep && options.deleteBranch) {
2387
+ log.warn(
2388
+ "--delete-branch is ignored when --keep is set (branch is needed by the worktree)."
2389
+ );
2390
+ }
2362
2391
  if (!options.keep) {
2363
2392
  const tmux = new TmuxManager();
2364
2393
  const sessionName = tmux.getWorktreeSessionName(displayName, name);
@@ -2374,21 +2403,22 @@ ${chalk4.bold("Merge operation:")}`);
2374
2403
  removeSpinner.warn(`Failed to remove worktree: ${error.message}`);
2375
2404
  log.info(`You can remove it manually with: workon worktrees remove ${name}`);
2376
2405
  }
2377
- if (!options.yes) {
2378
- const shouldDeleteBranch = await confirm6({
2406
+ let shouldDeleteBranch = options.deleteBranch || false;
2407
+ if (!shouldDeleteBranch && !options.yes) {
2408
+ shouldDeleteBranch = await confirm6({
2379
2409
  message: `Delete the merged branch '${worktree.branch}'?`,
2380
2410
  default: false
2381
2411
  });
2382
- if (shouldDeleteBranch) {
2383
- const deleteSpinner = ora3(`Deleting branch '${worktree.branch}'...`).start();
2384
- try {
2385
- const { simpleGit: simpleGit6 } = await import("simple-git");
2386
- const git = simpleGit6(projectPath);
2387
- await git.deleteLocalBranch(worktree.branch, true);
2388
- deleteSpinner.succeed(`Branch '${worktree.branch}' deleted`);
2389
- } catch (error) {
2390
- deleteSpinner.warn(`Failed to delete branch: ${error.message}`);
2391
- }
2412
+ }
2413
+ if (shouldDeleteBranch) {
2414
+ const deleteSpinner = ora3(`Deleting branch '${worktree.branch}'...`).start();
2415
+ try {
2416
+ const { simpleGit: simpleGit6 } = await import("simple-git");
2417
+ const git = simpleGit6(projectPath);
2418
+ await git.deleteLocalBranch(worktree.branch, true);
2419
+ deleteSpinner.succeed(`Branch '${worktree.branch}' deleted`);
2420
+ } catch (error) {
2421
+ deleteSpinner.warn(`Failed to delete branch: ${error.message}`);
2392
2422
  }
2393
2423
  }
2394
2424
  }
@@ -2414,7 +2444,7 @@ import { confirm as confirm7 } from "@inquirer/prompts";
2414
2444
  import { simpleGit as simpleGit4 } from "simple-git";
2415
2445
  function createBranchCommand(ctx) {
2416
2446
  const { config, log } = ctx;
2417
- return new Command5("branch").description("Create a branch from a worktree (useful for detached HEAD state)").argument("<worktree>", "Worktree name").argument("<branch>", "New branch name to create").option("-p, --push", "Push the branch to origin after creating").option("-f, --force", "Overwrite existing branch").action(async (worktreeName, branchName, options) => {
2447
+ return new Command5("branch").description("Create a branch from a worktree (useful for detached HEAD state)").argument("<worktree>", "Worktree name").argument("<branch>", "New branch name to create").option("-p, --push", "Push the branch to origin after creating").option("-f, --force", "Overwrite existing branch").option("-y, --yes", "Skip all confirmation prompts (non-interactive mode)").action(async (worktreeName, branchName, options) => {
2418
2448
  const projectCtx = await resolveProjectFromCwd(config, log);
2419
2449
  if (!projectCtx) {
2420
2450
  log.error("Not in a git repository. Run this command from within a git project.");
@@ -2477,6 +2507,8 @@ ${chalk5.bold("Action:")}`);
2477
2507
  pushSpinner.fail(`Failed to push: ${error.message}`);
2478
2508
  log.info(`You can push manually with: git push -u origin ${branchName}`);
2479
2509
  }
2510
+ } else if (options.yes) {
2511
+ log.info(`You can push manually with: git push -u origin ${branchName}`);
2480
2512
  } else {
2481
2513
  const shouldPush = await confirm7({
2482
2514
  message: "Push branch to origin for PR?",
@@ -2579,13 +2611,12 @@ __export(open_exports, {
2579
2611
  });
2580
2612
  import { Command as Command7 } from "commander";
2581
2613
  import chalk6 from "chalk";
2582
- import File4 from "phylo";
2583
2614
  import path6 from "path";
2584
2615
  import { exec as execCallback3 } from "child_process";
2585
2616
  import { promisify as promisify3 } from "util";
2586
2617
  function createOpenCommand(ctx) {
2587
2618
  const { config, log } = ctx;
2588
- return new Command7("open").description("Open a workon session in a worktree").argument("<name>", "Worktree name").option("-d, --debug", "Enable debug logging").option("--shell", "Output shell commands instead of spawning processes").action(async (name, options) => {
2619
+ return new Command7("open").description("Open a workon session in a worktree").argument("<name>", "Worktree name").option("-d, --debug", "Enable debug logging").option("--shell", "Output shell commands instead of spawning processes").option("-y, --yes", "Skip all confirmation prompts (non-interactive mode)").action(async (name, options) => {
2589
2620
  if (options.debug) {
2590
2621
  log.setLogLevel("debug");
2591
2622
  }
@@ -2598,12 +2629,16 @@ function createOpenCommand(ctx) {
2598
2629
  process.exit(1);
2599
2630
  }
2600
2631
  if (!projectCtx.isRegistered) {
2601
- log.warn("Project is not registered. Opening with basic shell layout.");
2602
- const shouldRegister = await promptToRegisterProject(projectCtx.projectPath, config, log);
2603
- if (shouldRegister) {
2604
- projectCtx.projectName = shouldRegister.projectName;
2605
- projectCtx.projectConfig = shouldRegister.projectConfig;
2606
- projectCtx.isRegistered = true;
2632
+ if (options.yes) {
2633
+ log.info("Project is not registered. Opening with basic shell layout.");
2634
+ } else {
2635
+ log.warn("Project is not registered. Opening with basic shell layout.");
2636
+ const shouldRegister = await promptToRegisterProject(projectCtx.projectPath, config, log);
2637
+ if (shouldRegister) {
2638
+ projectCtx.projectName = shouldRegister.projectName;
2639
+ projectCtx.projectConfig = shouldRegister.projectConfig;
2640
+ projectCtx.isRegistered = true;
2641
+ }
2607
2642
  }
2608
2643
  }
2609
2644
  await runWorktreeOpen(projectCtx, name, options, { config, log });
@@ -2636,7 +2671,7 @@ async function runWorktreeOpen(projectCtx, worktreeName, options, ctx) {
2636
2671
  let hasNpmEvent = false;
2637
2672
  if (isRegistered && projectName && projectConfig) {
2638
2673
  project = new Project(projectName, projectConfig, defaults);
2639
- project._path = File4.from(worktree.path).absolutify();
2674
+ project.overridePath(worktree.path);
2640
2675
  const events = project.events || {};
2641
2676
  hasClaudeEvent = !!events.claude;
2642
2677
  hasNpmEvent = !!events.npm;
@@ -2855,7 +2890,7 @@ __export(interactive_exports, {
2855
2890
  });
2856
2891
  import { select as select4, input as input5, checkbox as checkbox2, confirm as confirm8 } from "@inquirer/prompts";
2857
2892
  import { existsSync as existsSync5 } from "fs";
2858
- import File5 from "phylo";
2893
+ import File4 from "phylo";
2859
2894
  import path7 from "path";
2860
2895
  import deepAssign2 from "deep-assign";
2861
2896
  import chalk7 from "chalk";
@@ -2863,7 +2898,7 @@ async function runInteractive(ctx) {
2863
2898
  const { config, log, environment, suggestedName } = ctx;
2864
2899
  showLogo(config);
2865
2900
  log.log("");
2866
- const defaultName = suggestedName ?? (environment.$isProjectEnvironment ? environment.project.name : File5.cwd().name);
2901
+ const defaultName = suggestedName ?? (environment.$isProjectEnvironment ? environment.project.name : File4.cwd().name);
2867
2902
  const fromUser = !!suggestedName;
2868
2903
  await startInteractive(defaultName, fromUser, ctx);
2869
2904
  }
@@ -2964,15 +2999,15 @@ async function initProject(defaultName, fromUser, ctx) {
2964
2999
  let basePath;
2965
3000
  if (isBranch) {
2966
3001
  const projectName = name.substring(0, name.indexOf("#"));
2967
- basePath = defaults?.base ? File5.from(defaults.base).join(projects[projectName].path).absolutePath() : projects[projectName].path;
3002
+ basePath = defaults?.base ? File4.from(defaults.base).join(projects[projectName].path).absolutePath() : projects[projectName].path;
2968
3003
  log.log(`Project path: ${basePath}`);
2969
3004
  } else {
2970
3005
  const pathAnswer = await input5({
2971
3006
  message: "What is the path to the project?",
2972
- default: defaults?.base ? File5.from(defaults.base).join(name).path : name
3007
+ default: defaults?.base ? File4.from(defaults.base).join(name).path : name
2973
3008
  });
2974
- let answerFile = File5.from(pathAnswer);
2975
- const defaultBase = defaults?.base ? File5.from(defaults.base).absolutify() : File5.cwd();
3009
+ let answerFile = File4.from(pathAnswer);
3010
+ const defaultBase = defaults?.base ? File4.from(defaults.base).absolutify() : File4.cwd();
2976
3011
  if (!answerFile.isAbsolute()) {
2977
3012
  answerFile = defaultBase.join(answerFile.path);
2978
3013
  }
@@ -3180,15 +3215,15 @@ async function createProjectManage(ctx) {
3180
3215
  return true;
3181
3216
  }
3182
3217
  });
3183
- const defaultPath = defaults?.base ? File5.from(defaults.base).absolutify().join(name).path : name;
3218
+ const defaultPath = defaults?.base ? File4.from(defaults.base).absolutify().join(name).path : name;
3184
3219
  const pathInput = await input5({
3185
3220
  message: "Project path:",
3186
3221
  default: defaultPath
3187
3222
  });
3188
3223
  let relativePath = pathInput;
3189
3224
  if (defaults?.base) {
3190
- const baseDir = File5.from(defaults.base).absolutify();
3191
- const pathFile = File5.from(pathInput);
3225
+ const baseDir = File4.from(defaults.base).absolutify();
3226
+ const pathFile = File4.from(pathInput);
3192
3227
  try {
3193
3228
  if (pathFile.isAbsolute()) {
3194
3229
  const relPath = pathFile.relativize(baseDir.path);
@@ -3255,8 +3290,8 @@ async function editProjectManage(ctx) {
3255
3290
  });
3256
3291
  let relativePath = pathInput;
3257
3292
  if (defaults?.base) {
3258
- const baseDir = File5.from(defaults.base).absolutify();
3259
- const pathFile = File5.from(pathInput);
3293
+ const baseDir = File4.from(defaults.base).absolutify();
3294
+ const pathFile = File4.from(pathInput);
3260
3295
  try {
3261
3296
  if (pathFile.isAbsolute()) {
3262
3297
  const relPath = pathFile.relativize(baseDir.path);
@@ -3359,7 +3394,7 @@ function listProjectsManage(ctx) {
3359
3394
  const baseProjects = Object.keys(projects).filter((name) => !name.includes("#"));
3360
3395
  for (const name of baseProjects) {
3361
3396
  const project = projects[name];
3362
- const fullPath = defaults?.base ? File5.from(defaults.base).join(project.path).path : project.path;
3397
+ const fullPath = defaults?.base ? File4.from(defaults.base).join(project.path).path : project.path;
3363
3398
  console.log(` ${name}`);
3364
3399
  console.log(` Path: ${fullPath}`);
3365
3400
  console.log(` IDE: ${project.ide || "not set"}`);
@@ -3483,11 +3518,11 @@ async function manageWorktrees(projectName, ctx) {
3483
3518
  const projectConfig = projects[projectName];
3484
3519
  const basePath = defaults?.base || "";
3485
3520
  let projectPath;
3486
- const configPath = File5.from(projectConfig.path);
3521
+ const configPath = File4.from(projectConfig.path);
3487
3522
  if (configPath.path.startsWith("/") || configPath.path.startsWith("~")) {
3488
3523
  projectPath = configPath.absolutify().path;
3489
3524
  } else if (basePath) {
3490
- projectPath = File5.from(basePath).absolutify().join(projectConfig.path).path;
3525
+ projectPath = File4.from(basePath).absolutify().join(projectConfig.path).path;
3491
3526
  } else {
3492
3527
  projectPath = configPath.absolutify().path;
3493
3528
  }
@@ -3618,11 +3653,11 @@ async function openWorktreeManage(projectName, manager, config, log) {
3618
3653
  const projectConfig = projects[projectName];
3619
3654
  const basePath = defaults?.base || "";
3620
3655
  let projectPath;
3621
- const configPath = File5.from(projectConfig.path);
3656
+ const configPath = File4.from(projectConfig.path);
3622
3657
  if (configPath.path.startsWith("/") || configPath.path.startsWith("~")) {
3623
3658
  projectPath = configPath.absolutify().path;
3624
3659
  } else if (basePath) {
3625
- projectPath = File5.from(basePath).absolutify().join(projectConfig.path).path;
3660
+ projectPath = File4.from(basePath).absolutify().join(projectConfig.path).path;
3626
3661
  } else {
3627
3662
  projectPath = configPath.absolutify().path;
3628
3663
  }
@@ -3865,7 +3900,7 @@ __export(open_exports2, {
3865
3900
  runOpen: () => runOpen
3866
3901
  });
3867
3902
  import { Command as Command8 } from "commander";
3868
- import File6 from "phylo";
3903
+ import File5 from "phylo";
3869
3904
  async function runOpen(projectArg, options, ctx) {
3870
3905
  const { log } = ctx;
3871
3906
  if (options.debug) {
@@ -3884,7 +3919,7 @@ function createOpenCommand2(ctx) {
3884
3919
  } else {
3885
3920
  log.debug("No project name provided, starting interactive mode");
3886
3921
  const { runInteractive: runInteractive2 } = await Promise.resolve().then(() => (init_interactive(), interactive_exports));
3887
- const environment = await EnvironmentRecognizer.recognize(File6.cwd());
3922
+ const environment = await EnvironmentRecognizer.recognize(File5.cwd());
3888
3923
  await runInteractive2({ config, log, environment });
3889
3924
  }
3890
3925
  });
@@ -3892,18 +3927,28 @@ function createOpenCommand2(ctx) {
3892
3927
  }
3893
3928
  async function processProject(projectParam, options, ctx) {
3894
3929
  const { config, log } = ctx;
3895
- const [projectName, commandsString] = projectParam.split(":");
3896
- const requestedCommands = commandsString ? commandsString.split(",").map((cmd) => cmd.trim()) : null;
3930
+ const parts = projectParam.split(":");
3931
+ const projectName = parts[0];
3932
+ const commandsString = parts[1] || null;
3933
+ const worktreeName = parts[2] || null;
3934
+ const requestedCommands = commandsString && commandsString !== "help" ? commandsString.split(",").map((cmd) => cmd.trim()) : null;
3897
3935
  if (commandsString === "help") {
3898
3936
  await showProjectHelp(projectName, ctx);
3899
3937
  return;
3900
3938
  }
3901
3939
  log.debug(
3902
- `Project: ${projectName}, Commands: ${requestedCommands ? requestedCommands.join(", ") : "all"}`
3940
+ `Project: ${projectName}, Commands: ${requestedCommands ? requestedCommands.join(", ") : "all"}` + (worktreeName ? `, Worktree: ${worktreeName}` : "")
3903
3941
  );
3904
3942
  const projects = config.getProjects();
3905
- const environment = await EnvironmentRecognizer.recognize(File6.cwd());
3943
+ const environment = await EnvironmentRecognizer.recognize(File5.cwd());
3906
3944
  if (environment.$isProjectEnvironment && (projectName === "this" || projectName === ".")) {
3945
+ if (worktreeName) {
3946
+ log.error(
3947
+ `Worktree syntax is not supported with '${projectName}'. Use the full project name instead:`
3948
+ );
3949
+ log.info(` workon ${environment.project.name}::${worktreeName}`);
3950
+ process.exit(1);
3951
+ }
3907
3952
  log.info(`Opening current project: ${environment.project.name}`);
3908
3953
  await switchTo(environment, requestedCommands, options, ctx);
3909
3954
  return;
@@ -3915,7 +3960,23 @@ async function processProject(projectParam, options, ctx) {
3915
3960
  validateRequestedCommands(requestedCommands, projectCfg, projectName);
3916
3961
  }
3917
3962
  const projectEnv = ProjectEnvironment.load(projectCfg, config.getDefaults());
3918
- await switchTo(projectEnv, requestedCommands, options, ctx);
3963
+ if (worktreeName) {
3964
+ const projectPath = projectEnv.project.path.path;
3965
+ const manager = new WorktreeManager(projectPath, projectName);
3966
+ const worktree = await manager.get(worktreeName);
3967
+ if (!worktree) {
3968
+ log.error(`Worktree '${worktreeName}' not found for project '${projectName}'.`);
3969
+ const worktrees = await manager.listManagedWorktrees();
3970
+ if (worktrees.length > 0) {
3971
+ log.info("Available worktrees:");
3972
+ worktrees.forEach((wt) => log.info(` - ${wt.name}`));
3973
+ }
3974
+ process.exit(1);
3975
+ }
3976
+ log.debug(`Using worktree path: ${worktree.path}`);
3977
+ projectEnv.project.overridePath(worktree.path);
3978
+ }
3979
+ await switchTo(projectEnv, requestedCommands, options, ctx, worktreeName);
3919
3980
  } else {
3920
3981
  log.error(`Project '${projectName}' not found.`);
3921
3982
  log.info(`Run 'workon' without arguments to see available projects or create a new one.`);
@@ -3933,7 +3994,7 @@ Available commands: ${availableCommands}`
3933
3994
  );
3934
3995
  }
3935
3996
  }
3936
- async function switchTo(environment, requestedCommands, options, ctx) {
3997
+ async function switchTo(environment, requestedCommands, options, ctx, worktreeName) {
3937
3998
  const { log } = ctx;
3938
3999
  const project = environment.project;
3939
4000
  let events;
@@ -3957,11 +4018,35 @@ async function switchTo(environment, requestedCommands, options, ctx) {
3957
4018
  const hasNpmEvent = events.includes("npm");
3958
4019
  const dryRun = options.dryRun || false;
3959
4020
  if (hasCwd && hasClaudeEvent && hasNpmEvent) {
3960
- await handleThreePaneLayout(project, isShellMode, dryRun, shellCommands, events, ctx);
4021
+ await handleThreePaneLayout(
4022
+ project,
4023
+ isShellMode,
4024
+ dryRun,
4025
+ shellCommands,
4026
+ events,
4027
+ ctx,
4028
+ worktreeName
4029
+ );
3961
4030
  } else if (hasCwd && hasNpmEvent) {
3962
- await handleTwoPaneNpmLayout(project, isShellMode, dryRun, shellCommands, events, ctx);
4031
+ await handleTwoPaneNpmLayout(
4032
+ project,
4033
+ isShellMode,
4034
+ dryRun,
4035
+ shellCommands,
4036
+ events,
4037
+ ctx,
4038
+ worktreeName
4039
+ );
3963
4040
  } else if (hasCwd && hasClaudeEvent) {
3964
- await handleSplitTerminal(project, isShellMode, dryRun, shellCommands, events, ctx);
4041
+ await handleSplitTerminal(
4042
+ project,
4043
+ isShellMode,
4044
+ dryRun,
4045
+ shellCommands,
4046
+ events,
4047
+ ctx,
4048
+ worktreeName
4049
+ );
3965
4050
  } else {
3966
4051
  for (const event of events) {
3967
4052
  if (!dryRun) {
@@ -3995,10 +4080,11 @@ async function getNpmCommand2(project) {
3995
4080
  const { NpmEvent: NpmEvent2 } = await Promise.resolve().then(() => (init_npm(), npm_exports));
3996
4081
  return NpmEvent2.getNpmCommand(npmConfig);
3997
4082
  }
3998
- async function handleTmuxLayout(project, layout, options, shellCommands, events, ctx) {
4083
+ async function handleTmuxLayout(project, layout, options, shellCommands, events, ctx, worktreeName) {
3999
4084
  const { log } = ctx;
4000
4085
  const tmux = new TmuxManager();
4001
4086
  const { isShellMode, dryRun } = options;
4087
+ const tmuxSessionId = worktreeName ? `${project.name}_wt_${worktreeName}` : project.name;
4002
4088
  let tmuxHandled = false;
4003
4089
  if (isShellMode) {
4004
4090
  if (await tmux.isTmuxAvailable()) {
@@ -4014,7 +4100,7 @@ async function handleTmuxLayout(project, layout, options, shellCommands, events,
4014
4100
  shellCommands.push(...cmds);
4015
4101
  }
4016
4102
  }
4017
- const commands = buildLayoutShellCommands(tmux, project, layout);
4103
+ const commands = buildLayoutShellCommands(tmux, tmuxSessionId, project, layout);
4018
4104
  shellCommands.push(...commands);
4019
4105
  tmuxHandled = true;
4020
4106
  } else {
@@ -4026,7 +4112,7 @@ async function handleTmuxLayout(project, layout, options, shellCommands, events,
4026
4112
  } else if (!dryRun) {
4027
4113
  if (await tmux.isTmuxAvailable()) {
4028
4114
  try {
4029
- const sessionName = await createTmuxSession(tmux, project, layout);
4115
+ const sessionName = await createTmuxSession(tmux, tmuxSessionId, project, layout);
4030
4116
  await tmux.attachToSession(sessionName);
4031
4117
  tmuxHandled = true;
4032
4118
  } catch (error) {
@@ -4050,19 +4136,19 @@ async function handleTmuxLayout(project, layout, options, shellCommands, events,
4050
4136
  }
4051
4137
  }
4052
4138
  }
4053
- function buildLayoutShellCommands(tmux, project, layout) {
4139
+ function buildLayoutShellCommands(tmux, sessionId, project, layout) {
4054
4140
  switch (layout.type) {
4055
4141
  case "split-claude":
4056
- return tmux.buildShellCommands(project.name, project.path.path, layout.claudeArgs);
4142
+ return tmux.buildShellCommands(sessionId, project.path.path, layout.claudeArgs);
4057
4143
  case "three-pane":
4058
4144
  return tmux.buildThreePaneShellCommands(
4059
- project.name,
4145
+ sessionId,
4060
4146
  project.path.path,
4061
4147
  layout.claudeArgs,
4062
4148
  layout.npmCommand
4063
4149
  );
4064
4150
  case "two-pane-npm":
4065
- return tmux.buildTwoPaneNpmShellCommands(project.name, project.path.path, layout.npmCommand);
4151
+ return tmux.buildTwoPaneNpmShellCommands(sessionId, project.path.path, layout.npmCommand);
4066
4152
  }
4067
4153
  }
4068
4154
  function buildFallbackCommandsWithEvents(shellCommands, project, layout, remainingEvents, _ctx) {
@@ -4080,50 +4166,77 @@ function buildFallbackCommandsWithEvents(shellCommands, project, layout, remaini
4080
4166
  }
4081
4167
  }
4082
4168
  }
4083
- async function createTmuxSession(tmux, project, layout) {
4169
+ async function createTmuxSession(tmux, sessionId, project, layout) {
4084
4170
  switch (layout.type) {
4085
4171
  case "split-claude":
4086
- return tmux.createSplitSession(project.name, project.path.path, layout.claudeArgs);
4172
+ return tmux.createSplitSession(sessionId, project.path.path, layout.claudeArgs);
4087
4173
  case "three-pane":
4088
4174
  return tmux.createThreePaneSession(
4089
- project.name,
4175
+ sessionId,
4090
4176
  project.path.path,
4091
4177
  layout.claudeArgs,
4092
4178
  layout.npmCommand
4093
4179
  );
4094
4180
  case "two-pane-npm":
4095
- return tmux.createTwoPaneNpmSession(project.name, project.path.path, layout.npmCommand);
4181
+ return tmux.createTwoPaneNpmSession(sessionId, project.path.path, layout.npmCommand);
4096
4182
  }
4097
4183
  }
4098
- async function handleSplitTerminal(project, isShellMode, dryRun, shellCommands, events, ctx) {
4184
+ async function handleSplitTerminal(project, isShellMode, dryRun, shellCommands, events, ctx, worktreeName) {
4185
+ const sessionLabel = worktreeName ? `${project.name}::${worktreeName}` : project.name;
4099
4186
  const layout = {
4100
4187
  type: "split-claude",
4101
4188
  handledEvents: ["cwd", "claude"],
4102
- dryRunMessage: `Would create split tmux session '${project.name}' with Claude`,
4189
+ dryRunMessage: `Would create split tmux session '${sessionLabel}' with Claude`,
4103
4190
  claudeArgs: getClaudeArgs2(project),
4104
4191
  npmCommand: null
4105
4192
  };
4106
- await handleTmuxLayout(project, layout, { isShellMode, dryRun }, shellCommands, events, ctx);
4193
+ await handleTmuxLayout(
4194
+ project,
4195
+ layout,
4196
+ { isShellMode, dryRun },
4197
+ shellCommands,
4198
+ events,
4199
+ ctx,
4200
+ worktreeName
4201
+ );
4107
4202
  }
4108
- async function handleThreePaneLayout(project, isShellMode, dryRun, shellCommands, events, ctx) {
4203
+ async function handleThreePaneLayout(project, isShellMode, dryRun, shellCommands, events, ctx, worktreeName) {
4204
+ const sessionLabel = worktreeName ? `${project.name}::${worktreeName}` : project.name;
4109
4205
  const layout = {
4110
4206
  type: "three-pane",
4111
4207
  handledEvents: ["cwd", "claude", "npm"],
4112
- dryRunMessage: `Would create three-pane tmux session '${project.name}' with Claude and NPM`,
4208
+ dryRunMessage: `Would create three-pane tmux session '${sessionLabel}' with Claude and NPM`,
4113
4209
  claudeArgs: getClaudeArgs2(project),
4114
4210
  npmCommand: await getNpmCommand2(project)
4115
4211
  };
4116
- await handleTmuxLayout(project, layout, { isShellMode, dryRun }, shellCommands, events, ctx);
4212
+ await handleTmuxLayout(
4213
+ project,
4214
+ layout,
4215
+ { isShellMode, dryRun },
4216
+ shellCommands,
4217
+ events,
4218
+ ctx,
4219
+ worktreeName
4220
+ );
4117
4221
  }
4118
- async function handleTwoPaneNpmLayout(project, isShellMode, dryRun, shellCommands, events, ctx) {
4222
+ async function handleTwoPaneNpmLayout(project, isShellMode, dryRun, shellCommands, events, ctx, worktreeName) {
4223
+ const sessionLabel = worktreeName ? `${project.name}::${worktreeName}` : project.name;
4119
4224
  const layout = {
4120
4225
  type: "two-pane-npm",
4121
4226
  handledEvents: ["cwd", "npm"],
4122
- dryRunMessage: `Would create two-pane tmux session '${project.name}' with NPM`,
4227
+ dryRunMessage: `Would create two-pane tmux session '${sessionLabel}' with NPM`,
4123
4228
  claudeArgs: [],
4124
4229
  npmCommand: await getNpmCommand2(project)
4125
4230
  };
4126
- await handleTmuxLayout(project, layout, { isShellMode, dryRun }, shellCommands, events, ctx);
4231
+ await handleTmuxLayout(
4232
+ project,
4233
+ layout,
4234
+ { isShellMode, dryRun },
4235
+ shellCommands,
4236
+ events,
4237
+ ctx,
4238
+ worktreeName
4239
+ );
4127
4240
  }
4128
4241
  async function processEvent(event, context, ctx) {
4129
4242
  const { log } = ctx;
@@ -4175,7 +4288,9 @@ Available commands for '${projectName}':`);
4175
4288
  const twoCommands = configuredEvents.slice(0, 2).join(",");
4176
4289
  console.log(` workon ${projectName}:${twoCommands.padEnd(12)} # Multiple commands`);
4177
4290
  }
4178
- console.log(` workon ${projectName}:cwd --shell # Output shell commands
4291
+ console.log(` workon ${projectName}:cwd --shell # Output shell commands`);
4292
+ console.log(` workon ${projectName}:cwd:my-worktree # Run in a worktree`);
4293
+ console.log(` workon ${projectName}::my-worktree # All commands in a worktree
4179
4294
  `);
4180
4295
  }
4181
4296
  var init_open2 = __esm({
@@ -4184,6 +4299,7 @@ var init_open2 = __esm({
4184
4299
  init_environment();
4185
4300
  init_tmux();
4186
4301
  init_registry();
4302
+ init_worktree();
4187
4303
  }
4188
4304
  });
4189
4305
 
@@ -4198,7 +4314,7 @@ import { join as join2, dirname as dirname2 } from "path";
4198
4314
  import { fileURLToPath } from "url";
4199
4315
  import loog from "loog";
4200
4316
  import omelette from "omelette";
4201
- import File9 from "phylo";
4317
+ import File8 from "phylo";
4202
4318
 
4203
4319
  // src/commands/config/index.ts
4204
4320
  import { Command as Command12 } from "commander";
@@ -4295,7 +4411,7 @@ init_registry();
4295
4411
  init_constants();
4296
4412
  import { Command as Command13 } from "commander";
4297
4413
  import { select as select5, input as input6, confirm as confirm9, checkbox as checkbox3 } from "@inquirer/prompts";
4298
- import File7 from "phylo";
4414
+ import File6 from "phylo";
4299
4415
  function createManageCommand(ctx) {
4300
4416
  const { log } = ctx;
4301
4417
  return new Command13("manage").description("Interactive project management").option("-d, --debug", "Enable debug logging").action(async (options) => {
@@ -4354,12 +4470,12 @@ async function createProject(ctx) {
4354
4470
  return true;
4355
4471
  }
4356
4472
  });
4357
- const defaultPath = defaults?.base ? File7.from(defaults.base).join(name).path : name;
4473
+ const defaultPath = defaults?.base ? File6.from(defaults.base).join(name).path : name;
4358
4474
  const pathInput = await input6({
4359
4475
  message: "Project path:",
4360
4476
  default: defaultPath,
4361
4477
  validate: (value) => {
4362
- const path8 = File7.from(value);
4478
+ const path8 = File6.from(value);
4363
4479
  try {
4364
4480
  const exists = path8.exists();
4365
4481
  if (!exists) return `Path does not exist: ${value}`;
@@ -4373,8 +4489,8 @@ async function createProject(ctx) {
4373
4489
  });
4374
4490
  let relativePath = pathInput;
4375
4491
  if (defaults?.base) {
4376
- const baseDir = File7.from(defaults.base).absolutify();
4377
- const pathFile = File7.from(pathInput);
4492
+ const baseDir = File6.from(defaults.base).absolutify();
4493
+ const pathFile = File6.from(pathInput);
4378
4494
  try {
4379
4495
  const relPath = pathFile.relativize(baseDir.path);
4380
4496
  if (relPath && !relPath.path.startsWith("..")) {
@@ -4451,8 +4567,8 @@ async function editProject(ctx) {
4451
4567
  });
4452
4568
  let relativePath = pathInput;
4453
4569
  if (defaults?.base) {
4454
- const baseDir = File7.from(defaults.base).absolutify();
4455
- const pathFile = File7.from(pathInput);
4570
+ const baseDir = File6.from(defaults.base).absolutify();
4571
+ const pathFile = File6.from(pathInput);
4456
4572
  try {
4457
4573
  if (pathFile.isAbsolute()) {
4458
4574
  const relPath = pathFile.relativize(baseDir.path);
@@ -4552,7 +4668,7 @@ async function listProjects(ctx) {
4552
4668
  const defaults = config.getDefaults();
4553
4669
  console.log("\nConfigured projects:\n");
4554
4670
  for (const [name, project] of Object.entries(projects)) {
4555
- const fullPath = defaults?.base ? File7.from(defaults.base).join(project.path).path : project.path;
4671
+ const fullPath = defaults?.base ? File6.from(defaults.base).join(project.path).path : project.path;
4556
4672
  console.log(` ${name}`);
4557
4673
  console.log(` Path: ${fullPath}`);
4558
4674
  console.log(` IDE: ${project.ide || "not set"}`);
@@ -4568,7 +4684,7 @@ async function listProjects(ctx) {
4568
4684
  import { Command as Command14 } from "commander";
4569
4685
  import { existsSync as existsSync6, readFileSync } from "fs";
4570
4686
  import { basename as basename2, resolve } from "path";
4571
- import File8 from "phylo";
4687
+ import File7 from "phylo";
4572
4688
  import { confirm as confirm10 } from "@inquirer/prompts";
4573
4689
  function createAddCommand2(ctx) {
4574
4690
  const { log } = ctx;
@@ -4592,7 +4708,7 @@ async function addProject(pathArg, options, ctx) {
4592
4708
  log.error(`Path does not exist: ${targetPath}`);
4593
4709
  process.exit(1);
4594
4710
  }
4595
- const pathFile = File8.from(targetPath);
4711
+ const pathFile = File7.from(targetPath);
4596
4712
  try {
4597
4713
  const stat = pathFile.stat();
4598
4714
  if (!stat.isDirectory()) {
@@ -4626,7 +4742,7 @@ async function addProject(pathArg, options, ctx) {
4626
4742
  log.debug(`IDE: ${ide}`);
4627
4743
  let relativePath = targetPath;
4628
4744
  if (defaults?.base) {
4629
- const baseDir = File8.from(defaults.base).absolutify();
4745
+ const baseDir = File7.from(defaults.base).absolutify();
4630
4746
  try {
4631
4747
  const relPath = pathFile.relativize(baseDir.path);
4632
4748
  if (relPath && !relPath.path.startsWith("..")) {
@@ -4755,19 +4871,21 @@ function createWorktreeCommand(ctx) {
4755
4871
  }
4756
4872
  await showWorktreeStatus(worktreeInfo, log);
4757
4873
  });
4758
- command.command("merge").description("Merge this worktree branch into a target branch").option("-i, --into <branch>", "Target branch to merge into").option("-s, --squash", "Use squash merge").option("-k, --keep", "Keep the worktree after merging").option("-y, --yes", "Skip confirmation prompts").action(async (options) => {
4759
- const worktreeInfo = await detectWorktreeContext();
4760
- if (!worktreeInfo) {
4761
- log.error("Not in a git repository.");
4762
- process.exit(1);
4763
- }
4764
- if (!worktreeInfo.isWorktree) {
4765
- log.error("You're in the main repository, not a worktree.");
4766
- log.info(`Use 'workon worktrees merge <name>' from the main repository.`);
4767
- process.exit(1);
4874
+ command.command("merge").description("Merge this worktree branch into a target branch").option("-i, --into <branch>", "Target branch to merge into").option("-s, --squash", "Use squash merge").option("-k, --keep", "Keep the worktree after merging").option("-y, --yes", "Skip confirmation prompts").option("--delete-branch", "Delete the merged branch after merge").action(
4875
+ async (options) => {
4876
+ const worktreeInfo = await detectWorktreeContext();
4877
+ if (!worktreeInfo) {
4878
+ log.error("Not in a git repository.");
4879
+ process.exit(1);
4880
+ }
4881
+ if (!worktreeInfo.isWorktree) {
4882
+ log.error("You're in the main repository, not a worktree.");
4883
+ log.info(`Use 'workon worktrees merge <name>' from the main repository.`);
4884
+ process.exit(1);
4885
+ }
4886
+ await mergeCurrentWorktree(worktreeInfo, options, ctx);
4768
4887
  }
4769
- await mergeCurrentWorktree(worktreeInfo, options, ctx);
4770
- });
4888
+ );
4771
4889
  command.command("remove").description("Remove the current worktree").option("-f, --force", "Force removal even with uncommitted changes").option("-y, --yes", "Skip confirmation prompt").action(async (options) => {
4772
4890
  const worktreeInfo = await detectWorktreeContext();
4773
4891
  if (!worktreeInfo) {
@@ -4852,11 +4970,16 @@ async function mergeCurrentWorktree(worktreeInfo, options, ctx) {
4852
4970
  }
4853
4971
  const commonTargets = ["main", "master", "develop", "dev"];
4854
4972
  const defaultTarget = commonTargets.find((t) => targetBranches.includes(t)) || targetBranches[0];
4855
- targetBranch = await select6({
4856
- message: `Merge '${worktreeInfo.branch}' into which branch?`,
4857
- choices: targetBranches.map((b) => ({ name: b, value: b })),
4858
- default: defaultTarget
4859
- });
4973
+ if (options.yes) {
4974
+ targetBranch = defaultTarget;
4975
+ log.info(`Auto-selected target branch: '${targetBranch}'`);
4976
+ } else {
4977
+ targetBranch = await select6({
4978
+ message: `Merge '${worktreeInfo.branch}' into which branch?`,
4979
+ choices: targetBranches.map((b) => ({ name: b, value: b })),
4980
+ default: defaultTarget
4981
+ });
4982
+ }
4860
4983
  }
4861
4984
  if (!await manager.branchExists(targetBranch)) {
4862
4985
  log.error(`Target branch '${targetBranch}' does not exist.`);
@@ -4898,12 +5021,18 @@ ${chalk8.bold("Merge operation:")}`);
4898
5021
  log.info("You may need to resolve conflicts manually.");
4899
5022
  process.exit(1);
4900
5023
  }
5024
+ if (options.keep && options.deleteBranch) {
5025
+ log.warn("--delete-branch is ignored when --keep is set (branch is needed by the worktree).");
5026
+ }
4901
5027
  if (!options.keep) {
4902
- log.warn("You need to exit this worktree directory before it can be removed.");
4903
- const shouldContinue = await confirm11({
4904
- message: `Remove worktree '${worktreeInfo.worktreeName}'? (You'll need to cd out first)`,
4905
- default: true
4906
- });
5028
+ let shouldContinue = true;
5029
+ if (!options.yes) {
5030
+ log.warn("You need to exit this worktree directory before it can be removed.");
5031
+ shouldContinue = await confirm11({
5032
+ message: `Remove worktree '${worktreeInfo.worktreeName}'? (You'll need to cd out first)`,
5033
+ default: true
5034
+ });
5035
+ }
4907
5036
  if (shouldContinue) {
4908
5037
  const tmux = new TmuxManager();
4909
5038
  const sessionName = tmux.getWorktreeSessionName(
@@ -4919,20 +5048,21 @@ To complete removal, run from the main project directory:`);
4919
5048
  console.log(chalk8.cyan(` cd ${worktreeInfo.mainRepoPath}`));
4920
5049
  console.log(chalk8.cyan(` workon worktrees remove ${worktreeInfo.worktreeName}`));
4921
5050
  }
4922
- if (!options.yes) {
4923
- const shouldDeleteBranch = await confirm11({
5051
+ let shouldDeleteBranch = options.deleteBranch || false;
5052
+ if (!shouldDeleteBranch && !options.yes) {
5053
+ shouldDeleteBranch = await confirm11({
4924
5054
  message: `Delete the merged branch '${worktreeInfo.branch}'?`,
4925
5055
  default: false
4926
5056
  });
4927
- if (shouldDeleteBranch) {
4928
- const deleteSpinner = ora5(`Deleting branch '${worktreeInfo.branch}'...`).start();
4929
- try {
4930
- const git = simpleGit5(worktreeInfo.mainRepoPath);
4931
- await git.deleteLocalBranch(worktreeInfo.branch, true);
4932
- deleteSpinner.succeed(`Branch '${worktreeInfo.branch}' deleted`);
4933
- } catch (error) {
4934
- deleteSpinner.warn(`Failed to delete branch: ${error.message}`);
4935
- }
5057
+ }
5058
+ if (shouldDeleteBranch) {
5059
+ const deleteSpinner = ora5(`Deleting branch '${worktreeInfo.branch}'...`).start();
5060
+ try {
5061
+ const git = simpleGit5(worktreeInfo.mainRepoPath);
5062
+ await git.deleteLocalBranch(worktreeInfo.branch, true);
5063
+ deleteSpinner.succeed(`Branch '${worktreeInfo.branch}' deleted`);
5064
+ } catch (error) {
5065
+ deleteSpinner.warn(`Failed to delete branch: ${error.message}`);
4936
5066
  }
4937
5067
  }
4938
5068
  }
@@ -5046,7 +5176,7 @@ function createCli() {
5046
5176
  await runOpen2(project, { debug: options.debug, shell: options.shell }, { config, log });
5047
5177
  return;
5048
5178
  }
5049
- const environment = await EnvironmentRecognizer.recognize(File9.cwd());
5179
+ const environment = await EnvironmentRecognizer.recognize(File8.cwd());
5050
5180
  program2.setOptionValue("_environment", environment);
5051
5181
  program2.setOptionValue("_config", config);
5052
5182
  program2.setOptionValue("_log", log);