yggtree 1.4.2 → 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
 
@@ -223,21 +273,21 @@ Options:
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
- * `--open / --no-open`
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-open
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
 
@@ -287,12 +349,12 @@ Options:
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
 
@@ -351,99 +413,53 @@ Notes:
351
413
 
352
414
  ---
353
415
 
354
- ### `yggtree wt enter [worktree]`
355
-
356
- Enter a worktree using a sub‑shell.
357
-
358
- * Uses your default shell
359
- * Type `exit` to return
360
-
361
- Optional:
362
-
363
- * `--exec "<command>"`
364
-
365
- <details>
366
- <summary>Example</summary>
367
-
368
- ```bash
369
- yggtree wt enter feat/new-ui --exec "npm test"
370
- ```
371
-
372
- </details>
373
-
374
- ---
375
-
376
- ### `yggtree wt close`
377
-
378
- Gracefully exit a worktree sub-shell with an option to delete it.
379
-
380
- Behavior:
381
-
382
- * Only works inside an Yggdrasil sub-shell (entered via `wt enter` or post-creation).
383
- * Asks whether you want to delete the worktree before leaving.
384
- * Includes double-confirmation for safety.
385
- * Main worktree is never offered for deletion.
386
-
387
- <details>
388
- <summary>Example</summary>
389
-
390
- ```bash
391
- # Inside a worktree sub-shell:
392
- yggtree wt close
393
- # → "Delete this worktree before leaving? (y/N)"
394
- # → If yes: removes the worktree, then exits
395
- # → If no: exits normally
396
- ```
397
-
398
- </details>
399
-
400
- ---
401
-
402
- ### `yggtree wt open [worktree]`
416
+ ### `yggtree open [worktree]`
403
417
 
404
- Open a worktree in an IDE or agent CLI.
418
+ Open a worktree in an editor or supported desktop app.
405
419
 
406
420
  Behavior:
407
421
 
408
422
  * If `[worktree]` is omitted, you can pick from the worktree list with type-to-filter search.
409
- * Detects available tool commands in your `PATH` (for example: IDEs like `cursor`, `code`, `zed`; agents like `claude`, `codex`, `gemini`, `opencode`).
410
- * Lets you choose one interactively, or pass `--tool`.
411
- * 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.
412
428
 
413
429
  Options:
414
430
 
415
- * `--tool <command>`
431
+ * `--tool <command>` (for example: `cursor`, `code`, `codex`, or `codex-app`)
416
432
 
417
433
  <details>
418
434
  <summary>Examples</summary>
419
435
 
420
436
  ```bash
421
- yggtree wt open
422
- yggtree wt open feat/new-ui --tool cursor
423
- yggtree wt open feat/new-ui --tool claude
424
- 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
425
441
  ```
426
442
 
427
443
  </details>
428
444
 
429
445
  ---
430
446
 
431
- ### `yggtree wt exec [worktree] -- <command>`
447
+ ### `yggtree exec [worktree] -- <command>`
432
448
 
433
- Run a command inside a worktree **without entering**.
449
+ Run a command inside a worktree without changing your current terminal.
434
450
 
435
451
  <details>
436
452
  <summary>Example</summary>
437
453
 
438
454
  ```bash
439
- yggtree wt exec feat/new-ui -- npm test
455
+ yggtree exec feat/new-ui -- npm test
440
456
  ```
441
457
 
442
458
  </details>
443
459
 
444
460
  ---
445
461
 
446
- ### `yggtree wt path [worktree]`
462
+ ### `yggtree path [worktree]`
447
463
 
448
464
  Print a `cd` command for a worktree.
449
465
 
@@ -451,13 +467,13 @@ Useful for scripting and shell aliases.
451
467
 
452
468
  ---
453
469
 
454
- ### `yggtree wt bootstrap`
470
+ ### `yggtree bootstrap`
455
471
 
456
472
  Re‑run bootstrap commands for a worktree.
457
473
 
458
474
  ---
459
475
 
460
- ### `yggtree wt delete`
476
+ ### `yggtree delete`
461
477
 
462
478
  Interactively delete worktrees.
463
479
 
@@ -474,7 +490,7 @@ Optional:
474
490
 
475
491
  ---
476
492
 
477
- ### `yggtree wt prune`
493
+ ### `yggtree prune`
478
494
 
479
495
  Clean up stale git worktree metadata.
480
496
 
@@ -500,7 +516,7 @@ Yggdrasil is ideal when:
500
516
  **Command:**
501
517
 
502
518
  ```
503
- yggtree wt create feat/login-flow
519
+ yggtree create feat/login-flow
504
520
  ```
505
521
 
506
522
  **What happens:**
@@ -508,7 +524,7 @@ yggtree wt create feat/login-flow
508
524
  * Creates a new branch if it doesn’t exist (without inheriting base tracking), then publishes it to `origin` when possible
509
525
  * Creates a dedicated worktree
510
526
  * Runs bootstrap if enabled
511
- * Lets you choose whether to open an IDE or agent after creation
527
+ * Lets you choose whether to open an editor after creation
512
528
 
513
529
 
514
530
  </details>
@@ -520,13 +536,13 @@ yggtree wt create feat/login-flow
520
536
  **Command:**
521
537
 
522
538
  ```
523
- yggtree wt create feat/cleanup-api --no-bootstrap --no-open
539
+ yggtree create feat/cleanup-api --no-bootstrap --no-open
524
540
  ```
525
541
 
526
542
  **When to use:**
527
543
 
528
544
  * You just want the folder ready
529
- * You’ll open or enter it later if needed
545
+ * You’ll open it or move into its shell later if needed
530
546
  * You don’t want installs running automatically
531
547
 
532
548
  </details>
@@ -538,14 +554,13 @@ yggtree wt create feat/cleanup-api --no-bootstrap --no-open
538
554
  **Command:**
539
555
 
540
556
  ```
541
- yggtree wt create feat/ui-refactor --exec "cursor ."
557
+ yggtree create feat/ui-refactor --exec "cursor ."
542
558
  ```
543
559
 
544
560
  Works with:
545
561
 
546
562
  * `cursor .`
547
563
  * `code .`
548
- * `codex`
549
564
  * Any custom command available in your shell
550
565
 
551
566
  </details>
@@ -557,31 +572,32 @@ Works with:
557
572
  **Command:**
558
573
 
559
574
  ```
560
- yggtree wt exec test -- npm test
575
+ yggtree exec test -- npm test
561
576
  ```
562
577
 
563
578
  **What this does:**
564
579
 
565
580
  * Runs the command inside the selected worktree
566
- * Does not enter a sub-shell
581
+ * Keeps your current terminal where it is
567
582
  * Ideal for CI-like checks, scripts, or quick validations
568
583
 
569
584
  </details>
570
585
  ---
571
586
 
572
587
  <details>
573
- <summary>Enter a worktree and run a command before entering</summary>
588
+ <summary>Checkout a branch and run a startup command</summary>
574
589
 
575
590
  **Command:**
576
591
 
577
592
  ```
578
- yggtree wt enter test --exec "codex"
593
+ yggtree wc --ref test --open
579
594
  ```
580
595
 
581
596
  **What happens:**
582
597
 
583
- * Executes the command inside the worktree
584
- * 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`
585
601
  * Type `exit` to return to your original directory
586
602
 
587
603
  </details>
@@ -593,7 +609,7 @@ yggtree wt enter test --exec "codex"
593
609
  **Command:**
594
610
 
595
611
  ```
596
- yggtree wt path test
612
+ yggtree path test
597
613
  ```
598
614
 
599
615
  **Output:**
@@ -614,7 +630,7 @@ Useful when you want to manually navigate or copy the path into scripts.
614
630
  **Command:**
615
631
 
616
632
  ```bash
617
- yggtree wt create-sandbox --carry
633
+ yggtree create-sandbox --carry
618
634
  ```
619
635
 
620
636
  **Scenario:**
@@ -622,7 +638,7 @@ yggtree wt create-sandbox --carry
622
638
  1. You have 5 files changed in your main repo but aren't sure about the direction.
623
639
  2. Run `create-sandbox --carry` to move those changes into an isolated `sandbox-a3f2_feature-branch` folder.
624
640
  3. Experiment freely.
625
- 4. If it works: `yggtree wt apply`.
641
+ 4. If it works: `yggtree apply`.
626
642
  5. If it fails: Just delete the sandbox or `unapply`.
627
643
 
628
644
  </details>
@@ -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 { promptAndCopyEnvFiles } from '../../lib/env-files.js';
8
9
  import { detectInstalledOpenTools, launchOpenTool, promptOpenToolSelection, } from './open.js';
9
10
  import { execa } from 'execa';
10
11
  import fs from 'fs-extra';
@@ -56,7 +57,7 @@ export async function createCommandNew(options) {
56
57
  {
57
58
  type: 'confirm',
58
59
  name: 'shouldOpenTool',
59
- message: 'Open a tool after creation? (IDE or agent CLI)',
60
+ message: 'Open an editor after creation?',
60
61
  default: false,
61
62
  when: options.exec === undefined && options.open === undefined && options.enter === undefined,
62
63
  },
@@ -148,6 +149,7 @@ export async function createCommandNew(options) {
148
149
  'Attempt to push manually: git push -u origin HEAD',
149
150
  ]);
150
151
  }
152
+ await promptAndCopyEnvFiles(repoRoot, wtPath);
151
153
  if (shouldBootstrap) {
152
154
  await runBootstrap(wtPath, repoRoot);
153
155
  }
@@ -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
  }
@@ -6,6 +6,7 @@ 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
8
  import { generateSandboxName, normalizeSandboxName, writeSandboxMeta } from '../../lib/sandbox.js';
9
+ import { promptAndCopyEnvFiles } from '../../lib/env-files.js';
9
10
  import { detectInstalledOpenTools, launchOpenTool, promptOpenToolSelection, } from './open.js';
10
11
  import { execa } from 'execa';
11
12
  import fs from 'fs-extra';
@@ -66,7 +67,7 @@ export async function createSandboxCommand(options = {}) {
66
67
  {
67
68
  type: 'confirm',
68
69
  name: 'shouldOpenTool',
69
- message: 'Open a tool after creation? (IDE or agent CLI)',
70
+ message: 'Open an editor after creation?',
70
71
  default: false,
71
72
  when: options.exec === undefined && options.open === undefined && options.enter === undefined,
72
73
  },
@@ -181,6 +182,7 @@ export async function createSandboxCommand(options = {}) {
181
182
  spinner.succeed(`Sandbox created: ${chalk.cyan(sandboxName)}`);
182
183
  log.dim('This is a local sandbox - no remote branch will be pushed.');
183
184
  // 8. Bootstrap
185
+ await promptAndCopyEnvFiles(repoRoot, wtPath);
184
186
  if (shouldBootstrap) {
185
187
  await runBootstrap(wtPath, repoRoot);
186
188
  }