code-squad-cli 1.2.22 → 2.0.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/dist/index.js CHANGED
@@ -1,11 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // dist/index.js
4
- import * as path12 from "path";
5
- import * as fs11 from "fs";
6
- import * as os5 from "os";
7
- import * as crypto from "crypto";
8
- import chalk2 from "chalk";
4
+ import * as path11 from "path";
5
+ import chalk from "chalk";
9
6
 
10
7
  // dist/adapters/GitAdapter.js
11
8
  import { exec as execCallback } from "child_process";
@@ -23,8 +20,17 @@ var GitAdapter = class {
23
20
  }
24
21
  }
25
22
  async getCurrentBranch(workspaceRoot) {
26
- const { stdout } = await exec(`cd "${workspaceRoot}" && git rev-parse --abbrev-ref HEAD`, execOptions);
27
- return stdout.trim();
23
+ try {
24
+ const { stdout } = await exec(`cd "${workspaceRoot}" && git rev-parse --abbrev-ref HEAD`, execOptions);
25
+ return stdout.trim();
26
+ } catch {
27
+ try {
28
+ const { stdout } = await exec(`cd "${workspaceRoot}" && git symbolic-ref --short HEAD`, execOptions);
29
+ return stdout.trim();
30
+ } catch {
31
+ return "";
32
+ }
33
+ }
28
34
  }
29
35
  async listWorktrees(workspaceRoot) {
30
36
  try {
@@ -44,11 +50,11 @@ var GitAdapter = class {
44
50
  const headMatch = headLine.match(/^HEAD (.+)$/);
45
51
  const branchMatch = branchLine?.match(/^branch refs\/heads\/(.+)$/);
46
52
  if (pathMatch && headMatch) {
47
- const path13 = pathMatch[1];
53
+ const path12 = pathMatch[1];
48
54
  const head = headMatch[1];
49
55
  const branch = branchMatch ? branchMatch[1] : "HEAD";
50
- if (path13 !== workspaceRoot) {
51
- worktrees.push({ path: path13, branch, head });
56
+ if (path12 !== workspaceRoot) {
57
+ worktrees.push({ path: path12, branch, head });
52
58
  }
53
59
  }
54
60
  i += 3;
@@ -59,9 +65,11 @@ var GitAdapter = class {
59
65
  }
60
66
  }
61
67
  async createWorktree(worktreePath, branch, workspaceRoot) {
68
+ await exec(`cd "${workspaceRoot}" && git worktree prune`, execOptions).catch(() => {
69
+ });
62
70
  const parentDir = worktreePath.substring(0, worktreePath.lastIndexOf("/"));
63
71
  const mkdirCmd = parentDir ? `mkdir -p "${parentDir}" && ` : "";
64
- await exec(`cd "${workspaceRoot}" && ${mkdirCmd}git worktree add "${worktreePath}" -b "${branch}"`, execOptions);
72
+ await exec(`cd "${workspaceRoot}" && ${mkdirCmd}git worktree add -f "${worktreePath}" -b "${branch}"`, execOptions);
65
73
  }
66
74
  async removeWorktree(worktreePath, workspaceRoot, force = false) {
67
75
  const forceFlag = force ? " --force" : "";
@@ -79,19 +87,19 @@ var GitAdapter = class {
79
87
  throw new Error(`Failed to delete branch: ${error.message}`);
80
88
  }
81
89
  }
82
- async isValidWorktree(path13, workspaceRoot) {
90
+ async isValidWorktree(path12, workspaceRoot) {
83
91
  try {
84
- await fs.promises.access(path13, fs.constants.R_OK);
92
+ await fs.promises.access(path12, fs.constants.R_OK);
85
93
  } catch {
86
94
  return false;
87
95
  }
88
96
  try {
89
- await exec(`cd "${path13}" && git rev-parse --git-dir`, execOptions);
97
+ await exec(`cd "${path12}" && git rev-parse --git-dir`, execOptions);
90
98
  } catch {
91
99
  return false;
92
100
  }
93
101
  const worktrees = await this.listWorktrees(workspaceRoot);
94
- return worktrees.some((wt) => wt.path === path13);
102
+ return worktrees.some((wt) => wt.path === path12);
95
103
  }
96
104
  async getWorktreeBranch(worktreePath) {
97
105
  try {
@@ -141,277 +149,8 @@ var GitAdapter = class {
141
149
  }
142
150
  };
143
151
 
144
- // dist/ui/prompts.js
145
- import { createPrompt, useState, useKeypress, usePrefix, isEnterKey, isBackspaceKey } from "@inquirer/core";
146
- import { confirm } from "@inquirer/prompts";
147
- import chalk from "chalk";
148
- import * as path from "path";
149
- var cancelableInput = createPrompt((config, done) => {
150
- const [value, setValue] = useState(config.default || "");
151
- const [error, setError] = useState(null);
152
- const prefix = usePrefix({ status: "idle" });
153
- useKeypress((key, rl) => {
154
- if (key.name === "escape") {
155
- done(null);
156
- } else if (isEnterKey(key)) {
157
- if (config.validate) {
158
- const result = config.validate(value);
159
- if (result !== true) {
160
- setError(typeof result === "string" ? result : "Invalid input");
161
- return;
162
- }
163
- }
164
- done(value);
165
- } else if (isBackspaceKey(key)) {
166
- setValue(value.slice(0, -1));
167
- setError(null);
168
- } else if (key.ctrl || key.name === "tab" || key.name === "up" || key.name === "down") {
169
- } else {
170
- const seq = key.sequence;
171
- if (seq && seq.length === 1 && seq >= " ") {
172
- setValue(value + seq);
173
- setError(null);
174
- }
175
- }
176
- });
177
- const errorMsg = error ? chalk.red(`
178
- ${error}`) : "";
179
- return `${prefix} ${config.message} ${chalk.cyan(value)}${errorMsg}
180
- ${chalk.dim("ESC:cancel Enter:confirm")}`;
181
- });
182
- function truncatePath(fullPath, maxLen) {
183
- if (fullPath.length <= maxLen)
184
- return fullPath;
185
- const home = process.env.HOME || "";
186
- let display = fullPath.startsWith(home) ? "~" + fullPath.slice(home.length) : fullPath;
187
- if (display.length <= maxLen)
188
- return display;
189
- const parts = display.split(path.sep);
190
- if (parts.length > 2) {
191
- return "\u2026/" + parts.slice(-2).join("/");
192
- }
193
- return "\u2026" + display.slice(-maxLen + 1);
194
- }
195
- var vimSelect = createPrompt((config, done) => {
196
- const { choices, pageSize = 15, shortcuts = [] } = config;
197
- const enabledChoices = choices.filter((c) => !c.disabled);
198
- const [selectedIndex, setSelectedIndex] = useState(0);
199
- const prefix = usePrefix({ status: "idle" });
200
- useKeypress((key) => {
201
- if (key.name === "j" || key.name === "down") {
202
- const nextIndex = (selectedIndex + 1) % enabledChoices.length;
203
- setSelectedIndex(nextIndex);
204
- } else if (key.name === "k" || key.name === "up") {
205
- const prevIndex = (selectedIndex - 1 + enabledChoices.length) % enabledChoices.length;
206
- setSelectedIndex(prevIndex);
207
- } else if (isEnterKey(key)) {
208
- done(enabledChoices[selectedIndex].value);
209
- } else if (key.name === "escape" || key.name === "b") {
210
- const backShortcut = shortcuts.find((s) => s.key === "back");
211
- if (backShortcut) {
212
- done(backShortcut.value);
213
- }
214
- } else {
215
- const shortcut = shortcuts.find((s) => s.key === key.name);
216
- if (shortcut) {
217
- done(shortcut.value);
218
- }
219
- }
220
- });
221
- const totalItems = enabledChoices.length;
222
- const halfPage = Math.floor(pageSize / 2);
223
- let startIndex = 0;
224
- if (totalItems > pageSize) {
225
- if (selectedIndex <= halfPage) {
226
- startIndex = 0;
227
- } else if (selectedIndex >= totalItems - halfPage) {
228
- startIndex = totalItems - pageSize;
229
- } else {
230
- startIndex = selectedIndex - halfPage;
231
- }
232
- }
233
- const visibleChoices = enabledChoices.slice(startIndex, startIndex + pageSize);
234
- const lines = visibleChoices.map((choice, i) => {
235
- const actualIndex = startIndex + i;
236
- const isSelected = actualIndex === selectedIndex;
237
- const cursor = isSelected ? chalk.cyan("\u276F") : " ";
238
- const name = isSelected ? chalk.cyan(choice.name) : choice.name;
239
- return `${cursor} ${name}`;
240
- });
241
- if (startIndex > 0) {
242
- lines.unshift(chalk.dim(" \u2191 more"));
243
- }
244
- if (startIndex + pageSize < totalItems) {
245
- lines.push(chalk.dim(" \u2193 more"));
246
- }
247
- const shortcutHints = shortcuts.filter((s) => s.description).map((s) => chalk.dim(`${s.key}:${s.description}`)).join(" ");
248
- const hint = chalk.dim("j/k:navigate enter:select") + (shortcutHints ? " " + shortcutHints : "");
249
- return `${prefix} ${chalk.bold(config.message)}
250
- ${lines.join("\n")}
251
- ${hint}`;
252
- });
253
- async function selectThread(threads, repoName) {
254
- const cols = process.stdout.columns || 80;
255
- const nameWidth = 18;
256
- const prefixWidth = 6;
257
- const pathMaxLen = Math.max(20, cols - nameWidth - prefixWidth - 5);
258
- const threadChoices = threads.map((t) => {
259
- const typeIcon = t.type === "worktree" ? chalk.cyan("[W]") : chalk.yellow("[L]");
260
- const displayPath = truncatePath(t.path, pathMaxLen);
261
- return {
262
- name: `${typeIcon} ${t.name.padEnd(nameWidth)} ${chalk.dim(displayPath)}`,
263
- value: { type: "existing", thread: t },
264
- thread: t
265
- };
266
- });
267
- const newChoice = {
268
- name: chalk.green("+ \uC0C8 \uC791\uC5C5"),
269
- value: { type: "new" },
270
- thread: null
271
- };
272
- const allChoices = [...threadChoices, newChoice];
273
- const threadSelect = createPrompt((config, done) => {
274
- const [selectedIndex, setSelectedIndex] = useState(0);
275
- const prefix = usePrefix({ status: "idle" });
276
- const pageSize = 15;
277
- useKeypress((key) => {
278
- if (key.name === "j" || key.name === "down") {
279
- setSelectedIndex((selectedIndex + 1) % allChoices.length);
280
- } else if (key.name === "k" || key.name === "up") {
281
- setSelectedIndex((selectedIndex - 1 + allChoices.length) % allChoices.length);
282
- } else if (isEnterKey(key)) {
283
- done(allChoices[selectedIndex].value);
284
- } else if (key.name === "n") {
285
- done({ type: "new" });
286
- } else if (key.name === "q") {
287
- done({ type: "exit" });
288
- } else if (key.name === "d") {
289
- const current = allChoices[selectedIndex];
290
- if (current.thread) {
291
- done({ type: "delete-selected", thread: current.thread });
292
- }
293
- }
294
- });
295
- const totalItems = allChoices.length;
296
- const halfPage = Math.floor(pageSize / 2);
297
- let startIndex = 0;
298
- if (totalItems > pageSize) {
299
- if (selectedIndex <= halfPage) {
300
- startIndex = 0;
301
- } else if (selectedIndex >= totalItems - halfPage) {
302
- startIndex = totalItems - pageSize;
303
- } else {
304
- startIndex = selectedIndex - halfPage;
305
- }
306
- }
307
- const visibleChoices = allChoices.slice(startIndex, startIndex + pageSize);
308
- const lines = visibleChoices.map((choice, i) => {
309
- const actualIndex = startIndex + i;
310
- const isSelected = actualIndex === selectedIndex;
311
- const cursor = isSelected ? chalk.cyan("\u276F") : " ";
312
- const name = isSelected ? chalk.cyan(choice.name) : choice.name;
313
- return `${cursor} ${name}`;
314
- });
315
- if (startIndex > 0) {
316
- lines.unshift(chalk.dim(" \u2191 more"));
317
- }
318
- if (startIndex + pageSize < totalItems) {
319
- lines.push(chalk.dim(" \u2193 more"));
320
- }
321
- const hint = chalk.dim("j/k:nav n:new d:delete q:quit");
322
- return `${prefix} ${config.message}
323
- ${lines.join("\n")}
324
- ${hint}`;
325
- });
326
- return threadSelect({ message: chalk.bold(repoName) });
327
- }
328
- async function selectThreadAction(threadName) {
329
- const choices = [
330
- { name: "\uD130\uBBF8\uB110 \uC5F4\uAE30", value: "open" },
331
- { name: chalk.red("\uC0AD\uC81C\uD558\uAE30"), value: "delete" },
332
- { name: chalk.dim("\u2190 \uB4A4\uB85C"), value: "back" }
333
- ];
334
- return vimSelect({
335
- message: `'${threadName}'`,
336
- choices,
337
- shortcuts: [{ key: "back", value: "back" }]
338
- });
339
- }
340
- async function selectNewThreadType() {
341
- const choices = [
342
- {
343
- name: chalk.cyan("\uC6CC\uD06C\uD2B8\uB9AC") + chalk.dim(" - \uC0C8 \uBE0C\uB79C\uCE58\uC640 \uB514\uB809\uD1A0\uB9AC \uC0DD\uC131"),
344
- value: "worktree"
345
- },
346
- {
347
- name: chalk.yellow("\uB85C\uCEEC") + chalk.dim(" - \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC\uC5D0\uC11C \uC791\uC5C5"),
348
- value: "local"
349
- },
350
- { name: chalk.dim("\u2190 \uB4A4\uB85C"), value: "back" }
351
- ];
352
- return vimSelect({
353
- message: "\uC0C8 \uC791\uC5C5 \uD0C0\uC785",
354
- choices,
355
- shortcuts: [{ key: "back", value: "back" }]
356
- });
357
- }
358
- async function newWorktreeForm(defaultBasePath) {
359
- const name = await cancelableInput({
360
- message: "\uC6CC\uD06C\uD2B8\uB9AC \uC774\uB984:",
361
- validate: (value) => {
362
- if (!value.trim())
363
- return "\uC774\uB984\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694";
364
- if (!/^[a-zA-Z0-9_-]+$/.test(value)) {
365
- return "\uC601\uBB38, \uC22B\uC790, -, _ \uB9CC \uC0AC\uC6A9 \uAC00\uB2A5";
366
- }
367
- return true;
368
- }
369
- });
370
- if (!name)
371
- return null;
372
- const defaultPath = `${defaultBasePath}/${name}`;
373
- const pathInput = await cancelableInput({
374
- message: "\uACBD\uB85C:",
375
- default: defaultPath
376
- });
377
- if (!pathInput)
378
- return null;
379
- return { name, path: pathInput };
380
- }
381
- async function newLocalForm() {
382
- const name = await cancelableInput({
383
- message: "\uB85C\uCEEC \uC2A4\uB808\uB4DC \uC774\uB984:",
384
- validate: (value) => {
385
- if (!value.trim())
386
- return "\uC774\uB984\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694";
387
- return true;
388
- }
389
- });
390
- return name || null;
391
- }
392
- async function confirmDeleteWorktree(threadName) {
393
- const confirmed = await confirm({
394
- message: `'${threadName}' \uC6CC\uD06C\uD2B8\uB9AC\uB97C \uC0AD\uC81C\uD560\uAE4C\uC694?`,
395
- default: true
396
- });
397
- if (!confirmed) {
398
- return { confirmed: false, removeGitWorktree: false };
399
- }
400
- const removeGitWorktree = await confirm({
401
- message: "Git worktree\uC640 \uBE0C\uB79C\uCE58\uB3C4 \uD568\uAED8 \uC0AD\uC81C\uD560\uAE4C\uC694?",
402
- default: true
403
- });
404
- return { confirmed, removeGitWorktree };
405
- }
406
- async function confirmDeleteLocal(threadName) {
407
- return await confirm({
408
- message: `'${threadName}' \uB85C\uCEEC \uC2A4\uB808\uB4DC\uB97C \uC0AD\uC81C\uD560\uAE4C\uC694?`,
409
- default: true
410
- });
411
- }
412
-
413
152
  // dist/index.js
414
- import { confirm as confirm2 } from "@inquirer/prompts";
153
+ import { confirm } from "@inquirer/prompts";
415
154
 
416
155
  // dist/flip/server/Server.js
417
156
  import express2 from "express";
@@ -422,7 +161,7 @@ import net from "net";
422
161
  // dist/flip/routes/files.js
423
162
  import { Router } from "express";
424
163
  import fs2 from "fs";
425
- import path2 from "path";
164
+ import path from "path";
426
165
 
427
166
  // dist/flip/constants/filters.js
428
167
  var FILTERED_PATTERNS = /* @__PURE__ */ new Set([
@@ -489,8 +228,8 @@ function buildFileTree(rootPath, currentPath, maxDepth, depth = 0) {
489
228
  return a.name.localeCompare(b.name);
490
229
  });
491
230
  for (const entry of entries) {
492
- const fullPath = path2.join(currentPath, entry.name);
493
- const relativePath = path2.relative(rootPath, fullPath);
231
+ const fullPath = path.join(currentPath, entry.name);
232
+ const relativePath = path.relative(rootPath, fullPath);
494
233
  const filtered = isFiltered(entry.name);
495
234
  const node = {
496
235
  path: relativePath,
@@ -510,8 +249,8 @@ function collectFlatFiles(rootPath, currentPath, maxDepth, depth = 0, result = {
510
249
  return result;
511
250
  const entries = fs2.readdirSync(currentPath, { withFileTypes: true });
512
251
  for (const entry of entries) {
513
- const fullPath = path2.join(currentPath, entry.name);
514
- const relativePath = path2.relative(rootPath, fullPath);
252
+ const fullPath = path.join(currentPath, entry.name);
253
+ const relativePath = path.relative(rootPath, fullPath);
515
254
  if (isFiltered(entry.name)) {
516
255
  if (entry.isDirectory()) {
517
256
  result.filteredDirs.push(relativePath);
@@ -581,7 +320,7 @@ router.get("/flat", (req, res) => {
581
320
  // dist/flip/routes/file.js
582
321
  import { Router as Router2 } from "express";
583
322
  import fs3 from "fs";
584
- import path3 from "path";
323
+ import path2 from "path";
585
324
  var router2 = Router2();
586
325
  var extensionMap = {
587
326
  // JavaScript/TypeScript
@@ -694,11 +433,11 @@ var filenameMap = {
694
433
  "CODEOWNERS": "gitignore"
695
434
  };
696
435
  function detectLanguage(filePath) {
697
- const basename2 = path3.basename(filePath);
436
+ const basename2 = path2.basename(filePath);
698
437
  if (filenameMap[basename2]) {
699
438
  return filenameMap[basename2];
700
439
  }
701
- const ext = path3.extname(filePath).slice(1).toLowerCase();
440
+ const ext = path2.extname(filePath).slice(1).toLowerCase();
702
441
  if (extensionMap[ext]) {
703
442
  return extensionMap[ext];
704
443
  }
@@ -727,9 +466,9 @@ router2.get("/", (req, res) => {
727
466
  res.status(400).json({ error: "Missing path parameter" });
728
467
  return;
729
468
  }
730
- const filePath = path3.join(cwd, relativePath);
731
- const resolvedPath = path3.resolve(filePath);
732
- const resolvedCwd = path3.resolve(cwd);
469
+ const filePath = path2.join(cwd, relativePath);
470
+ const resolvedPath = path2.resolve(filePath);
471
+ const resolvedCwd = path2.resolve(cwd);
733
472
  if (!resolvedPath.startsWith(resolvedCwd)) {
734
473
  res.status(403).json({ error: "Access denied" });
735
474
  return;
@@ -756,7 +495,7 @@ router2.get("/", (req, res) => {
756
495
  import { Router as Router3 } from "express";
757
496
  import { execSync } from "child_process";
758
497
  import * as fs4 from "fs";
759
- import * as path4 from "path";
498
+ import * as path3 from "path";
760
499
  var router3 = Router3();
761
500
  function parseGitStatus(output) {
762
501
  const files = [];
@@ -916,7 +655,7 @@ router3.get("/diff", (req, res) => {
916
655
  res.status(400).json({ error: "Missing path parameter" });
917
656
  return;
918
657
  }
919
- const fullPath = path4.join(cwd, relativePath);
658
+ const fullPath = path3.join(cwd, relativePath);
920
659
  let fileStatus = "modified";
921
660
  try {
922
661
  const statusOutput = execSync(`git status --porcelain -- "${relativePath}"`, {
@@ -992,10 +731,10 @@ function formatComments(comments) {
992
731
  // dist/flip/output/clipboard.js
993
732
  import { spawn } from "child_process";
994
733
  import fs5 from "fs";
995
- import path5 from "path";
734
+ import path4 from "path";
996
735
  import os from "os";
997
736
  async function copyToClipboard(text) {
998
- const tmpFile = path5.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
737
+ const tmpFile = path4.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
999
738
  const cleanupTmpFile = () => {
1000
739
  try {
1001
740
  fs5.unlinkSync(tmpFile);
@@ -1041,7 +780,7 @@ async function copyToClipboard(text) {
1041
780
  // dist/flip/output/autopaste.js
1042
781
  import { spawn as spawn2 } from "child_process";
1043
782
  import fs6 from "fs";
1044
- import path6 from "path";
783
+ import path5 from "path";
1045
784
  import os2 from "os";
1046
785
  async function schedulePaste(sessionId) {
1047
786
  if (process.platform !== "darwin") {
@@ -1051,7 +790,7 @@ async function schedulePaste(sessionId) {
1051
790
  await pasteToOriginalSession(sessionId);
1052
791
  }
1053
792
  async function pasteToOriginalSession(sessionId) {
1054
- const sessionFile = path6.join(os2.tmpdir(), `flip-view-session-${sessionId}`);
793
+ const sessionFile = path5.join(os2.tmpdir(), `flip-view-session-${sessionId}`);
1055
794
  let itermSessionId;
1056
795
  try {
1057
796
  itermSessionId = fs6.readFileSync(sessionFile, "utf-8").trim();
@@ -1098,7 +837,7 @@ async function pasteToOriginalSession(sessionId) {
1098
837
  `;
1099
838
  }
1100
839
  try {
1101
- const tmpScript = path6.join(os2.tmpdir(), `flip-paste-${Date.now()}.scpt`);
840
+ const tmpScript = path5.join(os2.tmpdir(), `flip-paste-${Date.now()}.scpt`);
1102
841
  fs6.writeFileSync(tmpScript, script);
1103
842
  const cleanupScript = () => {
1104
843
  try {
@@ -1177,21 +916,21 @@ router5.post("/", async (req, res) => {
1177
916
  // dist/flip/routes/static.js
1178
917
  import { Router as Router6 } from "express";
1179
918
  import express from "express";
1180
- import path7 from "path";
919
+ import path6 from "path";
1181
920
  import { fileURLToPath } from "url";
1182
921
  import fs7 from "fs";
1183
922
  function createStaticRouter() {
1184
923
  const router6 = Router6();
1185
924
  const __filename = fileURLToPath(import.meta.url);
1186
- const __dirname = path7.dirname(__filename);
1187
- let distPath = path7.resolve(__dirname, "flip-ui/dist");
925
+ const __dirname = path6.dirname(__filename);
926
+ let distPath = path6.resolve(__dirname, "flip-ui/dist");
1188
927
  if (!fs7.existsSync(distPath)) {
1189
- distPath = path7.resolve(__dirname, "../../../flip-ui/dist");
928
+ distPath = path6.resolve(__dirname, "../../../flip-ui/dist");
1190
929
  }
1191
930
  if (fs7.existsSync(distPath)) {
1192
931
  router6.use(express.static(distPath));
1193
932
  router6.get("*", (req, res) => {
1194
- const indexPath = path7.join(distPath, "index.html");
933
+ const indexPath = path6.join(distPath, "index.html");
1195
934
  if (fs7.existsSync(indexPath)) {
1196
935
  res.sendFile(indexPath);
1197
936
  } else {
@@ -1299,7 +1038,7 @@ function createChangesRouter(sessionManager) {
1299
1038
 
1300
1039
  // dist/flip/watcher/FileWatcher.js
1301
1040
  import chokidar from "chokidar";
1302
- import * as path8 from "path";
1041
+ import * as path7 from "path";
1303
1042
  var FileWatcher = class {
1304
1043
  watcher = null;
1305
1044
  cwd;
@@ -1316,8 +1055,8 @@ var FileWatcher = class {
1316
1055
  }
1317
1056
  start() {
1318
1057
  const shouldIgnore = (filePath) => {
1319
- const relativePath = path8.relative(this.cwd, filePath);
1320
- const segments = relativePath.split(path8.sep);
1058
+ const relativePath = path7.relative(this.cwd, filePath);
1059
+ const segments = relativePath.split(path7.sep);
1321
1060
  return segments.some((segment) => segment !== ".git" && FILTERED_PATTERNS.has(segment));
1322
1061
  };
1323
1062
  this.watcher = chokidar.watch(this.cwd, {
@@ -1365,7 +1104,7 @@ var FileWatcher = class {
1365
1104
  this.gitChangedCallbacks.push(callback);
1366
1105
  }
1367
1106
  handleFileEvent(filePath, event) {
1368
- const relativePath = path8.relative(this.cwd, filePath);
1107
+ const relativePath = path7.relative(this.cwd, filePath);
1369
1108
  if (relativePath.startsWith(".git")) {
1370
1109
  this.emitGitChanged();
1371
1110
  return;
@@ -1379,7 +1118,7 @@ var FileWatcher = class {
1379
1118
  this.emitGitChanged();
1380
1119
  }
1381
1120
  handleDirEvent(dirPath, event) {
1382
- const relativePath = path8.relative(this.cwd, dirPath);
1121
+ const relativePath = path7.relative(this.cwd, dirPath);
1383
1122
  if (relativePath.startsWith(".git")) {
1384
1123
  return;
1385
1124
  }
@@ -1739,7 +1478,7 @@ async function findExistingServer(startPort, endPort) {
1739
1478
 
1740
1479
  // dist/flip/index.js
1741
1480
  import open from "open";
1742
- import path9 from "path";
1481
+ import path8 from "path";
1743
1482
  import fs8 from "fs";
1744
1483
  import os3 from "os";
1745
1484
  import http2 from "http";
@@ -1838,7 +1577,7 @@ async function runFlip(args) {
1838
1577
  } else {
1839
1578
  command = "oneshot";
1840
1579
  }
1841
- const cwd = pathArg ? path9.resolve(pathArg) : process.cwd();
1580
+ const cwd = pathArg ? path8.resolve(pathArg) : process.cwd();
1842
1581
  const finalSessionId = sessionId || getSessionId();
1843
1582
  switch (command) {
1844
1583
  case "setup": {
@@ -1952,7 +1691,7 @@ async function setupHotkey() {
1952
1691
  } catch {
1953
1692
  csqPath = new URL(import.meta.url).pathname;
1954
1693
  }
1955
- const nodeDir = path9.dirname(nodePath);
1694
+ const nodeDir = path8.dirname(nodePath);
1956
1695
  const wrapperScript = `#!/bin/bash
1957
1696
  # Add node to PATH (coprocess doesn't inherit shell PATH)
1958
1697
  export PATH="${nodeDir}:$PATH"
@@ -1978,8 +1717,8 @@ else
1978
1717
  exec ${csqPath} flip
1979
1718
  fi
1980
1719
  `;
1981
- const scriptDir = path9.join(os3.homedir(), ".config", "csq");
1982
- const scriptPath = path9.join(scriptDir, "flip-hotkey.sh");
1720
+ const scriptDir = path8.join(os3.homedir(), ".config", "csq");
1721
+ const scriptPath = path8.join(scriptDir, "flip-hotkey.sh");
1983
1722
  if (!fs8.existsSync(scriptDir)) {
1984
1723
  fs8.mkdirSync(scriptDir, { recursive: true });
1985
1724
  }
@@ -2008,8 +1747,8 @@ fi
2008
1747
  // dist/config.js
2009
1748
  import * as fs9 from "fs";
2010
1749
  import * as os4 from "os";
2011
- import * as path10 from "path";
2012
- var GLOBAL_CONFIG_PATH = path10.join(os4.homedir(), ".code-squad", "config.json");
1750
+ import * as path9 from "path";
1751
+ var GLOBAL_CONFIG_PATH = path9.join(os4.homedir(), ".code-squad", "config.json");
2013
1752
  async function loadGlobalConfig() {
2014
1753
  try {
2015
1754
  const content = await fs9.promises.readFile(GLOBAL_CONFIG_PATH, "utf-8");
@@ -2024,7 +1763,7 @@ async function loadGlobalConfig() {
2024
1763
  }
2025
1764
  async function loadConfig(workspaceRoot) {
2026
1765
  const globalConfig = await loadGlobalConfig();
2027
- const normalizedPath = path10.resolve(workspaceRoot);
1766
+ const normalizedPath = path9.resolve(workspaceRoot);
2028
1767
  const projectConfig = globalConfig.projects?.[normalizedPath] ?? {};
2029
1768
  const defaults = globalConfig.defaults ?? {};
2030
1769
  return {
@@ -2044,7 +1783,7 @@ function getWorktreeCopyPatterns(config) {
2044
1783
 
2045
1784
  // dist/fileUtils.js
2046
1785
  import * as fs10 from "fs";
2047
- import * as path11 from "path";
1786
+ import * as path10 from "path";
2048
1787
  import fg from "fast-glob";
2049
1788
  async function copyFilesWithPatterns(sourceRoot, destRoot, patterns) {
2050
1789
  const copied = [];
@@ -2064,10 +1803,10 @@ async function copyFilesWithPatterns(sourceRoot, destRoot, patterns) {
2064
1803
  for (const absolutePath of files) {
2065
1804
  try {
2066
1805
  await copySingleFile(absolutePath, sourceRoot, destRoot);
2067
- const relativePath = path11.relative(sourceRoot, absolutePath);
1806
+ const relativePath = path10.relative(sourceRoot, absolutePath);
2068
1807
  copied.push(relativePath);
2069
1808
  } catch {
2070
- const relativePath = path11.relative(sourceRoot, absolutePath);
1809
+ const relativePath = path10.relative(sourceRoot, absolutePath);
2071
1810
  failed.push(relativePath);
2072
1811
  }
2073
1812
  }
@@ -2077,9 +1816,9 @@ async function copyFilesWithPatterns(sourceRoot, destRoot, patterns) {
2077
1816
  return { copied, failed };
2078
1817
  }
2079
1818
  async function copySingleFile(absolutePath, sourceRoot, destRoot) {
2080
- const relativePath = path11.relative(sourceRoot, absolutePath);
2081
- const destPath = path11.join(destRoot, relativePath);
2082
- const destDir = path11.dirname(destPath);
1819
+ const relativePath = path10.relative(sourceRoot, absolutePath);
1820
+ const destPath = path10.join(destRoot, relativePath);
1821
+ const destDir = path10.dirname(destPath);
2083
1822
  await fs10.promises.mkdir(destDir, { recursive: true });
2084
1823
  await fs10.promises.copyFile(absolutePath, destPath);
2085
1824
  }
@@ -2091,38 +1830,30 @@ process.on("SIGINT", () => {
2091
1830
  var gitAdapter = new GitAdapter();
2092
1831
  async function main() {
2093
1832
  const args = process.argv.slice(2);
2094
- const persistentMode = args.includes("-p") || args.includes("--persistent");
2095
- const filteredArgs = args.filter((a) => a !== "-p" && a !== "--persistent");
2096
- const command = filteredArgs[0];
1833
+ const command = args[0];
2097
1834
  if (command === "--init" || command === "init") {
2098
1835
  printShellInit();
2099
1836
  return;
2100
1837
  }
2101
1838
  if (command === "flip") {
2102
- await runFlip(filteredArgs.slice(1));
1839
+ await runFlip(args.slice(1));
2103
1840
  return;
2104
1841
  }
2105
1842
  const workspaceRoot = await findGitRoot(process.cwd());
2106
1843
  if (!workspaceRoot) {
2107
- console.error(chalk2.red("Error: Not a git repository"));
1844
+ console.error(chalk.red("Error: Not a git repository"));
2108
1845
  process.exit(1);
2109
1846
  }
2110
1847
  switch (command) {
2111
- case "list":
2112
- await listThreads(workspaceRoot);
2113
- break;
2114
1848
  case "new":
2115
- await createWorktreeCommand(workspaceRoot, filteredArgs.slice(1));
1849
+ await createWorktreeCommand(workspaceRoot, args.slice(1));
2116
1850
  break;
2117
1851
  case "quit":
2118
1852
  await quitWorktreeCommand();
2119
1853
  break;
1854
+ case "list":
2120
1855
  default:
2121
- if (persistentMode) {
2122
- await persistentInteractiveMode(workspaceRoot);
2123
- } else {
2124
- await interactiveMode(workspaceRoot);
2125
- }
1856
+ await listWorktrees(workspaceRoot);
2126
1857
  }
2127
1858
  }
2128
1859
  async function findGitRoot(cwd) {
@@ -2131,66 +1862,6 @@ async function findGitRoot(cwd) {
2131
1862
  }
2132
1863
  return cwd;
2133
1864
  }
2134
- function getProjectHash(workspaceRoot) {
2135
- return crypto.createHash("sha256").update(workspaceRoot).digest("hex").slice(0, 8);
2136
- }
2137
- function getSessionsPath(workspaceRoot) {
2138
- const projectHash = getProjectHash(workspaceRoot);
2139
- const projectName = path12.basename(workspaceRoot);
2140
- return path12.join(os5.homedir(), ".code-squad", "sessions", `${projectName}-${projectHash}.json`);
2141
- }
2142
- async function loadLocalThreads(workspaceRoot) {
2143
- const sessionsPath = getSessionsPath(workspaceRoot);
2144
- try {
2145
- const content = await fs11.promises.readFile(sessionsPath, "utf-8");
2146
- const data = JSON.parse(content);
2147
- return data.localThreads || [];
2148
- } catch {
2149
- return [];
2150
- }
2151
- }
2152
- async function saveLocalThreads(workspaceRoot, threads) {
2153
- const sessionsPath = getSessionsPath(workspaceRoot);
2154
- const dir = path12.dirname(sessionsPath);
2155
- await fs11.promises.mkdir(dir, { recursive: true });
2156
- await fs11.promises.writeFile(sessionsPath, JSON.stringify({ localThreads: threads }, null, 2));
2157
- }
2158
- async function addLocalThread(workspaceRoot, name) {
2159
- const threads = await loadLocalThreads(workspaceRoot);
2160
- const newThread = {
2161
- id: Date.now().toString(),
2162
- name,
2163
- path: workspaceRoot,
2164
- createdAt: Date.now()
2165
- };
2166
- threads.push(newThread);
2167
- await saveLocalThreads(workspaceRoot, threads);
2168
- return newThread;
2169
- }
2170
- async function removeLocalThread(workspaceRoot, id) {
2171
- const threads = await loadLocalThreads(workspaceRoot);
2172
- const filtered = threads.filter((t) => t.id !== id);
2173
- await saveLocalThreads(workspaceRoot, filtered);
2174
- }
2175
- async function getAllThreads(workspaceRoot) {
2176
- const worktrees = await gitAdapter.listWorktrees(workspaceRoot);
2177
- const localThreads = await loadLocalThreads(workspaceRoot);
2178
- const threads = [
2179
- ...worktrees.map((wt) => ({
2180
- type: "worktree",
2181
- name: wt.branch,
2182
- path: wt.path,
2183
- branch: wt.branch
2184
- })),
2185
- ...localThreads.map((lt) => ({
2186
- type: "local",
2187
- name: lt.name,
2188
- path: lt.path,
2189
- id: lt.id
2190
- }))
2191
- ];
2192
- return threads;
2193
- }
2194
1865
  function printShellInit() {
2195
1866
  const script = `
2196
1867
  csq() {
@@ -2221,56 +1892,33 @@ csq() {
2221
1892
  `.trim();
2222
1893
  console.log(script);
2223
1894
  }
2224
- async function listThreads(workspaceRoot) {
2225
- const threads = await getAllThreads(workspaceRoot);
2226
- if (threads.length === 0) {
2227
- console.log(chalk2.dim("No threads found."));
1895
+ async function listWorktrees(workspaceRoot) {
1896
+ const worktrees = await gitAdapter.listWorktrees(workspaceRoot);
1897
+ if (worktrees.length === 0) {
1898
+ console.log(chalk.dim("No worktrees found."));
2228
1899
  return;
2229
1900
  }
2230
- for (const t of threads) {
2231
- const typeLabel = t.type === "worktree" ? chalk2.cyan("[W]") : chalk2.yellow("[L]");
2232
- console.log(`${typeLabel} ${t.name.padEnd(20)} ${chalk2.dim(t.path)}`);
2233
- }
2234
- }
2235
- function parseNewArgs(args) {
2236
- let name;
2237
- let split = false;
2238
- for (const arg of args) {
2239
- if (arg === "-s" || arg === "--split") {
2240
- split = true;
2241
- } else if (!arg.startsWith("-") && !name) {
2242
- name = arg;
2243
- }
1901
+ for (const wt of worktrees) {
1902
+ console.log(`${chalk.cyan("[W]")} ${wt.branch.padEnd(20)} ${chalk.dim(wt.path)}`);
2244
1903
  }
2245
- return { name, split };
2246
1904
  }
2247
1905
  async function createWorktreeCommand(workspaceRoot, args) {
2248
- const { name, split } = parseNewArgs(args);
1906
+ const name = args.find((a) => !a.startsWith("-"));
2249
1907
  if (!name) {
2250
- console.error(chalk2.red("Error: Name is required"));
2251
- console.error(chalk2.dim("Usage: csq new <name> [-s|--split]"));
1908
+ console.error(chalk.red("Error: Name is required"));
1909
+ console.error(chalk.dim("Usage: csq new <name>"));
2252
1910
  process.exit(1);
2253
1911
  }
2254
- const repoName = path12.basename(workspaceRoot);
2255
- const defaultBasePath = path12.join(path12.dirname(workspaceRoot), `${repoName}.worktree`);
2256
- const worktreePath = path12.join(defaultBasePath, name);
1912
+ const repoName = path11.basename(workspaceRoot);
1913
+ const defaultBasePath = path11.join(path11.dirname(workspaceRoot), `${repoName}.worktree`);
1914
+ const worktreePath = path11.join(defaultBasePath, name);
2257
1915
  try {
2258
1916
  await gitAdapter.createWorktree(worktreePath, name, workspaceRoot);
2259
- console.log(chalk2.green(`\u2713 Created worktree: ${name}`));
1917
+ console.log(chalk.green(`\u2713 Created worktree: ${name}`));
2260
1918
  await copyWorktreeFiles(workspaceRoot, worktreePath);
2261
- if (split) {
2262
- await openNewTerminal(worktreePath);
2263
- } else if (process.platform === "darwin") {
2264
- const success = await cdInCurrentTerminal(worktreePath);
2265
- if (!success) {
2266
- console.log(chalk2.dim("\nNote: Auto-cd may require shell function setup."));
2267
- console.log(chalk2.dim('Run: eval "$(csq --init)"'));
2268
- }
2269
- } else {
2270
- console.log(worktreePath);
2271
- }
1919
+ console.log(worktreePath);
2272
1920
  } catch (error) {
2273
- console.error(chalk2.red(`Failed to create worktree: ${error.message}`));
1921
+ console.error(chalk.red(`Failed to create worktree: ${error.message}`));
2274
1922
  process.exit(1);
2275
1923
  }
2276
1924
  }
@@ -2278,35 +1926,31 @@ async function quitWorktreeCommand() {
2278
1926
  const cwd = process.cwd();
2279
1927
  const context = await gitAdapter.getWorktreeContext(cwd);
2280
1928
  if (!context.isWorktree) {
2281
- console.error(chalk2.red("Error: Not in a worktree"));
1929
+ console.error(chalk.red("Error: Not in a worktree"));
2282
1930
  process.exit(1);
2283
1931
  }
2284
1932
  if (!context.mainRoot || !context.branch) {
2285
- console.error(chalk2.red("Error: Could not determine worktree context"));
1933
+ console.error(chalk.red("Error: Could not determine worktree context"));
2286
1934
  process.exit(1);
2287
1935
  }
2288
1936
  const isDirty = await gitAdapter.hasDirtyState(cwd);
2289
1937
  if (isDirty) {
2290
- const confirmed = await confirm2({
1938
+ const confirmed = await confirm({
2291
1939
  message: "Uncommitted changes detected. Delete anyway?",
2292
1940
  default: false
2293
1941
  });
2294
1942
  if (!confirmed) {
2295
- console.log(chalk2.dim("Cancelled."));
1943
+ console.log(chalk.dim("Cancelled."));
2296
1944
  process.exit(0);
2297
1945
  }
2298
1946
  }
2299
1947
  try {
2300
1948
  await gitAdapter.removeWorktree(context.currentPath, context.mainRoot, true);
2301
1949
  await gitAdapter.deleteBranch(context.branch, context.mainRoot, true);
2302
- console.log(chalk2.green(`\u2713 Deleted worktree and branch: ${context.branch}`));
2303
- if (process.platform === "darwin") {
2304
- await cdInCurrentTerminal(context.mainRoot);
2305
- } else {
2306
- console.log(context.mainRoot);
2307
- }
1950
+ console.log(chalk.green(`\u2713 Deleted worktree and branch: ${context.branch}`));
1951
+ console.log(context.mainRoot);
2308
1952
  } catch (error) {
2309
- console.error(chalk2.red(`Failed to quit: ${error.message}`));
1953
+ console.error(chalk.red(`Failed to quit: ${error.message}`));
2310
1954
  process.exit(1);
2311
1955
  }
2312
1956
  }
@@ -2318,224 +1962,16 @@ async function copyWorktreeFiles(sourceRoot, destRoot) {
2318
1962
  }
2319
1963
  const { copied, failed } = await copyFilesWithPatterns(sourceRoot, destRoot, patterns);
2320
1964
  if (copied.length > 0) {
2321
- console.log(chalk2.green(`\u2713 Copied ${copied.length} file(s) to worktree`));
1965
+ console.log(chalk.green(`\u2713 Copied ${copied.length} file(s) to worktree`));
2322
1966
  }
2323
1967
  if (failed.length > 0) {
2324
- console.log(chalk2.yellow(`\u26A0 Failed to copy ${failed.length} file(s)`));
2325
- }
2326
- }
2327
- async function cdInCurrentTerminal(targetPath) {
2328
- const { exec: exec2 } = await import("child_process");
2329
- const escapedPath = targetPath.replace(/'/g, "'\\''");
2330
- const termProgram = process.env.TERM_PROGRAM;
2331
- if (termProgram === "vscode" || termProgram?.includes("cursor")) {
2332
- console.log(targetPath);
2333
- return true;
2334
- }
2335
- if (termProgram === "iTerm.app") {
2336
- const script = `
2337
- tell application "iTerm"
2338
- tell current session of current window
2339
- write text "cd '${escapedPath}'"
2340
- end tell
2341
- end tell`;
2342
- return new Promise((resolve2) => {
2343
- exec2(`osascript -e '${script}'`, (error, stdout, stderr) => {
2344
- if (error) {
2345
- console.log(targetPath);
2346
- resolve2(true);
2347
- return;
2348
- }
2349
- resolve2(true);
2350
- });
2351
- });
2352
- }
2353
- if (termProgram === "Apple_Terminal") {
2354
- const terminalScript = `
2355
- tell application "Terminal"
2356
- do script "cd '${escapedPath}'" in front window
2357
- end tell`;
2358
- return new Promise((resolve2) => {
2359
- exec2(`osascript -e '${terminalScript}'`, (error, stdout, stderr) => {
2360
- if (error) {
2361
- console.log(targetPath);
2362
- resolve2(true);
2363
- return;
2364
- }
2365
- resolve2(true);
2366
- });
2367
- });
2368
- }
2369
- const hasIterm = await new Promise((resolve2) => {
2370
- exec2('mdfind "kMDItemCFBundleIdentifier == com.googlecode.iterm2"', (error, stdout) => {
2371
- resolve2(!error && stdout.trim().length > 0);
2372
- });
2373
- });
2374
- if (hasIterm) {
2375
- const script = `
2376
- tell application "iTerm2"
2377
- tell current session of current window
2378
- write text "cd '${escapedPath}'"
2379
- end tell
2380
- end tell`;
2381
- return new Promise((resolve2) => {
2382
- exec2(`osascript -e '${script}'`, (error) => {
2383
- if (error) {
2384
- console.log(targetPath);
2385
- }
2386
- resolve2(true);
2387
- });
2388
- });
2389
- }
2390
- console.log(targetPath);
2391
- return true;
2392
- }
2393
- async function openNewTerminal(targetPath) {
2394
- const { exec: exec2 } = await import("child_process");
2395
- const escapedPath = targetPath.replace(/'/g, "'\\''");
2396
- const hasIterm = await new Promise((resolve2) => {
2397
- exec2('mdfind "kMDItemCFBundleIdentifier == com.googlecode.iterm2"', (error, stdout) => {
2398
- resolve2(!error && stdout.trim().length > 0);
2399
- });
2400
- });
2401
- if (hasIterm) {
2402
- const script = `
2403
- tell application "iTerm2"
2404
- tell current session of current window
2405
- set newSession to (split vertically with default profile)
2406
- tell newSession
2407
- write text "cd '${escapedPath}'"
2408
- end tell
2409
- end tell
2410
- end tell`;
2411
- return new Promise((resolve2) => {
2412
- exec2(`osascript -e '${script}'`, (error) => {
2413
- resolve2(!error);
2414
- });
2415
- });
2416
- }
2417
- const terminalScript = `
2418
- tell application "Terminal"
2419
- activate
2420
- do script "cd '${escapedPath}'"
2421
- end tell`;
2422
- return new Promise((resolve2) => {
2423
- exec2(`osascript -e '${terminalScript}'`, (error) => {
2424
- resolve2(!error);
2425
- });
2426
- });
2427
- }
2428
- async function interactiveMode(workspaceRoot) {
2429
- const result = await runInteraction(workspaceRoot);
2430
- if (result?.cdPath) {
2431
- await cdInCurrentTerminal(result.cdPath);
2432
- }
2433
- }
2434
- async function persistentInteractiveMode(workspaceRoot) {
2435
- while (true) {
2436
- console.clear();
2437
- const result = await runInteraction(workspaceRoot, true);
2438
- if (result?.exit) {
2439
- break;
2440
- }
2441
- if (result?.cdPath) {
2442
- await openNewTerminal(result.cdPath);
2443
- }
1968
+ console.log(chalk.yellow(`\u26A0 Failed to copy ${failed.length} file(s)`));
2444
1969
  }
2445
1970
  }
2446
- async function executeDelete(thread, workspaceRoot) {
2447
- if (thread.type === "local") {
2448
- const confirmed = await confirmDeleteLocal(thread.name);
2449
- if (confirmed) {
2450
- await removeLocalThread(workspaceRoot, thread.id);
2451
- console.log(chalk2.green(`\u2713 Deleted local thread: ${thread.name}`));
2452
- } else {
2453
- console.log(chalk2.dim("Cancelled."));
2454
- }
2455
- } else {
2456
- const { confirmed, removeGitWorktree } = await confirmDeleteWorktree(thread.name);
2457
- if (confirmed && removeGitWorktree) {
2458
- try {
2459
- await gitAdapter.removeWorktree(thread.path, workspaceRoot, true);
2460
- await gitAdapter.deleteBranch(thread.branch, workspaceRoot, true);
2461
- console.log(chalk2.green(`\u2713 Deleted worktree and branch: ${thread.name}`));
2462
- } catch (error) {
2463
- console.error(chalk2.red(`Failed to delete: ${error.message}`));
2464
- }
2465
- } else if (confirmed) {
2466
- console.log(chalk2.yellow("Worktree kept."));
2467
- } else {
2468
- console.log(chalk2.dim("Cancelled."));
2469
- }
2470
- }
2471
- }
2472
- async function runInteraction(workspaceRoot, _persistent = false) {
2473
- const threads = await getAllThreads(workspaceRoot);
2474
- const repoName = path12.basename(workspaceRoot);
2475
- const choice = await selectThread(threads, repoName);
2476
- if (choice.type === "exit") {
2477
- return { exit: true };
2478
- }
2479
- let targetPath;
2480
- switch (choice.type) {
2481
- case "existing": {
2482
- const thread = choice.thread;
2483
- const action = await selectThreadAction(thread.name);
2484
- if (action === "open") {
2485
- targetPath = thread.path;
2486
- } else if (action === "delete") {
2487
- await executeDelete(thread, workspaceRoot);
2488
- return null;
2489
- } else {
2490
- return null;
2491
- }
2492
- break;
2493
- }
2494
- case "delete-selected": {
2495
- const thread = choice.thread;
2496
- await executeDelete(thread, workspaceRoot);
2497
- return null;
2498
- }
2499
- case "new": {
2500
- const newType = await selectNewThreadType();
2501
- if (newType === "back") {
2502
- return null;
2503
- }
2504
- if (newType === "worktree") {
2505
- const defaultBasePath = path12.join(path12.dirname(workspaceRoot), `${repoName}.worktree`);
2506
- const form = await newWorktreeForm(defaultBasePath);
2507
- if (!form) {
2508
- return null;
2509
- }
2510
- try {
2511
- await gitAdapter.createWorktree(form.path, form.name, workspaceRoot);
2512
- console.log(chalk2.green(`\u2713 Created worktree: ${form.name}`));
2513
- await copyWorktreeFiles(workspaceRoot, form.path);
2514
- targetPath = form.path;
2515
- } catch (error) {
2516
- console.error(chalk2.red(`Failed to create worktree: ${error.message}`));
2517
- }
2518
- } else {
2519
- const name = await newLocalForm();
2520
- if (!name) {
2521
- return null;
2522
- }
2523
- await addLocalThread(workspaceRoot, name);
2524
- console.log(chalk2.green(`\u2713 Created local thread: ${name}`));
2525
- targetPath = workspaceRoot;
2526
- }
2527
- break;
2528
- }
2529
- }
2530
- if (targetPath) {
2531
- return { cdPath: targetPath };
2532
- }
2533
- return null;
2534
- }
2535
1971
  main().catch((error) => {
2536
1972
  if (error.message?.includes("SIGINT") || error.message?.includes("force closed")) {
2537
1973
  process.exit(130);
2538
1974
  }
2539
- console.error(chalk2.red(`Error: ${error.message}`));
1975
+ console.error(chalk.red(`Error: ${error.message}`));
2540
1976
  process.exit(1);
2541
1977
  });