@staff0rd/assist 0.66.0 → 0.67.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
@@ -6,7 +6,7 @@ import { Command } from "commander";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@staff0rd/assist",
9
- version: "0.66.0",
9
+ version: "0.67.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -28,7 +28,8 @@ var package_default = {
28
28
  "verify:knip": "knip --no-progress --treat-config-hints-as-errors",
29
29
  "verify:duplicate-code": "jscpd --format 'typescript,tsx' --exitCode 1 --ignore '**/*.test.*' -r consoleFull src",
30
30
  "verify:maintainability": "assist complexity maintainability ./src --threshold 70",
31
- "verify:custom-lint": "assist lint"
31
+ "verify:custom-lint": "assist lint",
32
+ "verify:react-build": 'esbuild src/commands/backlog/web/ui/App.tsx --bundle --minify --format=iife --target=es2020 --outfile=dist/commands/backlog/web/bundle.js --jsx=automatic --jsx-import-source=react "--define:process.env.NODE_ENV=\\"production\\""'
32
33
  },
33
34
  keywords: [],
34
35
  author: "",
@@ -58,9 +59,15 @@ var package_default = {
58
59
  "@semantic-release/git": "^10.0.1",
59
60
  "@types/node": "^24.10.1",
60
61
  "@types/node-notifier": "^8.0.5",
62
+ "@types/react": "^19.2.14",
63
+ "@types/react-dom": "^19.2.3",
61
64
  "@types/semver": "^7.7.1",
65
+ esbuild: "^0.27.3",
62
66
  jscpd: "^4.0.5",
63
67
  knip: "^5.71.0",
68
+ marked: "^15.0.12",
69
+ react: "^19.2.4",
70
+ "react-dom": "^19.2.4",
64
71
  "semantic-release": "^25.0.2",
65
72
  tsup: "^8.5.1"
66
73
  }
@@ -147,9 +154,11 @@ function loadConfig() {
147
154
  const merged = { ...globalRaw, ...projectRaw };
148
155
  return assistConfigSchema.parse(merged);
149
156
  }
150
- function loadGlobalConfig() {
151
- const raw = loadRawConfig(getGlobalConfigPath());
152
- return assistConfigSchema.parse(raw);
157
+ function loadProjectConfig() {
158
+ return loadRawConfig(getConfigPath());
159
+ }
160
+ function loadGlobalConfigRaw() {
161
+ return loadRawConfig(getGlobalConfigPath());
153
162
  }
154
163
  function saveGlobalConfig(config) {
155
164
  writeFileSync(getGlobalConfigPath(), stringifyYaml(config, { lineWidth: 0 }));
@@ -291,14 +300,10 @@ function exitValidationFailed(issues, key) {
291
300
  function validateConfig(updated, key) {
292
301
  const result = assistConfigSchema.safeParse(updated);
293
302
  if (!result.success) return exitValidationFailed(result.error.issues, key);
294
- return result.data;
303
+ return updated;
295
304
  }
296
305
  function applyConfigSet(key, coerced) {
297
- const updated = setNestedValue(
298
- loadConfig(),
299
- key,
300
- coerced
301
- );
306
+ const updated = setNestedValue(loadProjectConfig(), key, coerced);
302
307
  saveConfig(validateConfig(updated, key));
303
308
  }
304
309
  function configSet(key, value) {
@@ -2082,6 +2087,202 @@ async function start(id) {
2082
2087
  }
2083
2088
  }
2084
2089
 
2090
+ // src/commands/backlog/web/index.ts
2091
+ import { createServer } from "http";
2092
+ import chalk28 from "chalk";
2093
+
2094
+ // src/commands/backlog/web/handleRequest.ts
2095
+ import { readFileSync as readFileSync11 } from "fs";
2096
+ import { dirname as dirname11, join as join10 } from "path";
2097
+ import { fileURLToPath as fileURLToPath3 } from "url";
2098
+
2099
+ // src/commands/backlog/web/getHtml.ts
2100
+ function getHtml() {
2101
+ return `<!DOCTYPE html>
2102
+ <html lang="en">
2103
+ <head>
2104
+ <meta charset="UTF-8">
2105
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
2106
+ <title>Backlog</title>
2107
+ <style>
2108
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
2109
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f5f5; color: #333; line-height: 1.5; }
2110
+ .container { max-width: 800px; margin: 0 auto; padding: 24px 16px; }
2111
+ header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; }
2112
+ header h1 { font-size: 1.5rem; }
2113
+ button { cursor: pointer; border: none; border-radius: 6px; padding: 8px 16px; font-size: 0.875rem; font-weight: 500; }
2114
+ .btn-primary { background: #2563eb; color: #fff; }
2115
+ .btn-primary:hover { background: #1d4ed8; }
2116
+ .btn-secondary { background: #e5e7eb; color: #333; }
2117
+ .btn-secondary:hover { background: #d1d5db; }
2118
+ .btn-danger { background: #ef4444; color: #fff; }
2119
+ .btn-danger:hover { background: #dc2626; }
2120
+ .card { background: #fff; border-radius: 8px; padding: 16px; margin-bottom: 8px; cursor: pointer; border: 1px solid #e5e7eb; transition: box-shadow 0.15s; display: flex; align-items: center; gap: 12px; }
2121
+ .card:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
2122
+ .status-icon { font-size: 1.1rem; flex-shrink: 0; }
2123
+ .status-todo { color: #9ca3af; }
2124
+ .status-in-progress { color: #f59e0b; }
2125
+ .status-done { color: #22c55e; }
2126
+ .card-id { color: #9ca3af; font-size: 0.85rem; flex-shrink: 0; }
2127
+ .card-name { font-weight: 500; }
2128
+ .detail { background: #fff; border-radius: 8px; padding: 24px; border: 1px solid #e5e7eb; }
2129
+ .detail h2 { margin-bottom: 4px; }
2130
+ .detail-id { color: #9ca3af; font-size: 0.9rem; margin-bottom: 16px; }
2131
+ .detail-section { margin-bottom: 16px; }
2132
+ .detail-section h3 { font-size: 0.85rem; text-transform: uppercase; color: #6b7280; margin-bottom: 8px; letter-spacing: 0.05em; }
2133
+ .detail-section .markdown { line-height: 1.7; }
2134
+ .detail-section .markdown p { margin-bottom: 0.5em; }
2135
+ .detail-section .markdown pre { background: #f3f4f6; padding: 12px; border-radius: 6px; overflow-x: auto; }
2136
+ .detail-section .markdown code { background: #f3f4f6; padding: 2px 4px; border-radius: 3px; font-size: 0.9em; }
2137
+ .detail-section .markdown pre code { background: none; padding: 0; }
2138
+ .ac-list { list-style: none; }
2139
+ .ac-list li { padding: 4px 0; }
2140
+ .ac-list li::before { content: "\\2022"; color: #6b7280; margin-right: 8px; }
2141
+ .back-link { display: inline-block; margin-bottom: 16px; color: #2563eb; text-decoration: none; font-size: 0.9rem; }
2142
+ .back-link:hover { text-decoration: underline; }
2143
+ .form { background: #fff; border-radius: 8px; padding: 24px; border: 1px solid #e5e7eb; }
2144
+ .form h2 { margin-bottom: 16px; }
2145
+ .field { margin-bottom: 16px; }
2146
+ .field label { display: block; font-weight: 500; margin-bottom: 4px; font-size: 0.9rem; }
2147
+ .field input, .field textarea { width: 100%; padding: 8px 12px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; font-family: inherit; }
2148
+ .field textarea { min-height: 120px; resize: vertical; }
2149
+ .ac-inputs { display: flex; flex-direction: column; gap: 8px; }
2150
+ .ac-row { display: flex; gap: 8px; }
2151
+ .ac-row input { flex: 1; }
2152
+ .form-actions { display: flex; gap: 8px; margin-top: 16px; }
2153
+ .preview-toggle { font-size: 0.8rem; color: #2563eb; cursor: pointer; margin-left: 8px; }
2154
+ .preview-box { border: 1px solid #e5e7eb; border-radius: 6px; padding: 12px; margin-top: 8px; min-height: 60px; background: #fafafa; }
2155
+ .empty { text-align: center; color: #9ca3af; padding: 48px 16px; }
2156
+ .status-badge { display: inline-block; padding: 2px 10px; border-radius: 999px; font-size: 0.8rem; font-weight: 500; }
2157
+ .badge-todo { background: #f3f4f6; color: #6b7280; }
2158
+ .badge-in-progress { background: #fef3c7; color: #92400e; }
2159
+ .badge-done { background: #d1fae5; color: #065f46; }
2160
+ </style>
2161
+ </head>
2162
+ <body>
2163
+ <div class="container" id="app"></div>
2164
+ <script src="/bundle.js"></script>
2165
+ </body>
2166
+ </html>`;
2167
+ }
2168
+
2169
+ // src/commands/backlog/web/shared.ts
2170
+ function respondJson(res, status, data) {
2171
+ res.writeHead(status, { "Content-Type": "application/json" });
2172
+ res.end(JSON.stringify(data));
2173
+ }
2174
+ function readBody(req) {
2175
+ return new Promise((resolve3, reject) => {
2176
+ let body = "";
2177
+ req.on("data", (chunk) => {
2178
+ body += chunk.toString();
2179
+ });
2180
+ req.on("end", () => resolve3(body));
2181
+ req.on("error", reject);
2182
+ });
2183
+ }
2184
+ function listItems(_req, res) {
2185
+ respondJson(res, 200, loadBacklog());
2186
+ }
2187
+ function getItemById(res, id) {
2188
+ const items = loadBacklog();
2189
+ const item = items.find((i) => i.id === id);
2190
+ if (!item) {
2191
+ respondJson(res, 404, { error: "Not found" });
2192
+ return;
2193
+ }
2194
+ respondJson(res, 200, item);
2195
+ }
2196
+ async function createItem(req, res) {
2197
+ const body = JSON.parse(await readBody(req));
2198
+ const items = loadBacklog();
2199
+ const id = getNextId(items);
2200
+ const newItem = {
2201
+ id,
2202
+ name: body.name,
2203
+ description: body.description,
2204
+ acceptanceCriteria: body.acceptanceCriteria ?? [],
2205
+ status: "todo"
2206
+ };
2207
+ items.push(newItem);
2208
+ saveBacklog(items);
2209
+ respondJson(res, 201, newItem);
2210
+ }
2211
+ async function updateItem(req, res, id) {
2212
+ const body = JSON.parse(await readBody(req));
2213
+ const items = loadBacklog();
2214
+ const item = items.find((i) => i.id === id);
2215
+ if (!item) {
2216
+ respondJson(res, 404, { error: "Not found" });
2217
+ return;
2218
+ }
2219
+ item.name = body.name;
2220
+ item.description = body.description;
2221
+ item.acceptanceCriteria = body.acceptanceCriteria ?? [];
2222
+ saveBacklog(items);
2223
+ respondJson(res, 200, item);
2224
+ }
2225
+
2226
+ // src/commands/backlog/web/handleRequest.ts
2227
+ var __dirname4 = dirname11(fileURLToPath3(import.meta.url));
2228
+ var bundleCache;
2229
+ function serveBundle(_req, res) {
2230
+ if (!bundleCache) {
2231
+ bundleCache = readFileSync11(
2232
+ join10(__dirname4, "commands/backlog/web/bundle.js"),
2233
+ "utf-8"
2234
+ );
2235
+ }
2236
+ res.writeHead(200, { "Content-Type": "application/javascript" });
2237
+ res.end(bundleCache);
2238
+ }
2239
+ function serveHtml(_req, res) {
2240
+ res.writeHead(200, { "Content-Type": "text/html" });
2241
+ res.end(getHtml());
2242
+ }
2243
+ var routes = {
2244
+ "GET /": serveHtml,
2245
+ "GET /bundle.js": serveBundle,
2246
+ "GET /api/items": listItems,
2247
+ "POST /api/items": createItem
2248
+ };
2249
+ async function handleRequest(req, res, port) {
2250
+ const url = new URL(req.url ?? "/", `http://localhost:${port}`);
2251
+ const method = req.method ?? "GET";
2252
+ const key = `${method} ${url.pathname}`;
2253
+ const handler = routes[key];
2254
+ if (handler) {
2255
+ await handler(req, res);
2256
+ return;
2257
+ }
2258
+ const itemMatch = url.pathname.match(/^\/api\/items\/(\d+)$/);
2259
+ if (itemMatch) {
2260
+ const id = Number.parseInt(itemMatch[1], 10);
2261
+ if (method === "GET") {
2262
+ getItemById(res, id);
2263
+ return;
2264
+ }
2265
+ if (method === "PUT") {
2266
+ await updateItem(req, res, id);
2267
+ return;
2268
+ }
2269
+ }
2270
+ res.writeHead(404);
2271
+ res.end();
2272
+ }
2273
+
2274
+ // src/commands/backlog/web/index.ts
2275
+ async function web(options2) {
2276
+ const port = Number.parseInt(options2.port, 10);
2277
+ const server = createServer((req, res) => {
2278
+ handleRequest(req, res, port);
2279
+ });
2280
+ server.listen(port, () => {
2281
+ console.log(chalk28.green(`Backlog web view: http://localhost:${port}`));
2282
+ console.log(chalk28.dim("Press Ctrl+C to stop"));
2283
+ });
2284
+ }
2285
+
2085
2286
  // src/commands/registerBacklog.ts
2086
2287
  function registerBacklog(program2) {
2087
2288
  const backlogCommand = program2.command("backlog").description("Manage a backlog of work items").action(list);
@@ -2090,18 +2291,19 @@ function registerBacklog(program2) {
2090
2291
  backlogCommand.command("add").description("Add a new backlog item").action(add);
2091
2292
  backlogCommand.command("start <id>").description("Set a backlog item to in-progress").action(start);
2092
2293
  backlogCommand.command("done <id>").description("Set a backlog item to done").action(done);
2294
+ backlogCommand.command("web").description("Start a web view of the backlog").option("-p, --port <number>", "Port to listen on", "3000").action(web);
2093
2295
  }
2094
2296
 
2095
2297
  // src/commands/complexity/analyze.ts
2096
- import chalk33 from "chalk";
2298
+ import chalk34 from "chalk";
2097
2299
 
2098
2300
  // src/commands/complexity/cyclomatic.ts
2099
- import chalk29 from "chalk";
2301
+ import chalk30 from "chalk";
2100
2302
 
2101
2303
  // src/commands/complexity/shared/index.ts
2102
2304
  import fs11 from "fs";
2103
2305
  import path16 from "path";
2104
- import chalk28 from "chalk";
2306
+ import chalk29 from "chalk";
2105
2307
  import ts5 from "typescript";
2106
2308
 
2107
2309
  // src/commands/complexity/findSourceFiles.ts
@@ -2347,7 +2549,7 @@ function createSourceFromFile(filePath) {
2347
2549
  function withSourceFiles(pattern2, callback) {
2348
2550
  const files = findSourceFiles2(pattern2);
2349
2551
  if (files.length === 0) {
2350
- console.log(chalk28.yellow("No files found matching pattern"));
2552
+ console.log(chalk29.yellow("No files found matching pattern"));
2351
2553
  return void 0;
2352
2554
  }
2353
2555
  return callback(files);
@@ -2380,11 +2582,11 @@ async function cyclomatic(pattern2 = "**/*.ts", options2 = {}) {
2380
2582
  results.sort((a, b) => b.complexity - a.complexity);
2381
2583
  for (const { file, name, complexity } of results) {
2382
2584
  const exceedsThreshold = options2.threshold !== void 0 && complexity > options2.threshold;
2383
- const color = exceedsThreshold ? chalk29.red : chalk29.white;
2384
- console.log(`${color(`${file}:${name}`)} \u2192 ${chalk29.cyan(complexity)}`);
2585
+ const color = exceedsThreshold ? chalk30.red : chalk30.white;
2586
+ console.log(`${color(`${file}:${name}`)} \u2192 ${chalk30.cyan(complexity)}`);
2385
2587
  }
2386
2588
  console.log(
2387
- chalk29.dim(
2589
+ chalk30.dim(
2388
2590
  `
2389
2591
  Analyzed ${results.length} functions across ${files.length} files`
2390
2592
  )
@@ -2396,7 +2598,7 @@ Analyzed ${results.length} functions across ${files.length} files`
2396
2598
  }
2397
2599
 
2398
2600
  // src/commands/complexity/halstead.ts
2399
- import chalk30 from "chalk";
2601
+ import chalk31 from "chalk";
2400
2602
  async function halstead(pattern2 = "**/*.ts", options2 = {}) {
2401
2603
  withSourceFiles(pattern2, (files) => {
2402
2604
  const results = [];
@@ -2411,13 +2613,13 @@ async function halstead(pattern2 = "**/*.ts", options2 = {}) {
2411
2613
  results.sort((a, b) => b.metrics.effort - a.metrics.effort);
2412
2614
  for (const { file, name, metrics } of results) {
2413
2615
  const exceedsThreshold = options2.threshold !== void 0 && metrics.volume > options2.threshold;
2414
- const color = exceedsThreshold ? chalk30.red : chalk30.white;
2616
+ const color = exceedsThreshold ? chalk31.red : chalk31.white;
2415
2617
  console.log(
2416
- `${color(`${file}:${name}`)} \u2192 volume: ${chalk30.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk30.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk30.magenta(metrics.effort.toFixed(1))}`
2618
+ `${color(`${file}:${name}`)} \u2192 volume: ${chalk31.cyan(metrics.volume.toFixed(1))}, difficulty: ${chalk31.yellow(metrics.difficulty.toFixed(1))}, effort: ${chalk31.magenta(metrics.effort.toFixed(1))}`
2417
2619
  );
2418
2620
  }
2419
2621
  console.log(
2420
- chalk30.dim(
2622
+ chalk31.dim(
2421
2623
  `
2422
2624
  Analyzed ${results.length} functions across ${files.length} files`
2423
2625
  )
@@ -2432,28 +2634,28 @@ Analyzed ${results.length} functions across ${files.length} files`
2432
2634
  import fs12 from "fs";
2433
2635
 
2434
2636
  // src/commands/complexity/maintainability/displayMaintainabilityResults.ts
2435
- import chalk31 from "chalk";
2637
+ import chalk32 from "chalk";
2436
2638
  function displayMaintainabilityResults(results, threshold) {
2437
2639
  const filtered = threshold !== void 0 ? results.filter((r) => r.minMaintainability < threshold) : results;
2438
2640
  if (threshold !== void 0 && filtered.length === 0) {
2439
- console.log(chalk31.green("All files pass maintainability threshold"));
2641
+ console.log(chalk32.green("All files pass maintainability threshold"));
2440
2642
  } else {
2441
2643
  for (const { file, avgMaintainability, minMaintainability } of filtered) {
2442
- const color = threshold !== void 0 ? chalk31.red : chalk31.white;
2644
+ const color = threshold !== void 0 ? chalk32.red : chalk32.white;
2443
2645
  console.log(
2444
- `${color(file)} \u2192 avg: ${chalk31.cyan(avgMaintainability.toFixed(1))}, min: ${chalk31.yellow(minMaintainability.toFixed(1))}`
2646
+ `${color(file)} \u2192 avg: ${chalk32.cyan(avgMaintainability.toFixed(1))}, min: ${chalk32.yellow(minMaintainability.toFixed(1))}`
2445
2647
  );
2446
2648
  }
2447
2649
  }
2448
- console.log(chalk31.dim(`
2650
+ console.log(chalk32.dim(`
2449
2651
  Analyzed ${results.length} files`));
2450
2652
  if (filtered.length > 0 && threshold !== void 0) {
2451
2653
  console.error(
2452
- chalk31.red(
2654
+ chalk32.red(
2453
2655
  `
2454
2656
  Fail: ${filtered.length} file(s) below threshold ${threshold}. Maintainability index (0\u2013100) is derived from Halstead volume, cyclomatic complexity, and lines of code.
2455
2657
 
2456
- \u26A0\uFE0F ${chalk31.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
2658
+ \u26A0\uFE0F ${chalk32.bold("Diagnose and fix one file at a time")} \u2014 do not investigate or fix multiple files in parallel. Run 'assist complexity <file>' to see all metrics. For larger files, start by extracting responsibilities into smaller files.`
2457
2659
  )
2458
2660
  );
2459
2661
  process.exit(1);
@@ -2510,7 +2712,7 @@ async function maintainability(pattern2 = "**/*.ts", options2 = {}) {
2510
2712
 
2511
2713
  // src/commands/complexity/sloc.ts
2512
2714
  import fs13 from "fs";
2513
- import chalk32 from "chalk";
2715
+ import chalk33 from "chalk";
2514
2716
  async function sloc(pattern2 = "**/*.ts", options2 = {}) {
2515
2717
  withSourceFiles(pattern2, (files) => {
2516
2718
  const results = [];
@@ -2526,12 +2728,12 @@ async function sloc(pattern2 = "**/*.ts", options2 = {}) {
2526
2728
  results.sort((a, b) => b.lines - a.lines);
2527
2729
  for (const { file, lines } of results) {
2528
2730
  const exceedsThreshold = options2.threshold !== void 0 && lines > options2.threshold;
2529
- const color = exceedsThreshold ? chalk32.red : chalk32.white;
2530
- console.log(`${color(file)} \u2192 ${chalk32.cyan(lines)} lines`);
2731
+ const color = exceedsThreshold ? chalk33.red : chalk33.white;
2732
+ console.log(`${color(file)} \u2192 ${chalk33.cyan(lines)} lines`);
2531
2733
  }
2532
2734
  const total = results.reduce((sum, r) => sum + r.lines, 0);
2533
2735
  console.log(
2534
- chalk32.dim(`
2736
+ chalk33.dim(`
2535
2737
  Total: ${total} lines across ${files.length} files`)
2536
2738
  );
2537
2739
  if (hasViolation) {
@@ -2545,21 +2747,21 @@ async function analyze(pattern2) {
2545
2747
  const searchPattern = pattern2.includes("*") || pattern2.includes("/") ? pattern2 : `**/${pattern2}`;
2546
2748
  const files = findSourceFiles2(searchPattern);
2547
2749
  if (files.length === 0) {
2548
- console.log(chalk33.yellow("No files found matching pattern"));
2750
+ console.log(chalk34.yellow("No files found matching pattern"));
2549
2751
  return;
2550
2752
  }
2551
2753
  if (files.length === 1) {
2552
2754
  const file = files[0];
2553
- console.log(chalk33.bold.underline("SLOC"));
2755
+ console.log(chalk34.bold.underline("SLOC"));
2554
2756
  await sloc(file);
2555
2757
  console.log();
2556
- console.log(chalk33.bold.underline("Cyclomatic Complexity"));
2758
+ console.log(chalk34.bold.underline("Cyclomatic Complexity"));
2557
2759
  await cyclomatic(file);
2558
2760
  console.log();
2559
- console.log(chalk33.bold.underline("Halstead Metrics"));
2761
+ console.log(chalk34.bold.underline("Halstead Metrics"));
2560
2762
  await halstead(file);
2561
2763
  console.log();
2562
- console.log(chalk33.bold.underline("Maintainability Index"));
2764
+ console.log(chalk34.bold.underline("Maintainability Index"));
2563
2765
  await maintainability(file);
2564
2766
  return;
2565
2767
  }
@@ -2586,8 +2788,8 @@ function registerComplexity(program2) {
2586
2788
  }
2587
2789
 
2588
2790
  // src/commands/deploy/redirect.ts
2589
- import { existsSync as existsSync15, readFileSync as readFileSync11, writeFileSync as writeFileSync12 } from "fs";
2590
- import chalk34 from "chalk";
2791
+ import { existsSync as existsSync15, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
2792
+ import chalk35 from "chalk";
2591
2793
  var TRAILING_SLASH_SCRIPT = ` <script>
2592
2794
  if (!window.location.pathname.endsWith('/')) {
2593
2795
  window.location.href = \`\${window.location.pathname}/\${window.location.search}\${window.location.hash}\`;
@@ -2596,22 +2798,22 @@ var TRAILING_SLASH_SCRIPT = ` <script>
2596
2798
  function redirect() {
2597
2799
  const indexPath = "index.html";
2598
2800
  if (!existsSync15(indexPath)) {
2599
- console.log(chalk34.yellow("No index.html found"));
2801
+ console.log(chalk35.yellow("No index.html found"));
2600
2802
  return;
2601
2803
  }
2602
- const content = readFileSync11(indexPath, "utf-8");
2804
+ const content = readFileSync12(indexPath, "utf-8");
2603
2805
  if (content.includes("window.location.pathname.endsWith('/')")) {
2604
- console.log(chalk34.dim("Trailing slash script already present"));
2806
+ console.log(chalk35.dim("Trailing slash script already present"));
2605
2807
  return;
2606
2808
  }
2607
2809
  const headCloseIndex = content.indexOf("</head>");
2608
2810
  if (headCloseIndex === -1) {
2609
- console.log(chalk34.red("Could not find </head> tag in index.html"));
2811
+ console.log(chalk35.red("Could not find </head> tag in index.html"));
2610
2812
  return;
2611
2813
  }
2612
2814
  const newContent = content.slice(0, headCloseIndex) + TRAILING_SLASH_SCRIPT + "\n " + content.slice(headCloseIndex);
2613
2815
  writeFileSync12(indexPath, newContent);
2614
- console.log(chalk34.green("Added trailing slash redirect to index.html"));
2816
+ console.log(chalk35.green("Added trailing slash redirect to index.html"));
2615
2817
  }
2616
2818
 
2617
2819
  // src/commands/registerDeploy.ts
@@ -2627,19 +2829,19 @@ import { basename as basename3 } from "path";
2627
2829
 
2628
2830
  // src/commands/devlog/shared.ts
2629
2831
  import { execSync as execSync11 } from "child_process";
2630
- import chalk35 from "chalk";
2832
+ import chalk36 from "chalk";
2631
2833
 
2632
2834
  // src/commands/devlog/loadDevlogEntries.ts
2633
- import { readdirSync, readFileSync as readFileSync12 } from "fs";
2835
+ import { readdirSync, readFileSync as readFileSync13 } from "fs";
2634
2836
  import { homedir as homedir2 } from "os";
2635
- import { join as join10 } from "path";
2636
- var DEVLOG_DIR = join10(homedir2(), "git/blog/src/content/devlog");
2837
+ import { join as join11 } from "path";
2838
+ var DEVLOG_DIR = join11(homedir2(), "git/blog/src/content/devlog");
2637
2839
  function loadDevlogEntries(repoName) {
2638
2840
  const entries = /* @__PURE__ */ new Map();
2639
2841
  try {
2640
2842
  const files = readdirSync(DEVLOG_DIR).filter((f) => f.endsWith(".md"));
2641
2843
  for (const file of files) {
2642
- const content = readFileSync12(join10(DEVLOG_DIR, file), "utf-8");
2844
+ const content = readFileSync13(join11(DEVLOG_DIR, file), "utf-8");
2643
2845
  const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
2644
2846
  if (frontmatterMatch) {
2645
2847
  const frontmatter = frontmatterMatch[1];
@@ -2688,13 +2890,13 @@ function shouldIgnoreCommit(files, ignorePaths) {
2688
2890
  }
2689
2891
  function printCommitsWithFiles(commits, ignore2, verbose) {
2690
2892
  for (const commit2 of commits) {
2691
- console.log(` ${chalk35.yellow(commit2.hash)} ${commit2.message}`);
2893
+ console.log(` ${chalk36.yellow(commit2.hash)} ${commit2.message}`);
2692
2894
  if (verbose) {
2693
2895
  const visibleFiles = commit2.files.filter(
2694
2896
  (file) => !ignore2.some((p) => file.startsWith(p))
2695
2897
  );
2696
2898
  for (const file of visibleFiles) {
2697
- console.log(` ${chalk35.dim(file)}`);
2899
+ console.log(` ${chalk36.dim(file)}`);
2698
2900
  }
2699
2901
  }
2700
2902
  }
@@ -2719,15 +2921,15 @@ function parseGitLogCommits(output, ignore2, afterDate) {
2719
2921
  }
2720
2922
 
2721
2923
  // src/commands/devlog/list/printDateHeader.ts
2722
- import chalk36 from "chalk";
2924
+ import chalk37 from "chalk";
2723
2925
  function printDateHeader(date, isSkipped, entries) {
2724
2926
  if (isSkipped) {
2725
- console.log(`${chalk36.bold.blue(date)} ${chalk36.dim("skipped")}`);
2927
+ console.log(`${chalk37.bold.blue(date)} ${chalk37.dim("skipped")}`);
2726
2928
  } else if (entries && entries.length > 0) {
2727
- const entryInfo = entries.map((e) => `${chalk36.green(e.version)} ${e.title}`).join(" | ");
2728
- console.log(`${chalk36.bold.blue(date)} ${entryInfo}`);
2929
+ const entryInfo = entries.map((e) => `${chalk37.green(e.version)} ${e.title}`).join(" | ");
2930
+ console.log(`${chalk37.bold.blue(date)} ${entryInfo}`);
2729
2931
  } else {
2730
- console.log(`${chalk36.bold.blue(date)} ${chalk36.red("\u26A0 devlog missing")}`);
2932
+ console.log(`${chalk37.bold.blue(date)} ${chalk37.red("\u26A0 devlog missing")}`);
2731
2933
  }
2732
2934
  }
2733
2935
 
@@ -2830,24 +3032,24 @@ function bumpVersion(version2, type) {
2830
3032
 
2831
3033
  // src/commands/devlog/next/displayNextEntry/index.ts
2832
3034
  import { execSync as execSync14 } from "child_process";
2833
- import chalk38 from "chalk";
3035
+ import chalk39 from "chalk";
2834
3036
 
2835
3037
  // src/commands/devlog/next/displayNextEntry/displayVersion.ts
2836
- import chalk37 from "chalk";
3038
+ import chalk38 from "chalk";
2837
3039
  function displayVersion(conventional, firstHash, patchVersion, minorVersion) {
2838
3040
  if (conventional && firstHash) {
2839
3041
  const version2 = getVersionAtCommit(firstHash);
2840
3042
  if (version2) {
2841
- console.log(`${chalk37.bold("version:")} ${stripToMinor(version2)}`);
3043
+ console.log(`${chalk38.bold("version:")} ${stripToMinor(version2)}`);
2842
3044
  } else {
2843
- console.log(`${chalk37.bold("version:")} ${chalk37.red("unknown")}`);
3045
+ console.log(`${chalk38.bold("version:")} ${chalk38.red("unknown")}`);
2844
3046
  }
2845
3047
  } else if (patchVersion && minorVersion) {
2846
3048
  console.log(
2847
- `${chalk37.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
3049
+ `${chalk38.bold("version:")} ${patchVersion} (patch) or ${minorVersion} (minor)`
2848
3050
  );
2849
3051
  } else {
2850
- console.log(`${chalk37.bold("version:")} v0.1 (initial)`);
3052
+ console.log(`${chalk38.bold("version:")} v0.1 (initial)`);
2851
3053
  }
2852
3054
  }
2853
3055
 
@@ -2894,16 +3096,16 @@ function noCommitsMessage(hasLastInfo) {
2894
3096
  return hasLastInfo ? "No commits after last versioned entry" : "No commits found";
2895
3097
  }
2896
3098
  function logName(repoName) {
2897
- console.log(`${chalk38.bold("name:")} ${repoName}`);
3099
+ console.log(`${chalk39.bold("name:")} ${repoName}`);
2898
3100
  }
2899
3101
  function displayNextEntry(ctx, targetDate, commits) {
2900
3102
  logName(ctx.repoName);
2901
3103
  printVersionInfo(ctx.config, ctx.lastInfo, commits[0]?.hash);
2902
- console.log(chalk38.bold.blue(targetDate));
3104
+ console.log(chalk39.bold.blue(targetDate));
2903
3105
  printCommitsWithFiles(commits, ctx.ignore, ctx.verbose);
2904
3106
  }
2905
3107
  function logNoCommits(lastInfo) {
2906
- console.log(chalk38.dim(noCommitsMessage(!!lastInfo)));
3108
+ console.log(chalk39.dim(noCommitsMessage(!!lastInfo)));
2907
3109
  }
2908
3110
 
2909
3111
  // src/commands/devlog/next/index.ts
@@ -2938,42 +3140,40 @@ function next(options2) {
2938
3140
  }
2939
3141
 
2940
3142
  // src/commands/devlog/skip.ts
2941
- import chalk39 from "chalk";
3143
+ import chalk40 from "chalk";
2942
3144
  function skip(date) {
2943
3145
  if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
2944
- console.log(chalk39.red("Invalid date format. Use YYYY-MM-DD"));
3146
+ console.log(chalk40.red("Invalid date format. Use YYYY-MM-DD"));
2945
3147
  process.exit(1);
2946
3148
  }
2947
- const config = loadConfig();
2948
- const skipDays = config.devlog?.skip?.days ?? [];
3149
+ const config = loadProjectConfig();
3150
+ const devlog = config.devlog ?? {};
3151
+ const skip2 = devlog.skip ?? {};
3152
+ const skipDays = skip2.days ?? [];
2949
3153
  if (skipDays.includes(date)) {
2950
- console.log(chalk39.yellow(`${date} is already in skip list`));
3154
+ console.log(chalk40.yellow(`${date} is already in skip list`));
2951
3155
  return;
2952
3156
  }
2953
3157
  skipDays.push(date);
2954
3158
  skipDays.sort();
2955
- config.devlog = {
2956
- ...config.devlog,
2957
- skip: {
2958
- ...config.devlog?.skip,
2959
- days: skipDays
2960
- }
2961
- };
3159
+ skip2.days = skipDays;
3160
+ devlog.skip = skip2;
3161
+ config.devlog = devlog;
2962
3162
  saveConfig(config);
2963
- console.log(chalk39.green(`Added ${date} to skip list`));
3163
+ console.log(chalk40.green(`Added ${date} to skip list`));
2964
3164
  }
2965
3165
 
2966
3166
  // src/commands/devlog/version.ts
2967
- import chalk40 from "chalk";
3167
+ import chalk41 from "chalk";
2968
3168
  function version() {
2969
3169
  const config = loadConfig();
2970
3170
  const name = getRepoName();
2971
3171
  const lastInfo = getLastVersionInfo(name, config);
2972
3172
  const lastVersion = lastInfo?.version ?? null;
2973
3173
  const nextVersion = lastVersion ? bumpVersion(lastVersion, "patch") : null;
2974
- console.log(`${chalk40.bold("name:")} ${name}`);
2975
- console.log(`${chalk40.bold("last:")} ${lastVersion ?? chalk40.dim("none")}`);
2976
- console.log(`${chalk40.bold("next:")} ${nextVersion ?? chalk40.dim("none")}`);
3174
+ console.log(`${chalk41.bold("name:")} ${name}`);
3175
+ console.log(`${chalk41.bold("last:")} ${lastVersion ?? chalk41.dim("none")}`);
3176
+ console.log(`${chalk41.bold("next:")} ${nextVersion ?? chalk41.dim("none")}`);
2977
3177
  }
2978
3178
 
2979
3179
  // src/commands/registerDevlog.ts
@@ -2996,21 +3196,21 @@ import { execSync as execSync17 } from "child_process";
2996
3196
  import { execSync as execSync16 } from "child_process";
2997
3197
  import { unlinkSync as unlinkSync4, writeFileSync as writeFileSync13 } from "fs";
2998
3198
  import { tmpdir as tmpdir2 } from "os";
2999
- import { join as join12 } from "path";
3199
+ import { join as join13 } from "path";
3000
3200
 
3001
3201
  // src/commands/prs/loadCommentsCache.ts
3002
- import { existsSync as existsSync16, readFileSync as readFileSync13, unlinkSync as unlinkSync3 } from "fs";
3003
- import { join as join11 } from "path";
3202
+ import { existsSync as existsSync16, readFileSync as readFileSync14, unlinkSync as unlinkSync3 } from "fs";
3203
+ import { join as join12 } from "path";
3004
3204
  import { parse } from "yaml";
3005
3205
  function getCachePath(prNumber) {
3006
- return join11(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
3206
+ return join12(process.cwd(), ".assist", `pr-${prNumber}-comments.yaml`);
3007
3207
  }
3008
3208
  function loadCommentsCache(prNumber) {
3009
3209
  const cachePath = getCachePath(prNumber);
3010
3210
  if (!existsSync16(cachePath)) {
3011
3211
  return null;
3012
3212
  }
3013
- const content = readFileSync13(cachePath, "utf-8");
3213
+ const content = readFileSync14(cachePath, "utf-8");
3014
3214
  return parse(content);
3015
3215
  }
3016
3216
  function deleteCommentsCache(prNumber) {
@@ -3066,7 +3266,7 @@ function replyToComment(org, repo, prNumber, commentId, message) {
3066
3266
  }
3067
3267
  function resolveThread(threadId) {
3068
3268
  const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
3069
- const queryFile = join12(tmpdir2(), `gh-mutation-${Date.now()}.graphql`);
3269
+ const queryFile = join13(tmpdir2(), `gh-mutation-${Date.now()}.graphql`);
3070
3270
  writeFileSync13(queryFile, mutation);
3071
3271
  try {
3072
3272
  execSync16(
@@ -3148,7 +3348,7 @@ function fixed(commentId, sha) {
3148
3348
 
3149
3349
  // src/commands/prs/listComments/index.ts
3150
3350
  import { existsSync as existsSync17, mkdirSync as mkdirSync4, writeFileSync as writeFileSync15 } from "fs";
3151
- import { join as join14 } from "path";
3351
+ import { join as join15 } from "path";
3152
3352
  import { stringify } from "yaml";
3153
3353
 
3154
3354
  // src/lib/isClaudeCode.ts
@@ -3160,10 +3360,10 @@ function isClaudeCode2() {
3160
3360
  import { execSync as execSync18 } from "child_process";
3161
3361
  import { unlinkSync as unlinkSync5, writeFileSync as writeFileSync14 } from "fs";
3162
3362
  import { tmpdir as tmpdir3 } from "os";
3163
- import { join as join13 } from "path";
3363
+ import { join as join14 } from "path";
3164
3364
  var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
3165
3365
  function fetchThreadIds(org, repo, prNumber) {
3166
- const queryFile = join13(tmpdir3(), `gh-query-${Date.now()}.graphql`);
3366
+ const queryFile = join14(tmpdir3(), `gh-query-${Date.now()}.graphql`);
3167
3367
  writeFileSync14(queryFile, THREAD_QUERY);
3168
3368
  try {
3169
3369
  const result = execSync18(
@@ -3230,20 +3430,20 @@ function fetchLineComments(org, repo, prNumber, threadInfo) {
3230
3430
  }
3231
3431
 
3232
3432
  // src/commands/prs/listComments/formatForHuman.ts
3233
- import chalk41 from "chalk";
3433
+ import chalk42 from "chalk";
3234
3434
  function formatForHuman(comment) {
3235
3435
  if (comment.type === "review") {
3236
- const stateColor = comment.state === "APPROVED" ? chalk41.green : comment.state === "CHANGES_REQUESTED" ? chalk41.red : chalk41.yellow;
3436
+ const stateColor = comment.state === "APPROVED" ? chalk42.green : comment.state === "CHANGES_REQUESTED" ? chalk42.red : chalk42.yellow;
3237
3437
  return [
3238
- `${chalk41.cyan("Review")} by ${chalk41.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
3438
+ `${chalk42.cyan("Review")} by ${chalk42.bold(comment.user)} ${stateColor(`[${comment.state}]`)}`,
3239
3439
  comment.body,
3240
3440
  ""
3241
3441
  ].join("\n");
3242
3442
  }
3243
3443
  const location = comment.line ? `:${comment.line}` : "";
3244
3444
  return [
3245
- `${chalk41.cyan("Line comment")} by ${chalk41.bold(comment.user)} on ${chalk41.dim(`${comment.path}${location}`)}`,
3246
- chalk41.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
3445
+ `${chalk42.cyan("Line comment")} by ${chalk42.bold(comment.user)} on ${chalk42.dim(`${comment.path}${location}`)}`,
3446
+ chalk42.dim(comment.diff_hunk.split("\n").slice(-3).join("\n")),
3247
3447
  comment.body,
3248
3448
  ""
3249
3449
  ].join("\n");
@@ -3266,7 +3466,7 @@ function printComments(comments) {
3266
3466
  }
3267
3467
  }
3268
3468
  function writeCommentsCache(prNumber, comments) {
3269
- const assistDir = join14(process.cwd(), ".assist");
3469
+ const assistDir = join15(process.cwd(), ".assist");
3270
3470
  if (!existsSync17(assistDir)) {
3271
3471
  mkdirSync4(assistDir, { recursive: true });
3272
3472
  }
@@ -3275,7 +3475,7 @@ function writeCommentsCache(prNumber, comments) {
3275
3475
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString(),
3276
3476
  comments
3277
3477
  };
3278
- const cachePath = join14(assistDir, `pr-${prNumber}-comments.yaml`);
3478
+ const cachePath = join15(assistDir, `pr-${prNumber}-comments.yaml`);
3279
3479
  writeFileSync15(cachePath, stringify(cacheData));
3280
3480
  }
3281
3481
  function handleKnownErrors(error) {
@@ -3322,13 +3522,13 @@ import { execSync as execSync20 } from "child_process";
3322
3522
  import enquirer5 from "enquirer";
3323
3523
 
3324
3524
  // src/commands/prs/prs/displayPaginated/printPr.ts
3325
- import chalk42 from "chalk";
3525
+ import chalk43 from "chalk";
3326
3526
  var STATUS_MAP = {
3327
- MERGED: (pr) => pr.mergedAt ? { label: chalk42.magenta("merged"), date: pr.mergedAt } : null,
3328
- CLOSED: (pr) => pr.closedAt ? { label: chalk42.red("closed"), date: pr.closedAt } : null
3527
+ MERGED: (pr) => pr.mergedAt ? { label: chalk43.magenta("merged"), date: pr.mergedAt } : null,
3528
+ CLOSED: (pr) => pr.closedAt ? { label: chalk43.red("closed"), date: pr.closedAt } : null
3329
3529
  };
3330
3530
  function defaultStatus(pr) {
3331
- return { label: chalk42.green("opened"), date: pr.createdAt };
3531
+ return { label: chalk43.green("opened"), date: pr.createdAt };
3332
3532
  }
3333
3533
  function getStatus(pr) {
3334
3534
  return STATUS_MAP[pr.state]?.(pr) ?? defaultStatus(pr);
@@ -3337,11 +3537,11 @@ function formatDate(dateStr) {
3337
3537
  return new Date(dateStr).toISOString().split("T")[0];
3338
3538
  }
3339
3539
  function formatPrHeader(pr, status) {
3340
- return `${chalk42.cyan(`#${pr.number}`)} ${pr.title} ${chalk42.dim(`(${pr.author.login},`)} ${status.label} ${chalk42.dim(`${formatDate(status.date)})`)}`;
3540
+ return `${chalk43.cyan(`#${pr.number}`)} ${pr.title} ${chalk43.dim(`(${pr.author.login},`)} ${status.label} ${chalk43.dim(`${formatDate(status.date)})`)}`;
3341
3541
  }
3342
3542
  function logPrDetails(pr) {
3343
3543
  console.log(
3344
- chalk42.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
3544
+ chalk43.dim(` ${pr.changedFiles.toLocaleString()} files | ${pr.url}`)
3345
3545
  );
3346
3546
  console.log();
3347
3547
  }
@@ -3508,7 +3708,7 @@ import { spawn as spawn3 } from "child_process";
3508
3708
  import * as path17 from "path";
3509
3709
 
3510
3710
  // src/commands/refactor/logViolations.ts
3511
- import chalk43 from "chalk";
3711
+ import chalk44 from "chalk";
3512
3712
  var DEFAULT_MAX_LINES = 100;
3513
3713
  function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
3514
3714
  if (violations.length === 0) {
@@ -3517,43 +3717,43 @@ function logViolations(violations, maxLines = DEFAULT_MAX_LINES) {
3517
3717
  }
3518
3718
  return;
3519
3719
  }
3520
- console.error(chalk43.red(`
3720
+ console.error(chalk44.red(`
3521
3721
  Refactor check failed:
3522
3722
  `));
3523
- console.error(chalk43.red(` The following files exceed ${maxLines} lines:
3723
+ console.error(chalk44.red(` The following files exceed ${maxLines} lines:
3524
3724
  `));
3525
3725
  for (const violation of violations) {
3526
- console.error(chalk43.red(` ${violation.file} (${violation.lines} lines)`));
3726
+ console.error(chalk44.red(` ${violation.file} (${violation.lines} lines)`));
3527
3727
  }
3528
3728
  console.error(
3529
- chalk43.yellow(
3729
+ chalk44.yellow(
3530
3730
  `
3531
3731
  Each file needs to be sensibly refactored, or if there is no sensible
3532
3732
  way to refactor it, ignore it with:
3533
3733
  `
3534
3734
  )
3535
3735
  );
3536
- console.error(chalk43.gray(` assist refactor ignore <file>
3736
+ console.error(chalk44.gray(` assist refactor ignore <file>
3537
3737
  `));
3538
3738
  if (process.env.CLAUDECODE) {
3539
- console.error(chalk43.cyan(`
3739
+ console.error(chalk44.cyan(`
3540
3740
  ## Extracting Code to New Files
3541
3741
  `));
3542
3742
  console.error(
3543
- chalk43.cyan(
3743
+ chalk44.cyan(
3544
3744
  ` When extracting logic from one file to another, consider where the extracted code belongs:
3545
3745
  `
3546
3746
  )
3547
3747
  );
3548
3748
  console.error(
3549
- chalk43.cyan(
3749
+ chalk44.cyan(
3550
3750
  ` 1. Keep related logic together: If the extracted code is tightly coupled to the
3551
3751
  original file's domain, create a new folder containing both the original and extracted files.
3552
3752
  `
3553
3753
  )
3554
3754
  );
3555
3755
  console.error(
3556
- chalk43.cyan(
3756
+ chalk44.cyan(
3557
3757
  ` 2. Share common utilities: If the extracted code can be reused across multiple
3558
3758
  domains, move it to a common/shared folder.
3559
3759
  `
@@ -3709,11 +3909,11 @@ async function check(pattern2, options2) {
3709
3909
 
3710
3910
  // src/commands/refactor/ignore.ts
3711
3911
  import fs16 from "fs";
3712
- import chalk44 from "chalk";
3912
+ import chalk45 from "chalk";
3713
3913
  var REFACTOR_YML_PATH2 = "refactor.yml";
3714
3914
  function ignore(file) {
3715
3915
  if (!fs16.existsSync(file)) {
3716
- console.error(chalk44.red(`Error: File does not exist: ${file}`));
3916
+ console.error(chalk45.red(`Error: File does not exist: ${file}`));
3717
3917
  process.exit(1);
3718
3918
  }
3719
3919
  const content = fs16.readFileSync(file, "utf-8");
@@ -3729,7 +3929,7 @@ function ignore(file) {
3729
3929
  fs16.writeFileSync(REFACTOR_YML_PATH2, entry);
3730
3930
  }
3731
3931
  console.log(
3732
- chalk44.green(
3932
+ chalk45.green(
3733
3933
  `Added ${file} to refactor ignore list (max ${maxLines} lines)`
3734
3934
  )
3735
3935
  );
@@ -3737,7 +3937,7 @@ function ignore(file) {
3737
3937
 
3738
3938
  // src/commands/refactor/restructure/index.ts
3739
3939
  import path26 from "path";
3740
- import chalk47 from "chalk";
3940
+ import chalk48 from "chalk";
3741
3941
 
3742
3942
  // src/commands/refactor/restructure/buildImportGraph/index.ts
3743
3943
  import path18 from "path";
@@ -3980,50 +4180,50 @@ function computeRewrites(moves, edges, allProjectFiles) {
3980
4180
 
3981
4181
  // src/commands/refactor/restructure/displayPlan.ts
3982
4182
  import path22 from "path";
3983
- import chalk45 from "chalk";
4183
+ import chalk46 from "chalk";
3984
4184
  function relPath(filePath) {
3985
4185
  return path22.relative(process.cwd(), filePath);
3986
4186
  }
3987
4187
  function displayMoves(plan) {
3988
4188
  if (plan.moves.length === 0) return;
3989
- console.log(chalk45.bold("\nFile moves:"));
4189
+ console.log(chalk46.bold("\nFile moves:"));
3990
4190
  for (const move of plan.moves) {
3991
4191
  console.log(
3992
- ` ${chalk45.red(relPath(move.from))} \u2192 ${chalk45.green(relPath(move.to))}`
4192
+ ` ${chalk46.red(relPath(move.from))} \u2192 ${chalk46.green(relPath(move.to))}`
3993
4193
  );
3994
- console.log(chalk45.dim(` ${move.reason}`));
4194
+ console.log(chalk46.dim(` ${move.reason}`));
3995
4195
  }
3996
4196
  }
3997
4197
  function displayRewrites(rewrites) {
3998
4198
  if (rewrites.length === 0) return;
3999
4199
  const affectedFiles = new Set(rewrites.map((r) => r.file));
4000
- console.log(chalk45.bold(`
4200
+ console.log(chalk46.bold(`
4001
4201
  Import rewrites (${affectedFiles.size} files):`));
4002
4202
  for (const file of affectedFiles) {
4003
- console.log(` ${chalk45.cyan(relPath(file))}:`);
4203
+ console.log(` ${chalk46.cyan(relPath(file))}:`);
4004
4204
  for (const { oldSpecifier, newSpecifier } of rewrites.filter(
4005
4205
  (r) => r.file === file
4006
4206
  )) {
4007
4207
  console.log(
4008
- ` ${chalk45.red(`"${oldSpecifier}"`)} \u2192 ${chalk45.green(`"${newSpecifier}"`)}`
4208
+ ` ${chalk46.red(`"${oldSpecifier}"`)} \u2192 ${chalk46.green(`"${newSpecifier}"`)}`
4009
4209
  );
4010
4210
  }
4011
4211
  }
4012
4212
  }
4013
4213
  function displayPlan(plan) {
4014
4214
  if (plan.warnings.length > 0) {
4015
- console.log(chalk45.yellow("\nWarnings:"));
4016
- for (const w of plan.warnings) console.log(chalk45.yellow(` ${w}`));
4215
+ console.log(chalk46.yellow("\nWarnings:"));
4216
+ for (const w of plan.warnings) console.log(chalk46.yellow(` ${w}`));
4017
4217
  }
4018
4218
  if (plan.newDirectories.length > 0) {
4019
- console.log(chalk45.bold("\nNew directories:"));
4219
+ console.log(chalk46.bold("\nNew directories:"));
4020
4220
  for (const dir of plan.newDirectories)
4021
- console.log(chalk45.green(` ${dir}/`));
4221
+ console.log(chalk46.green(` ${dir}/`));
4022
4222
  }
4023
4223
  displayMoves(plan);
4024
4224
  displayRewrites(plan.rewrites);
4025
4225
  console.log(
4026
- chalk45.dim(
4226
+ chalk46.dim(
4027
4227
  `
4028
4228
  Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rewritten`
4029
4229
  )
@@ -4033,18 +4233,18 @@ Summary: ${plan.moves.length} file(s) moved, ${plan.rewrites.length} imports rew
4033
4233
  // src/commands/refactor/restructure/executePlan.ts
4034
4234
  import fs18 from "fs";
4035
4235
  import path23 from "path";
4036
- import chalk46 from "chalk";
4236
+ import chalk47 from "chalk";
4037
4237
  function executePlan(plan) {
4038
4238
  const updatedContents = applyRewrites(plan.rewrites);
4039
4239
  for (const [file, content] of updatedContents) {
4040
4240
  fs18.writeFileSync(file, content, "utf-8");
4041
4241
  console.log(
4042
- chalk46.cyan(` Rewrote imports in ${path23.relative(process.cwd(), file)}`)
4242
+ chalk47.cyan(` Rewrote imports in ${path23.relative(process.cwd(), file)}`)
4043
4243
  );
4044
4244
  }
4045
4245
  for (const dir of plan.newDirectories) {
4046
4246
  fs18.mkdirSync(dir, { recursive: true });
4047
- console.log(chalk46.green(` Created ${path23.relative(process.cwd(), dir)}/`));
4247
+ console.log(chalk47.green(` Created ${path23.relative(process.cwd(), dir)}/`));
4048
4248
  }
4049
4249
  for (const move of plan.moves) {
4050
4250
  const targetDir = path23.dirname(move.to);
@@ -4053,7 +4253,7 @@ function executePlan(plan) {
4053
4253
  }
4054
4254
  fs18.renameSync(move.from, move.to);
4055
4255
  console.log(
4056
- chalk46.white(
4256
+ chalk47.white(
4057
4257
  ` Moved ${path23.relative(process.cwd(), move.from)} \u2192 ${path23.relative(process.cwd(), move.to)}`
4058
4258
  )
4059
4259
  );
@@ -4068,7 +4268,7 @@ function removeEmptyDirectories(dirs) {
4068
4268
  if (entries.length === 0) {
4069
4269
  fs18.rmdirSync(dir);
4070
4270
  console.log(
4071
- chalk46.dim(
4271
+ chalk47.dim(
4072
4272
  ` Removed empty directory ${path23.relative(process.cwd(), dir)}`
4073
4273
  )
4074
4274
  );
@@ -4199,22 +4399,22 @@ async function restructure(pattern2, options2 = {}) {
4199
4399
  const targetPattern = pattern2 ?? "src";
4200
4400
  const files = findSourceFiles2(targetPattern);
4201
4401
  if (files.length === 0) {
4202
- console.log(chalk47.yellow("No files found matching pattern"));
4402
+ console.log(chalk48.yellow("No files found matching pattern"));
4203
4403
  return;
4204
4404
  }
4205
4405
  const tsConfigPath = path26.resolve("tsconfig.json");
4206
4406
  const plan = buildPlan(files, tsConfigPath);
4207
4407
  if (plan.moves.length === 0) {
4208
- console.log(chalk47.green("No restructuring needed"));
4408
+ console.log(chalk48.green("No restructuring needed"));
4209
4409
  return;
4210
4410
  }
4211
4411
  displayPlan(plan);
4212
4412
  if (options2.apply) {
4213
- console.log(chalk47.bold("\nApplying changes..."));
4413
+ console.log(chalk48.bold("\nApplying changes..."));
4214
4414
  executePlan(plan);
4215
- console.log(chalk47.green("\nRestructuring complete"));
4415
+ console.log(chalk48.green("\nRestructuring complete"));
4216
4416
  } else {
4217
- console.log(chalk47.dim("\nDry run. Use --apply to execute."));
4417
+ console.log(chalk48.dim("\nDry run. Use --apply to execute."));
4218
4418
  }
4219
4419
  }
4220
4420
 
@@ -4238,7 +4438,7 @@ function registerRefactor(program2) {
4238
4438
 
4239
4439
  // src/commands/transcript/shared.ts
4240
4440
  import { existsSync as existsSync18, readdirSync as readdirSync2, statSync } from "fs";
4241
- import { basename as basename4, join as join15, relative } from "path";
4441
+ import { basename as basename4, join as join16, relative } from "path";
4242
4442
  import * as readline2 from "readline";
4243
4443
  var DATE_PREFIX_REGEX = /^\d{4}-\d{2}-\d{2}/;
4244
4444
  function getDatePrefix(daysOffset = 0) {
@@ -4256,7 +4456,7 @@ function collectFiles(dir, extension) {
4256
4456
  if (!existsSync18(dir)) return [];
4257
4457
  const results = [];
4258
4458
  for (const entry of readdirSync2(dir)) {
4259
- const fullPath = join15(dir, entry);
4459
+ const fullPath = join16(dir, entry);
4260
4460
  if (statSync(fullPath).isDirectory()) {
4261
4461
  results.push(...collectFiles(fullPath, extension));
4262
4462
  } else if (entry.endsWith(extension)) {
@@ -4333,7 +4533,7 @@ function validateDirectories(transcript) {
4333
4533
  }
4334
4534
  async function configure() {
4335
4535
  const rl = createReadlineInterface();
4336
- const config = loadConfig();
4536
+ const config = loadProjectConfig();
4337
4537
  const existing = config.transcript;
4338
4538
  console.log("Configure transcript directories\n");
4339
4539
  if (existing) printExisting(existing);
@@ -4353,11 +4553,11 @@ async function configure() {
4353
4553
  import { existsSync as existsSync20 } from "fs";
4354
4554
 
4355
4555
  // src/commands/transcript/format/fixInvalidDatePrefixes/index.ts
4356
- import { dirname as dirname12, join as join17 } from "path";
4556
+ import { dirname as dirname13, join as join18 } from "path";
4357
4557
 
4358
4558
  // src/commands/transcript/format/fixInvalidDatePrefixes/promptForDateFix.ts
4359
4559
  import { renameSync } from "fs";
4360
- import { join as join16 } from "path";
4560
+ import { join as join17 } from "path";
4361
4561
  async function resolveDate(rl, choice) {
4362
4562
  if (choice === "1") return getDatePrefix(0);
4363
4563
  if (choice === "2") return getDatePrefix(-1);
@@ -4372,7 +4572,7 @@ async function resolveDate(rl, choice) {
4372
4572
  }
4373
4573
  function renameWithPrefix(vttDir, vttFile, prefix) {
4374
4574
  const newFilename = `${prefix}.${vttFile}`;
4375
- renameSync(join16(vttDir, vttFile), join16(vttDir, newFilename));
4575
+ renameSync(join17(vttDir, vttFile), join17(vttDir, newFilename));
4376
4576
  console.log(`Renamed to: ${newFilename}`);
4377
4577
  return newFilename;
4378
4578
  }
@@ -4403,15 +4603,15 @@ async function fixInvalidDatePrefixes(vttFiles) {
4403
4603
  for (let i = 0; i < vttFiles.length; i++) {
4404
4604
  const vttFile = vttFiles[i];
4405
4605
  if (!isValidDatePrefix(vttFile.filename)) {
4406
- const vttFileDir = dirname12(vttFile.absolutePath);
4606
+ const vttFileDir = dirname13(vttFile.absolutePath);
4407
4607
  const newFilename = await promptForDateFix(vttFile.filename, vttFileDir);
4408
4608
  if (newFilename) {
4409
- const newRelativePath = join17(
4410
- dirname12(vttFile.relativePath),
4609
+ const newRelativePath = join18(
4610
+ dirname13(vttFile.relativePath),
4411
4611
  newFilename
4412
4612
  );
4413
4613
  vttFiles[i] = {
4414
- absolutePath: join17(vttFileDir, newFilename),
4614
+ absolutePath: join18(vttFileDir, newFilename),
4415
4615
  relativePath: newRelativePath,
4416
4616
  filename: newFilename
4417
4617
  };
@@ -4424,8 +4624,8 @@ async function fixInvalidDatePrefixes(vttFiles) {
4424
4624
  }
4425
4625
 
4426
4626
  // src/commands/transcript/format/processVttFile/index.ts
4427
- import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync14, writeFileSync as writeFileSync16 } from "fs";
4428
- import { basename as basename5, dirname as dirname13, join as join18 } from "path";
4627
+ import { existsSync as existsSync19, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync16 } from "fs";
4628
+ import { basename as basename5, dirname as dirname14, join as join19 } from "path";
4429
4629
 
4430
4630
  // src/commands/transcript/cleanText.ts
4431
4631
  function cleanText(text) {
@@ -4635,17 +4835,17 @@ function toMdFilename(vttFilename) {
4635
4835
  return `${basename5(vttFilename, ".vtt").replace(/\s*Transcription\s*/g, " ").trim()}.md`;
4636
4836
  }
4637
4837
  function resolveOutputDir(relativeDir, transcriptsDir) {
4638
- return relativeDir === "." ? transcriptsDir : join18(transcriptsDir, relativeDir);
4838
+ return relativeDir === "." ? transcriptsDir : join19(transcriptsDir, relativeDir);
4639
4839
  }
4640
4840
  function buildOutputPaths(vttFile, transcriptsDir) {
4641
4841
  const mdFile = toMdFilename(vttFile.filename);
4642
- const relativeDir = dirname13(vttFile.relativePath);
4842
+ const relativeDir = dirname14(vttFile.relativePath);
4643
4843
  const outputDir = resolveOutputDir(relativeDir, transcriptsDir);
4644
- const outputPath = join18(outputDir, mdFile);
4844
+ const outputPath = join19(outputDir, mdFile);
4645
4845
  return { outputDir, outputPath, mdFile, relativeDir };
4646
4846
  }
4647
4847
  function logSkipped(relativeDir, mdFile) {
4648
- console.log(`Skipping (already exists): ${join18(relativeDir, mdFile)}`);
4848
+ console.log(`Skipping (already exists): ${join19(relativeDir, mdFile)}`);
4649
4849
  return "skipped";
4650
4850
  }
4651
4851
  function ensureDirectory(dir, label2) {
@@ -4672,7 +4872,7 @@ function logReduction(cueCount, messageCount) {
4672
4872
  }
4673
4873
  function readAndParseCues(inputPath) {
4674
4874
  console.log(`Reading: ${inputPath}`);
4675
- return processCues(readFileSync14(inputPath, "utf-8"));
4875
+ return processCues(readFileSync15(inputPath, "utf-8"));
4676
4876
  }
4677
4877
  function writeFormatted(outputPath, content) {
4678
4878
  writeFileSync16(outputPath, content, "utf-8");
@@ -4744,27 +4944,27 @@ async function format() {
4744
4944
 
4745
4945
  // src/commands/transcript/summarise/index.ts
4746
4946
  import { existsSync as existsSync22 } from "fs";
4747
- import { basename as basename6, dirname as dirname15, join as join20, relative as relative2 } from "path";
4947
+ import { basename as basename6, dirname as dirname16, join as join21, relative as relative2 } from "path";
4748
4948
 
4749
4949
  // src/commands/transcript/summarise/processStagedFile/index.ts
4750
4950
  import {
4751
4951
  existsSync as existsSync21,
4752
4952
  mkdirSync as mkdirSync6,
4753
- readFileSync as readFileSync15,
4953
+ readFileSync as readFileSync16,
4754
4954
  renameSync as renameSync2,
4755
4955
  rmSync
4756
4956
  } from "fs";
4757
- import { dirname as dirname14, join as join19 } from "path";
4957
+ import { dirname as dirname15, join as join20 } from "path";
4758
4958
 
4759
4959
  // src/commands/transcript/summarise/processStagedFile/validateStagedContent.ts
4760
- import chalk48 from "chalk";
4960
+ import chalk49 from "chalk";
4761
4961
  var FULL_TRANSCRIPT_REGEX = /^\[Full Transcript\]\(([^)]+)\)/;
4762
4962
  function validateStagedContent(filename, content) {
4763
4963
  const firstLine = content.split("\n")[0];
4764
4964
  const match = firstLine.match(FULL_TRANSCRIPT_REGEX);
4765
4965
  if (!match) {
4766
4966
  console.error(
4767
- chalk48.red(
4967
+ chalk49.red(
4768
4968
  `Staged file ${filename} missing [Full Transcript](<path>) link on first line.`
4769
4969
  )
4770
4970
  );
@@ -4773,7 +4973,7 @@ function validateStagedContent(filename, content) {
4773
4973
  const contentAfterLink = content.slice(firstLine.length).trim();
4774
4974
  if (!contentAfterLink) {
4775
4975
  console.error(
4776
- chalk48.red(
4976
+ chalk49.red(
4777
4977
  `Staged file ${filename} has no summary content after the transcript link.`
4778
4978
  )
4779
4979
  );
@@ -4783,7 +4983,7 @@ function validateStagedContent(filename, content) {
4783
4983
  }
4784
4984
 
4785
4985
  // src/commands/transcript/summarise/processStagedFile/index.ts
4786
- var STAGING_DIR = join19(process.cwd(), ".assist", "transcript");
4986
+ var STAGING_DIR = join20(process.cwd(), ".assist", "transcript");
4787
4987
  function processStagedFile() {
4788
4988
  if (!existsSync21(STAGING_DIR)) {
4789
4989
  return false;
@@ -4794,7 +4994,7 @@ function processStagedFile() {
4794
4994
  }
4795
4995
  const { transcriptsDir, summaryDir } = getTranscriptConfig();
4796
4996
  const stagedFile = stagedFiles[0];
4797
- const content = readFileSync15(stagedFile.absolutePath, "utf-8");
4997
+ const content = readFileSync16(stagedFile.absolutePath, "utf-8");
4798
4998
  validateStagedContent(stagedFile.filename, content);
4799
4999
  const stagedBaseName = getTranscriptBaseName(stagedFile.filename);
4800
5000
  const transcriptFiles = findMdFilesRecursive(transcriptsDir);
@@ -4807,8 +5007,8 @@ function processStagedFile() {
4807
5007
  );
4808
5008
  process.exit(1);
4809
5009
  }
4810
- const destPath = join19(summaryDir, matchingTranscript.relativePath);
4811
- const destDir = dirname14(destPath);
5010
+ const destPath = join20(summaryDir, matchingTranscript.relativePath);
5011
+ const destDir = dirname15(destPath);
4812
5012
  if (!existsSync21(destDir)) {
4813
5013
  mkdirSync6(destDir, { recursive: true });
4814
5014
  }
@@ -4822,8 +5022,8 @@ function processStagedFile() {
4822
5022
 
4823
5023
  // src/commands/transcript/summarise/index.ts
4824
5024
  function buildRelativeKey(relativePath, baseName) {
4825
- const relDir = dirname15(relativePath);
4826
- return relDir === "." ? baseName : join20(relDir, baseName);
5025
+ const relDir = dirname16(relativePath);
5026
+ return relDir === "." ? baseName : join21(relDir, baseName);
4827
5027
  }
4828
5028
  function buildSummaryIndex(summaryDir) {
4829
5029
  const summaryFiles = findMdFilesRecursive(summaryDir);
@@ -4857,8 +5057,8 @@ function summarise() {
4857
5057
  }
4858
5058
  const next2 = missing[0];
4859
5059
  const outputFilename = `${getTranscriptBaseName(next2.filename)}.md`;
4860
- const outputPath = join20(STAGING_DIR, outputFilename);
4861
- const summaryFileDir = join20(summaryDir, dirname15(next2.relativePath));
5060
+ const outputPath = join21(STAGING_DIR, outputFilename);
5061
+ const summaryFileDir = join21(summaryDir, dirname16(next2.relativePath));
4862
5062
  const relativeTranscriptPath = encodeURI(
4863
5063
  relative2(summaryFileDir, next2.absolutePath).replace(/\\/g, "/")
4864
5064
  );
@@ -4891,7 +5091,7 @@ function registerVerify(program2) {
4891
5091
 
4892
5092
  // src/commands/roam/auth.ts
4893
5093
  import { randomBytes } from "crypto";
4894
- import chalk49 from "chalk";
5094
+ import chalk50 from "chalk";
4895
5095
 
4896
5096
  // src/lib/openBrowser.ts
4897
5097
  import { execSync as execSync23 } from "child_process";
@@ -4938,7 +5138,7 @@ ${url}`);
4938
5138
  }
4939
5139
 
4940
5140
  // src/commands/roam/waitForCallback.ts
4941
- import { createServer } from "http";
5141
+ import { createServer as createServer2 } from "http";
4942
5142
  function respondHtml(res, status, title) {
4943
5143
  res.writeHead(status, { "Content-Type": "text/html" });
4944
5144
  res.end(
@@ -4961,7 +5161,7 @@ function waitForCallback(port, expectedState) {
4961
5161
  server.close();
4962
5162
  reject(new Error("Authorization timed out after 120 seconds"));
4963
5163
  }, 12e4);
4964
- const server = createServer((req, res) => {
5164
+ const server = createServer2((req, res) => {
4965
5165
  const url = new URL(req.url ?? "/", `http://localhost:${port}`);
4966
5166
  if (url.pathname !== "/callback") {
4967
5167
  res.writeHead(404);
@@ -5057,19 +5257,22 @@ async function promptCredentials(existing) {
5057
5257
 
5058
5258
  // src/commands/roam/auth.ts
5059
5259
  async function auth() {
5060
- const config = loadGlobalConfig();
5061
- const { clientId, clientSecret } = await promptCredentials(config.roam);
5062
- config.roam = { ...config.roam, clientId, clientSecret };
5260
+ const config = loadGlobalConfigRaw();
5261
+ const { clientId, clientSecret } = await promptCredentials(
5262
+ config.roam
5263
+ );
5264
+ const existingRoam = config.roam ?? {};
5265
+ config.roam = { ...existingRoam, clientId, clientSecret };
5063
5266
  saveGlobalConfig(config);
5064
5267
  const state = randomBytes(16).toString("hex");
5065
5268
  console.log(
5066
- chalk49.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
5269
+ chalk50.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
5067
5270
  );
5068
- console.log(chalk49.white("http://localhost:14523/callback\n"));
5069
- console.log(chalk49.blue("Opening browser for authorization..."));
5070
- console.log(chalk49.dim("Waiting for authorization callback..."));
5271
+ console.log(chalk50.white("http://localhost:14523/callback\n"));
5272
+ console.log(chalk50.blue("Opening browser for authorization..."));
5273
+ console.log(chalk50.dim("Waiting for authorization callback..."));
5071
5274
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
5072
- console.log(chalk49.dim("Exchanging code for tokens..."));
5275
+ console.log(chalk50.dim("Exchanging code for tokens..."));
5073
5276
  const tokens = await exchangeToken({
5074
5277
  code,
5075
5278
  clientId,
@@ -5085,7 +5288,7 @@ async function auth() {
5085
5288
  };
5086
5289
  saveGlobalConfig(config);
5087
5290
  console.log(
5088
- chalk49.green("Roam credentials and tokens saved to ~/.assist.yml")
5291
+ chalk50.green("Roam credentials and tokens saved to ~/.assist.yml")
5089
5292
  );
5090
5293
  }
5091
5294
 
@@ -5100,7 +5303,7 @@ import { spawn as spawn4 } from "child_process";
5100
5303
 
5101
5304
  // src/commands/run/add.ts
5102
5305
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync17 } from "fs";
5103
- import { join as join21 } from "path";
5306
+ import { join as join22 } from "path";
5104
5307
  function findAddIndex() {
5105
5308
  const addIndex = process.argv.indexOf("add");
5106
5309
  if (addIndex === -1 || addIndex + 2 >= process.argv.length) return -1;
@@ -5143,7 +5346,7 @@ function requireParsedArgs() {
5143
5346
  return parsed;
5144
5347
  }
5145
5348
  function getOrInitRunList() {
5146
- const config = loadConfig();
5349
+ const config = loadProjectConfig();
5147
5350
  if (!config.run) config.run = [];
5148
5351
  return { config, runList: config.run };
5149
5352
  }
@@ -5154,7 +5357,7 @@ function saveNewRunConfig(name, command, args) {
5154
5357
  saveConfig(config);
5155
5358
  }
5156
5359
  function createCommandFile(name) {
5157
- const dir = join21(".claude", "commands");
5360
+ const dir = join22(".claude", "commands");
5158
5361
  mkdirSync7(dir, { recursive: true });
5159
5362
  const content = `---
5160
5363
  description: Run ${name}
@@ -5162,7 +5365,7 @@ description: Run ${name}
5162
5365
 
5163
5366
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
5164
5367
  `;
5165
- const filePath = join21(dir, `${name}.md`);
5368
+ const filePath = join22(dir, `${name}.md`);
5166
5369
  writeFileSync17(filePath, content);
5167
5370
  console.log(`Created command file: ${filePath}`);
5168
5371
  }
@@ -5243,12 +5446,12 @@ async function statusLine() {
5243
5446
  import * as fs23 from "fs";
5244
5447
  import * as os from "os";
5245
5448
  import * as path29 from "path";
5246
- import { fileURLToPath as fileURLToPath3 } from "url";
5449
+ import { fileURLToPath as fileURLToPath4 } from "url";
5247
5450
 
5248
5451
  // src/commands/sync/syncClaudeMd.ts
5249
5452
  import * as fs21 from "fs";
5250
5453
  import * as path27 from "path";
5251
- import chalk50 from "chalk";
5454
+ import chalk51 from "chalk";
5252
5455
  async function syncClaudeMd(claudeDir, targetBase) {
5253
5456
  const source = path27.join(claudeDir, "CLAUDE.md");
5254
5457
  const target = path27.join(targetBase, "CLAUDE.md");
@@ -5257,12 +5460,12 @@ async function syncClaudeMd(claudeDir, targetBase) {
5257
5460
  const targetContent = fs21.readFileSync(target, "utf-8");
5258
5461
  if (sourceContent !== targetContent) {
5259
5462
  console.log(
5260
- chalk50.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
5463
+ chalk51.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
5261
5464
  );
5262
5465
  console.log();
5263
5466
  printDiff(targetContent, sourceContent);
5264
5467
  const confirm = await promptConfirm(
5265
- chalk50.red("Overwrite existing CLAUDE.md?"),
5468
+ chalk51.red("Overwrite existing CLAUDE.md?"),
5266
5469
  false
5267
5470
  );
5268
5471
  if (!confirm) {
@@ -5278,7 +5481,7 @@ async function syncClaudeMd(claudeDir, targetBase) {
5278
5481
  // src/commands/sync/syncSettings.ts
5279
5482
  import * as fs22 from "fs";
5280
5483
  import * as path28 from "path";
5281
- import chalk51 from "chalk";
5484
+ import chalk52 from "chalk";
5282
5485
  async function syncSettings(claudeDir, targetBase) {
5283
5486
  const source = path28.join(claudeDir, "settings.json");
5284
5487
  const target = path28.join(targetBase, "settings.json");
@@ -5289,12 +5492,12 @@ async function syncSettings(claudeDir, targetBase) {
5289
5492
  const normalizedTarget = JSON.stringify(JSON.parse(targetContent), null, 2);
5290
5493
  if (normalizedSource !== normalizedTarget) {
5291
5494
  console.log(
5292
- chalk51.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
5495
+ chalk52.yellow("\n\u26A0\uFE0F Warning: settings.json differs from existing file")
5293
5496
  );
5294
5497
  console.log();
5295
5498
  printDiff(targetContent, sourceContent);
5296
5499
  const confirm = await promptConfirm(
5297
- chalk51.red("Overwrite existing settings.json?"),
5500
+ chalk52.red("Overwrite existing settings.json?"),
5298
5501
  false
5299
5502
  );
5300
5503
  if (!confirm) {
@@ -5308,10 +5511,10 @@ async function syncSettings(claudeDir, targetBase) {
5308
5511
  }
5309
5512
 
5310
5513
  // src/commands/sync.ts
5311
- var __filename2 = fileURLToPath3(import.meta.url);
5312
- var __dirname4 = path29.dirname(__filename2);
5514
+ var __filename2 = fileURLToPath4(import.meta.url);
5515
+ var __dirname5 = path29.dirname(__filename2);
5313
5516
  async function sync() {
5314
- const claudeDir = path29.join(__dirname4, "..", "claude");
5517
+ const claudeDir = path29.join(__dirname5, "..", "claude");
5315
5518
  const targetBase = path29.join(os.homedir(), ".claude");
5316
5519
  syncCommands(claudeDir, targetBase);
5317
5520
  await syncSettings(claudeDir, targetBase);
@@ -5332,11 +5535,11 @@ function syncCommands(claudeDir, targetBase) {
5332
5535
  // src/commands/update.ts
5333
5536
  import { execSync as execSync24 } from "child_process";
5334
5537
  import * as path30 from "path";
5335
- import { fileURLToPath as fileURLToPath4 } from "url";
5336
- var __filename3 = fileURLToPath4(import.meta.url);
5337
- var __dirname5 = path30.dirname(__filename3);
5538
+ import { fileURLToPath as fileURLToPath5 } from "url";
5539
+ var __filename3 = fileURLToPath5(import.meta.url);
5540
+ var __dirname6 = path30.dirname(__filename3);
5338
5541
  function getInstallDir() {
5339
- return path30.resolve(__dirname5, "..");
5542
+ return path30.resolve(__dirname6, "..");
5340
5543
  }
5341
5544
  function isGitRepo(dir) {
5342
5545
  try {