@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/LICENSE +21 -0
- package/README.ko.md +833 -0
- package/README.md +851 -0
- package/dist/omw.js +221 -0
- package/package.json +36 -0
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
|