@getsolaris/oh-my-worktree 0.7.2

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 ADDED
@@ -0,0 +1,851 @@
1
+ <p align="center">
2
+ <img src="./banner.png" alt="oh-my-worktree" />
3
+ </p>
4
+
5
+ # 🌳 oh-my-worktree
6
+
7
+ **English** | [Korean](./README.ko.md)
8
+
9
+ > Git worktree manager with a beautiful TUI — inspired by the oh-my-\* family
10
+
11
+ Manage git worktrees with ease. Create, switch, and clean up worktrees with config-driven automation, monorepo support, and built-in health checks.
12
+
13
+ ## Features
14
+
15
+ - **TUI mode** — interactive terminal UI (`omw`)
16
+ - **CLI mode** — scriptable commands (`omw add`, `omw list`, etc.)
17
+ - **Config-driven** — per-repo hooks, file copying, symlinks
18
+ - **Monorepo support** — auto-detect packages, per-package hooks, focus tracking
19
+ - **Health checks** — `omw doctor` diagnoses worktree issues
20
+ - **Centralized worktrees** — all worktrees under `~/.omw/worktrees/` by default
21
+ - **Smart cleanup** — auto-detect and remove merged worktrees
22
+ - **Themes** — 6 built-in color themes (OpenCode, Tokyo Night, Dracula, Nord, Catppuccin, GitHub Dark)
23
+ - **Templates** — reusable worktree presets (`omw add --template review`)
24
+ - **Cross-worktree exec** — run commands across all worktrees (`omw exec "bun test"`)
25
+ - **GitHub PR integration** — create worktrees from PRs (`omw add --pr 123`)
26
+ - **Fuzzy branch picker** — interactive branch selection in TUI with type-ahead filtering
27
+ - **Lifecycle management** — auto-detect stale/merged worktrees, configurable limits
28
+ - **Shared dependencies** — save disk with hardlink/symlink strategies for `node_modules`
29
+ - **Worktree diff** — compare changes between worktrees (`omw diff feature/a feature/b`)
30
+ - **Pin protection** — protect worktrees from auto-cleanup (`omw pin`)
31
+ - **Activity log** — track create/delete/switch/rename/archive/import events (`omw log`)
32
+ - **Archive** — preserve worktree changes as patches before removal (`omw archive`)
33
+ - **Branch rename** — rename worktree branches with metadata migration (`omw rename`)
34
+ - **Clone & init** — clone repos with omw config initialization (`omw clone`)
35
+ - **Import worktrees** — adopt manually-created worktrees (`omw import`)
36
+ - **Detail view** — expanded worktree info with commits, diff stats, upstream status (TUI)
37
+ - **Bulk actions** — multi-select and batch operations on worktrees (TUI)
38
+ - **Toast notifications** — non-blocking operation feedback (TUI)
39
+ - **Shell completions** — tab completion for bash/zsh/fish (`omw shell-init --completions`)
40
+ - **Config profiles** — switch between configuration sets (`omw config --profiles`)
41
+ - **Tmux sessions** — auto-create/kill tmux sessions per worktree with layout templates (`omw session`)
42
+ - **AI agent init** — create config by default or install omw skill for Claude Code, Codex, OpenCode (`omw init`, `omw init --skill`)
43
+
44
+ ## Requirements
45
+
46
+ - [Bun](https://bun.sh) runtime
47
+ - git 2.17+
48
+ - macOS or Linux
49
+ - [gh CLI](https://cli.github.com) (optional, for `--pr` flag)
50
+ - [tmux](https://github.com/tmux/tmux) (optional, for `omw session`)
51
+
52
+ ## Installation
53
+
54
+ ### Homebrew (macOS/Linux)
55
+
56
+ ```bash
57
+ brew install getsolaris/tap/oh-my-worktree
58
+ ```
59
+
60
+ ### curl (one-liner)
61
+
62
+ ```bash
63
+ curl -fsSL https://raw.githubusercontent.com/getsolaris/oh-my-worktree/main/install.sh | bash
64
+ ```
65
+
66
+ ### npm / bun
67
+
68
+ ```bash
69
+ bun install -g @getsolaris/oh-my-worktree
70
+ # or
71
+ npm install -g @getsolaris/oh-my-worktree
72
+ ```
73
+
74
+ ## Local Development
75
+
76
+ For local contributor testing, run the repo directly with Bun:
77
+
78
+ ```bash
79
+ bun install
80
+ bun run src/index.ts
81
+ bun run src/index.ts <cmd>
82
+ bun run typecheck
83
+ bun test
84
+ bun run build
85
+ ```
86
+
87
+ Prefer targeted tests first when you change covered code, then run the full checks before opening a PR. If you change CLI or TUI behavior, manually run the affected flows locally as well.
88
+
89
+ ## Quick Start
90
+
91
+ ```bash
92
+ # Launch TUI
93
+ omw
94
+
95
+ # List worktrees
96
+ omw list
97
+
98
+ # Create a new worktree
99
+ omw add feature/my-feature
100
+
101
+ # Create with monorepo focus
102
+ omw add feature/my-feature --focus apps/web,apps/api
103
+
104
+ # Create from a GitHub PR
105
+ omw add --pr 123
106
+
107
+ # Use a template
108
+ omw add feature/login --template review
109
+
110
+ # Pin a worktree to protect from cleanup
111
+ omw pin feature/important --reason "active sprint"
112
+
113
+ # View activity log
114
+ omw log
115
+
116
+ # Archive worktree changes before removing
117
+ omw archive feature/done --yes
118
+
119
+ # Rename a worktree branch
120
+ omw rename old-name new-name
121
+
122
+ # Clone and initialize omw
123
+ omw clone https://github.com/user/repo.git
124
+
125
+ # Import an existing worktree
126
+ omw import /path/to/worktree
127
+
128
+ # Open/attach tmux session for a worktree
129
+ omw session feature/my-feature
130
+
131
+ # Create worktree with tmux session
132
+ omw add feature/new --session
133
+
134
+ # Run command across all worktrees
135
+ omw exec "bun test"
136
+
137
+ # Compare two worktrees
138
+ omw diff feature/a feature/b --stat
139
+
140
+ # Check worktree health
141
+ omw doctor
142
+
143
+ # Switch to a worktree (requires shell integration)
144
+ omw switch feature/my-feature
145
+
146
+ # Remove a worktree
147
+ omw remove feature/my-feature --yes
148
+
149
+ # Clean up merged worktrees
150
+ omw clean --dry-run
151
+
152
+ # Initialize config file
153
+ omw init
154
+
155
+ # Generate AI agent skill file
156
+ omw init --skill claude-code
157
+ ```
158
+
159
+ ## TUI Usage
160
+
161
+ Launch with `omw` (no arguments).
162
+
163
+ ### Keyboard Shortcuts
164
+
165
+ | Key | Action |
166
+ | --------- | ---------------------- |
167
+ | `j` / `k` | Navigate worktree list |
168
+ | `a` | Add worktree |
169
+ | `d` | Delete worktree |
170
+ | `h` | Doctor (health check) |
171
+ | `Enter` | Open detail view |
172
+ | `Escape` | Close detail view |
173
+ | `Space` | Toggle worktree selection |
174
+ | `Ctrl+A` | Select all worktrees |
175
+ | `x` | Bulk actions menu |
176
+ | `r` | Refresh list |
177
+ | `Ctrl+P` | Command palette |
178
+ | `?` | Help |
179
+ | `q` | Quit |
180
+
181
+ ### Command Palette (`Ctrl+P`)
182
+
183
+ Searchable command menu with:
184
+
185
+ - Add / Delete / Refresh worktrees
186
+ - Run Doctor
187
+ - Open Config
188
+ - Switch theme
189
+ - Quit
190
+
191
+ Type to filter, `↑↓` to navigate, `Enter` to execute, `Esc` to close.
192
+
193
+ ### Worktree Creation Flow
194
+
195
+ 1. Press `a` to open the Create view
196
+ 2. Start typing a branch name — matching branches appear as you type
197
+ 3. Use `↑↓` to select from suggestions, or keep typing for a new branch
198
+ 4. Press `Tab` to switch to the Focus field (optional)
199
+ 5. Type focus paths (e.g. `apps/web,apps/api`)
200
+ 6. Press `Enter` to preview
201
+ 7. Press `Enter` to confirm
202
+
203
+ The fuzzy branch picker shows local and remote branches sorted by last commit date, filtered in real-time as you type.
204
+
205
+ After creation, the configured `copyFiles`, `linkFiles`, `postCreate` hooks, and monorepo hooks run automatically.
206
+
207
+ ### Doctor View
208
+
209
+ Press `h` to open the Doctor tab. Shows health check results:
210
+
211
+ - ✓ Git version check
212
+ - ✓ Config validation
213
+ - ✓ Stale worktree detection
214
+ - ✓ Orphaned directory detection
215
+ - ✓ Lock status check
216
+ - ✓ Dirty worktree detection
217
+
218
+ Press `r` to recheck, `Esc` to go back.
219
+
220
+ ## CLI Commands
221
+
222
+ | Command | Description |
223
+ | ------------------------ | ------------------------------------ |
224
+ | `omw` | Launch TUI |
225
+ | `omw list` | List all worktrees (with focus info) |
226
+ | `omw add <branch>` | Create worktree |
227
+ | `omw remove <branch>` | Remove worktree |
228
+ | `omw switch <branch>` | Switch to worktree |
229
+ | `omw clean` | Remove merged worktrees |
230
+ | `omw doctor` | Check worktree health |
231
+ | `omw config` | Manage configuration |
232
+ | `omw exec <command>` | Run command in each worktree |
233
+ | `omw diff <ref1> [ref2]` | Diff between worktrees/branches |
234
+ | `omw pin <branch>` | Pin/unpin worktree (protect from cleanup) |
235
+ | `omw log` | Show worktree activity log |
236
+ | `omw archive <branch>` | Archive changes and optionally remove |
237
+ | `omw rename <old> <new>` | Rename worktree branch |
238
+ | `omw clone <url>` | Clone repo and initialize omw |
239
+ | `omw import <path>` | Adopt worktree with omw metadata |
240
+ | `omw session [branch]` | Manage tmux sessions for worktrees |
241
+ | `omw init` | Initialize config or install AI agent skills |
242
+
243
+ ### `omw add`
244
+
245
+ ```bash
246
+ omw add feature/login # Create branch if needed + worktree
247
+ omw add feature/login --base main # New branches start from main
248
+ omw add existing-branch # Worktree for existing branch
249
+
250
+ # Monorepo: create with focus packages
251
+ omw add feature/login --focus apps/web,apps/api
252
+ omw add feature/login --focus apps/web --focus apps/api
253
+
254
+ # Use a template
255
+ omw add feature/login --template review
256
+
257
+ # Create from a GitHub PR (requires gh CLI)
258
+ omw add --pr 123
259
+ omw add --pr 456 --template review
260
+ ```
261
+
262
+ ### `omw doctor`
263
+
264
+ ```bash
265
+ omw doctor # Human-readable output
266
+ omw doctor --json # JSON output for scripting
267
+ ```
268
+
269
+ Exit code: `0` if healthy, `1` if any warnings or errors.
270
+
271
+ ```
272
+ oh-my-worktree doctor
273
+
274
+ ✓ Git version: 2.39.0 (>= 2.17 required)
275
+ ✓ Configuration: valid
276
+ ✓ Stale worktrees: none
277
+ ✓ Orphaned directories: none
278
+ ✓ Worktree locks: all clear
279
+ ✓ Dirty worktrees: none
280
+
281
+ All checks passed.
282
+ ```
283
+
284
+ ### `omw list`
285
+
286
+ ```bash
287
+ omw list # Table with Focus column
288
+ omw list --json # JSON with focus array
289
+ omw list --porcelain # Machine-readable
290
+ ```
291
+
292
+ Output includes a `Focus` column showing monorepo focus paths per worktree.
293
+
294
+ ### `omw remove`
295
+
296
+ ```bash
297
+ omw remove feature/login # Remove by branch name
298
+ omw remove feature/login --force # Force remove (dirty worktree)
299
+ omw remove feature/login --yes # Skip confirmation
300
+ ```
301
+
302
+ ### `omw clean`
303
+
304
+ ```bash
305
+ omw clean --dry-run # Preview what would be removed
306
+ omw clean # Remove all merged worktrees
307
+ omw clean --stale # Also show stale worktrees (uses lifecycle config)
308
+ ```
309
+
310
+ ### `omw exec`
311
+
312
+ Run a shell command in every non-main worktree.
313
+
314
+ ```bash
315
+ omw exec "bun test" # Run in all worktrees (sequential)
316
+ omw exec "bun test" --parallel # Run in parallel
317
+ omw exec "git pull" --all # Across all configured repos
318
+ omw exec "bun install" --dirty # Only dirty worktrees
319
+ omw exec "git rebase main" --behind # Only worktrees behind upstream
320
+ omw exec "bun test" --json # JSON output
321
+ ```
322
+
323
+ | Flag | Description |
324
+ | ------------------- | ------------------------------------- |
325
+ | `--parallel` / `-p` | Run commands in parallel |
326
+ | `--all` / `-a` | Include all configured repos |
327
+ | `--dirty` | Only run in dirty worktrees |
328
+ | `--clean` | Only run in clean worktrees |
329
+ | `--behind` | Only run in worktrees behind upstream |
330
+ | `--json` / `-j` | Output results as JSON |
331
+
332
+ Environment variables available in commands: `OMW_BRANCH`, `OMW_WORKTREE_PATH`, `OMW_REPO_PATH`.
333
+
334
+ ### `omw diff`
335
+
336
+ Show diff between two worktree branches.
337
+
338
+ ```bash
339
+ omw diff feature/a feature/b # Full diff
340
+ omw diff feature/a feature/b --stat # Diffstat summary
341
+ omw diff feature/a --name-only # Changed file names only
342
+ omw diff feature/a # Compare against current HEAD
343
+ ```
344
+
345
+ ### `omw pin`
346
+
347
+ ```bash
348
+ omw pin feature/auth --reason "active sprint" # Pin with reason
349
+ omw pin --list # List pinned worktrees
350
+ omw pin --list --json # JSON output
351
+ omw unpin feature/auth # Unpin
352
+ ```
353
+
354
+ Pinned worktrees are excluded from `omw clean` and lifecycle auto-cleanup.
355
+
356
+ ### `omw log`
357
+
358
+ ```bash
359
+ omw log # Show last 20 events
360
+ omw log --limit 50 # Show last 50 events
361
+ omw log --json # JSON output
362
+ omw log --clear # Clear activity log
363
+ ```
364
+
365
+ Events are color-coded: create (green), delete (red), switch (blue), rename (yellow), archive (magenta), import (cyan).
366
+
367
+ ### `omw archive`
368
+
369
+ ```bash
370
+ omw archive feature/done --yes # Archive and remove
371
+ omw archive feature/wip --keep # Archive without removing
372
+ omw archive --list # List all archives
373
+ omw archive --list --json # JSON output
374
+ ```
375
+
376
+ Archives are stored as patch files in `~/.omw/archives/`.
377
+
378
+ ### `omw rename`
379
+
380
+ ```bash
381
+ omw rename old-branch new-branch # Rename branch
382
+ omw rename old-branch new-branch --move-path # Also move worktree directory
383
+ ```
384
+
385
+ ### `omw clone`
386
+
387
+ ```bash
388
+ omw clone https://github.com/user/repo.git # Clone and init
389
+ omw clone https://github.com/user/repo.git ./my-dir # Custom target path
390
+ omw clone https://github.com/user/repo.git --template review # Apply template
391
+ omw clone https://github.com/user/repo.git --no-init-config # Skip config init
392
+ ```
393
+
394
+ ### `omw import`
395
+
396
+ ```bash
397
+ omw import /path/to/worktree # Adopt worktree
398
+ omw import /path/to/worktree --focus apps/web,apps/api # With focus
399
+ omw import /path/to/worktree --pin # Pin immediately
400
+ ```
401
+
402
+ ### `omw session`
403
+
404
+ Manage tmux sessions for worktrees. Requires tmux.
405
+
406
+ ```bash
407
+ omw session feature/auth # Open/attach session (create if needed)
408
+ omw session feature/auth --layout api # Use named layout from config
409
+ omw session --list # List active omw sessions
410
+ omw session --list --json # JSON output
411
+ omw session feature/auth --kill # Kill session for worktree
412
+ omw session --kill-all # Kill all omw sessions
413
+ ```
414
+
415
+ Sessions are auto-created/killed when `sessions.autoCreate` / `sessions.autoKill` are enabled in config.
416
+
417
+ ```bash
418
+ # Create worktree with tmux session
419
+ omw add feature/login --session
420
+ omw add feature/login --session --layout api
421
+ ```
422
+
423
+ When `sessions.enabled` is `true` and you're inside tmux, `omw switch` automatically switches to the target worktree's tmux session.
424
+
425
+ ### `omw init`
426
+
427
+ Initialize omw config by default, or install omw skill for AI coding agents so they can use omw commands.
428
+
429
+ ```bash
430
+ omw init # → ~/.config/oh-my-worktree/config.json
431
+ omw init --skill claude-code # → ~/.claude/skills/omw/
432
+ omw init --skill codex # → ~/.agents/skills/omw/
433
+ omw init --skill opencode # → ~/.config/opencode/skill/omw/
434
+ ```
435
+
436
+ | Platform | Skill Path |
437
+ |----------|-----------|
438
+ | `claude-code` | `~/.claude/skills/omw/` |
439
+ | `codex` | `~/.agents/skills/omw/` |
440
+ | `opencode` | `~/.config/opencode/skill/omw/` |
441
+
442
+ Each skill directory contains:
443
+ - `SKILL.md` — overview and common workflows
444
+ - `references/` — detailed per-command documentation (21 files)
445
+
446
+ Without `--skill`, the command reuses the normal config initializer and creates only `config.json`.
447
+ The command is idempotent — running it again updates the skill directory.
448
+
449
+ ## Configuration
450
+
451
+ Config file: `~/.config/oh-my-worktree/config.json`
452
+
453
+ Initialize with: `omw config --init`
454
+
455
+ ### Full Example
456
+
457
+ ```json
458
+ {
459
+ "$schema": "https://raw.githubusercontent.com/getsolaris/oh-my-worktree/main/schema.json",
460
+ "version": 1,
461
+ "theme": "dracula",
462
+ "defaults": {
463
+ "worktreeDir": "~/.omw/worktrees/{repo}-{branch}",
464
+ "copyFiles": [".env"],
465
+ "linkFiles": ["node_modules"],
466
+ "postCreate": ["bun install"],
467
+ "postRemove": [],
468
+ "sharedDeps": {
469
+ "strategy": "hardlink",
470
+ "paths": ["node_modules"],
471
+ "invalidateOn": ["package.json", "bun.lockb"]
472
+ }
473
+ },
474
+ "templates": {
475
+ "review": {
476
+ "copyFiles": [".env.local"],
477
+ "postCreate": ["bun install", "bun run build"],
478
+ "autoUpstream": true
479
+ },
480
+ "hotfix": {
481
+ "base": "main",
482
+ "copyFiles": [".env.production"],
483
+ "postCreate": ["bun install"]
484
+ },
485
+ "experiment": {
486
+ "worktreeDir": "~/tmp/experiments/{branch}",
487
+ "postRemove": []
488
+ }
489
+ },
490
+ "lifecycle": {
491
+ "autoCleanMerged": true,
492
+ "staleAfterDays": 14,
493
+ "maxWorktrees": 10
494
+ },
495
+ "sessions": {
496
+ "enabled": true,
497
+ "autoCreate": false,
498
+ "autoKill": true,
499
+ "prefix": "omw",
500
+ "defaultLayout": "dev",
501
+ "layouts": {
502
+ "dev": {
503
+ "windows": [
504
+ { "name": "editor", "command": "$EDITOR ." },
505
+ { "name": "dev", "command": "bun dev" },
506
+ { "name": "test", "command": "bun test --watch" }
507
+ ]
508
+ },
509
+ "minimal": {
510
+ "windows": [
511
+ { "name": "shell" }
512
+ ]
513
+ }
514
+ }
515
+ },
516
+ "repos": [
517
+ {
518
+ "path": "/Users/me/dev/frontend",
519
+ "copyFiles": [".env", ".env.local"],
520
+ "linkFiles": ["node_modules", ".next"],
521
+ "postCreate": ["bun install", "bun run build"]
522
+ },
523
+ {
524
+ "path": "/Users/me/dev/backend",
525
+ "copyFiles": [".env"],
526
+ "postCreate": ["pip install -r requirements.txt"]
527
+ },
528
+ {
529
+ "path": "/Users/me/dev/monorepo",
530
+ "copyFiles": [".env"],
531
+ "postCreate": ["pnpm install"],
532
+ "monorepo": {
533
+ "autoDetect": true,
534
+ "extraPatterns": ["apps/*/*"],
535
+ "hooks": [
536
+ {
537
+ "glob": "apps/web",
538
+ "copyFiles": [".env"],
539
+ "postCreate": ["cd {packagePath} && pnpm install"]
540
+ },
541
+ {
542
+ "glob": "apps/api",
543
+ "copyFiles": [".env"],
544
+ "linkFiles": ["node_modules"],
545
+ "postCreate": ["cd {packagePath} && pnpm install && pnpm build"]
546
+ }
547
+ ]
548
+ }
549
+ }
550
+ ]
551
+ }
552
+ ```
553
+
554
+ ### Config Fields
555
+
556
+ #### `defaults`
557
+
558
+ All repos inherit these unless overridden.
559
+
560
+ | Field | Type | Default | Description |
561
+ | ------------- | ---------- | ---------------------------------- | --------------------------------------- |
562
+ | `worktreeDir` | `string` | `~/.omw/worktrees/{repo}-{branch}` | Worktree directory pattern |
563
+ | `copyFiles` | `string[]` | `[]` | Files to copy from main repo |
564
+ | `linkFiles` | `string[]` | `[]` | Files/dirs to symlink (saves disk) |
565
+ | `postCreate` | `string[]` | `[]` | Commands to run after worktree creation |
566
+ | `postRemove` | `string[]` | `[]` | Commands to run before worktree removal |
567
+
568
+ #### `repos[]`
569
+
570
+ Per-repo overrides. Each entry requires `path`.
571
+
572
+ | Field | Type | Required | Description |
573
+ | ------------- | ---------- | -------- | ----------------------------------- |
574
+ | `path` | `string` | Yes | Absolute path to the repository |
575
+ | `worktreeDir` | `string` | No | Override default worktree directory |
576
+ | `copyFiles` | `string[]` | No | Override default copy files |
577
+ | `linkFiles` | `string[]` | No | Override default link files |
578
+ | `postCreate` | `string[]` | No | Override default post-create hooks |
579
+ | `postRemove` | `string[]` | No | Override default post-remove hooks |
580
+ | `monorepo` | `object` | No | Monorepo support config |
581
+
582
+ #### `monorepo`
583
+
584
+ Universal monorepo support. Auto-detects packages from workspace config files and supports per-package hooks.
585
+
586
+ ```json
587
+ {
588
+ "monorepo": {
589
+ "autoDetect": true,
590
+ "extraPatterns": ["apps/*/*"],
591
+ "hooks": [
592
+ {
593
+ "glob": "apps/mobile/*",
594
+ "copyFiles": [".env"],
595
+ "linkFiles": ["node_modules"],
596
+ "postCreate": ["cd {packagePath} && pnpm install"]
597
+ }
598
+ ]
599
+ }
600
+ }
601
+ ```
602
+
603
+ | Field | Type | Default | Description |
604
+ | --------------- | ---------- | ------- | ----------------------------------------- |
605
+ | `autoDetect` | `boolean` | `true` | Auto-detect monorepo tools |
606
+ | `extraPatterns` | `string[]` | `[]` | Extra glob patterns for package discovery |
607
+ | `hooks` | `array` | `[]` | Per-package hook definitions |
608
+
609
+ **Auto-detection** supports: pnpm workspaces, Turborepo, Nx, Lerna, npm/yarn workspaces.
610
+
611
+ **`extraPatterns`** catches packages not covered by auto-detection. For example, if your `pnpm-workspace.yaml` only covers `packages/*` but you also have apps at `apps/frontend/dashboard`, use `extraPatterns: ["apps/*/*"]`.
612
+
613
+ #### `monorepo.hooks[]`
614
+
615
+ Per-package hooks matched by glob pattern against focus paths.
616
+
617
+ | Field | Type | Required | Description |
618
+ | ------------ | ---------- | -------- | ------------------------------------------------------------------------------ |
619
+ | `glob` | `string` | Yes | Glob to match focus paths (e.g. `apps/*`, `apps/mobile/*`) |
620
+ | `copyFiles` | `string[]` | No | Files to copy within the matched package directory |
621
+ | `linkFiles` | `string[]` | No | Files/dirs to symlink within the matched package directory |
622
+ | `postCreate` | `string[]` | No | Commands to run after creation. Supports `{packagePath}`, `{repo}`, `{branch}` |
623
+ | `postRemove` | `string[]` | No | Commands to run before removal |
624
+
625
+ Hooks execute in declaration order, after the repo-level `postCreate`/`postRemove`.
626
+
627
+ **`copyFiles`/`linkFiles` in hooks** operate on the **package subdirectory**, not the repo root. For example, with `glob: "apps/mobile/*"` and `copyFiles: [".env"]`, the `.env` file is copied from `<main-repo>/apps/mobile/ios/.env` to `<worktree>/apps/mobile/ios/.env`.
628
+
629
+ #### `templates`
630
+
631
+ Named presets for worktree creation. Each template can override any default field.
632
+
633
+ ```json
634
+ {
635
+ "templates": {
636
+ "review": {
637
+ "copyFiles": [".env.local"],
638
+ "postCreate": ["bun install", "bun run build"],
639
+ "autoUpstream": true
640
+ },
641
+ "hotfix": {
642
+ "base": "main",
643
+ "copyFiles": [".env.production"],
644
+ "postCreate": ["bun install"]
645
+ }
646
+ }
647
+ }
648
+ ```
649
+
650
+ | Field | Type | Description |
651
+ | -------------- | ---------- | ---------------------------------- |
652
+ | `worktreeDir` | `string` | Override worktree directory |
653
+ | `copyFiles` | `string[]` | Override files to copy |
654
+ | `linkFiles` | `string[]` | Override files to symlink |
655
+ | `postCreate` | `string[]` | Override post-create hooks |
656
+ | `postRemove` | `string[]` | Override post-remove hooks |
657
+ | `autoUpstream` | `boolean` | Override upstream tracking |
658
+ | `base` | `string` | Default base branch for newly created branches |
659
+
660
+ Usage: `omw add feature/login --template review`
661
+
662
+ Template values override the resolved repo config. The `base` field sets a default for `--base` if not explicitly provided.
663
+
664
+ #### `lifecycle`
665
+
666
+ Automatic worktree lifecycle management. Used by `omw clean --stale`.
667
+
668
+ ```json
669
+ {
670
+ "lifecycle": {
671
+ "autoCleanMerged": true,
672
+ "staleAfterDays": 14,
673
+ "maxWorktrees": 10
674
+ }
675
+ }
676
+ ```
677
+
678
+ | Field | Type | Default | Description |
679
+ | ----------------- | --------- | ------- | ------------------------------------------- |
680
+ | `autoCleanMerged` | `boolean` | `false` | Flag merged worktrees for cleanup |
681
+ | `staleAfterDays` | `number` | — | Days of inactivity before flagging as stale |
682
+ | `maxWorktrees` | `number` | — | Warn when exceeding this count |
683
+
684
+ #### Config Profiles
685
+
686
+ Switch between different configuration sets.
687
+
688
+ ```bash
689
+ omw config --profiles # List profiles
690
+ omw config --profile work --activate # Activate profile
691
+ omw config --profile personal --delete # Delete profile
692
+ ```
693
+
694
+ #### `sessions`
695
+
696
+ Tmux session management for worktrees.
697
+
698
+ ```json
699
+ {
700
+ "sessions": {
701
+ "enabled": true,
702
+ "autoCreate": true,
703
+ "autoKill": true,
704
+ "prefix": "omw",
705
+ "defaultLayout": "dev",
706
+ "layouts": {
707
+ "dev": {
708
+ "windows": [
709
+ { "name": "editor", "command": "$EDITOR ." },
710
+ { "name": "dev", "command": "bun dev" },
711
+ { "name": "test", "command": "bun test --watch" }
712
+ ]
713
+ }
714
+ }
715
+ }
716
+ }
717
+ ```
718
+
719
+ | Field | Type | Default | Description |
720
+ | --------------- | --------- | ------- | -------------------------------------------------- |
721
+ | `enabled` | `boolean` | `false` | Enable session integration (auto-switch in tmux) |
722
+ | `autoCreate` | `boolean` | `false` | Auto-create tmux session on `omw add` |
723
+ | `autoKill` | `boolean` | `false` | Auto-kill tmux session on `omw remove` |
724
+ | `prefix` | `string` | `"omw"` | Prefix for tmux session names |
725
+ | `defaultLayout` | `string` | — | Default layout name for new sessions |
726
+ | `layouts` | `object` | `{}` | Named layouts with window definitions |
727
+
728
+ **Layout windows:**
729
+
730
+ | Field | Type | Required | Description |
731
+ | --------- | -------- | -------- | ------------------------------ |
732
+ | `name` | `string` | Yes | Window name |
733
+ | `command` | `string` | No | Command to run in the window |
734
+
735
+ Session naming: branch `feat/auth-token` → tmux session `omw_feat-auth-token`.
736
+
737
+ #### `sharedDeps`
738
+
739
+ Share dependencies between main repo and worktrees to save disk space. Can be set in `defaults` or per-repo.
740
+
741
+ ```json
742
+ {
743
+ "defaults": {
744
+ "sharedDeps": {
745
+ "strategy": "hardlink",
746
+ "paths": ["node_modules"],
747
+ "invalidateOn": ["package.json", "bun.lockb"]
748
+ }
749
+ }
750
+ }
751
+ ```
752
+
753
+ | Field | Type | Default | Description |
754
+ | -------------- | ---------- | ----------- | ------------------------------------------ |
755
+ | `strategy` | `string` | `"symlink"` | `"hardlink"`, `"symlink"`, or `"copy"` |
756
+ | `paths` | `string[]` | `[]` | Directories/files to share |
757
+ | `invalidateOn` | `string[]` | `[]` | Files that trigger re-sharing when changed |
758
+
759
+ **Strategies:**
760
+
761
+ - `hardlink` — Create hard links for each file (saves disk, each worktree can modify independently for files that get rewritten)
762
+ - `symlink` — Create a symlink to the source directory (most disk savings, shared state)
763
+ - `copy` — Fall back to regular copy
764
+
765
+ ### `--focus` Flag
766
+
767
+ Track which monorepo packages a worktree is working on.
768
+
769
+ ```bash
770
+ omw add feature/login --focus apps/web,apps/api
771
+ ```
772
+
773
+ - Supports comma-separated, space-separated, or multiple `--focus` flags
774
+ - Focus metadata is stored in git internals (not in the worktree root)
775
+ - `omw list` shows focus paths per worktree
776
+ - Monorepo hooks only fire for matching focus paths
777
+ - Focus is optional — omitting it creates a normal worktree
778
+
779
+ ### Template Variables
780
+
781
+ Available in `worktreeDir` and monorepo hook commands:
782
+
783
+ | Variable | Description | Example |
784
+ | --------------- | ------------------------------------------ | -------------- |
785
+ | `{repo}` | Repository directory name | `my-app` |
786
+ | `{branch}` | Branch name (`/` replaced with `-`) | `feature-auth` |
787
+ | `{packagePath}` | Matched package path (monorepo hooks only) | `apps/web` |
788
+ | `~` | Home directory (only at path start) | `/Users/me` |
789
+
790
+ ### Priority
791
+
792
+ Per-repo settings completely replace defaults (no merging):
793
+
794
+ ```
795
+ repos[].copyFiles exists? → use repos[].copyFiles
796
+ repos[].copyFiles missing? → use defaults.copyFiles
797
+ defaults.copyFiles missing? → use [] (empty)
798
+ ```
799
+
800
+ ### Themes
801
+
802
+ Set via config or command palette (`Ctrl+P`):
803
+
804
+ ```json
805
+ { "theme": "tokyo-night" }
806
+ ```
807
+
808
+ Available: `opencode`, `tokyo-night`, `dracula`, `nord`, `catppuccin`, `github-dark`
809
+
810
+ ## Shell Integration
811
+
812
+ Use `omw shell-init` to install shell integration for `omw switch`.
813
+
814
+ ### Completions
815
+
816
+ ```bash
817
+ # Add completions (bash)
818
+ eval "$(omw shell-init --completions bash)"
819
+
820
+ # Add completions (zsh)
821
+ eval "$(omw shell-init --completions zsh)"
822
+
823
+ # Add completions (fish)
824
+ omw shell-init --completions fish | source
825
+ ```
826
+
827
+ ### Examples
828
+
829
+ ```bash
830
+ # zsh
831
+ echo 'eval "$(omw shell-init zsh)"' >> ~/.zshrc
832
+ source ~/.zshrc
833
+
834
+ # bash
835
+ echo 'eval "$(omw shell-init bash)"' >> ~/.bashrc
836
+ source ~/.bashrc
837
+
838
+ # fish
839
+ omw shell-init fish >> ~/.config/fish/config.fish
840
+ source ~/.config/fish/config.fish
841
+ ```
842
+
843
+ You can also preview the generated wrapper before saving it:
844
+
845
+ ```bash
846
+ omw shell-init zsh
847
+ ```
848
+
849
+ ## License
850
+
851
+ MIT © getsolaris