@cestoliv/wt 0.5.0-pr22.gbb5b3fa → 0.5.0-pr24.g2e0b1ed

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
@@ -16,7 +16,10 @@ prompt.
16
16
  npm install -g @cestoliv/wt # also the update command
17
17
  ```
18
18
 
19
- Requires Node.js 20+ and Git. The command is `wt`.
19
+ Requires Node.js 20+ and Git. The command is `wt`. Optionally install the
20
+ [`gh`](https://cli.github.com/) and/or [`glab`](https://gitlab.com/gitlab-org/cli)
21
+ CLIs (authenticated) to let `wt prune` confirm merges via merged PRs/MRs — see
22
+ [Prune](#prune--wt-prune).
20
23
 
21
24
  ## Let your AI assistant set it up
22
25
 
@@ -37,7 +40,7 @@ infer from this project. Write the result to the config file (find its path with
37
40
  wt # Browse worktrees (interactive TUI)
38
41
  wt create my-feat # New worktree, opens your IDE
39
42
  wt agent my-feat "Plan the feature" # New worktree + AI agent in Zed (macOS)
40
- wt agent fix-bug "Fix bug" --mode auto # Use auto mode instead of plan
43
+ wt agent fix-bug "Fix bug" --mode auto # Use auto mode instead of the default
41
44
  wt prune # Remove merged worktrees (per-branch confirm)
42
45
  wt config # Edit config in $EDITOR
43
46
  wt skill # Print the skill file (for AI agents)
@@ -52,14 +55,15 @@ wt agent refactor "Refactor API layer" --mode default
52
55
  ```
53
56
 
54
57
  Creates a worktree exactly like `wt create`, then auto-starts your agent
55
- (default `claude --permission-mode plan`) in Zed's integrated terminal —
56
- pre-filled with your prompt and left interactive for you to take over.
58
+ (default `claude`, run with `--permission-mode default`) in Zed's integrated
59
+ terminal — pre-filled with your prompt and left interactive for you to take over.
57
60
 
58
- **Available modes** (`--mode`, defaults to `plan`):
61
+ **Available modes** (`--mode`, defaults to `default`; change the default with
62
+ the `agent_mode` config key):
59
63
 
60
- - `default` — Standard interactive mode with approval for each action
64
+ - `default` — Standard interactive mode with approval for each action (default)
61
65
  - `acceptEdits` — Allow file changes but keep command execution controlled
62
- - `plan` — Architecture-first mode with no surprise mutations (default)
66
+ - `plan` — Architecture-first mode with no surprise mutations
63
67
  - `auto` — Claude's safety model makes decisions instead of prompting
64
68
  - `dontAsk` — Minimal interruptions in trusted environments
65
69
  - `bypassPermissions` — Skip all permission checks (dangerous, CI/sandbox only)
@@ -139,8 +143,16 @@ and force-confirming when git refuses (submodules or uncommitted changes), just
139
143
  like a manual `D` delete. The branch itself stays; only the worktree is removed.
140
144
  Your `teardown_commands` run before each removal.
141
145
 
142
- Merge detection is patch-id based (via `git cherry`), so a single-commit branch
143
- **squash-merged** through a PR is still detected. `wt prune` best-effort fetches
146
+ Merge detection is tiered. Patch-id matches (via `git cherry`) catch a
147
+ single-commit branch **squash-merged** through a PR, offline. For the ambiguous
148
+ case — the branch tip is an ancestor of base but 0 commits ahead, which both a
149
+ **fast-forward / merge-commit** merge and a worktree holding only *uncommitted*
150
+ work produce — it consults the **forge**: a merged PR/MR (via `gh` for GitHub or
151
+ `glab` for GitLab, including self-hosted, auto-detected from the remote) is the
152
+ only reliable signal, so a branch with unmerged work-in-progress is never
153
+ mistaken for merged. If no forge CLI is available (or you're offline) such
154
+ branches are simply left alone. A worktree still sitting exactly on the base
155
+ commit is never offered. `wt prune` best-effort fetches
144
156
  the remote first; if the base ref can't be resolved (offline, missing), it
145
157
  removes nothing. The TUI exposes the same action under the `P` key. Works in
146
158
  repo mode and across all registered repos in global mode (each against its own
@@ -159,7 +171,8 @@ Edit with `wt config` (`wt config --path` prints the file location —
159
171
  | `worktree_path` | `"../"` | Where worktrees are placed (relative to repo) |
160
172
  | `setup_commands` | `[]` | Commands to run in new worktrees |
161
173
  | `teardown_commands` | `[]` | Commands to run in a worktree just before it is deleted (e.g. `["docker compose down -v"]`) |
162
- | `agent_command` | `"claude --permission-mode plan"` | Base command; `--permission-mode` replaced by `--mode` option, then prompt appended |
174
+ | `agent_command` | `"claude"` | Base command; `--permission-mode <mode>` injected, then prompt appended |
175
+ | `agent_mode` | `"default"` | Default permission mode for `wt agent` (overridden by `--mode`) |
163
176
  | `agent_trigger_chord` | `"ctrl-shift-cmd-c"` | Zed keymap chord `wt agent` installs and presses |
164
177
  | `auto_refresh_minutes`| `5` | How often the interactive list re-fetches worktrees (shows a "last refreshed" header); `0` disables it |
165
178
  | `repo_overrides` | `{}` | Per-repo overrides for any key above |
package/SKILL.md CHANGED
@@ -66,11 +66,12 @@ wt agent feature/fix 'Fix the bug in payment processing' --mode auto
66
66
  wt agent refactor/api 'Refactor the API layer' --mode default
67
67
  ```
68
68
 
69
- The `--mode` flag sets Claude Code's permission mode (defaults to `plan`):
69
+ The `--mode` flag sets Claude Code's permission mode (defaults to `default`;
70
+ change the default with the `agent_mode` config key):
70
71
 
71
- - `default` — Standard interactive mode with approval for each action
72
+ - `default` — Standard interactive mode with approval for each action (default)
72
73
  - `acceptEdits` — Allow file changes but keep command execution controlled
73
- - `plan` — Architecture-first mode with no surprise mutations (default)
74
+ - `plan` — Architecture-first mode with no surprise mutations
74
75
  - `auto` — Claude's safety model makes decisions instead of prompting
75
76
  - `dontAsk` — Minimal interruptions in trusted environments
76
77
  - `bypassPermissions` — Skip all permission checks (dangerous, CI/sandbox only)
@@ -110,9 +111,17 @@ only the worktree is removed.
110
111
  wt prune # review and remove merged worktrees, one prompt per branch
111
112
  ```
112
113
 
113
- Merge detection is patch-id based (via `git cherry`), so a single-commit branch
114
- that was **squash-merged** through a PR is still recognized as merged. It also
115
- best-effort fetches the remote first so detection sees up-to-date refs; if the
114
+ Merge detection works in tiers. A branch whose diff already exists in base by
115
+ patch id (via `git cherry`, so a single-commit branch **squash-merged** through a
116
+ PR is recognized offline) is merged. For the ambiguous case the branch tip is
117
+ an ancestor of base but 0 commits ahead, which a **fast-forward / merge-commit**
118
+ merge and a worktree holding only *uncommitted* work both produce — it consults
119
+ the **forge**: a merged PR/MR (via `gh` for GitHub, `glab` for GitLab incl.
120
+ self-hosted, auto-detected from the remote) is the only reliable signal. If the
121
+ forge can't answer (CLI missing, offline, branch unpushed, no merged PR/MR) the
122
+ branch is left alone. A worktree still sitting exactly on the base commit is
123
+ never offered. `wt prune` also best-effort fetches the remote first so detection
124
+ sees up-to-date refs; if the
116
125
  base ref can't be resolved (e.g. offline), nothing is removed. Works in repo
117
126
  mode (current repo) and global mode (all registered repos, each against its own
118
127
  `base_branch`). The TUI exposes the same action under the `p` key.
@@ -144,7 +153,8 @@ Config is stored as JSON. Get the path with `wt config --path`.
144
153
  | `teardown_commands` | `string[]` | `[]` | Commands to run in a worktree just before it is deleted (e.g. `["docker compose down -v"]`); on failure you are prompted whether to delete anyway |
145
154
  | `ide` | `string` | `"zed"` | IDE command to open worktrees with |
146
155
  | `ide_open_args` | `string[]` | `["-n"]` | Arguments passed to the IDE command |
147
- | `agent_command` | `string` | `"claude --permission-mode plan"` | Base command `wt agent` runs in Zed; any `--permission-mode` flag is replaced by the `--mode` option (defaults to `plan`), then `<plan_prompt>` is appended single-quoted |
156
+ | `agent_command` | `string` | `"claude"` | Base command `wt agent` runs in Zed; `--permission-mode <mode>` is injected (any existing one replaced), then `<plan_prompt>` is appended single-quoted |
157
+ | `agent_mode` | `string` | `"default"` | Default Claude Code permission mode for `wt agent`; the `--mode` flag overrides it. One of `default`, `acceptEdits`, `plan`, `auto`, `dontAsk`, `bypassPermissions` |
148
158
  | `agent_trigger_chord` | `string` | `"ctrl-shift-cmd-c"` | Zed keymap chord `wt agent` installs/presses to spawn the agent task |
149
159
  | `auto_refresh_minutes`| `number` | `5` | How often the interactive list (`wt`) re-fetches worktrees and updates the "last refreshed" header; `0` disables auto-refresh |
150
160
  | `repos` | `string[]` | `[]` | Registered repo paths (auto-populated on first use) |
@@ -152,7 +162,7 @@ Config is stored as JSON. Get the path with `wt config --path`.
152
162
 
153
163
  ### Per-repo overrides
154
164
 
155
- Override any field (`worktree_path`, `base_branch`, `setup_commands`, `teardown_commands`, `ide`, `ide_open_args`, `agent_command`, `agent_trigger_chord`, `auto_refresh_minutes`) for a specific repo:
165
+ Override any field (`worktree_path`, `base_branch`, `setup_commands`, `teardown_commands`, `ide`, `ide_open_args`, `agent_command`, `agent_mode`, `agent_trigger_chord`, `auto_refresh_minutes`) for a specific repo:
156
166
 
157
167
  ```json
158
168
  {
@@ -3,9 +3,9 @@ import {
3
3
  openConfiguredIde,
4
4
  prepareWorktree,
5
5
  promptExistingWorktree
6
- } from "./chunk-Q6NNNYDJ.js";
7
- import "./chunk-YXA6CZ2L.js";
8
- import "./chunk-QVYSEMSL.js";
6
+ } from "./chunk-DA4PICTI.js";
7
+ import "./chunk-HHCUDNDE.js";
8
+ import "./chunk-OUWQ6NIV.js";
9
9
 
10
10
  // src/commands/agent.ts
11
11
  import * as clack from "@clack/prompts";
@@ -424,19 +424,30 @@ var VALID_MODES = [
424
424
  "dontAsk",
425
425
  "bypassPermissions"
426
426
  ];
427
+ var isValidMode = (mode) => VALID_MODES.includes(mode);
427
428
  var CLEANUP_DELAY_MS = 2e4;
428
429
  var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
429
430
  async function createAgentWorktree(branch, planPrompt, options = {}) {
430
- const mode = options.mode ?? "plan";
431
- if (!VALID_MODES.includes(mode)) {
431
+ if (options.mode !== void 0 && !isValidMode(options.mode)) {
432
432
  console.error(
433
- pc.red(`Invalid mode "${mode}". Valid modes: ${VALID_MODES.join(", ")}`)
433
+ pc.red(
434
+ `Invalid mode "${options.mode}". Valid modes: ${VALID_MODES.join(", ")}`
435
+ )
434
436
  );
435
437
  process.exit(1);
436
438
  }
437
439
  const prepared = await prepareWorktree(branch, options);
438
440
  if (!prepared) return;
439
441
  const { status, config, worktreePath } = prepared;
442
+ let mode = options.mode ?? config.agent_mode ?? "default";
443
+ if (!isValidMode(mode)) {
444
+ console.warn(
445
+ pc.yellow(
446
+ `\u26A0 Invalid agent_mode "${mode}" in config; using "default". Valid modes: ${VALID_MODES.join(", ")}`
447
+ )
448
+ );
449
+ mode = "default";
450
+ }
440
451
  if (status === "exists") {
441
452
  const prompt = options.existingWorktreePrompt ?? promptExistingWorktree;
442
453
  const action = await prompt(worktreePath, { allowAgent: true });
@@ -14,12 +14,12 @@ import {
14
14
  runInteractiveList,
15
15
  runRepoPicker,
16
16
  runWizard
17
- } from "./chunk-YXA6CZ2L.js";
17
+ } from "./chunk-HHCUDNDE.js";
18
18
  import {
19
19
  createStore,
20
20
  getEffectiveConfig,
21
21
  getGlobalConfig
22
- } from "./chunk-QVYSEMSL.js";
22
+ } from "./chunk-OUWQ6NIV.js";
23
23
 
24
24
  // src/commands/list.ts
25
25
  import * as clack from "@clack/prompts";
@@ -96,14 +96,13 @@ async function runList(options = {}) {
96
96
  if (!await runWizard(steps)) return;
97
97
  if (state.pickedRepo === void 0 || state.branch === void 0)
98
98
  return;
99
- const { createWorktree } = await import("./create-DYM7QWI5.js");
99
+ const { createWorktree } = await import("./create-7MZPUETI.js");
100
100
  await createWorktree(state.branch, { cwd: state.pickedRepo, store });
101
101
  },
102
102
  onAgent: async () => {
103
- const { createAgentWorktree, VALID_MODES } = await import("./agent-575QKWIG.js");
103
+ const { createAgentWorktree, VALID_MODES } = await import("./agent-A5EP5ZPW.js");
104
104
  const state = {
105
- pickedRepo: repoRoot ?? void 0,
106
- mode: "plan"
105
+ pickedRepo: repoRoot ?? void 0
107
106
  };
108
107
  const steps = buildWorktreeSteps(repoRoot, store, state);
109
108
  steps.push(async () => {
@@ -117,9 +116,10 @@ async function runList(options = {}) {
117
116
  return true;
118
117
  });
119
118
  steps.push(async () => {
119
+ const configuredMode = state.pickedRepo ? getEffectiveConfig(state.pickedRepo, store).agent_mode : void 0;
120
120
  const chosen = await clack.select({
121
121
  message: "Permission mode:",
122
- initialValue: state.mode,
122
+ initialValue: state.mode ?? configuredMode,
123
123
  options: VALID_MODES.map((m) => ({ value: String(m), label: m }))
124
124
  });
125
125
  if (clack.isCancel(chosen)) return false;
@@ -13,11 +13,11 @@ import {
13
13
  runCommands,
14
14
  runRepoPicker,
15
15
  setUpstreamTracking
16
- } from "./chunk-YXA6CZ2L.js";
16
+ } from "./chunk-HHCUDNDE.js";
17
17
  import {
18
18
  createStore,
19
19
  getEffectiveConfig
20
- } from "./chunk-QVYSEMSL.js";
20
+ } from "./chunk-OUWQ6NIV.js";
21
21
 
22
22
  // src/commands/create.ts
23
23
  import { existsSync } from "fs";
@@ -2,16 +2,89 @@
2
2
  import {
3
3
  createStore,
4
4
  getGlobalConfig
5
- } from "./chunk-QVYSEMSL.js";
5
+ } from "./chunk-OUWQ6NIV.js";
6
6
 
7
7
  // src/lib/git.ts
8
- import { execFileSync } from "child_process";
8
+ import { execFileSync as execFileSync2 } from "child_process";
9
9
  import { existsSync, realpathSync, rmSync } from "fs";
10
10
  import path from "path";
11
+
12
+ // src/lib/forge.ts
13
+ import { execFileSync } from "child_process";
14
+ function parseRemoteHost(url) {
15
+ const u = url.trim();
16
+ if (!u) return null;
17
+ const scp = u.match(/^(?:[^@/]+@)?([^:/]+):(?!\/\/)/);
18
+ if (scp) return scp[1].toLowerCase();
19
+ const schemed = u.match(/^[a-z][a-z0-9+.-]*:\/\/(?:[^@/]+@)?([^:/]+)/i);
20
+ if (schemed) return schemed[1].toLowerCase();
21
+ return null;
22
+ }
23
+ function selectForgeTool(host) {
24
+ if (!host) return null;
25
+ if (host === "github.com" || host.endsWith(".github.com")) return "gh";
26
+ if (host.includes("github")) return "gh";
27
+ return "glab";
28
+ }
29
+ function buildMergedQuery(tool, branch) {
30
+ if (tool === "gh") {
31
+ return [
32
+ "pr",
33
+ "list",
34
+ "--head",
35
+ branch,
36
+ "--state",
37
+ "merged",
38
+ "--json",
39
+ "number"
40
+ ];
41
+ }
42
+ return ["mr", "list", "--merged", "--source-branch", branch, "-F", "json"];
43
+ }
44
+ function parseMergedResult(stdout) {
45
+ try {
46
+ const data = JSON.parse(stdout);
47
+ return Array.isArray(data) && data.length > 0;
48
+ } catch {
49
+ return false;
50
+ }
51
+ }
52
+ var defaultRunner = {
53
+ remoteUrl(repoRoot, remote) {
54
+ return execFileSync("git", ["remote", "get-url", remote], {
55
+ cwd: repoRoot,
56
+ encoding: "utf8",
57
+ stdio: "pipe"
58
+ }).trim();
59
+ },
60
+ query(repoRoot, tool, args) {
61
+ return execFileSync(tool, args, {
62
+ cwd: repoRoot,
63
+ encoding: "utf8",
64
+ stdio: "pipe",
65
+ timeout: 15e3
66
+ });
67
+ }
68
+ };
69
+ function hasMergedPullRequest(repoRoot, branch, remote = "origin", runner = defaultRunner) {
70
+ try {
71
+ const tool = selectForgeTool(
72
+ parseRemoteHost(runner.remoteUrl(repoRoot, remote))
73
+ );
74
+ if (!tool) return false;
75
+ return parseMergedResult(
76
+ runner.query(repoRoot, tool, buildMergedQuery(tool, branch))
77
+ );
78
+ } catch {
79
+ return false;
80
+ }
81
+ }
82
+
83
+ // src/lib/git.ts
11
84
  function getRepoRoot(cwd = process.cwd()) {
12
85
  try {
13
86
  const realCwd = realpathSync(cwd);
14
- const output = execFileSync("git", ["worktree", "list", "--porcelain"], {
87
+ const output = execFileSync2("git", ["worktree", "list", "--porcelain"], {
15
88
  cwd: realCwd,
16
89
  encoding: "utf8",
17
90
  stdio: "pipe"
@@ -25,7 +98,7 @@ function getRepoRoot(cwd = process.cwd()) {
25
98
  function listWorktrees(repoRoot, cwd = process.cwd()) {
26
99
  const realRepoRoot = realpathSync(repoRoot);
27
100
  const realCwd = realpathSync(cwd);
28
- const output = execFileSync("git", ["worktree", "list", "--porcelain"], {
101
+ const output = execFileSync2("git", ["worktree", "list", "--porcelain"], {
29
102
  cwd: realRepoRoot,
30
103
  encoding: "utf8"
31
104
  });
@@ -35,7 +108,7 @@ function listWorktrees(repoRoot, cwd = process.cwd()) {
35
108
  ).join('; echo "---SEP---"; ');
36
109
  let commits = [];
37
110
  try {
38
- const batchOutput = execFileSync("sh", ["-c", script], {
111
+ const batchOutput = execFileSync2("sh", ["-c", script], {
39
112
  encoding: "utf8",
40
113
  timeout: 8e3
41
114
  });
@@ -65,7 +138,7 @@ function parseWorktreeList(output, repoRoot, cwd) {
65
138
  }
66
139
  function addWorktree(repoRoot, worktreePath, branch, baseBranch) {
67
140
  if (baseBranch) {
68
- execFileSync(
141
+ execFileSync2(
69
142
  "git",
70
143
  ["worktree", "add", "-b", branch, worktreePath, baseBranch],
71
144
  {
@@ -73,7 +146,7 @@ function addWorktree(repoRoot, worktreePath, branch, baseBranch) {
73
146
  }
74
147
  );
75
148
  } else {
76
- execFileSync("git", ["worktree", "add", worktreePath, branch], {
149
+ execFileSync2("git", ["worktree", "add", worktreePath, branch], {
77
150
  cwd: repoRoot
78
151
  });
79
152
  }
@@ -90,7 +163,7 @@ function removeWorktree(repoRoot, worktreePath, force = false) {
90
163
  throw new Error("Refusing to remove the main worktree");
91
164
  }
92
165
  try {
93
- execFileSync(
166
+ execFileSync2(
94
167
  "git",
95
168
  ["worktree", "remove", ...force ? ["--force"] : [], worktreePath],
96
169
  { cwd: repoRoot, stdio: "pipe" }
@@ -100,7 +173,7 @@ function removeWorktree(repoRoot, worktreePath, force = false) {
100
173
  if (existsSync(worktreePath)) {
101
174
  rmSync(worktreePath, { recursive: true, force: true });
102
175
  }
103
- execFileSync("git", ["worktree", "prune"], {
176
+ execFileSync2("git", ["worktree", "prune"], {
104
177
  cwd: repoRoot,
105
178
  stdio: "pipe"
106
179
  });
@@ -108,7 +181,7 @@ function removeWorktree(repoRoot, worktreePath, force = false) {
108
181
  }
109
182
  function listWorktreeDirtyFiles(worktreePath) {
110
183
  try {
111
- const out = execFileSync("git", ["status", "--short"], {
184
+ const out = execFileSync2("git", ["status", "--short"], {
112
185
  cwd: worktreePath,
113
186
  encoding: "utf8"
114
187
  });
@@ -119,12 +192,12 @@ function listWorktreeDirtyFiles(worktreePath) {
119
192
  }
120
193
  function branchExists(repoRoot, branch) {
121
194
  try {
122
- const local = execFileSync("git", ["branch", "--list", branch], {
195
+ const local = execFileSync2("git", ["branch", "--list", branch], {
123
196
  cwd: repoRoot,
124
197
  encoding: "utf8"
125
198
  }).trim();
126
199
  if (local) return true;
127
- const remote = execFileSync(
200
+ const remote = execFileSync2(
128
201
  "git",
129
202
  ["ls-remote", "--heads", "origin", branch],
130
203
  {
@@ -138,22 +211,45 @@ function branchExists(repoRoot, branch) {
138
211
  return false;
139
212
  }
140
213
  }
141
- function isBranchMerged(repoRoot, branch, baseBranch) {
214
+ function isAncestor(repoRoot, ancestor, descendant) {
142
215
  try {
143
- const out = execFileSync("git", ["cherry", baseBranch, branch], {
216
+ execFileSync2("git", ["merge-base", "--is-ancestor", ancestor, descendant], {
217
+ cwd: repoRoot,
218
+ stdio: "pipe"
219
+ });
220
+ return true;
221
+ } catch {
222
+ return false;
223
+ }
224
+ }
225
+ function isBranchMerged(repoRoot, branch, baseBranch, forgeCheck = hasMergedPullRequest) {
226
+ try {
227
+ const revParse = (ref) => execFileSync2("git", ["rev-parse", ref], {
228
+ cwd: repoRoot,
229
+ encoding: "utf8",
230
+ stdio: "pipe"
231
+ }).trim();
232
+ const baseTip = revParse(baseBranch);
233
+ const tip = revParse(branch);
234
+ const out = execFileSync2("git", ["cherry", baseBranch, branch], {
144
235
  cwd: repoRoot,
145
236
  encoding: "utf8",
146
237
  stdio: "pipe"
147
238
  });
148
239
  const lines = out.split("\n").filter((l) => l.trim().length > 0);
149
- return lines.length > 0 && lines.every((l) => l.startsWith("-"));
240
+ if (lines.length > 0 && lines.every((l) => l.startsWith("-"))) return true;
241
+ if (tip !== baseTip && isAncestor(repoRoot, branch, baseBranch)) {
242
+ const remote = baseBranch.includes("/") ? baseBranch.split("/", 1)[0] : "origin";
243
+ return forgeCheck(repoRoot, branch, remote);
244
+ }
245
+ return false;
150
246
  } catch {
151
247
  return false;
152
248
  }
153
249
  }
154
250
  function setUpstreamTracking(worktreePath, branch, remote = "origin") {
155
251
  try {
156
- execFileSync(
252
+ execFileSync2(
157
253
  "git",
158
254
  ["branch", "--set-upstream-to", `${remote}/${branch}`, branch],
159
255
  { cwd: worktreePath, stdio: "pipe" }
@@ -162,7 +258,7 @@ function setUpstreamTracking(worktreePath, branch, remote = "origin") {
162
258
  }
163
259
  }
164
260
  function fetchRemote(repoRoot, remote = "origin") {
165
- execFileSync("git", ["fetch", remote], {
261
+ execFileSync2("git", ["fetch", remote], {
166
262
  cwd: repoRoot,
167
263
  stdio: "pipe",
168
264
  timeout: 3e4
@@ -68,9 +68,10 @@ var DEFAULT_CONFIG = {
68
68
  teardown_commands: [],
69
69
  ide: "zed",
70
70
  ide_open_args: ["-n"],
71
- agent_command: "claude --permission-mode plan",
71
+ agent_command: "claude",
72
72
  agent_trigger_chord: "ctrl-shift-cmd-c",
73
73
  auto_refresh_minutes: 5,
74
+ agent_mode: "default",
74
75
  repos: [],
75
76
  repo_overrides: {}
76
77
  };
package/dist/cli.js CHANGED
@@ -3,41 +3,40 @@
3
3
  // src/cli.ts
4
4
  import { Command } from "commander";
5
5
  var program = new Command();
6
- program.name("wt").description("Git worktree manager").version("0.5.0-pr22.gbb5b3fa").action(async () => {
7
- const { runList } = await import("./list-XRECVEUI.js");
6
+ program.name("wt").description("Git worktree manager").version("0.5.0-pr24.g2e0b1ed").action(async () => {
7
+ const { runList } = await import("./list-VACQ5XDH.js");
8
8
  await runList();
9
9
  });
10
10
  program.command("create [branch]").description("Create a new worktree").action(async (branch) => {
11
- const { createWorktree } = await import("./create-DYM7QWI5.js");
11
+ const { createWorktree } = await import("./create-7MZPUETI.js");
12
12
  await createWorktree(branch);
13
13
  });
14
14
  program.command("agent <branch> <plan_prompt>").description("Create a worktree and auto-start an AI agent in Zed (macOS)").option(
15
15
  "--mode <mode>",
16
- "Claude Code permission mode (default, plan, auto, etc.)",
17
- "plan"
16
+ "Claude Code permission mode (default, plan, auto, etc.); overrides the configured agent_mode"
18
17
  ).action(
19
18
  async (branch, planPrompt, options) => {
20
- const { createAgentWorktree } = await import("./agent-575QKWIG.js");
19
+ const { createAgentWorktree } = await import("./agent-A5EP5ZPW.js");
21
20
  await createAgentWorktree(branch, planPrompt, { mode: options.mode });
22
21
  }
23
22
  );
24
23
  program.command("prune").description(
25
24
  "Remove worktrees whose branch has been merged into the base branch"
26
25
  ).action(async () => {
27
- const { runPrune } = await import("./prune-LOO5KMBU.js");
26
+ const { runPrune } = await import("./prune-ZKL3TFIH.js");
28
27
  await runPrune();
29
28
  });
30
29
  program.command("config").description("Open the config file in $EDITOR").option("--path", "Print the config file path and exit").action(async (options) => {
31
30
  if (options.path) {
32
- const { printConfigPath } = await import("./config-QLWPW2UZ.js");
31
+ const { printConfigPath } = await import("./config-QSYG3JDC.js");
33
32
  printConfigPath();
34
33
  } else {
35
- const { openConfig } = await import("./config-QLWPW2UZ.js");
34
+ const { openConfig } = await import("./config-QSYG3JDC.js");
36
35
  openConfig();
37
36
  }
38
37
  });
39
38
  program.command("skill").description("Print the wt skill file to stdout").action(async () => {
40
- const { printSkill } = await import("./skill-5JFC6Q33.js");
39
+ const { printSkill } = await import("./skill-T5VOI4ZB.js");
41
40
  printSkill();
42
41
  });
43
42
  await program.parseAsync(process.argv);
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getConfigFilePath
4
- } from "./chunk-QVYSEMSL.js";
4
+ } from "./chunk-OUWQ6NIV.js";
5
5
 
6
6
  // src/commands/config.ts
7
7
  import { spawn } from "child_process";
@@ -4,9 +4,9 @@ import {
4
4
  openConfiguredIde,
5
5
  prepareWorktree,
6
6
  promptExistingWorktree
7
- } from "./chunk-Q6NNNYDJ.js";
8
- import "./chunk-YXA6CZ2L.js";
9
- import "./chunk-QVYSEMSL.js";
7
+ } from "./chunk-DA4PICTI.js";
8
+ import "./chunk-HHCUDNDE.js";
9
+ import "./chunk-OUWQ6NIV.js";
10
10
  export {
11
11
  createWorktree,
12
12
  openConfiguredIde,
@@ -6,9 +6,9 @@ import {
6
6
  runList,
7
7
  selectWipeCandidates,
8
8
  wipeWorktrees
9
- } from "./chunk-QHNOUX63.js";
10
- import "./chunk-YXA6CZ2L.js";
11
- import "./chunk-QVYSEMSL.js";
9
+ } from "./chunk-C4MR7ZNK.js";
10
+ import "./chunk-HHCUDNDE.js";
11
+ import "./chunk-OUWQ6NIV.js";
12
12
  export {
13
13
  buildMergedPredicate,
14
14
  deleteWorktree,
@@ -2,11 +2,11 @@
2
2
  import {
3
3
  prepareListItems,
4
4
  wipeWorktrees
5
- } from "./chunk-QHNOUX63.js";
6
- import "./chunk-YXA6CZ2L.js";
5
+ } from "./chunk-C4MR7ZNK.js";
6
+ import "./chunk-HHCUDNDE.js";
7
7
  import {
8
8
  createStore
9
- } from "./chunk-QVYSEMSL.js";
9
+ } from "./chunk-OUWQ6NIV.js";
10
10
 
11
11
  // src/commands/prune.ts
12
12
  import pc from "picocolors";
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/commands/skill.ts
4
+ function printSkill() {
5
+ console.log('---\nname: wt-worktree-manager\ndescription: Use the wt CLI to create, browse, open, and delete git worktrees across repos. Use when the user asks to manage worktrees, create isolated branches, or configure worktree defaults.\n---\n\n# wt \u2014 Git Worktree Manager\n\n`wt` is a CLI for managing git worktrees. It provides an interactive TUI to browse, create, open in your IDE, and delete worktrees across multiple repos.\n\n## Commands\n\n### `wt` (no subcommand)\n\nLaunch the interactive TUI. Shows worktrees for the current repo (repo mode) or all registered repos (global mode, when run outside a repo).\n\n**Keybindings in the TUI:**\n\n- Arrow keys \u2014 navigate\n- `Enter` \u2014 open worktree in IDE (exits the TUI)\n- `D` \u2014 delete worktree (the main worktree is tagged `(main)` and cannot be deleted \u2014 only linked worktrees can)\n- `P` \u2014 prune all merged worktrees (per-branch confirmation)\n- `C` \u2014 create a new worktree (works in both repo and global mode)\n- `A` \u2014 create a worktree and start an AI agent in it (works in both modes)\n- type to search \xB7 `Backspace` \u2014 edit search\n- `Q` / `Esc` \u2014 quit\n\n`C` and `A` are step-by-step wizards. In global mode (run from outside a repo /\n"home") they start by prompting for the repo (picker), then the branch; in repo\nmode the repo is fixed so they start at the branch. `A` then adds two more\nsteps:\n\n- `C` \u2014 **worktree (repo \u2192 branch)**\n- `A` \u2014 **worktree (repo \u2192 branch) \u2192 plan prompt \u2192 permission mode**\n\nPressing `Esc` at any step goes back to the previous step (your earlier answers\nare preserved); pressing `Esc` on the first step returns to the list.\n\nAfter a create or agent action the TUI **refreshes and stays open** on the list\n(your search and cursor are preserved) rather than exiting \u2014 only `Enter` (open)\nand `Q`/`Esc` exit.\n\nBecause `a`/`A`, `c`/`C`, `d`/`D`, and `p`/`P` are reserved as command keys,\nthose letters can\'t be typed into the search box.\n\n### `wt create [branch]`\n\nCreate a new worktree. If `branch` is omitted, prompts interactively.\n\nThe worktree is created as a sibling directory to the repo: `<parent>/<repo-name>-<branch-name>`.\n\nAfter creation, `wt` runs any configured `setup_commands` and opens the worktree in your IDE.\n\nIf the worktree path already exists, `wt create` doesn\'t error \u2014 it prompts you\nto **open it in the IDE** or **quit**. (In a non-interactive shell it errors\nwith a non-zero exit instead of prompting.)\n\n### `wt agent <branch> <plan_prompt> [--mode <mode>]`\n\nCreate a worktree (same as `wt create`) **and** auto-start an AI agent in Zed\'s\nintegrated terminal, pre-filled with `<plan_prompt>` and left interactive for\nyou to take over.\n\n```bash\nwt agent feature/login \'Read the codebase, then propose a plan for login.\'\nwt agent feature/fix \'Fix the bug in payment processing\' --mode auto\nwt agent refactor/api \'Refactor the API layer\' --mode default\n```\n\nThe `--mode` flag sets Claude Code\'s permission mode (defaults to `default`;\nchange the default with the `agent_mode` config key):\n\n- `default` \u2014 Standard interactive mode with approval for each action (default)\n- `acceptEdits` \u2014 Allow file changes but keep command execution controlled\n- `plan` \u2014 Architecture-first mode with no surprise mutations\n- `auto` \u2014 Claude\'s safety model makes decisions instead of prompting\n- `dontAsk` \u2014 Minimal interruptions in trusted environments\n- `bypassPermissions` \u2014 Skip all permission checks (dangerous, CI/sandbox only)\n\nIt writes a temporary `.zed/tasks.json` running\n`<agent_command> --permission-mode <mode> \'<plan_prompt>\'`, ensures a global Zed keymap chord\n(`agent_trigger_chord`) spawns that task, opens Zed, presses the chord via\n`osascript`, then removes the temporary task so the repo is left clean.\n\n**macOS + Zed only.** Requires Accessibility permission for the app that runs\n`wt` (Zed itself, when run from its integrated terminal). If it isn\'t granted,\n`wt agent` opens the _Privacy & Security \u2192 Accessibility_ settings pane and waits\nfor you to grant it and confirm, then retries automatically. On other platforms\n(or when `ide` is not `zed`) the worktree is still created and opened, but the\nagent is not auto-started.\n\nOver SSH it still works, provided the same user has an active graphical login on\nthe Mac: the keystroke is run inside the GUI session via Launch Services\n(`open -a Terminal` briefly flashes a Terminal window). Grant Accessibility to\nTerminal (not Zed) the first time. With no one logged in graphically there is\nnothing to drive, so it falls back to the manual "press the chord in Zed"\nmessage.\n\nIf the worktree path already exists, `wt agent` prompts you to **open it in the\nIDE**, **open it and start the agent**, or **quit** \u2014 instead of erroring. (In a\nnon-interactive shell it errors with a non-zero exit instead of prompting.)\n\n### `wt prune`\n\nRemove every worktree whose branch has already been merged into the base\nbranch (`base_branch`, default `origin/main`). Each candidate is confirmed\nindividually \u2014 and force-confirmed when git refuses (submodules / uncommitted\nchanges), exactly like a manual `d` delete. The branch itself is left intact;\nonly the worktree is removed.\n\n```bash\nwt prune # review and remove merged worktrees, one prompt per branch\n```\n\nMerge detection works in tiers. A branch whose diff already exists in base by\npatch id (via `git cherry`, so a single-commit branch **squash-merged** through a\nPR is recognized offline) is merged. For the ambiguous case \u2014 the branch tip is\nan ancestor of base but 0 commits ahead, which a **fast-forward / merge-commit**\nmerge and a worktree holding only *uncommitted* work both produce \u2014 it consults\nthe **forge**: a merged PR/MR (via `gh` for GitHub, `glab` for GitLab incl.\nself-hosted, auto-detected from the remote) is the only reliable signal. If the\nforge can\'t answer (CLI missing, offline, branch unpushed, no merged PR/MR) the\nbranch is left alone. A worktree still sitting exactly on the base commit is\nnever offered. `wt prune` also best-effort fetches the remote first so detection\nsees up-to-date refs; if the\nbase ref can\'t be resolved (e.g. offline), nothing is removed. Works in repo\nmode (current repo) and global mode (all registered repos, each against its own\n`base_branch`). The TUI exposes the same action under the `p` key.\n\n### `wt config`\n\nOpen the global config file in `$EDITOR` (defaults to `nano`).\n\n```bash\nwt config # open in editor\nwt config --path # print config file path only\n```\n\n### `wt skill`\n\nPrint this skill file to stdout. Useful for piping to agents or copying to a project.\n\n## Configuration\n\nConfig is stored as JSON. Get the path with `wt config --path`.\n\n### Schema\n\n| Key | Type | Default | Description |\n| --------------------- | ---------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `worktree_path` | `string` | `"../"` | Where to place new worktrees, relative to the repo root |\n| `base_branch` | `string` | `"origin/main"` | Branch to base new worktrees on |\n| `setup_commands` | `string[]` | `[]` | Commands to run in a new worktree after creation (e.g. `["npm install"]`) |\n| `teardown_commands` | `string[]` | `[]` | Commands to run in a worktree just before it is deleted (e.g. `["docker compose down -v"]`); on failure you are prompted whether to delete anyway |\n| `ide` | `string` | `"zed"` | IDE command to open worktrees with |\n| `ide_open_args` | `string[]` | `["-n"]` | Arguments passed to the IDE command |\n| `agent_command` | `string` | `"claude"` | Base command `wt agent` runs in Zed; `--permission-mode <mode>` is injected (any existing one replaced), then `<plan_prompt>` is appended single-quoted |\n| `agent_mode` | `string` | `"default"` | Default Claude Code permission mode for `wt agent`; the `--mode` flag overrides it. One of `default`, `acceptEdits`, `plan`, `auto`, `dontAsk`, `bypassPermissions` |\n| `agent_trigger_chord` | `string` | `"ctrl-shift-cmd-c"` | Zed keymap chord `wt agent` installs/presses to spawn the agent task |\n| `auto_refresh_minutes`| `number` | `5` | How often the interactive list (`wt`) re-fetches worktrees and updates the "last refreshed" header; `0` disables auto-refresh |\n| `repos` | `string[]` | `[]` | Registered repo paths (auto-populated on first use) |\n| `repo_overrides` | `object` | `{}` | Per-repo config overrides (see below) |\n\n### Per-repo overrides\n\nOverride any field (`worktree_path`, `base_branch`, `setup_commands`, `teardown_commands`, `ide`, `ide_open_args`, `agent_command`, `agent_mode`, `agent_trigger_chord`, `auto_refresh_minutes`) for a specific repo:\n\n```json\n{\n "base_branch": "origin/main",\n "ide": "zed",\n "repo_overrides": {\n "/path/to/my-repo": {\n "base_branch": "origin/develop",\n "setup_commands": ["npm install", "npm run build"]\n }\n }\n}\n```\n\n## Common workflows\n\n### Create a worktree for a new feature\n\n```bash\ncd /path/to/repo\nwt create feature/my-branch\n```\n\n### Configure setup commands for a repo\n\n```bash\nwt config\n# Then add to the JSON:\n# "repo_overrides": {\n# "/path/to/repo": {\n# "setup_commands": ["npm install"]\n# }\n# }\n```\n\n### Browse all worktrees across repos\n\nRun `wt` from any directory outside a git repo to see worktrees from all registered repos.\n');
6
+ }
7
+ export {
8
+ printSkill
9
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cestoliv/wt",
3
- "version": "0.5.0-pr22.gbb5b3fa",
3
+ "version": "0.5.0-pr24.g2e0b1ed",
4
4
  "description": "Fast, interactive TUI to browse, create, open, and delete git worktrees across repos.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/commands/skill.ts
4
- function printSkill() {
5
- console.log('---\nname: wt-worktree-manager\ndescription: Use the wt CLI to create, browse, open, and delete git worktrees across repos. Use when the user asks to manage worktrees, create isolated branches, or configure worktree defaults.\n---\n\n# wt \u2014 Git Worktree Manager\n\n`wt` is a CLI for managing git worktrees. It provides an interactive TUI to browse, create, open in your IDE, and delete worktrees across multiple repos.\n\n## Commands\n\n### `wt` (no subcommand)\n\nLaunch the interactive TUI. Shows worktrees for the current repo (repo mode) or all registered repos (global mode, when run outside a repo).\n\n**Keybindings in the TUI:**\n\n- Arrow keys \u2014 navigate\n- `Enter` \u2014 open worktree in IDE (exits the TUI)\n- `D` \u2014 delete worktree (the main worktree is tagged `(main)` and cannot be deleted \u2014 only linked worktrees can)\n- `P` \u2014 prune all merged worktrees (per-branch confirmation)\n- `C` \u2014 create a new worktree (works in both repo and global mode)\n- `A` \u2014 create a worktree and start an AI agent in it (works in both modes)\n- type to search \xB7 `Backspace` \u2014 edit search\n- `Q` / `Esc` \u2014 quit\n\n`C` and `A` are step-by-step wizards. In global mode (run from outside a repo /\n"home") they start by prompting for the repo (picker), then the branch; in repo\nmode the repo is fixed so they start at the branch. `A` then adds two more\nsteps:\n\n- `C` \u2014 **worktree (repo \u2192 branch)**\n- `A` \u2014 **worktree (repo \u2192 branch) \u2192 plan prompt \u2192 permission mode**\n\nPressing `Esc` at any step goes back to the previous step (your earlier answers\nare preserved); pressing `Esc` on the first step returns to the list.\n\nAfter a create or agent action the TUI **refreshes and stays open** on the list\n(your search and cursor are preserved) rather than exiting \u2014 only `Enter` (open)\nand `Q`/`Esc` exit.\n\nBecause `a`/`A`, `c`/`C`, `d`/`D`, and `p`/`P` are reserved as command keys,\nthose letters can\'t be typed into the search box.\n\n### `wt create [branch]`\n\nCreate a new worktree. If `branch` is omitted, prompts interactively.\n\nThe worktree is created as a sibling directory to the repo: `<parent>/<repo-name>-<branch-name>`.\n\nAfter creation, `wt` runs any configured `setup_commands` and opens the worktree in your IDE.\n\nIf the worktree path already exists, `wt create` doesn\'t error \u2014 it prompts you\nto **open it in the IDE** or **quit**. (In a non-interactive shell it errors\nwith a non-zero exit instead of prompting.)\n\n### `wt agent <branch> <plan_prompt> [--mode <mode>]`\n\nCreate a worktree (same as `wt create`) **and** auto-start an AI agent in Zed\'s\nintegrated terminal, pre-filled with `<plan_prompt>` and left interactive for\nyou to take over.\n\n```bash\nwt agent feature/login \'Read the codebase, then propose a plan for login.\'\nwt agent feature/fix \'Fix the bug in payment processing\' --mode auto\nwt agent refactor/api \'Refactor the API layer\' --mode default\n```\n\nThe `--mode` flag sets Claude Code\'s permission mode (defaults to `plan`):\n\n- `default` \u2014 Standard interactive mode with approval for each action\n- `acceptEdits` \u2014 Allow file changes but keep command execution controlled\n- `plan` \u2014 Architecture-first mode with no surprise mutations (default)\n- `auto` \u2014 Claude\'s safety model makes decisions instead of prompting\n- `dontAsk` \u2014 Minimal interruptions in trusted environments\n- `bypassPermissions` \u2014 Skip all permission checks (dangerous, CI/sandbox only)\n\nIt writes a temporary `.zed/tasks.json` running\n`<agent_command> --permission-mode <mode> \'<plan_prompt>\'`, ensures a global Zed keymap chord\n(`agent_trigger_chord`) spawns that task, opens Zed, presses the chord via\n`osascript`, then removes the temporary task so the repo is left clean.\n\n**macOS + Zed only.** Requires Accessibility permission for the app that runs\n`wt` (Zed itself, when run from its integrated terminal). If it isn\'t granted,\n`wt agent` opens the _Privacy & Security \u2192 Accessibility_ settings pane and waits\nfor you to grant it and confirm, then retries automatically. On other platforms\n(or when `ide` is not `zed`) the worktree is still created and opened, but the\nagent is not auto-started.\n\nOver SSH it still works, provided the same user has an active graphical login on\nthe Mac: the keystroke is run inside the GUI session via Launch Services\n(`open -a Terminal` briefly flashes a Terminal window). Grant Accessibility to\nTerminal (not Zed) the first time. With no one logged in graphically there is\nnothing to drive, so it falls back to the manual "press the chord in Zed"\nmessage.\n\nIf the worktree path already exists, `wt agent` prompts you to **open it in the\nIDE**, **open it and start the agent**, or **quit** \u2014 instead of erroring. (In a\nnon-interactive shell it errors with a non-zero exit instead of prompting.)\n\n### `wt prune`\n\nRemove every worktree whose branch has already been merged into the base\nbranch (`base_branch`, default `origin/main`). Each candidate is confirmed\nindividually \u2014 and force-confirmed when git refuses (submodules / uncommitted\nchanges), exactly like a manual `d` delete. The branch itself is left intact;\nonly the worktree is removed.\n\n```bash\nwt prune # review and remove merged worktrees, one prompt per branch\n```\n\nMerge detection is patch-id based (via `git cherry`), so a single-commit branch\nthat was **squash-merged** through a PR is still recognized as merged. It also\nbest-effort fetches the remote first so detection sees up-to-date refs; if the\nbase ref can\'t be resolved (e.g. offline), nothing is removed. Works in repo\nmode (current repo) and global mode (all registered repos, each against its own\n`base_branch`). The TUI exposes the same action under the `p` key.\n\n### `wt config`\n\nOpen the global config file in `$EDITOR` (defaults to `nano`).\n\n```bash\nwt config # open in editor\nwt config --path # print config file path only\n```\n\n### `wt skill`\n\nPrint this skill file to stdout. Useful for piping to agents or copying to a project.\n\n## Configuration\n\nConfig is stored as JSON. Get the path with `wt config --path`.\n\n### Schema\n\n| Key | Type | Default | Description |\n| --------------------- | ---------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `worktree_path` | `string` | `"../"` | Where to place new worktrees, relative to the repo root |\n| `base_branch` | `string` | `"origin/main"` | Branch to base new worktrees on |\n| `setup_commands` | `string[]` | `[]` | Commands to run in a new worktree after creation (e.g. `["npm install"]`) |\n| `teardown_commands` | `string[]` | `[]` | Commands to run in a worktree just before it is deleted (e.g. `["docker compose down -v"]`); on failure you are prompted whether to delete anyway |\n| `ide` | `string` | `"zed"` | IDE command to open worktrees with |\n| `ide_open_args` | `string[]` | `["-n"]` | Arguments passed to the IDE command |\n| `agent_command` | `string` | `"claude --permission-mode plan"` | Base command `wt agent` runs in Zed; any `--permission-mode` flag is replaced by the `--mode` option (defaults to `plan`), then `<plan_prompt>` is appended single-quoted |\n| `agent_trigger_chord` | `string` | `"ctrl-shift-cmd-c"` | Zed keymap chord `wt agent` installs/presses to spawn the agent task |\n| `auto_refresh_minutes`| `number` | `5` | How often the interactive list (`wt`) re-fetches worktrees and updates the "last refreshed" header; `0` disables auto-refresh |\n| `repos` | `string[]` | `[]` | Registered repo paths (auto-populated on first use) |\n| `repo_overrides` | `object` | `{}` | Per-repo config overrides (see below) |\n\n### Per-repo overrides\n\nOverride any field (`worktree_path`, `base_branch`, `setup_commands`, `teardown_commands`, `ide`, `ide_open_args`, `agent_command`, `agent_trigger_chord`, `auto_refresh_minutes`) for a specific repo:\n\n```json\n{\n "base_branch": "origin/main",\n "ide": "zed",\n "repo_overrides": {\n "/path/to/my-repo": {\n "base_branch": "origin/develop",\n "setup_commands": ["npm install", "npm run build"]\n }\n }\n}\n```\n\n## Common workflows\n\n### Create a worktree for a new feature\n\n```bash\ncd /path/to/repo\nwt create feature/my-branch\n```\n\n### Configure setup commands for a repo\n\n```bash\nwt config\n# Then add to the JSON:\n# "repo_overrides": {\n# "/path/to/repo": {\n# "setup_commands": ["npm install"]\n# }\n# }\n```\n\n### Browse all worktrees across repos\n\nRun `wt` from any directory outside a git repo to see worktrees from all registered repos.\n');
6
- }
7
- export {
8
- printSkill
9
- };