@cestoliv/wt 0.1.0-pr5.g3ca944a → 0.1.0-pr5.gd63269d

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.
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- openConfiguredIde,
4
3
  prepareWorktree
5
- } from "./chunk-YNGWUXCX.js";
6
- import "./chunk-FSARWOCW.js";
4
+ } from "./chunk-D4BVSTNE.js";
5
+ import {
6
+ openIde
7
+ } from "./chunk-FSARWOCW.js";
7
8
  import "./chunk-IQWENLPW.js";
8
9
 
9
10
  // src/commands/agent.ts
@@ -13,6 +14,7 @@ import pc from "picocolors";
13
14
  // src/lib/zed.ts
14
15
  import { spawn } from "child_process";
15
16
  import {
17
+ copyFileSync,
16
18
  existsSync,
17
19
  mkdirSync,
18
20
  readdirSync,
@@ -37,6 +39,13 @@ function buildAgentTask(agentCommand, prompt, label) {
37
39
  shell: "system"
38
40
  };
39
41
  }
42
+ function upsertTask(tasks, task) {
43
+ const idx = tasks.findIndex((t) => t.label === task.label);
44
+ if (idx === -1) return [...tasks, task];
45
+ const next = [...tasks];
46
+ next[idx] = task;
47
+ return next;
48
+ }
40
49
  function removeTask(tasks, label) {
41
50
  return tasks.filter((t) => t.label !== label);
42
51
  }
@@ -55,12 +64,6 @@ function upsertKeymapBinding(keymap, chord, label) {
55
64
  if (already) return keymap;
56
65
  return [...keymap, target];
57
66
  }
58
- function hasConflictingChord(keymap, chord, label) {
59
- const ours = JSON.stringify(buildKeymapBinding(chord, label).bindings[chord]);
60
- return keymap.some(
61
- (e) => e.bindings != null && e.bindings[chord] !== void 0 && JSON.stringify(e.bindings[chord]) !== ours
62
- );
63
- }
64
67
  var MODIFIER_MAP = {
65
68
  ctrl: "control down",
66
69
  control: "control down",
@@ -72,37 +75,6 @@ var MODIFIER_MAP = {
72
75
  opt: "option down",
73
76
  option: "option down"
74
77
  };
75
- var KEY_CODE_MAP = {
76
- space: 49,
77
- tab: 48,
78
- return: 36,
79
- enter: 36,
80
- escape: 53,
81
- esc: 53,
82
- delete: 51,
83
- backspace: 51,
84
- forwarddelete: 117,
85
- up: 126,
86
- down: 125,
87
- left: 123,
88
- right: 124,
89
- home: 115,
90
- end: 119,
91
- pageup: 116,
92
- pagedown: 121,
93
- f1: 122,
94
- f2: 120,
95
- f3: 99,
96
- f4: 118,
97
- f5: 96,
98
- f6: 97,
99
- f7: 98,
100
- f8: 100,
101
- f9: 101,
102
- f10: 109,
103
- f11: 103,
104
- f12: 111
105
- };
106
78
  function parseChord(chord) {
107
79
  const parts = chord.split("-").map((p) => p.trim().toLowerCase()).filter(Boolean);
108
80
  if (parts.length === 0) {
@@ -122,35 +94,17 @@ function buildOsascript(chord, opts = {}) {
122
94
  const { loadDelay = 3, activateDelay = 0.8 } = opts;
123
95
  const { key, modifiers } = parseChord(chord);
124
96
  const using = modifiers.length > 0 ? ` using {${modifiers.join(", ")}}` : "";
125
- let press;
126
- if (key.length === 1) {
127
- const escaped = key.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
128
- press = `keystroke "${escaped}"`;
129
- } else {
130
- const code = KEY_CODE_MAP[key];
131
- if (code === void 0) {
132
- throw new Error(
133
- `Unsupported key "${key}" in chord "${chord}". Use a single character or one of: ${Object.keys(KEY_CODE_MAP).join(", ")}.`
134
- );
135
- }
136
- press = `key code ${code}`;
137
- }
138
97
  return [
139
98
  `delay ${loadDelay}`,
140
99
  'tell application "Zed" to activate',
141
100
  `delay ${activateDelay}`,
142
- `tell application "System Events" to ${press}${using}`
101
+ `tell application "System Events" to keystroke "${key}"${using}`
143
102
  ].join("\n");
144
103
  }
145
- function parseTasks(raw) {
146
- const errors = [];
147
- const parsed = parse(raw, errors, { allowTrailingComma: true });
148
- if (errors.length > 0 || !Array.isArray(parsed)) return null;
149
- return parsed;
150
- }
151
104
  function readTasks(tasksPath) {
152
105
  try {
153
- return parseTasks(readFileSync(tasksPath, "utf8")) ?? [];
106
+ const parsed = JSON.parse(readFileSync(tasksPath, "utf8"));
107
+ return Array.isArray(parsed) ? parsed : [];
154
108
  } catch {
155
109
  return [];
156
110
  }
@@ -161,28 +115,9 @@ function writeAgentTask(worktreePath, task) {
161
115
  const createdDir = !existsSync(zedDir);
162
116
  if (createdDir) mkdirSync(zedDir, { recursive: true });
163
117
  const createdFile = !existsSync(tasksPath);
164
- if (createdFile) {
165
- writeFileSync(tasksPath, `${JSON.stringify([task], null, 2)}
166
- `);
167
- return { createdDir, createdFile };
168
- }
169
- const raw = readFileSync(tasksPath, "utf8");
170
- const tasks = parseTasks(raw);
171
- if (tasks === null) {
172
- process.stderr.write(
173
- `
174
- Warning: could not parse ${tasksPath}; not modifying it. The agent task was not added.
175
- `
176
- );
177
- return { createdDir, createdFile };
178
- }
179
- const idx = tasks.findIndex((t) => t.label === task.label);
180
- const edits = modify(raw, idx === -1 ? [tasks.length] : [idx], task, {
181
- isArrayInsertion: idx === -1,
182
- formattingOptions: { insertSpaces: true, tabSize: 2 }
183
- });
184
- const updated = applyEdits(raw, edits);
185
- writeFileSync(tasksPath, updated.endsWith("\n") ? updated : `${updated}
118
+ const existing = createdFile ? [] : readTasks(tasksPath);
119
+ const next = upsertTask(existing, task);
120
+ writeFileSync(tasksPath, `${JSON.stringify(next, null, 2)}
186
121
  `);
187
122
  return { createdDir, createdFile };
188
123
  }
@@ -190,30 +125,12 @@ function cleanupAgentTask(worktreePath, label, created) {
190
125
  const zedDir = join(worktreePath, ".zed");
191
126
  const tasksPath = join(zedDir, "tasks.json");
192
127
  if (existsSync(tasksPath)) {
193
- try {
194
- if (created.createdFile) {
195
- const next = removeTask(readTasks(tasksPath), label);
196
- if (next.length === 0) {
197
- rmSync(tasksPath, { force: true });
198
- } else {
199
- writeFileSync(tasksPath, `${JSON.stringify(next, null, 2)}
128
+ const next = removeTask(readTasks(tasksPath), label);
129
+ if (next.length === 0 && created.createdFile) {
130
+ rmSync(tasksPath, { force: true });
131
+ } else {
132
+ writeFileSync(tasksPath, `${JSON.stringify(next, null, 2)}
200
133
  `);
201
- }
202
- } else {
203
- const raw = readFileSync(tasksPath, "utf8");
204
- const tasks = parseTasks(raw);
205
- const idx = tasks?.findIndex((t) => t.label === label) ?? -1;
206
- if (idx !== -1) {
207
- const edits = modify(raw, [idx], void 0, {});
208
- const updated = applyEdits(raw, edits);
209
- writeFileSync(
210
- tasksPath,
211
- updated.endsWith("\n") ? updated : `${updated}
212
- `
213
- );
214
- }
215
- }
216
- } catch {
217
134
  }
218
135
  }
219
136
  if (created.createdDir && existsSync(zedDir)) {
@@ -255,18 +172,12 @@ ${JSON.stringify(binding, null, 2)}
255
172
  if (upsertKeymapBinding(keymap, chord, label) === keymap) {
256
173
  return true;
257
174
  }
258
- if (hasConflictingChord(keymap, chord, label)) {
259
- process.stderr.write(
260
- `
261
- Note: "${chord}" is already bound in ${keymapPath}; wt's agent binding will take precedence.
262
- `
263
- );
264
- }
265
175
  const edits = modify(raw, [keymap.length], binding, {
266
176
  isArrayInsertion: true,
267
177
  formattingOptions: { insertSpaces: true, tabSize: 2 }
268
178
  });
269
179
  const updated = applyEdits(raw, edits);
180
+ copyFileSync(keymapPath, `${keymapPath}.bak`);
270
181
  writeFileSync(keymapPath, updated.endsWith("\n") ? updated : `${updated}
271
182
  `);
272
183
  return true;
@@ -318,7 +229,7 @@ function openAccessibilitySettings(open = defaultOpen) {
318
229
  }
319
230
 
320
231
  // src/commands/agent.ts
321
- var CLEANUP_DELAY_MS = 2e4;
232
+ var CLEANUP_DELAY_MS = 2e3;
322
233
  var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
323
234
  async function createAgentWorktree(branch, planPrompt, options = {}) {
324
235
  const prepared = await prepareWorktree(branch, options);
@@ -330,14 +241,15 @@ async function createAgentWorktree(branch, planPrompt, options = {}) {
330
241
  `\u26A0 Agent auto-start requires Zed (ide is "${config.ide}"). Opening without starting the agent.`
331
242
  )
332
243
  );
333
- await openConfiguredIde(config, worktreePath);
244
+ if (config.ide) {
245
+ await openIde(config.ide, config.ide_open_args, worktreePath);
246
+ }
334
247
  return;
335
248
  }
336
249
  if (!config.agent_command) {
337
250
  console.error(
338
251
  pc.red("No agent_command configured. Set it with `wt config`.")
339
252
  );
340
- await openConfiguredIde(config, worktreePath);
341
253
  return;
342
254
  }
343
255
  const task = buildAgentTask(
@@ -346,21 +258,14 @@ async function createAgentWorktree(branch, planPrompt, options = {}) {
346
258
  AGENT_TASK_LABEL
347
259
  );
348
260
  const created = writeAgentTask(worktreePath, task);
349
- const keymapOk = ensureKeymap(config.agent_trigger_chord, AGENT_TASK_LABEL);
350
- const opened = await openConfiguredIde(config, worktreePath);
261
+ ensureKeymap(config.agent_trigger_chord, AGENT_TASK_LABEL);
262
+ const opened = await openIde("zed", config.ide_open_args, worktreePath);
351
263
  if (!opened) {
352
264
  console.error(pc.red("\u2717 Could not open Zed."));
353
265
  cleanupAgentTask(worktreePath, AGENT_TASK_LABEL, created);
354
266
  return;
355
267
  }
356
- if (!keymapOk) {
357
- console.warn(
358
- pc.yellow(
359
- `\u26A0 Could not install the Zed keybinding (see above). In Zed, press ${config.agent_trigger_chord} to start the agent manually.`
360
- )
361
- );
362
- return;
363
- }
268
+ console.log(pc.green("\u2713 Opened Zed"));
364
269
  console.log(pc.dim("Starting agent in Zed\u2026"));
365
270
  let result = await triggerChord(config.agent_trigger_chord);
366
271
  while (!result.ok && result.reason === "accessibility" && process.stdin.isTTY) {
@@ -140,22 +140,23 @@ async function prepareWorktree(branch, options = {}) {
140
140
  }
141
141
  return { repoRoot, worktreePath, config };
142
142
  }
143
- async function openConfiguredIde(config, worktreePath) {
144
- if (!config.ide) return false;
145
- const opened = await openIde(config.ide, config.ide_open_args, worktreePath);
146
- if (opened) {
147
- console.log(pc.green(`\u2713 Opened ${config.ide}`));
148
- }
149
- return opened;
150
- }
151
143
  async function createWorktree(branch, options = {}) {
152
144
  const prepared = await prepareWorktree(branch, options);
153
145
  if (!prepared) return;
154
- await openConfiguredIde(prepared.config, prepared.worktreePath);
146
+ const { config, worktreePath } = prepared;
147
+ if (config.ide) {
148
+ const opened = await openIde(
149
+ config.ide,
150
+ config.ide_open_args,
151
+ worktreePath
152
+ );
153
+ if (opened) {
154
+ console.log(pc.green(`\u2713 Opened ${config.ide}`));
155
+ }
156
+ }
155
157
  }
156
158
 
157
159
  export {
158
160
  prepareWorktree,
159
- openConfiguredIde,
160
161
  createWorktree
161
162
  };
package/dist/cli.js CHANGED
@@ -3,16 +3,16 @@
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.1.0-pr5.g3ca944a").action(async () => {
7
- const { runList } = await import("./list-KG6HKRMK.js");
6
+ program.name("wt").description("Git worktree manager").version("0.1.0-pr5.gd63269d").action(async () => {
7
+ const { runList } = await import("./list-HO42YAEG.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-66LRJRWI.js");
11
+ const { createWorktree } = await import("./create-55SXEUZV.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)").action(async (branch, planPrompt) => {
15
- const { createAgentWorktree } = await import("./agent-SKQRHH3U.js");
15
+ const { createAgentWorktree } = await import("./agent-PR7PGIE5.js");
16
16
  await createAgentWorktree(branch, planPrompt);
17
17
  });
18
18
  program.command("config").description("Open the config file in $EDITOR").option("--path", "Print the config file path and exit").action(async (options) => {
@@ -1,13 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createWorktree,
4
- openConfiguredIde,
5
4
  prepareWorktree
6
- } from "./chunk-YNGWUXCX.js";
5
+ } from "./chunk-D4BVSTNE.js";
7
6
  import "./chunk-FSARWOCW.js";
8
7
  import "./chunk-IQWENLPW.js";
9
8
  export {
10
9
  createWorktree,
11
- openConfiguredIde,
12
10
  prepareWorktree
13
11
  };
@@ -93,7 +93,7 @@ ${dirty.map((f) => ` ${f}`).join("\n")}`
93
93
  },
94
94
  onCreate: async () => {
95
95
  if (repoRoot) {
96
- const { createWorktree } = await import("./create-66LRJRWI.js");
96
+ const { createWorktree } = await import("./create-55SXEUZV.js");
97
97
  await createWorktree(void 0, { cwd: repoRoot, store });
98
98
  }
99
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cestoliv/wt",
3
- "version": "0.1.0-pr5.g3ca944a",
3
+ "version": "0.1.0-pr5.gd63269d",
4
4
  "description": "Fast, interactive TUI to browse, create, open, and delete git worktrees across repos.",
5
5
  "repository": {
6
6
  "type": "git",