@desplega.ai/wts 0.1.6 → 0.2.0

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.
Files changed (2) hide show
  1. package/dist/index.js +106 -6
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1877,7 +1877,7 @@ var {
1877
1877
  // package.json
1878
1878
  var package_default = {
1879
1879
  name: "@desplega.ai/wts",
1880
- version: "0.1.6",
1880
+ version: "0.2.0",
1881
1881
  description: "Git worktree manager with tmux integration",
1882
1882
  type: "module",
1883
1883
  bin: {
@@ -2614,7 +2614,8 @@ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
2614
2614
  var source_default = chalk;
2615
2615
 
2616
2616
  // src/config/local.ts
2617
- import { join as join3 } from "node:path";
2617
+ import { homedir as homedir3 } from "node:os";
2618
+ import { isAbsolute, join as join3 } from "node:path";
2618
2619
 
2619
2620
  // src/config/global.ts
2620
2621
  import { homedir as homedir2 } from "node:os";
@@ -2624,7 +2625,7 @@ import { join as join2 } from "node:path";
2624
2625
  var DEFAULT_GLOBAL_CONFIG = {
2625
2626
  projects: {},
2626
2627
  defaults: {
2627
- worktreeDir: ".worktrees",
2628
+ worktreeDir: "~/.worktrees",
2628
2629
  tmuxWindowTemplate: "{project}-{alias}",
2629
2630
  autoTmux: false,
2630
2631
  autoClaude: false
@@ -2708,7 +2709,14 @@ async function resolveConfig(gitRoot) {
2708
2709
  };
2709
2710
  }
2710
2711
  function getWorktreeBaseDir(config) {
2711
- return join3(config.gitRoot, config.worktreeDir, config.projectName);
2712
+ let baseDir = config.worktreeDir;
2713
+ if (baseDir.startsWith("~")) {
2714
+ baseDir = join3(homedir3(), baseDir.slice(1));
2715
+ }
2716
+ if (isAbsolute(baseDir)) {
2717
+ return join3(baseDir, config.projectName);
2718
+ }
2719
+ return join3(config.gitRoot, baseDir, config.projectName);
2712
2720
  }
2713
2721
 
2714
2722
  // src/utils/prompts.ts
@@ -3234,8 +3242,8 @@ Next steps:`));
3234
3242
  });
3235
3243
  async function promptForConfig(existing) {
3236
3244
  const config = {};
3237
- const worktreeDir = await prompt("Worktree directory", existing?.worktreeDir ?? ".worktrees");
3238
- if (worktreeDir !== ".worktrees") {
3245
+ const worktreeDir = await prompt("Worktree directory", existing?.worktreeDir ?? "~/.worktrees");
3246
+ if (worktreeDir !== "~/.worktrees") {
3239
3247
  config.worktreeDir = worktreeDir;
3240
3248
  }
3241
3249
  const autoTmux = await confirm("Auto-open tmux window on create?", existing?.autoTmux ?? false);
@@ -3328,6 +3336,97 @@ function printWorktreeTable(worktrees, projectName) {
3328
3336
  }
3329
3337
  }
3330
3338
 
3339
+ // src/commands/merge.ts
3340
+ var mergeCommand = new Command2("merge").description("Merge a worktree branch into main").argument("[alias]", "Alias of the worktree to merge").option("--no-cleanup", "Skip cleanup prompt").option("-f, --force", "Skip confirmations (except cleanup)").action(async (alias, options) => {
3341
+ const gitRoot = await getGitRoot();
3342
+ if (!gitRoot) {
3343
+ console.error(source_default.red("Error: Not in a git repository"));
3344
+ process.exit(1);
3345
+ }
3346
+ const config = await resolveConfig(gitRoot);
3347
+ const worktrees = await listWorktrees(gitRoot, config.projectName);
3348
+ let worktree;
3349
+ if (alias) {
3350
+ worktree = await findWorktreeByAlias(alias, gitRoot);
3351
+ if (!worktree) {
3352
+ console.error(source_default.red(`Error: No worktree found with alias "${alias}"`));
3353
+ process.exit(1);
3354
+ }
3355
+ } else {
3356
+ const nonMain = worktrees.filter((wt) => !wt.isMain);
3357
+ if (nonMain.length === 0) {
3358
+ console.error(source_default.yellow("No worktrees to merge"));
3359
+ process.exit(1);
3360
+ }
3361
+ worktree = await selectWorktree(worktrees, { excludeMain: true });
3362
+ if (!worktree) {
3363
+ console.log(source_default.dim("Cancelled"));
3364
+ return;
3365
+ }
3366
+ }
3367
+ if (worktree.isMain) {
3368
+ console.error(source_default.red("Error: Cannot merge the main worktree"));
3369
+ process.exit(1);
3370
+ }
3371
+ const defaultBranch = await getDefaultBranch(gitRoot);
3372
+ const branchToMerge = worktree.branch;
3373
+ console.log(source_default.bold(`
3374
+ Merging ${source_default.cyan(branchToMerge)} into ${source_default.cyan(defaultBranch)}
3375
+ `));
3376
+ if (!options.force) {
3377
+ const proceed = await confirm(`Switch to ${defaultBranch}?`, true);
3378
+ if (!proceed) {
3379
+ console.log(source_default.dim("Cancelled"));
3380
+ return;
3381
+ }
3382
+ }
3383
+ console.log(source_default.dim(`Switching to ${defaultBranch}...`));
3384
+ await Bun.$`git checkout ${defaultBranch}`.cwd(gitRoot);
3385
+ if (!options.force) {
3386
+ const proceed = await confirm(`Pull latest ${defaultBranch}?`, true);
3387
+ if (!proceed) {
3388
+ console.log(source_default.dim("Cancelled"));
3389
+ return;
3390
+ }
3391
+ }
3392
+ console.log(source_default.dim(`Pulling latest...`));
3393
+ await Bun.$`git pull`.cwd(gitRoot);
3394
+ if (!options.force) {
3395
+ const proceed = await confirm(`Merge ${branchToMerge}?`, true);
3396
+ if (!proceed) {
3397
+ console.log(source_default.dim("Cancelled"));
3398
+ return;
3399
+ }
3400
+ }
3401
+ console.log(source_default.dim(`Merging ${branchToMerge}...`));
3402
+ await Bun.$`git merge ${branchToMerge}`.cwd(gitRoot);
3403
+ if (!options.force) {
3404
+ const proceed = await confirm(`Push to origin?`, true);
3405
+ if (!proceed) {
3406
+ console.log(source_default.dim("Skipped push"));
3407
+ } else {
3408
+ console.log(source_default.dim(`Pushing...`));
3409
+ await Bun.$`git push`.cwd(gitRoot);
3410
+ }
3411
+ } else {
3412
+ console.log(source_default.dim(`Pushing...`));
3413
+ await Bun.$`git push`.cwd(gitRoot);
3414
+ }
3415
+ console.log(source_default.green(`
3416
+ ✓ Merged ${branchToMerge} into ${defaultBranch}`));
3417
+ if (options.cleanup !== false) {
3418
+ const cleanup = await confirm(`
3419
+ Clean up worktree and branch?`, false);
3420
+ if (cleanup) {
3421
+ console.log(source_default.dim(`Removing worktree...`));
3422
+ await removeWorktree(worktree.path, true, gitRoot);
3423
+ console.log(source_default.dim(`Deleting branch ${branchToMerge}...`));
3424
+ await deleteBranch(branchToMerge, true, gitRoot);
3425
+ console.log(source_default.green(`✓ Cleaned up`));
3426
+ }
3427
+ }
3428
+ });
3429
+
3331
3430
  // src/commands/pr.ts
3332
3431
  async function isGhAvailable() {
3333
3432
  try {
@@ -3606,6 +3705,7 @@ program3.addCommand(initCommand);
3606
3705
  program3.addCommand(listCommand);
3607
3706
  program3.addCommand(createCommand3);
3608
3707
  program3.addCommand(deleteCommand);
3708
+ program3.addCommand(mergeCommand);
3609
3709
  program3.addCommand(cdCommand);
3610
3710
  program3.addCommand(switchCommand);
3611
3711
  program3.addCommand(prCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@desplega.ai/wts",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "description": "Git worktree manager with tmux integration",
5
5
  "type": "module",
6
6
  "bin": {