yggtree 1.4.2 โ 1.4.4
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 +160 -113
- package/dist/commands/wt/create-branch.js +41 -27
- package/dist/commands/wt/create-multi.js +11 -2
- package/dist/commands/wt/create-sandbox.js +3 -1
- package/dist/commands/wt/create.js +132 -51
- package/dist/commands/wt/enter.js +3 -27
- package/dist/commands/wt/handoff.js +7 -0
- package/dist/commands/wt/open.js +269 -60
- package/dist/index.js +149 -126
- package/dist/lib/env-files.js +72 -0
- package/dist/lib/git.js +5 -0
- package/dist/lib/repo-context.js +46 -0
- package/dist/lib/update-check.js +55 -0
- package/package.json +8 -4
- package/dist/commands/wt/close.js +0 -96
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
40
|
-
yggtree
|
|
41
|
-
yggtree
|
|
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
|
|
@@ -96,7 +146,10 @@ Create, manage, and navigate Git worktrees as a primary workflow, not an afterth
|
|
|
96
146
|
Work on multiple branches at the same time, each in its own isolated environment.
|
|
97
147
|
|
|
98
148
|
๐งช **Sandbox worktrees for experimentation**
|
|
99
|
-
Prototyping something risky? Create a sandbox
|
|
149
|
+
Prototyping something risky? Create a sandbox, try different strategies, and apply the winner back to your origin branch.
|
|
150
|
+
|
|
151
|
+
๐ค **Handoff current work**
|
|
152
|
+
Started in your main checkout? Carry staged, unstaged, and untracked work into a named sandbox worktree and continue there.
|
|
100
153
|
|
|
101
154
|
๐ค **AI-friendly isolation**
|
|
102
155
|
One worktree per agent, per experiment, per idea. No shared state, no collisions.
|
|
@@ -118,9 +171,9 @@ Use the interactive UI or drive everything through commands and flags.
|
|
|
118
171
|
## ๐ง Parallel Development, Done Right
|
|
119
172
|
|
|
120
173
|
```bash
|
|
121
|
-
yggtree
|
|
122
|
-
yggtree
|
|
123
|
-
yggtree
|
|
174
|
+
yggtree create feat/city-selection
|
|
175
|
+
yggtree create fix/validation
|
|
176
|
+
yggtree create chore/cleanup-api
|
|
124
177
|
```
|
|
125
178
|
|
|
126
179
|
Each command creates:
|
|
@@ -142,8 +195,8 @@ Yggdrasil shines when paired with AI agents.
|
|
|
142
195
|
Instead of running agents against the same directory, you can assign **one worktree per agent**.
|
|
143
196
|
|
|
144
197
|
```bash
|
|
145
|
-
yggtree
|
|
146
|
-
yggtree
|
|
198
|
+
yggtree create feat/ai-refactor-a --exec "cursor ."
|
|
199
|
+
yggtree create feat/ai-refactor-b --exec "codex"
|
|
147
200
|
```
|
|
148
201
|
|
|
149
202
|
Each agent operates in its own realm:
|
|
@@ -162,12 +215,18 @@ Sometimes you don't want to "commit to a branch" yet. You just want to try somet
|
|
|
162
215
|
|
|
163
216
|
**Sandboxes** are temporary, local-only worktrees designed for this:
|
|
164
217
|
|
|
165
|
-
1. **Create**: `yggtree
|
|
218
|
+
1. **Create**: `yggtree create-sandbox` (creates something like `sandbox-a3f2_feature-branch`).
|
|
166
219
|
2. **Experiment**: Change files, run tests, try that risky refactor.
|
|
167
|
-
3. **Apply**: `yggtree
|
|
168
|
-
4. **Unapply**: Don't like it? `yggtree
|
|
220
|
+
3. **Apply**: `yggtree apply` to "push" those file changes back to your origin directory.
|
|
221
|
+
4. **Unapply**: Don't like it? `yggtree unapply` restores your origin to exactly how it was before.
|
|
222
|
+
|
|
223
|
+
Sandboxes are **not pushed to remote**. Omit the name for a generated temporary sandbox, or provide one when the work needs to be easy to find later.
|
|
224
|
+
|
|
225
|
+
Use `handoff` when you started in the origin checkout and want to continue that dirty work in a sandbox:
|
|
169
226
|
|
|
170
|
-
|
|
227
|
+
```bash
|
|
228
|
+
yggtree handoff --name auth-refactor
|
|
229
|
+
```
|
|
171
230
|
|
|
172
231
|
---
|
|
173
232
|
|
|
@@ -208,7 +267,7 @@ Open the interactive menu.
|
|
|
208
267
|
|
|
209
268
|
---
|
|
210
269
|
|
|
211
|
-
### `yggtree
|
|
270
|
+
### `yggtree create [branch]`
|
|
212
271
|
|
|
213
272
|
Create a worktree from a branch.
|
|
214
273
|
|
|
@@ -219,25 +278,27 @@ Options:
|
|
|
219
278
|
* `--source local|remote`
|
|
220
279
|
* `--no-bootstrap`
|
|
221
280
|
* `--open / --no-open`
|
|
281
|
+
* `--enter / --no-enter`
|
|
222
282
|
* `--exec "<command>"`
|
|
223
283
|
|
|
224
284
|
Interactive flow:
|
|
225
285
|
|
|
226
|
-
* Instead of asking for a free-form `exec` command, yggtree now asks if you want to open
|
|
286
|
+
* Instead of asking for a free-form `exec` command, yggtree now asks if you want to open an editor after creation.
|
|
287
|
+
* After creation, yggtree enters the new worktree shell unless you pass `--no-enter`.
|
|
227
288
|
* `--exec` remains available as an advanced explicit override.
|
|
228
289
|
|
|
229
290
|
<details>
|
|
230
291
|
<summary>Example</summary>
|
|
231
292
|
|
|
232
293
|
```bash
|
|
233
|
-
yggtree
|
|
294
|
+
yggtree create feat/new-ui --base main --exec "cursor ."
|
|
234
295
|
```
|
|
235
296
|
|
|
236
297
|
</details>
|
|
237
298
|
|
|
238
299
|
---
|
|
239
300
|
|
|
240
|
-
### `yggtree
|
|
301
|
+
### `yggtree worktree-checkout [name] [ref]`
|
|
241
302
|
|
|
242
303
|
Create a checkout-style worktree from an existing branch.
|
|
243
304
|
|
|
@@ -245,34 +306,48 @@ Behavior:
|
|
|
245
306
|
|
|
246
307
|
* Prompts a searchable branch picker (type to filter in real time).
|
|
247
308
|
* Attaches the new worktree directly to the selected branch (checkout-style).
|
|
309
|
+
* 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
310
|
* 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
|
|
311
|
+
* If that branch already has an active worktree, yggtree falls back to using that worktree instead of creating a duplicate.
|
|
312
|
+
* By default, yggtree ends the flow inside the worktree shell.
|
|
313
|
+
* `yggtree wc` is a short alias for the same flow.
|
|
250
314
|
|
|
251
315
|
Options:
|
|
252
316
|
|
|
253
317
|
* `-n, --name <slug>`
|
|
254
318
|
* `-r, --ref <ref>`: skip picker and use a specific branch (`feature/x` or `origin/feature/x`)
|
|
255
319
|
* `--no-bootstrap`
|
|
256
|
-
* `--open / --no-open
|
|
320
|
+
* `--open / --no-open`: choose whether to open editors or run a startup command before the worktree shell starts
|
|
321
|
+
* `--tool <command>`: open a specific editor, app, or terminal target and skip the open prompt (`cursor`, `code`, `codex-app`, `cmux`, `tmux`)
|
|
322
|
+
* `--no-enter`: finish after create/open and return to the caller
|
|
257
323
|
* `--exec "<command>"`
|
|
258
324
|
|
|
259
325
|
Interactive flow:
|
|
260
326
|
|
|
261
|
-
*
|
|
327
|
+
* Yggtree asks what to open before starting the worktree shell.
|
|
328
|
+
* Shell-entry flows use a single action picker, so pressing Enter on Cmux or Tmux chooses that terminal target directly.
|
|
329
|
+
* Plain `yggtree open` flows use the same single action picker and return after opening the selected target.
|
|
330
|
+
* Use `--tool` to skip the open prompt and launch one editor/app or terminal target directly.
|
|
331
|
+
* Cmux, Tmux, and `Other command...` are mutually exclusive because the open picker accepts one action.
|
|
332
|
+
* `Other command...` runs a command in the Yggtree shell first, then leaves you there.
|
|
333
|
+
* Use `--no-enter` when you only want the worktree created/opened and the command to return.
|
|
262
334
|
* `--exec` remains available as an advanced explicit override.
|
|
263
335
|
|
|
264
336
|
<details>
|
|
265
337
|
<summary>Example</summary>
|
|
266
338
|
|
|
267
339
|
```bash
|
|
268
|
-
yggtree
|
|
340
|
+
yggtree worktree-checkout -n hotfix-auth -r main --no-open
|
|
341
|
+
yggtree wc hotfix-auth main --open
|
|
342
|
+
yggtree wc hotfix-auth main --tool codex-app
|
|
343
|
+
yggtree wc hotfix-auth main --open --no-enter
|
|
269
344
|
```
|
|
270
345
|
|
|
271
346
|
</details>
|
|
272
347
|
|
|
273
348
|
---
|
|
274
349
|
|
|
275
|
-
### `yggtree
|
|
350
|
+
### `yggtree create-sandbox`
|
|
276
351
|
|
|
277
352
|
Create a temporary sandbox from your current local branch.
|
|
278
353
|
|
|
@@ -287,12 +362,27 @@ Options:
|
|
|
287
362
|
Interactive flow:
|
|
288
363
|
|
|
289
364
|
* 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
|
|
365
|
+
* Instead of asking for a free-form `exec` command, yggtree now asks if you want to open an editor after creation.
|
|
291
366
|
* `--exec` remains available as an advanced explicit override.
|
|
292
367
|
|
|
293
368
|
---
|
|
294
369
|
|
|
295
|
-
### `yggtree
|
|
370
|
+
### `yggtree handoff`
|
|
371
|
+
|
|
372
|
+
Carry uncommitted work from the current checkout into a sandbox worktree.
|
|
373
|
+
|
|
374
|
+
Options:
|
|
375
|
+
|
|
376
|
+
* `-n, --name <name>`: Optional handoff name (prompted when omitted).
|
|
377
|
+
* `--no-bootstrap`
|
|
378
|
+
* `--open / --no-open`
|
|
379
|
+
* `--exec "<command>"`
|
|
380
|
+
|
|
381
|
+
This is the continuation-focused version of `create-sandbox --carry`: it keeps sandbox metadata and apply/unapply behavior, but defaults to carrying staged, unstaged, and untracked files.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
### `yggtree apply`
|
|
296
386
|
|
|
297
387
|
Apply changes from the current sandbox back to the origin repository.
|
|
298
388
|
* **Backs up** origin files before overwriting.
|
|
@@ -300,7 +390,7 @@ Apply changes from the current sandbox back to the origin repository.
|
|
|
300
390
|
|
|
301
391
|
---
|
|
302
392
|
|
|
303
|
-
### `yggtree
|
|
393
|
+
### `yggtree unapply`
|
|
304
394
|
|
|
305
395
|
Undo a previous `apply` operation.
|
|
306
396
|
* Restores origin files from the sandbox's backup.
|
|
@@ -308,7 +398,7 @@ Undo a previous `apply` operation.
|
|
|
308
398
|
|
|
309
399
|
---
|
|
310
400
|
|
|
311
|
-
### `yggtree
|
|
401
|
+
### `yggtree create-multi`
|
|
312
402
|
|
|
313
403
|
Create multiple worktrees at once.
|
|
314
404
|
|
|
@@ -322,14 +412,14 @@ Options:
|
|
|
322
412
|
<summary>Example</summary>
|
|
323
413
|
|
|
324
414
|
```bash
|
|
325
|
-
yggtree
|
|
415
|
+
yggtree create-multi --base main
|
|
326
416
|
```
|
|
327
417
|
|
|
328
418
|
</details>
|
|
329
419
|
|
|
330
420
|
---
|
|
331
421
|
|
|
332
|
-
### `yggtree
|
|
422
|
+
### `yggtree list`
|
|
333
423
|
|
|
334
424
|
List all repo-linked worktrees with state.
|
|
335
425
|
|
|
@@ -351,99 +441,56 @@ Notes:
|
|
|
351
441
|
|
|
352
442
|
---
|
|
353
443
|
|
|
354
|
-
### `yggtree
|
|
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]`
|
|
444
|
+
### `yggtree open [worktree]`
|
|
403
445
|
|
|
404
|
-
Open a worktree in an
|
|
446
|
+
Open a worktree in an editor, supported desktop app, or terminal target.
|
|
405
447
|
|
|
406
448
|
Behavior:
|
|
407
449
|
|
|
408
450
|
* If `[worktree]` is omitted, you can pick from the worktree list with type-to-filter search.
|
|
409
|
-
* Detects available
|
|
410
|
-
*
|
|
411
|
-
*
|
|
451
|
+
* Detects available editor commands in your `PATH` (for example: `cursor`, `code`, `zed`, `webstorm`).
|
|
452
|
+
* Detects Codex App on macOS and launches it with `open -b com.openai.codex`.
|
|
453
|
+
* Detects Cmux and Tmux when their CLI commands are available.
|
|
454
|
+
* Lets you choose one editor, app, or terminal target interactively, or pass `--tool`.
|
|
455
|
+
* Keeps Cmux, Tmux, and `Other command...` mutually exclusive by using a single action picker.
|
|
456
|
+
* By default, `open` launches the selected target and returns, except foreground terminal targets such as Tmux.
|
|
457
|
+
* Use `wc --open` when you want to open a worktree and continue in its shell.
|
|
412
458
|
|
|
413
459
|
Options:
|
|
414
460
|
|
|
415
|
-
* `--tool <command>`
|
|
461
|
+
* `--tool <command>` (for example: `cursor`, `code`, `codex`, `codex-app`, `cmux`, or `tmux`)
|
|
416
462
|
|
|
417
463
|
<details>
|
|
418
464
|
<summary>Examples</summary>
|
|
419
465
|
|
|
420
466
|
```bash
|
|
421
|
-
yggtree
|
|
422
|
-
yggtree
|
|
423
|
-
yggtree
|
|
424
|
-
yggtree
|
|
467
|
+
yggtree open
|
|
468
|
+
yggtree open feat/new-ui --tool cursor
|
|
469
|
+
yggtree open feat/new-ui --tool codex-app
|
|
470
|
+
yggtree open feat/new-ui --tool tmux
|
|
471
|
+
yggtree list --open
|
|
425
472
|
```
|
|
426
473
|
|
|
427
474
|
</details>
|
|
428
475
|
|
|
429
476
|
---
|
|
430
477
|
|
|
431
|
-
### `yggtree
|
|
478
|
+
### `yggtree exec [worktree] -- <command>`
|
|
432
479
|
|
|
433
|
-
Run a command inside a worktree
|
|
480
|
+
Run a command inside a worktree without changing your current terminal.
|
|
434
481
|
|
|
435
482
|
<details>
|
|
436
483
|
<summary>Example</summary>
|
|
437
484
|
|
|
438
485
|
```bash
|
|
439
|
-
yggtree
|
|
486
|
+
yggtree exec feat/new-ui -- npm test
|
|
440
487
|
```
|
|
441
488
|
|
|
442
489
|
</details>
|
|
443
490
|
|
|
444
491
|
---
|
|
445
492
|
|
|
446
|
-
### `yggtree
|
|
493
|
+
### `yggtree path [worktree]`
|
|
447
494
|
|
|
448
495
|
Print a `cd` command for a worktree.
|
|
449
496
|
|
|
@@ -451,13 +498,13 @@ Useful for scripting and shell aliases.
|
|
|
451
498
|
|
|
452
499
|
---
|
|
453
500
|
|
|
454
|
-
### `yggtree
|
|
501
|
+
### `yggtree bootstrap`
|
|
455
502
|
|
|
456
503
|
Reโrun bootstrap commands for a worktree.
|
|
457
504
|
|
|
458
505
|
---
|
|
459
506
|
|
|
460
|
-
### `yggtree
|
|
507
|
+
### `yggtree delete`
|
|
461
508
|
|
|
462
509
|
Interactively delete worktrees.
|
|
463
510
|
|
|
@@ -474,7 +521,7 @@ Optional:
|
|
|
474
521
|
|
|
475
522
|
---
|
|
476
523
|
|
|
477
|
-
### `yggtree
|
|
524
|
+
### `yggtree prune`
|
|
478
525
|
|
|
479
526
|
Clean up stale git worktree metadata.
|
|
480
527
|
|
|
@@ -500,7 +547,7 @@ Yggdrasil is ideal when:
|
|
|
500
547
|
**Command:**
|
|
501
548
|
|
|
502
549
|
```
|
|
503
|
-
yggtree
|
|
550
|
+
yggtree create feat/login-flow
|
|
504
551
|
```
|
|
505
552
|
|
|
506
553
|
**What happens:**
|
|
@@ -508,25 +555,25 @@ yggtree wt create feat/login-flow
|
|
|
508
555
|
* Creates a new branch if it doesnโt exist (without inheriting base tracking), then publishes it to `origin` when possible
|
|
509
556
|
* Creates a dedicated worktree
|
|
510
557
|
* Runs bootstrap if enabled
|
|
511
|
-
* Lets you choose whether to open an
|
|
558
|
+
* Lets you choose whether to open an editor after creation
|
|
512
559
|
|
|
513
560
|
|
|
514
561
|
</details>
|
|
515
562
|
---
|
|
516
563
|
|
|
517
564
|
<details>
|
|
518
|
-
<summary>Create a worktree without bootstrap
|
|
565
|
+
<summary>Create a worktree without bootstrap, opening a tool, or entering</summary>
|
|
519
566
|
|
|
520
567
|
**Command:**
|
|
521
568
|
|
|
522
569
|
```
|
|
523
|
-
yggtree
|
|
570
|
+
yggtree create feat/cleanup-api --no-bootstrap --no-open --no-enter
|
|
524
571
|
```
|
|
525
572
|
|
|
526
573
|
**When to use:**
|
|
527
574
|
|
|
528
575
|
* You just want the folder ready
|
|
529
|
-
* Youโll open or
|
|
576
|
+
* Youโll open it or move into its shell later if needed
|
|
530
577
|
* You donโt want installs running automatically
|
|
531
578
|
|
|
532
579
|
</details>
|
|
@@ -538,14 +585,13 @@ yggtree wt create feat/cleanup-api --no-bootstrap --no-open
|
|
|
538
585
|
**Command:**
|
|
539
586
|
|
|
540
587
|
```
|
|
541
|
-
yggtree
|
|
588
|
+
yggtree create feat/ui-refactor --exec "cursor ."
|
|
542
589
|
```
|
|
543
590
|
|
|
544
591
|
Works with:
|
|
545
592
|
|
|
546
593
|
* `cursor .`
|
|
547
594
|
* `code .`
|
|
548
|
-
* `codex`
|
|
549
595
|
* Any custom command available in your shell
|
|
550
596
|
|
|
551
597
|
</details>
|
|
@@ -557,31 +603,32 @@ Works with:
|
|
|
557
603
|
**Command:**
|
|
558
604
|
|
|
559
605
|
```
|
|
560
|
-
yggtree
|
|
606
|
+
yggtree exec test -- npm test
|
|
561
607
|
```
|
|
562
608
|
|
|
563
609
|
**What this does:**
|
|
564
610
|
|
|
565
611
|
* Runs the command inside the selected worktree
|
|
566
|
-
*
|
|
612
|
+
* Keeps your current terminal where it is
|
|
567
613
|
* Ideal for CI-like checks, scripts, or quick validations
|
|
568
614
|
|
|
569
615
|
</details>
|
|
570
616
|
---
|
|
571
617
|
|
|
572
618
|
<details>
|
|
573
|
-
<summary>
|
|
619
|
+
<summary>Checkout a branch and run a startup command</summary>
|
|
574
620
|
|
|
575
621
|
**Command:**
|
|
576
622
|
|
|
577
623
|
```
|
|
578
|
-
yggtree
|
|
624
|
+
yggtree wc --ref test --open
|
|
579
625
|
```
|
|
580
626
|
|
|
581
627
|
**What happens:**
|
|
582
628
|
|
|
583
|
-
*
|
|
584
|
-
*
|
|
629
|
+
* Checks out or reuses the branch worktree
|
|
630
|
+
* Lets you choose an editor, supported app, or `Other command...`
|
|
631
|
+
* Starts a worktree shell unless you pass `--no-enter`
|
|
585
632
|
* Type `exit` to return to your original directory
|
|
586
633
|
|
|
587
634
|
</details>
|
|
@@ -593,7 +640,7 @@ yggtree wt enter test --exec "codex"
|
|
|
593
640
|
**Command:**
|
|
594
641
|
|
|
595
642
|
```
|
|
596
|
-
yggtree
|
|
643
|
+
yggtree path test
|
|
597
644
|
```
|
|
598
645
|
|
|
599
646
|
**Output:**
|
|
@@ -614,15 +661,15 @@ Useful when you want to manually navigate or copy the path into scripts.
|
|
|
614
661
|
**Command:**
|
|
615
662
|
|
|
616
663
|
```bash
|
|
617
|
-
yggtree
|
|
664
|
+
yggtree create-sandbox --carry
|
|
618
665
|
```
|
|
619
666
|
|
|
620
667
|
**Scenario:**
|
|
621
668
|
|
|
622
669
|
1. You have 5 files changed in your main repo but aren't sure about the direction.
|
|
623
|
-
2. Run `
|
|
670
|
+
2. Run `handoff --name risky-refactor` to carry those changes into an isolated `sandbox-risky-refactor` folder.
|
|
624
671
|
3. Experiment freely.
|
|
625
|
-
4. If it works: `yggtree
|
|
672
|
+
4. If it works: `yggtree apply`.
|
|
626
673
|
5. If it fails: Just delete the sandbox or `unapply`.
|
|
627
674
|
|
|
628
675
|
</details>
|
|
@@ -5,16 +5,19 @@ 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';
|
|
10
|
+
import { enterCommand } from './enter.js';
|
|
9
11
|
import { execa } from 'execa';
|
|
10
12
|
import fs from 'fs-extra';
|
|
13
|
+
export function shouldEnterCreatedWorktree(options) {
|
|
14
|
+
return options.enter !== false;
|
|
15
|
+
}
|
|
11
16
|
export async function createCommandNew(options) {
|
|
12
17
|
try {
|
|
13
18
|
const repoRoot = await getRepoRoot();
|
|
14
19
|
log.info(`Repo: ${chalk.dim(repoRoot)}`);
|
|
15
|
-
|
|
16
|
-
log.warning('`--enter` / `--no-enter` is deprecated. Use `--open` / `--no-open` instead.');
|
|
17
|
-
}
|
|
20
|
+
const shouldEnterShell = shouldEnterCreatedWorktree(options);
|
|
18
21
|
// 1. Gather inputs
|
|
19
22
|
const currentBranch = await getCurrentBranch();
|
|
20
23
|
const answers = await inquirer.prompt([
|
|
@@ -56,7 +59,7 @@ export async function createCommandNew(options) {
|
|
|
56
59
|
{
|
|
57
60
|
type: 'confirm',
|
|
58
61
|
name: 'shouldOpenTool',
|
|
59
|
-
message: 'Open
|
|
62
|
+
message: 'Open an editor after creation?',
|
|
60
63
|
default: false,
|
|
61
64
|
when: options.exec === undefined && options.open === undefined && options.enter === undefined,
|
|
62
65
|
},
|
|
@@ -67,9 +70,7 @@ export async function createCommandNew(options) {
|
|
|
67
70
|
const shouldBootstrap = options.bootstrap !== undefined ? options.bootstrap : answers.bootstrap;
|
|
68
71
|
const shouldOpenTool = options.open !== undefined
|
|
69
72
|
? options.open
|
|
70
|
-
:
|
|
71
|
-
? options.enter
|
|
72
|
-
: Boolean(answers.shouldOpenTool);
|
|
73
|
+
: Boolean(answers.shouldOpenTool);
|
|
73
74
|
let selectedTool;
|
|
74
75
|
if (options.exec === undefined && shouldOpenTool) {
|
|
75
76
|
const installedTools = await detectInstalledOpenTools();
|
|
@@ -148,38 +149,51 @@ 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
|
}
|
|
154
|
-
// 5.
|
|
156
|
+
// 5. Post-create actions
|
|
155
157
|
if (options.exec && options.exec.trim()) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
await execa(options.exec, {
|
|
159
|
-
cwd: wtPath,
|
|
160
|
-
stdio: 'inherit',
|
|
161
|
-
shell: true
|
|
162
|
-
});
|
|
158
|
+
if (shouldEnterShell) {
|
|
159
|
+
await enterCommand(wtPath, { exec: options.exec });
|
|
163
160
|
}
|
|
164
|
-
|
|
165
|
-
log.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
161
|
+
else {
|
|
162
|
+
log.info(`Executing: ${options.exec} in ${ui.path(wtPath)}`);
|
|
163
|
+
try {
|
|
164
|
+
await execa(options.exec, {
|
|
165
|
+
cwd: wtPath,
|
|
166
|
+
stdio: 'inherit',
|
|
167
|
+
shell: true
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
log.actionableError(error.message, options.exec, wtPath, [
|
|
172
|
+
`cd ${wtPath} && ${options.exec}`,
|
|
173
|
+
'Check your command syntax and environment variables'
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
169
176
|
}
|
|
170
177
|
}
|
|
171
|
-
else
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
178
|
+
else {
|
|
179
|
+
if (selectedTool) {
|
|
180
|
+
try {
|
|
181
|
+
log.info(`Opening ${ui.path(wtPath)} in ${chalk.cyan(selectedTool.name)}...`);
|
|
182
|
+
await launchOpenTool(selectedTool, wtPath);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
log.warning(`Could not open ${selectedTool.name}: ${error.message}`);
|
|
186
|
+
}
|
|
175
187
|
}
|
|
176
|
-
|
|
177
|
-
|
|
188
|
+
if (shouldEnterShell) {
|
|
189
|
+
await enterCommand(wtPath);
|
|
178
190
|
}
|
|
179
191
|
}
|
|
180
192
|
// 6. Final Output
|
|
181
193
|
log.success('Worktree ready!');
|
|
182
|
-
|
|
194
|
+
if (!shouldEnterShell) {
|
|
195
|
+
log.header(`cd "${wtPath}"`);
|
|
196
|
+
}
|
|
183
197
|
}
|
|
184
198
|
catch (error) {
|
|
185
199
|
log.actionableError(error.message, 'yggtree wt create');
|