yggtree 1.4.1 → 1.4.3

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/README.md CHANGED
@@ -7,22 +7,69 @@
7
7
 
8
8
  Like the mythical world tree connecting realms, Yggdrasil lets you grow isolated, parallel environments where ideas can evolve independently without colliding.
9
9
 
10
+ For guided workflows, command examples, and safety notes, read the full docs:
11
+ **[yggtree.logbookfordevs.com/docs](https://yggtree.logbookfordevs.com/docs)**.
12
+
10
13
  ---
11
14
 
12
15
  ## 🚀 Quick Start
13
16
 
14
17
  ### Installation
15
18
 
16
- Run without installing:
19
+ Install globally:
20
+
21
+ ```bash
22
+ npm install -g yggtree
23
+ ```
24
+
25
+ Or try it without installing:
17
26
 
18
27
  ```bash
19
28
  npx yggtree
20
29
  ```
21
30
 
22
- Or install globally:
31
+ ### Agent Skills
32
+
33
+ An agent skill is now available for your favorite agents.
34
+
35
+ `yggtree` ships one consolidated skill that helps agents choose the right
36
+ worktree workflow first, then load the smallest reference they need:
37
+
38
+ * **Create a task worktree**: start a brand-new branch-backed task in parallel.
39
+ * **Branch off without stashing**: jump into another branch without disturbing
40
+ the work already in progress.
41
+ * **Bootstrap and use a realm**: prepare a worktree, open it in your IDE, or
42
+ run commands inside it.
43
+ * **Run sandbox experiments**: try alternative approaches locally and
44
+ apply/unapply the winner safely.
45
+
46
+ This skill is especially useful with agents like **Claude Code**,
47
+ **Codex**, **Cursor**, **Gemini CLI**, and other tools that support the open
48
+ Skills ecosystem.
49
+
50
+ Install it with the Skills CLI:
23
51
 
24
52
  ```bash
25
- npm install -g yggtree
53
+ npx skills add logbookfordevs/yggdrasil-worktree
54
+ ```
55
+
56
+ Install it globally for your user:
57
+
58
+ ```bash
59
+ npx skills add logbookfordevs/yggdrasil-worktree --global
60
+ ```
61
+
62
+ Install only the consolidated `yggtree` skill:
63
+
64
+ ```bash
65
+ npx skills add logbookfordevs/yggdrasil-worktree --skill yggtree
66
+ ```
67
+
68
+ If your agent supports targeted installs, you can also point the install to a
69
+ specific agent runtime, for example:
70
+
71
+ ```bash
72
+ npx skills add logbookfordevs/yggdrasil-worktree --agent codex
26
73
  ```
27
74
 
28
75
  ### Basic Usage
@@ -36,11 +83,14 @@ yggtree
36
83
  Or use commands directly:
37
84
 
38
85
  ```bash
39
- yggtree wt create
40
- yggtree wt list
41
- yggtree wt enter my-feature
86
+ yggtree create
87
+ yggtree list
88
+ yggtree wc --ref my-feature
89
+ yggtree -v
42
90
  ```
43
91
 
92
+ The older `yggtree wt ...` form still works for compatibility, but direct commands are the preferred shape.
93
+
44
94
  ---
45
95
 
46
96
  ## 🧠 Mental Model
@@ -118,9 +168,9 @@ Use the interactive UI or drive everything through commands and flags.
118
168
  ## 🧠 Parallel Development, Done Right
119
169
 
120
170
  ```bash
121
- yggtree wt create feat/city-selection
122
- yggtree wt create fix/validation
123
- yggtree wt create chore/cleanup-api
171
+ yggtree create feat/city-selection
172
+ yggtree create fix/validation
173
+ yggtree create chore/cleanup-api
124
174
  ```
125
175
 
126
176
  Each command creates:
@@ -142,8 +192,8 @@ Yggdrasil shines when paired with AI agents.
142
192
  Instead of running agents against the same directory, you can assign **one worktree per agent**.
143
193
 
144
194
  ```bash
145
- yggtree wt create feat/ai-refactor-a --exec "cursor ."
146
- yggtree wt create feat/ai-refactor-b --exec "codex"
195
+ yggtree create feat/ai-refactor-a --exec "cursor ."
196
+ yggtree create feat/ai-refactor-b --exec "codex"
147
197
  ```
148
198
 
149
199
  Each agent operates in its own realm:
@@ -162,10 +212,10 @@ Sometimes you don't want to "commit to a branch" yet. You just want to try somet
162
212
 
163
213
  **Sandboxes** are temporary, local-only worktrees designed for this:
164
214
 
165
- 1. **Create**: `yggtree wt create-sandbox` (creates something like `sandbox-a3f2_feature-branch`).
215
+ 1. **Create**: `yggtree create-sandbox` (creates something like `sandbox-a3f2_feature-branch`).
166
216
  2. **Experiment**: Change files, run tests, try that risky refactor.
167
- 3. **Apply**: `yggtree wt apply` to "push" those file changes back to your origin directory.
168
- 4. **Unapply**: Don't like it? `yggtree wt unapply` restores your origin to exactly how it was before.
217
+ 3. **Apply**: `yggtree apply` to "push" those file changes back to your origin directory.
218
+ 4. **Unapply**: Don't like it? `yggtree unapply` restores your origin to exactly how it was before.
169
219
 
170
220
  Sandboxes are **not pushed to remote** and their names are randomly generated because they are meant to be temporary playgrounds.
171
221
 
@@ -208,7 +258,7 @@ Open the interactive menu.
208
258
 
209
259
  ---
210
260
 
211
- ### `yggtree wt create [branch]`
261
+ ### `yggtree create [branch]`
212
262
 
213
263
  Create a worktree from a branch.
214
264
 
@@ -218,26 +268,26 @@ Options:
218
268
  * `--base <ref>`
219
269
  * `--source local|remote`
220
270
  * `--no-bootstrap`
221
- * `--enter / --no-enter`
271
+ * `--open / --no-open`
222
272
  * `--exec "<command>"`
223
273
 
224
274
  Interactive flow:
225
275
 
226
- * Instead of asking for a free-form `exec` command, yggtree now asks if you want to open a tool after creation (IDE or agent CLI).
276
+ * Instead of asking for a free-form `exec` command, yggtree now asks if you want to open an editor after creation.
227
277
  * `--exec` remains available as an advanced explicit override.
228
278
 
229
279
  <details>
230
280
  <summary>Example</summary>
231
281
 
232
282
  ```bash
233
- yggtree wt create feat/new-ui --base main --exec "cursor ."
283
+ yggtree create feat/new-ui --base main --exec "cursor ."
234
284
  ```
235
285
 
236
286
  </details>
237
287
 
238
288
  ---
239
289
 
240
- ### `yggtree wt worktree-checkout [name] [ref]`
290
+ ### `yggtree worktree-checkout [name] [ref]`
241
291
 
242
292
  Create a checkout-style worktree from an existing branch.
243
293
 
@@ -245,34 +295,46 @@ Behavior:
245
295
 
246
296
  * Prompts a searchable branch picker (type to filter in real time).
247
297
  * Attaches the new worktree directly to the selected branch (checkout-style).
298
+ * If a branch exists both locally and on `origin`, the picker shows both `branch` (local) and `origin/branch` (remote tip, detached) as explicit choices.
248
299
  * If you select a remote-only branch (`origin/*`), yggtree creates the local branch in the new worktree automatically.
249
- * If that branch already has an active yggtree-managed worktree, yggtree falls back to entering that worktree instead of creating a duplicate.
300
+ * If that branch already has an active worktree, yggtree falls back to using that worktree instead of creating a duplicate.
301
+ * By default, yggtree ends the flow inside the worktree shell.
302
+ * `yggtree wc` is a short alias for the same flow.
250
303
 
251
304
  Options:
252
305
 
253
306
  * `-n, --name <slug>`
254
307
  * `-r, --ref <ref>`: skip picker and use a specific branch (`feature/x` or `origin/feature/x`)
255
308
  * `--no-bootstrap`
256
- * `--enter / --no-enter`
309
+ * `--open / --no-open`: choose whether to open editors or run a startup command before the worktree shell starts
310
+ * `--tool <command>`: open a specific editor/app and skip the open prompt (`cursor`, `code`, `codex-app`)
311
+ * `--no-enter`: finish after create/open and return to the caller
257
312
  * `--exec "<command>"`
258
313
 
259
314
  Interactive flow:
260
315
 
261
- * Instead of asking for a free-form `exec` command, yggtree now asks if you want to open a tool after creation (IDE or agent CLI).
316
+ * Yggtree asks what to open before starting the worktree shell.
317
+ * Editor choices can be selected together.
318
+ * Use `--tool` to skip the open prompt and launch one editor/app directly.
319
+ * `Other command...` runs a command in the Yggtree shell first, then leaves you there.
320
+ * Use `--no-enter` when you only want the worktree created/opened and the command to return.
262
321
  * `--exec` remains available as an advanced explicit override.
263
322
 
264
323
  <details>
265
324
  <summary>Example</summary>
266
325
 
267
326
  ```bash
268
- yggtree wt worktree-checkout -n hotfix-auth -r main --no-enter
327
+ yggtree worktree-checkout -n hotfix-auth -r main --no-open
328
+ yggtree wc hotfix-auth main --open
329
+ yggtree wc hotfix-auth main --tool codex-app
330
+ yggtree wc hotfix-auth main --open --no-enter
269
331
  ```
270
332
 
271
333
  </details>
272
334
 
273
335
  ---
274
336
 
275
- ### `yggtree wt create-sandbox`
337
+ ### `yggtree create-sandbox`
276
338
 
277
339
  Create a temporary sandbox from your current local branch.
278
340
 
@@ -281,18 +343,18 @@ Options:
281
343
  * `-n, --name <name>`: Optional sandbox name (auto-generated if omitted).
282
344
  * `--carry / --no-carry`: Bring uncommitted changes (staged/unstaged/untracked) with you.
283
345
  * `--no-bootstrap`
284
- * `--enter / --no-enter`
346
+ * `--open / --no-open`
285
347
  * `--exec "<command>"`
286
348
 
287
349
  Interactive flow:
288
350
 
289
351
  * Prompts for an optional sandbox name (leave empty to auto-generate one from current branch).
290
- * Instead of asking for a free-form `exec` command, yggtree now asks if you want to open a tool after creation (IDE or agent CLI).
352
+ * Instead of asking for a free-form `exec` command, yggtree now asks if you want to open an editor after creation.
291
353
  * `--exec` remains available as an advanced explicit override.
292
354
 
293
355
  ---
294
356
 
295
- ### `yggtree wt apply`
357
+ ### `yggtree apply`
296
358
 
297
359
  Apply changes from the current sandbox back to the origin repository.
298
360
  * **Backs up** origin files before overwriting.
@@ -300,7 +362,7 @@ Apply changes from the current sandbox back to the origin repository.
300
362
 
301
363
  ---
302
364
 
303
- ### `yggtree wt unapply`
365
+ ### `yggtree unapply`
304
366
 
305
367
  Undo a previous `apply` operation.
306
368
  * Restores origin files from the sandbox's backup.
@@ -308,7 +370,7 @@ Undo a previous `apply` operation.
308
370
 
309
371
  ---
310
372
 
311
- ### `yggtree wt create-multi`
373
+ ### `yggtree create-multi`
312
374
 
313
375
  Create multiple worktrees at once.
314
376
 
@@ -322,14 +384,14 @@ Options:
322
384
  <summary>Example</summary>
323
385
 
324
386
  ```bash
325
- yggtree wt create-multi --base main
387
+ yggtree create-multi --base main
326
388
  ```
327
389
 
328
390
  </details>
329
391
 
330
392
  ---
331
393
 
332
- ### `yggtree wt list`
394
+ ### `yggtree list`
333
395
 
334
396
  List all repo-linked worktrees with state.
335
397
 
@@ -338,6 +400,7 @@ Columns:
338
400
  * TYPE (`MAIN`, `MANAGED`, `LINKED`, `SANDBOX`)
339
401
  * STATE (clean / dirty)
340
402
  * LAST ACTIVE
403
+ * PR (optional — requires [GitHub CLI](https://cli.github.com/))
341
404
  * BRANCH
342
405
 
343
406
  Notes:
@@ -346,76 +409,57 @@ Notes:
346
409
  * `SANDBOX` and `MANAGED` are worktrees inside `~/.yggtree`.
347
410
  * External worktrees are labeled `LINKED`.
348
411
  * Use `--open` to switch this flow into "pick and open in tool" mode.
412
+ * The **PR** column shows the pull request status for each branch (e.g. `OPEN`, `IN REVIEW`, `APPROVED`, `MERGED`, `DRAFT`, `CHANGES`). It only appears when `gh` CLI is installed and authenticated — otherwise it's silently omitted.
349
413
 
350
414
  ---
351
415
 
352
- ### `yggtree wt enter [worktree]`
353
-
354
- Enter a worktree using a sub‑shell.
355
-
356
- * Uses your default shell
357
- * Type `exit` to return
358
-
359
- Optional:
360
-
361
- * `--exec "<command>"`
362
-
363
- <details>
364
- <summary>Example</summary>
365
-
366
- ```bash
367
- yggtree wt enter feat/new-ui --exec "npm test"
368
- ```
369
-
370
- </details>
371
-
372
- ---
373
-
374
- ### `yggtree wt open [worktree]`
416
+ ### `yggtree open [worktree]`
375
417
 
376
- Open a worktree in an IDE or agent CLI.
418
+ Open a worktree in an editor or supported desktop app.
377
419
 
378
420
  Behavior:
379
421
 
380
422
  * If `[worktree]` is omitted, you can pick from the worktree list with type-to-filter search.
381
- * Detects available tool commands in your `PATH` (for example: IDEs like `cursor`, `code`, `zed`; agents like `claude`, `codex`, `gemini`, `opencode`).
382
- * Lets you choose one interactively, or pass `--tool`.
383
- * If an agent CLI is selected, yggtree opens a sub-shell and launches it there.
423
+ * Detects available editor commands in your `PATH` (for example: `cursor`, `code`, `zed`, `webstorm`).
424
+ * Detects Codex App on macOS and launches it with `open -b com.openai.codex`.
425
+ * Lets you choose one or more editors/apps interactively, or pass `--tool`.
426
+ * By default, `open` launches editors/apps and returns.
427
+ * Use `wc --open` when you want to open a worktree and continue in its shell.
384
428
 
385
429
  Options:
386
430
 
387
- * `--tool <command>`
431
+ * `--tool <command>` (for example: `cursor`, `code`, `codex`, or `codex-app`)
388
432
 
389
433
  <details>
390
434
  <summary>Examples</summary>
391
435
 
392
436
  ```bash
393
- yggtree wt open
394
- yggtree wt open feat/new-ui --tool cursor
395
- yggtree wt open feat/new-ui --tool claude
396
- yggtree wt list --open
437
+ yggtree open
438
+ yggtree open feat/new-ui --tool cursor
439
+ yggtree open feat/new-ui --tool codex-app
440
+ yggtree list --open
397
441
  ```
398
442
 
399
443
  </details>
400
444
 
401
445
  ---
402
446
 
403
- ### `yggtree wt exec [worktree] -- <command>`
447
+ ### `yggtree exec [worktree] -- <command>`
404
448
 
405
- Run a command inside a worktree **without entering**.
449
+ Run a command inside a worktree without changing your current terminal.
406
450
 
407
451
  <details>
408
452
  <summary>Example</summary>
409
453
 
410
454
  ```bash
411
- yggtree wt exec feat/new-ui -- npm test
455
+ yggtree exec feat/new-ui -- npm test
412
456
  ```
413
457
 
414
458
  </details>
415
459
 
416
460
  ---
417
461
 
418
- ### `yggtree wt path [worktree]`
462
+ ### `yggtree path [worktree]`
419
463
 
420
464
  Print a `cd` command for a worktree.
421
465
 
@@ -423,13 +467,13 @@ Useful for scripting and shell aliases.
423
467
 
424
468
  ---
425
469
 
426
- ### `yggtree wt bootstrap`
470
+ ### `yggtree bootstrap`
427
471
 
428
472
  Re‑run bootstrap commands for a worktree.
429
473
 
430
474
  ---
431
475
 
432
- ### `yggtree wt delete`
476
+ ### `yggtree delete`
433
477
 
434
478
  Interactively delete worktrees.
435
479
 
@@ -446,7 +490,7 @@ Optional:
446
490
 
447
491
  ---
448
492
 
449
- ### `yggtree wt prune`
493
+ ### `yggtree prune`
450
494
 
451
495
  Clean up stale git worktree metadata.
452
496
 
@@ -467,12 +511,12 @@ Yggdrasil is ideal when:
467
511
  ## 📝 Practical Examples
468
512
 
469
513
  <details>
470
- <summary>Create a worktree and enter it immediately</summary>
514
+ <summary>Create a worktree with the guided post-create flow</summary>
471
515
 
472
516
  **Command:**
473
517
 
474
518
  ```
475
- yggtree wt create feat/login-flow
519
+ yggtree create feat/login-flow
476
520
  ```
477
521
 
478
522
  **What happens:**
@@ -480,25 +524,25 @@ yggtree wt create feat/login-flow
480
524
  * Creates a new branch if it doesn’t exist (without inheriting base tracking), then publishes it to `origin` when possible
481
525
  * Creates a dedicated worktree
482
526
  * Runs bootstrap if enabled
483
- * Drops you into a sub-shell inside the worktree
527
+ * Lets you choose whether to open an editor after creation
484
528
 
485
529
 
486
530
  </details>
487
531
  ---
488
532
 
489
533
  <details>
490
- <summary>Create a worktree without bootstrap and without entering</summary>
534
+ <summary>Create a worktree without bootstrap and without opening a tool</summary>
491
535
 
492
536
  **Command:**
493
537
 
494
538
  ```
495
- yggtree wt create feat/cleanup-api --no-bootstrap --no-enter
539
+ yggtree create feat/cleanup-api --no-bootstrap --no-open
496
540
  ```
497
541
 
498
542
  **When to use:**
499
543
 
500
544
  * You just want the folder ready
501
- * You’ll enter it later
545
+ * You’ll open it or move into its shell later if needed
502
546
  * You don’t want installs running automatically
503
547
 
504
548
  </details>
@@ -510,14 +554,13 @@ yggtree wt create feat/cleanup-api --no-bootstrap --no-enter
510
554
  **Command:**
511
555
 
512
556
  ```
513
- yggtree wt create feat/ui-refactor --exec "cursor ."
557
+ yggtree create feat/ui-refactor --exec "cursor ."
514
558
  ```
515
559
 
516
560
  Works with:
517
561
 
518
562
  * `cursor .`
519
563
  * `code .`
520
- * `codex`
521
564
  * Any custom command available in your shell
522
565
 
523
566
  </details>
@@ -529,31 +572,32 @@ Works with:
529
572
  **Command:**
530
573
 
531
574
  ```
532
- yggtree wt exec test -- npm test
575
+ yggtree exec test -- npm test
533
576
  ```
534
577
 
535
578
  **What this does:**
536
579
 
537
580
  * Runs the command inside the selected worktree
538
- * Does not enter a sub-shell
581
+ * Keeps your current terminal where it is
539
582
  * Ideal for CI-like checks, scripts, or quick validations
540
583
 
541
584
  </details>
542
585
  ---
543
586
 
544
587
  <details>
545
- <summary>Enter a worktree and run a command before entering</summary>
588
+ <summary>Checkout a branch and run a startup command</summary>
546
589
 
547
590
  **Command:**
548
591
 
549
592
  ```
550
- yggtree wt enter test --exec "codex"
593
+ yggtree wc --ref test --open
551
594
  ```
552
595
 
553
596
  **What happens:**
554
597
 
555
- * Executes the command inside the worktree
556
- * Then drops you into a sub-shell
598
+ * Checks out or reuses the branch worktree
599
+ * Lets you choose an editor, supported app, or `Other command...`
600
+ * Starts a worktree shell unless you pass `--no-enter`
557
601
  * Type `exit` to return to your original directory
558
602
 
559
603
  </details>
@@ -565,7 +609,7 @@ yggtree wt enter test --exec "codex"
565
609
  **Command:**
566
610
 
567
611
  ```
568
- yggtree wt path test
612
+ yggtree path test
569
613
  ```
570
614
 
571
615
  **Output:**
@@ -586,7 +630,7 @@ Useful when you want to manually navigate or copy the path into scripts.
586
630
  **Command:**
587
631
 
588
632
  ```bash
589
- yggtree wt create-sandbox --carry
633
+ yggtree create-sandbox --carry
590
634
  ```
591
635
 
592
636
  **Scenario:**
@@ -594,7 +638,7 @@ yggtree wt create-sandbox --carry
594
638
  1. You have 5 files changed in your main repo but aren't sure about the direction.
595
639
  2. Run `create-sandbox --carry` to move those changes into an isolated `sandbox-a3f2_feature-branch` folder.
596
640
  3. Experiment freely.
597
- 4. If it works: `yggtree wt apply`.
641
+ 4. If it works: `yggtree apply`.
598
642
  5. If it fails: Just delete the sandbox or `unapply`.
599
643
 
600
644
  </details>
@@ -5,14 +5,17 @@ import { getRepoRoot, getRepoName, verifyRef, fetchAll, getCurrentBranch, ensure
5
5
  import { runBootstrap } from '../../lib/config.js';
6
6
  import { WORKTREES_ROOT } from '../../lib/paths.js';
7
7
  import { log, ui, createSpinner } from '../../lib/ui.js';
8
- import { buildAgentExecCommand, detectInstalledOpenTools, isAgentTool, launchOpenTool, promptOpenToolSelection, } from './open.js';
8
+ import { promptAndCopyEnvFiles } from '../../lib/env-files.js';
9
+ import { detectInstalledOpenTools, launchOpenTool, promptOpenToolSelection, } from './open.js';
9
10
  import { execa } from 'execa';
10
- import { spawn } from 'child_process';
11
11
  import fs from 'fs-extra';
12
12
  export async function createCommandNew(options) {
13
13
  try {
14
14
  const repoRoot = await getRepoRoot();
15
15
  log.info(`Repo: ${chalk.dim(repoRoot)}`);
16
+ if (options.enter !== undefined) {
17
+ log.warning('`--enter` / `--no-enter` is deprecated. Use `--open` / `--no-open` instead.');
18
+ }
16
19
  // 1. Gather inputs
17
20
  const currentBranch = await getCurrentBranch();
18
21
  const answers = await inquirer.prompt([
@@ -51,28 +54,25 @@ export async function createCommandNew(options) {
51
54
  default: true,
52
55
  when: options.bootstrap !== false && options.bootstrap !== true,
53
56
  },
54
- {
55
- type: 'confirm',
56
- name: 'shouldEnter',
57
- message: 'Do you want to enter the new worktree now?',
58
- default: true,
59
- when: options.enter === undefined,
60
- },
61
57
  {
62
58
  type: 'confirm',
63
59
  name: 'shouldOpenTool',
64
- message: 'Open a tool after creation? (IDE or agent CLI)',
60
+ message: 'Open an editor after creation?',
65
61
  default: false,
66
- when: options.exec === undefined,
62
+ when: options.exec === undefined && options.open === undefined && options.enter === undefined,
67
63
  },
68
64
  ]);
69
65
  const branchName = options.branch || answers.branch;
70
66
  let baseRef = options.base || answers.base;
71
67
  const source = options.source || answers.source;
72
- const shouldEnter = options.enter !== undefined ? options.enter : answers.shouldEnter;
73
68
  const shouldBootstrap = options.bootstrap !== undefined ? options.bootstrap : answers.bootstrap;
69
+ const shouldOpenTool = options.open !== undefined
70
+ ? options.open
71
+ : options.enter !== undefined
72
+ ? options.enter
73
+ : Boolean(answers.shouldOpenTool);
74
74
  let selectedTool;
75
- if (options.exec === undefined && answers.shouldOpenTool) {
75
+ if (options.exec === undefined && shouldOpenTool) {
76
76
  const installedTools = await detectInstalledOpenTools();
77
77
  if (installedTools.length === 0) {
78
78
  log.warning('No IDE/agent tool detected in PATH. Skipping open step.');
@@ -81,7 +81,6 @@ export async function createCommandNew(options) {
81
81
  selectedTool = await promptOpenToolSelection(installedTools, 'Select tool to open:');
82
82
  }
83
83
  }
84
- const execCommandStr = options.exec || (selectedTool && isAgentTool(selectedTool) ? buildAgentExecCommand(selectedTool) : undefined);
85
84
  // Append origin/ if remote is selected and not already present
86
85
  if (!options.base && source === 'remote' && !baseRef.startsWith('origin/')) {
87
86
  baseRef = `origin/${baseRef}`;
@@ -150,27 +149,28 @@ export async function createCommandNew(options) {
150
149
  'Attempt to push manually: git push -u origin HEAD',
151
150
  ]);
152
151
  }
152
+ await promptAndCopyEnvFiles(repoRoot, wtPath);
153
153
  if (shouldBootstrap) {
154
154
  await runBootstrap(wtPath, repoRoot);
155
155
  }
156
156
  // 5. Exec Command
157
- if (execCommandStr && execCommandStr.trim()) {
158
- log.info(`Executing: ${execCommandStr} in ${ui.path(wtPath)}`);
157
+ if (options.exec && options.exec.trim()) {
158
+ log.info(`Executing: ${options.exec} in ${ui.path(wtPath)}`);
159
159
  try {
160
- await execa(execCommandStr, {
160
+ await execa(options.exec, {
161
161
  cwd: wtPath,
162
162
  stdio: 'inherit',
163
163
  shell: true
164
164
  });
165
165
  }
166
166
  catch (error) {
167
- log.actionableError(error.message, execCommandStr, wtPath, [
168
- `cd ${wtPath} && ${execCommandStr}`,
167
+ log.actionableError(error.message, options.exec, wtPath, [
168
+ `cd ${wtPath} && ${options.exec}`,
169
169
  'Check your command syntax and environment variables'
170
170
  ]);
171
171
  }
172
172
  }
173
- if (selectedTool && !isAgentTool(selectedTool)) {
173
+ else if (selectedTool) {
174
174
  try {
175
175
  log.info(`Opening ${ui.path(wtPath)} in ${chalk.cyan(selectedTool.name)}...`);
176
176
  await launchOpenTool(selectedTool, wtPath);
@@ -181,21 +181,7 @@ export async function createCommandNew(options) {
181
181
  }
182
182
  // 6. Final Output
183
183
  log.success('Worktree ready!');
184
- if (shouldEnter) {
185
- log.info(`Spawning sub-shell in ${ui.path(wtPath)}...`);
186
- log.dim('Type "exit" to return to the main terminal.');
187
- const shell = process.env.SHELL || 'zsh';
188
- const child = spawn(shell, [], {
189
- cwd: wtPath,
190
- stdio: 'inherit',
191
- });
192
- child.on('close', () => {
193
- log.info('Exited sub-shell.');
194
- });
195
- }
196
- else {
197
- log.header(`cd "${wtPath}"`);
198
- }
184
+ log.header(`cd "${wtPath}"`);
199
185
  }
200
186
  catch (error) {
201
187
  log.actionableError(error.message, 'yggtree wt create');
@@ -5,6 +5,7 @@ import { getRepoRoot, getRepoName, verifyRef, fetchAll, getCurrentBranch, ensure
5
5
  import { runBootstrap } from '../../lib/config.js';
6
6
  import { WORKTREES_ROOT } from '../../lib/paths.js';
7
7
  import { log, ui, createSpinner } from '../../lib/ui.js';
8
+ import { findLocalEnvFiles, promptAndCopyEnvFilesToWorktrees } from '../../lib/env-files.js';
8
9
  import { execa } from 'execa';
9
10
  import fs from 'fs-extra';
10
11
  export async function createCommandMulti(options) {
@@ -117,8 +118,16 @@ export async function createCommandMulti(options) {
117
118
  ]);
118
119
  }
119
120
  createdWorktrees.push(wtPath);
120
- // 4. Bootstrap
121
- if (shouldBootstrap) {
121
+ }
122
+ const envFiles = await findLocalEnvFiles(repoRoot);
123
+ if (envFiles.length > 0 && createdWorktrees.length > 0) {
124
+ await promptAndCopyEnvFilesToWorktrees(repoRoot, createdWorktrees, envFiles, {
125
+ promptMessage: `Copy local env file${envFiles.length === 1 ? '' : 's'} to all created worktrees? (${envFiles.join(', ')})`,
126
+ });
127
+ }
128
+ // 4. Bootstrap
129
+ if (shouldBootstrap) {
130
+ for (const wtPath of createdWorktrees) {
122
131
  await runBootstrap(wtPath, repoRoot);
123
132
  }
124
133
  }