@ogpoyraz/wtx 0.7.0 → 0.8.0

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
@@ -59,13 +59,16 @@ Run any command without a config and `wtx` walks you through setup: it scans com
59
59
  # create a worktree (deps + sync_files handled automatically)
60
60
  wtx create ogp/my-feature --repo my-frontend
61
61
 
62
+ # create a dependent worktree from another branch
63
+ wtx create ogp/my-ui --repo my-frontend --base ogp/my-api
64
+
62
65
  # hand it to a coding agent
63
66
  wtx create ogp/my-feature --repo my-frontend --agent claude --prompt "add OAuth login"
64
67
 
65
68
  # list everything across all repos
66
69
  wtx ls
67
70
 
68
- # rebase onto main when origin moves
71
+ # rebase onto the recorded base (main for independent branches)
69
72
  wtx rebase ogp/my-feature
70
73
 
71
74
  # remove when merged — refuses dirty worktrees unless forced
@@ -87,12 +90,13 @@ If origin already has a branch with that name owned by someone else, `wtx` warns
87
90
  | `rename` | `<old-branch> <new-branch>` | `--repo` | Rename the branch and move the checkout to the matching new directory |
88
91
  | `prune` | | `--repo`, `--force`, `--yes` | Remove worktrees whose PR has merged |
89
92
  | `open` | `<branch>` | `--repo`, `--ide` | Open worktree in IDE |
90
- | `rebase` | `<branch>` | `--repo` | Fetch base remote main, rebase worktree onto it |
93
+ | `rebase` | `<branch>` | `--repo`, `--onto <ref>` | Rebase worktree onto its recorded base, or an explicit ref |
91
94
  | `fetch` | | `--repo` | Fetch main for each repo |
92
95
  | `sync` | `<branch>` | `--repo` | Re-copy sync files, run post-sync hooks |
93
- | `deps` | `[branch]` | `--repo`, `--install`, `--symlink`, `--json` | Inspect or switch dependency strategy |
96
+ | `deps` | `[branch]` | `--repo`, `--install`, `--symlink`, `--json` | Inspect or switch dependency strategy; omit the branch and `--install` runs in the main checkout |
94
97
  | `ls` | | `--repo`, `--pr`, `--json` | List all worktrees with clean/dirty state |
95
- | `status` | `<branch>` | `--repo`, `--json` | Ahead/behind, dirty files, rebase state, deps strategy |
98
+ | `status` | `<branch>` | `--repo`, `--base <ref>`, `--json` | Ahead/behind against base, dirty files, rebase state, deps strategy |
99
+ | `stack` | `<branch>` | `--repo`, `--json` | Show recorded parent and descendant branches |
96
100
  | `prs` | | `--repo`, `--json`, `--all` | Pull request status across worktrees |
97
101
  | `exec` | `<branch> <command...>` | `--repo` | Run a command inside a worktree (`WTX_PORT` injected) |
98
102
  | `terminal` | | | Interactive worktree dashboard (requires Bun) |
@@ -167,7 +171,7 @@ Config lives at `~/.config/wtx/config.json`.
167
171
  | `repos.<name>.fetch_main_on_create` | `true` | Fetch before creating so branches start fresh |
168
172
  | `repos.<name>.sync_files` | `[]` | Files copied from main checkout on create and sync |
169
173
  | `repos.<name>.post_create` / `post_sync` | `[]` | Hook commands; failures fail the command with a rerun hint |
170
- | `repos.<name>.install_script` | `null` | Command run inside a worktree for `deps --install` and `create --deps install` (`{wt}`, `{branch}`, `{main}` expanded); when unset, the detected package manager performs a real install |
174
+ | `repos.<name>.install_script` | `null` | Command run inside a worktree (or the main checkout via `wtx deps --install`) for dependency installs (`{wt}`, `{branch}`, `{main}` expanded); when unset, the detected package manager performs a real install |
171
175
  | `repos.<name>.deps.manager` | `"auto"` | Force a manager: `npm` `bun` `pnpm` `yarn` `go` `python` `cargo` |
172
176
  | `repos.<name>.deps.strategy` | `"auto"` | `auto` `link` `symlink` `install` `off` — see below |
173
177
  | `repos.<name>.check_prs` | `true` | Set `false` to skip all PR lookups for this repo's branches (no `gh` calls) |
@@ -214,7 +218,7 @@ Hooks also receive `WTX_PORT` as an environment variable, as does `wtx exec`. Po
214
218
  | `install` | Always a real install in the worktree |
215
219
  | `off` | Leave dependencies alone |
216
220
 
217
- Per-repo `install_script` overrides the install command entirely — useful for non-standard setups (`pnpm install --frozen-lockfile`, bootstrap scripts, codegen steps). It runs inside the worktree with the same `{wt}` / `{branch}` / `{main}` template expansion as hooks.
221
+ Per-repo `install_script` overrides the install command entirely — useful for non-standard setups (`pnpm install --frozen-lockfile`, bootstrap scripts, codegen steps). It runs inside the worktree (or the main checkout when installing via `wtx deps --install` with no branch) with the same `{wt}` / `{branch}` / `{main}` template expansion as hooks.
218
222
 
219
223
  ### Safe linking (the `auto` default)
220
224
 
@@ -283,6 +287,23 @@ wtx prune # remove worktrees whose PR m
283
287
 
284
288
  Lookups degrade gracefully: if `gh` is missing or unauthenticated you get a warning and everything else keeps working. Fork workflows are covered by `check_prs` / `forge_provider` / `pr_lookup_repo`.
285
289
 
290
+ ### Stacked branches
291
+
292
+ Worktrees remain sibling directories on disk, while their branches can form a dependency stack:
293
+
294
+ ```bash
295
+ wtx create feat/api
296
+ wtx create feat/ui --base feat/api
297
+
298
+ # Open the PRs with these bases:
299
+ # feat/api -> main
300
+ # feat/ui -> feat/api
301
+ ```
302
+
303
+ `--base` accepts a normal Git ref and uses committed history only; uncommitted files in the parent worktree are not copied. The default remains the configured main branch. `wtx stack feat/ui` shows the recorded local relationship, and `wtx rebase feat/ui` rebases onto the recorded parent instead of flattening the stack onto main. After the parent merges, retarget the child PR to main before rebasing it onto main.
304
+
305
+ Stack metadata is stored under the repository's common Git directory and is not committed to the project. If a parent branch moves, `wtx status <child>` and the terminal dashboard mark the base as moved. Removing a parent with recorded children is refused unless `--force` is supplied.
306
+
286
307
  ---
287
308
 
288
309
  ## Terminal dashboard
@@ -59,7 +59,7 @@ _wtx() {
59
59
  'remove[Remove worktrees]' \
60
60
  'prune[Remove worktrees with merged PRs]' \
61
61
  'open[Open worktree in IDE]' \
62
- 'rebase[Fetch and rebase vs main]' \
62
+ 'rebase[Fetch and rebase onto recorded base]' \
63
63
  'pull[Fetch a PR and create its worktree]' \
64
64
  'pull-branch[Fast-forward pull a worktree branch]' \
65
65
  'rename[Rename branch and move worktree directory]' \
@@ -68,7 +68,8 @@ _wtx() {
68
68
  'deps[Manage node_modules strategy]' \
69
69
  'ls[List worktrees with status]' \
70
70
  'cd[Change directory to worktree]' \
71
- 'status[Show worktree status]' \
71
+ 'status[Show worktree status]' \
72
+ 'stack[Show recorded branch stack]' \
72
73
  'prs[Show pull request status across worktrees]' \
73
74
  'init[Output shell integration code]' \
74
75
  'skill[Manage AI agent skills]' \
@@ -127,6 +128,7 @@ _wtx() {
127
128
  _arguments \
128
129
  ':branch:_wtx_branches' \
129
130
  '--repo[Target specific repo(s)]:repo:_wtx_repos' \
131
+ '--onto[Override recorded base]:ref:' \
130
132
  {-q,--quiet}'[Suppress output]' \
131
133
  '--verbose[Show git commands]' \
132
134
  '--dry-run[Show what would happen]'
@@ -197,6 +199,16 @@ _wtx() {
197
199
  ':branch:_wtx_branches'
198
200
  ;;
199
201
  status)
202
+ _arguments \
203
+ ':branch:_wtx_branches' \
204
+ {-r,--repo}'[Target specific repo(s)]:repo:_wtx_repos' \
205
+ '--base[Override recorded base]:ref:' \
206
+ '--json[Output machine-readable JSON]' \
207
+ {-q,--quiet}'[Suppress output]' \
208
+ '--verbose[Show git commands]' \
209
+ '--dry-run[Show what would happen]'
210
+ ;;
211
+ stack)
200
212
  _arguments \
201
213
  ':branch:_wtx_branches' \
202
214
  {-r,--repo}'[Target specific repo(s)]:repo:_wtx_repos' \
@@ -43,7 +43,7 @@ _wtx_completions() {
43
43
  cword=$COMP_CWORD
44
44
  }
45
45
 
46
- local subcommands="config create remove prune open rebase fetch sync deps ls cd status prs pull pull-branch init skill terminal mcp exec rename"
46
+ local subcommands="config create remove prune open rebase fetch sync deps ls cd status prs pull pull-branch init skill terminal mcp exec rename stack"
47
47
  local config_subcommands="init show set add-repo remove-repo"
48
48
  local skill_subcommands="show path list"
49
49
  local skill_names="opencode cursor claude"
@@ -80,7 +80,7 @@ _wtx_completions() {
80
80
  return 0
81
81
  fi
82
82
 
83
- if [ "$prev" = "--base" ]; then
83
+ if [ "$prev" = "--base" ] || [ "$prev" = "--onto" ]; then
84
84
  COMPREPLY=($(compgen -W "main master develop dev" -- "$cur"))
85
85
  return 0
86
86
  fi
@@ -92,14 +92,15 @@ _wtx_completions() {
92
92
  remove) flags="-f --force -y --yes -r --repo -q --quiet --verbose --dry-run --help" ;;
93
93
  prune) flags="-f --force -y --yes -r --repo -q --quiet --verbose --dry-run --help" ;;
94
94
  open) flags="-r --repo --ide -q --quiet --verbose --dry-run --help" ;;
95
- rebase) flags="--repo -q --quiet --verbose --dry-run --help" ;;
95
+ rebase) flags="--repo --onto -q --quiet --verbose --dry-run --help" ;;
96
96
  rename) flags="-r --repo -q --quiet --verbose --dry-run --help" ;;
97
97
  fetch) flags="--repo -q --quiet --verbose --dry-run --help" ;;
98
98
  sync) flags="--repo -q --quiet --verbose --dry-run --help" ;;
99
99
  deps) flags="-r --repo --install --symlink --json -q --quiet --verbose --dry-run --help" ;;
100
100
  pull) flags="-r --repo -q --quiet --verbose --dry-run --help" ;;
101
101
  ls) flags="-r --repo --pr --json -q --quiet --verbose --dry-run --help" ;;
102
- status) flags="-r --repo --json -q --quiet --verbose --dry-run --help" ;;
102
+ status) flags="-r --repo --base --json -q --quiet --verbose --dry-run --help" ;;
103
+ stack) flags="-r --repo --json -q --quiet --verbose --dry-run --help" ;;
103
104
  prs) flags="-r --repo --json --all -q --quiet --verbose --dry-run --help" ;;
104
105
  config)
105
106
  case "$subsubcommand" in
@@ -153,7 +154,7 @@ _wtx_completions() {
153
154
  cd)
154
155
  [ "$prev" = "cd" ] && COMPREPLY=($(compgen -W "$(_wtx_get_repos)" -- "$cur")) && return 0
155
156
  ;;
156
- rebase|open|status|remove|sync|deps|rename)
157
+ rebase|open|status|remove|sync|deps|rename|stack)
157
158
  [ "$prev" = "$subcommand" ] && COMPREPLY=($(compgen -W "$(_wtx_get_branches)" -- "$cur")) && return 0
158
159
  ;;
159
160
  esac
@@ -41,7 +41,7 @@ complete -c wtx -l dry-run -d "Show what would happen"
41
41
  complete -c wtx -s h -l help -d "Display help for command"
42
42
 
43
43
  # Subcommands
44
- set -l commands config create remove prune open rebase fetch sync deps ls cd status prs pull pull-branch init skill terminal mcp exec rename
44
+ set -l commands config create remove prune open rebase fetch sync deps ls cd status prs pull pull-branch init skill terminal mcp exec rename stack
45
45
 
46
46
  # Setup completions for commands
47
47
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "config" -d "Manage configuration"
@@ -49,7 +49,7 @@ complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "create" -d "C
49
49
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "remove" -d "Remove worktrees"
50
50
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "prune" -d "Remove worktrees with merged PRs"
51
51
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "open" -d "Open worktree in IDE"
52
- complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "rebase" -d "Fetch and rebase vs main"
52
+ complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "rebase" -d "Fetch and rebase onto recorded base"
53
53
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "pull" -d "Fetch a PR and create its worktree"
54
54
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "pull-branch" -d "Fast-forward pull a worktree branch"
55
55
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "rename" -d "Rename branch and move worktree directory"
@@ -59,6 +59,7 @@ complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "deps" -d "Man
59
59
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "ls" -d "List worktrees with status"
60
60
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "cd" -d "Change directory to worktree"
61
61
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "status" -d "Show worktree status"
62
+ complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "stack" -d "Show recorded branch stack"
62
63
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "prs" -d "Show pull request status across worktrees"
63
64
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "init" -d "Output shell integration code"
64
65
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "skill" -d "Manage AI agent skills"
@@ -67,10 +68,10 @@ complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "mcp" -d "Run
67
68
  complete -c wtx -n "not __fish_seen_subcommand_from $commands" -a "exec" -d "Execute commands across worktrees"
68
69
 
69
70
  # Dynamically complete branch arguments
70
- complete -c wtx -n "__fish_seen_subcommand_from create open rebase sync deps status remove rename pull-branch" -a "(_wtx_get_branches)"
71
+ complete -c wtx -n "__fish_seen_subcommand_from create open rebase sync deps status remove rename pull-branch stack" -a "(_wtx_get_branches)"
71
72
 
72
73
  # Flags
73
- complete -c wtx -n "__fish_seen_subcommand_from create remove prune open rebase fetch sync deps ls status prs pull pull-branch rename" -s r -l repo -xa "(_wtx_get_repos)" -d "Target specific repo(s)"
74
+ complete -c wtx -n "__fish_seen_subcommand_from create remove prune open rebase fetch sync deps ls status stack prs pull pull-branch rename" -s r -l repo -xa "(_wtx_get_repos)" -d "Target specific repo(s)"
74
75
 
75
76
  # create flags
76
77
  complete -c wtx -n "__fish_seen_subcommand_from create" -l base -xa "main master develop dev" -d "Base ref"
@@ -90,7 +91,7 @@ complete -c wtx -n "__fish_seen_subcommand_from deps" -l install -d "Switch to i
90
91
  complete -c wtx -n "__fish_seen_subcommand_from deps" -l symlink -d "Switch to symlinked node_modules"
91
92
 
92
93
  # json flag
93
- complete -c wtx -n "__fish_seen_subcommand_from ls status prs deps" -l json -d "Output machine-readable JSON"
94
+ complete -c wtx -n "__fish_seen_subcommand_from ls status stack prs deps" -l json -d "Output machine-readable JSON"
94
95
 
95
96
  # ls flags
96
97
  complete -c wtx -n "__fish_seen_subcommand_from ls" -l pr -d "Include pull request status column"
@@ -98,6 +99,10 @@ complete -c wtx -n "__fish_seen_subcommand_from ls" -l pr -d "Include pull reque
98
99
  # prs flags
99
100
  complete -c wtx -n "__fish_seen_subcommand_from prs" -l all -d "Include drafts and closed/merged PRs"
100
101
 
102
+ # stack-aware flags
103
+ complete -c wtx -n "__fish_seen_subcommand_from rebase" -l onto -xa "main master develop dev" -d "Override recorded base"
104
+ complete -c wtx -n "__fish_seen_subcommand_from status" -l base -xa "main master develop dev" -d "Override recorded base"
105
+
101
106
  # config subcommands
102
107
  set -l config_commands init show set add-repo remove-repo
103
108
  complete -c wtx -n "__fish_seen_subcommand_from config; and not __fish_seen_subcommand_from $config_commands" -a "init" -d "Initialize configuration"