@staff0rd/assist 0.533.2 → 0.534.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.533.2",
9
+ version: "0.534.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -149,8 +149,8 @@ import { dirname as dirname2, join as join2 } from "path";
149
149
 
150
150
  // src/commands/backlog/getCurrentOrigin.ts
151
151
  import { execFileSync } from "child_process";
152
- function stripLeadingSlashes(path71) {
153
- return path71.replace(/^\/+/, "");
152
+ function stripLeadingSlashes(path73) {
153
+ return path73.replace(/^\/+/, "");
154
154
  }
155
155
  function normalizeOrigin(raw) {
156
156
  const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
@@ -225,9 +225,9 @@ function findGitLink(dir) {
225
225
  }
226
226
  return null;
227
227
  }
228
- function isFile(path71) {
228
+ function isFile(path73) {
229
229
  try {
230
- return statSync(path71).isFile();
230
+ return statSync(path73).isFile();
231
231
  } catch {
232
232
  return false;
233
233
  }
@@ -246,9 +246,9 @@ function linkedGitDirParent(gitDir) {
246
246
  const match = /^(.*)[/\\]worktrees[/\\][^/\\]+[/\\]?$/.exec(gitDir);
247
247
  return match ? match[1] : null;
248
248
  }
249
- function readTrimmed(path71) {
249
+ function readTrimmed(path73) {
250
250
  try {
251
- const content = readFileSync(path71, "utf8").trim();
251
+ const content = readFileSync(path73, "utf8").trim();
252
252
  return content === "" ? null : content;
253
253
  } catch {
254
254
  return null;
@@ -261,10 +261,10 @@ function absolute(target, from) {
261
261
  // src/shared/loadRawYaml.ts
262
262
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
263
263
  import { parse as parseYaml } from "yaml";
264
- function loadRawYaml(path71) {
265
- if (!existsSync2(path71)) return {};
264
+ function loadRawYaml(path73) {
265
+ if (!existsSync2(path73)) return {};
266
266
  try {
267
- const content = readFileSync2(path71, "utf8");
267
+ const content = readFileSync2(path73, "utf8");
268
268
  return parseYaml(content) || {};
269
269
  } catch {
270
270
  return {};
@@ -336,8 +336,8 @@ function mergeRawConfigs(globalRaw, projectRaw) {
336
336
  // src/commands/backlog/originDisplayName.ts
337
337
  function originDisplayName(origin) {
338
338
  if (origin.startsWith("local:")) {
339
- const path71 = origin.slice("local:".length).replace(/\/+$/, "");
340
- const segments = path71.split("/").filter(Boolean);
339
+ const path73 = origin.slice("local:".length).replace(/\/+$/, "");
340
+ const segments = path73.split("/").filter(Boolean);
341
341
  return segments[segments.length - 1] ?? origin;
342
342
  }
343
343
  const firstSlash = origin.indexOf("/");
@@ -1746,8 +1746,8 @@ function findUnmergedPaths() {
1746
1746
  }
1747
1747
  const found = /* @__PURE__ */ new Set();
1748
1748
  for (const line of output.split("\n")) {
1749
- const path71 = line.split(" ")[1];
1750
- if (path71) found.add(path71.trim());
1749
+ const path73 = line.split(" ")[1];
1750
+ if (path73) found.add(path73.trim());
1751
1751
  }
1752
1752
  return [...found];
1753
1753
  }
@@ -1857,8 +1857,8 @@ function getPreferredRemoteRepo(cwd) {
1857
1857
  function gitRefUrl(kind, ref, cwd) {
1858
1858
  const repo = getPreferredRemoteRepo(cwd);
1859
1859
  if (!repo) return void 0;
1860
- const path71 = kind === "branch" ? "tree" : "commit";
1861
- return `https://github.com/${repo.org}/${repo.repo}/${path71}/${ref}`;
1860
+ const path73 = kind === "branch" ? "tree" : "commit";
1861
+ return `https://github.com/${repo.org}/${repo.repo}/${path73}/${ref}`;
1862
1862
  }
1863
1863
 
1864
1864
  // src/commands/commit/collectCommitRefs.ts
@@ -3833,11 +3833,11 @@ function enumValues(node) {
3833
3833
  function opaqueConfigNode(inner, base) {
3834
3834
  return { ...base, kind: "other", type: leafTypeOf(inner) };
3835
3835
  }
3836
- function build(node, path71) {
3836
+ function build(node, path73) {
3837
3837
  const { inner, defaultValue, optional } = unwrapSchemaNode(node);
3838
3838
  const secret = isSecretSchemaNode(node) || isSecretSchemaNode(inner);
3839
3839
  const base = {
3840
- path: path71,
3840
+ path: path73,
3841
3841
  ...optional ? { optional: true } : {},
3842
3842
  ...defaultValue === void 0 ? {} : { defaultValue },
3843
3843
  ...secret ? { secret: true } : {}
@@ -3856,9 +3856,9 @@ function segmentText(segment) {
3856
3856
  if (segment.kind === "index") return `[${segment.index}]`;
3857
3857
  return "[]";
3858
3858
  }
3859
- function formatConfigPath(path71) {
3859
+ function formatConfigPath(path73) {
3860
3860
  let text17 = "";
3861
- for (const segment of path71) {
3861
+ for (const segment of path73) {
3862
3862
  const dotted = segment.kind === "key" || segment.kind === "entry";
3863
3863
  const rendered = segmentText(segment);
3864
3864
  text17 += dotted && text17 ? `.${rendered}` : rendered;
@@ -4471,9 +4471,9 @@ import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
4471
4471
 
4472
4472
  // src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
4473
4473
  import { minimatch as minimatch2 } from "minimatch";
4474
- function resolveStringsAtPath(data, path71) {
4474
+ function resolveStringsAtPath(data, path73) {
4475
4475
  let current = data;
4476
- for (const segment of path71.split(".")) {
4476
+ for (const segment of path73.split(".")) {
4477
4477
  if (current === null || typeof current !== "object") return [];
4478
4478
  current = current[segment];
4479
4479
  }
@@ -4486,10 +4486,10 @@ function resolveStringsAtPath(data, path71) {
4486
4486
  }
4487
4487
  function findRuleViolations(data, rule) {
4488
4488
  const violations = [];
4489
- for (const path71 of rule.paths) {
4490
- for (const value of resolveStringsAtPath(data, path71)) {
4489
+ for (const path73 of rule.paths) {
4490
+ for (const value of resolveStringsAtPath(data, path73)) {
4491
4491
  if (minimatch2(value, rule.disallowed))
4492
- violations.push({ file: rule.file, path: path71, value });
4492
+ violations.push({ file: rule.file, path: path73, value });
4493
4493
  }
4494
4494
  }
4495
4495
  return violations;
@@ -4528,8 +4528,8 @@ function forbiddenStrings() {
4528
4528
  process.exit(0);
4529
4529
  }
4530
4530
  console.log("Forbidden strings found:\n");
4531
- for (const { file, path: path71, value } of violations) {
4532
- console.log(` ${file} ${path71}: ${value}`);
4531
+ for (const { file, path: path73, value } of violations) {
4532
+ console.log(` ${file} ${path73}: ${value}`);
4533
4533
  }
4534
4534
  console.log(`
4535
4535
  Total: ${violations.length} forbidden string(s).`);
@@ -4844,15 +4844,15 @@ function readBaselineMigrations(repoRelativeDir, ref) {
4844
4844
  } catch {
4845
4845
  return baseline;
4846
4846
  }
4847
- const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path71) => MIGRATION_FILE3.test(basename2(path71)));
4848
- for (const path71 of paths) {
4847
+ const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path73) => MIGRATION_FILE3.test(basename2(path73)));
4848
+ for (const path73 of paths) {
4849
4849
  try {
4850
- const content = execSync14(`git show "${ref}:${path71}"`, {
4850
+ const content = execSync14(`git show "${ref}:${path73}"`, {
4851
4851
  encoding: "utf8",
4852
4852
  maxBuffer: 16 * 1024 * 1024,
4853
4853
  stdio: ["pipe", "pipe", "pipe"]
4854
4854
  });
4855
- baseline.set(basename2(path71), content);
4855
+ baseline.set(basename2(path73), content);
4856
4856
  } catch {
4857
4857
  }
4858
4858
  }
@@ -6286,10 +6286,10 @@ var hooksSettings = {
6286
6286
  }
6287
6287
  };
6288
6288
  function ensureHooksSettings() {
6289
- const path71 = daemonPaths.hooksSettings;
6290
- mkdirSync5(dirname13(path71), { recursive: true });
6291
- writeFileSync15(path71, JSON.stringify(hooksSettings, null, 2));
6292
- return path71;
6289
+ const path73 = daemonPaths.hooksSettings;
6290
+ mkdirSync5(dirname13(path73), { recursive: true });
6291
+ writeFileSync15(path73, JSON.stringify(hooksSettings, null, 2));
6292
+ return path73;
6293
6293
  }
6294
6294
 
6295
6295
  // src/shared/spawnInherit.ts
@@ -6587,9 +6587,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
6587
6587
  function backupLocalBacklogFiles(dir) {
6588
6588
  const moved = [];
6589
6589
  for (const name of LOCAL_FILES) {
6590
- const path71 = join15(dir, ".assist", name);
6591
- if (existsSync19(path71)) {
6592
- renameSync(path71, `${path71}.bak`);
6590
+ const path73 = join15(dir, ".assist", name);
6591
+ if (existsSync19(path73)) {
6592
+ renameSync(path73, `${path73}.bak`);
6593
6593
  moved.push(`${name} \u2192 ${name}.bak`);
6594
6594
  }
6595
6595
  }
@@ -7068,8 +7068,8 @@ var backlogItemSchema = z4.strictObject({
7068
7068
  var backlogFileSchema = z4.array(backlogItemSchema);
7069
7069
 
7070
7070
  // src/commands/backlog/parseBacklogJsonl.ts
7071
- function parseBacklogJsonl(path71) {
7072
- const content = readFileSync15(path71, "utf8").trim();
7071
+ function parseBacklogJsonl(path73) {
7072
+ const content = readFileSync15(path73, "utf8").trim();
7073
7073
  if (content.length === 0) return [];
7074
7074
  return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
7075
7075
  }
@@ -7856,24 +7856,24 @@ function getOwnerPath(itemId2) {
7856
7856
  function recordSignalOwner(itemId2) {
7857
7857
  const sessionId = process.env.ASSIST_SESSION_ID;
7858
7858
  if (!sessionId) return;
7859
- const path71 = getOwnerPath(itemId2);
7860
- mkdirSync7(dirname15(path71), { recursive: true });
7861
- writeFileSync17(path71, JSON.stringify({ sessionId }));
7859
+ const path73 = getOwnerPath(itemId2);
7860
+ mkdirSync7(dirname15(path73), { recursive: true });
7861
+ writeFileSync17(path73, JSON.stringify({ sessionId }));
7862
7862
  }
7863
7863
  function readSignalOwner(itemId2) {
7864
- const path71 = getOwnerPath(itemId2);
7865
- if (!existsSync23(path71)) return void 0;
7864
+ const path73 = getOwnerPath(itemId2);
7865
+ if (!existsSync23(path73)) return void 0;
7866
7866
  try {
7867
- const parsed = JSON.parse(readFileSync16(path71, "utf8"));
7867
+ const parsed = JSON.parse(readFileSync16(path73, "utf8"));
7868
7868
  return parsed.sessionId;
7869
7869
  } catch {
7870
7870
  return void 0;
7871
7871
  }
7872
7872
  }
7873
7873
  function clearSignalOwner(itemId2) {
7874
- const path71 = getOwnerPath(itemId2);
7874
+ const path73 = getOwnerPath(itemId2);
7875
7875
  try {
7876
- rmSync(path71);
7876
+ rmSync(path73);
7877
7877
  } catch {
7878
7878
  }
7879
7879
  }
@@ -7910,19 +7910,19 @@ function resolveSignalTarget(event, data) {
7910
7910
  function writeSignal(event, data) {
7911
7911
  const target = resolveSignalTarget(event, data);
7912
7912
  if (!target) return;
7913
- const path71 = getSignalPath(target);
7914
- if (!path71) return;
7913
+ const path73 = getSignalPath(target);
7914
+ if (!path73) return;
7915
7915
  const signal = { event, sessionId: target, ...data };
7916
- mkdirSync8(dirname16(path71), { recursive: true });
7917
- writeFileSync18(path71, JSON.stringify(signal));
7916
+ mkdirSync8(dirname16(path73), { recursive: true });
7917
+ writeFileSync18(path73, JSON.stringify(signal));
7918
7918
  }
7919
7919
 
7920
7920
  // src/commands/backlog/readSignal.ts
7921
7921
  function readSignal() {
7922
- const path71 = getSignalPath();
7923
- if (!path71 || !existsSync24(path71)) return void 0;
7922
+ const path73 = getSignalPath();
7923
+ if (!path73 || !existsSync24(path73)) return void 0;
7924
7924
  try {
7925
- return JSON.parse(readFileSync17(path71, "utf8"));
7925
+ return JSON.parse(readFileSync17(path73, "utf8"));
7926
7926
  } catch {
7927
7927
  return void 0;
7928
7928
  }
@@ -8119,13 +8119,13 @@ function activityPath(sessionId) {
8119
8119
  function emitActivity(activity2) {
8120
8120
  const sessionId = process.env.ASSIST_ACTIVITY_ID;
8121
8121
  if (!sessionId) return;
8122
- const path71 = activityPath(sessionId);
8123
- mkdirSync9(dirname17(path71), { recursive: true });
8124
- writeFileSync19(path71, JSON.stringify({ ...activity2, startedAt: Date.now() }));
8122
+ const path73 = activityPath(sessionId);
8123
+ mkdirSync9(dirname17(path73), { recursive: true });
8124
+ writeFileSync19(path73, JSON.stringify({ ...activity2, startedAt: Date.now() }));
8125
8125
  }
8126
- function readActivity(path71) {
8126
+ function readActivity(path73) {
8127
8127
  try {
8128
- return JSON.parse(readFileSync18(path71, "utf8"));
8128
+ return JSON.parse(readFileSync18(path73, "utf8"));
8129
8129
  } catch {
8130
8130
  return void 0;
8131
8131
  }
@@ -8135,9 +8135,9 @@ function reconcileActivity(sessionId, activity2) {
8135
8135
  removeActivity(sessionId);
8136
8136
  return;
8137
8137
  }
8138
- const path71 = activityPath(sessionId);
8139
- mkdirSync9(dirname17(path71), { recursive: true });
8140
- writeFileSync19(path71, JSON.stringify(activity2));
8138
+ const path73 = activityPath(sessionId);
8139
+ mkdirSync9(dirname17(path73), { recursive: true });
8140
+ writeFileSync19(path73, JSON.stringify(activity2));
8141
8141
  }
8142
8142
  function removeActivity(sessionId) {
8143
8143
  try {
@@ -9380,10 +9380,10 @@ function getStorePath(filename) {
9380
9380
  return join24(getStoreDir(), filename);
9381
9381
  }
9382
9382
  function loadJson(filename) {
9383
- const path71 = getStorePath(filename);
9384
- if (existsSync27(path71)) {
9383
+ const path73 = getStorePath(filename);
9384
+ if (existsSync27(path73)) {
9385
9385
  try {
9386
- return JSON.parse(readFileSync19(path71, "utf8"));
9386
+ return JSON.parse(readFileSync19(path73, "utf8"));
9387
9387
  } catch {
9388
9388
  return {};
9389
9389
  }
@@ -9402,22 +9402,22 @@ function saveJson(filename, data) {
9402
9402
  var REGISTRY_FILE = "worktrees.json";
9403
9403
  function readWorktreeRegistry() {
9404
9404
  const data = loadJson(REGISTRY_FILE);
9405
- return Object.entries(data).filter(([, record]) => !record.reaped).map(([path71, record]) => ({ path: path71, ...record }));
9405
+ return Object.entries(data).filter(([, record]) => !record.reaped).map(([path73, record]) => ({ path: path73, ...record }));
9406
9406
  }
9407
- function worktreeAttributionIncludingReaped(path71) {
9408
- const record = loadJson(REGISTRY_FILE)[path71];
9407
+ function worktreeAttributionIncludingReaped(path73) {
9408
+ const record = loadJson(REGISTRY_FILE)[path73];
9409
9409
  return record ? { clone: record.clone, origin: record.origin } : void 0;
9410
9410
  }
9411
- function recordWorktree(path71, clone, origin) {
9411
+ function recordWorktree(path73, clone, origin) {
9412
9412
  const data = loadJson(REGISTRY_FILE);
9413
- data[path71] = { clone, origin };
9413
+ data[path73] = { clone, origin };
9414
9414
  saveJson(REGISTRY_FILE, data);
9415
9415
  }
9416
- function forgetWorktree(path71) {
9416
+ function forgetWorktree(path73) {
9417
9417
  const data = loadJson(REGISTRY_FILE);
9418
- const record = data[path71];
9418
+ const record = data[path73];
9419
9419
  if (!record || record.reaped) return;
9420
- data[path71] = { ...record, reaped: true };
9420
+ data[path73] = { ...record, reaped: true };
9421
9421
  saveJson(REGISTRY_FILE, data);
9422
9422
  }
9423
9423
 
@@ -10173,8 +10173,8 @@ async function loadCommittedPaths(cwd, sessionId) {
10173
10173
  for (const commit2 of commits2) {
10174
10174
  const resolved = await resolveCommit(cwd, commit2.sha);
10175
10175
  if (!resolved) continue;
10176
- for (const path71 of resolved.paths) {
10177
- if (!bases.has(path71)) bases.set(path71, resolved.base);
10176
+ for (const path73 of resolved.paths) {
10177
+ if (!bases.has(path73)) bases.set(path73, resolved.base);
10178
10178
  }
10179
10179
  }
10180
10180
  return { commits: commits2, bases };
@@ -10192,16 +10192,16 @@ async function itemChangeSet(cwd, sessionId) {
10192
10192
  }
10193
10193
  function groupByBase(bases) {
10194
10194
  const groups = /* @__PURE__ */ new Map();
10195
- for (const [path71, base] of bases) {
10195
+ for (const [path73, base] of bases) {
10196
10196
  const paths = groups.get(base);
10197
- if (paths) paths.push(path71);
10198
- else groups.set(base, [path71]);
10197
+ if (paths) paths.push(path73);
10198
+ else groups.set(base, [path73]);
10199
10199
  }
10200
10200
  return [...groups].map(([base, paths]) => ({ base, paths: paths.sort() }));
10201
10201
  }
10202
10202
  async function dirtyPaths(cwd, bases) {
10203
10203
  const output = await execGit(cwd, ["diff", "--name-only", "HEAD"]);
10204
- return output.split("\n").filter((path71) => path71 && !bases.has(path71)).sort();
10204
+ return output.split("\n").filter((path73) => path73 && !bases.has(path73)).sort();
10205
10205
  }
10206
10206
 
10207
10207
  // src/commands/sessions/web/scopedDiff.ts
@@ -10210,8 +10210,8 @@ async function scopedDiff(cwd, session, scope) {
10210
10210
  if (scope.kind === "commit") return commitDiff(cwd, scope.sha);
10211
10211
  return await trackedScopeDiff(cwd, session, scope) + await untrackedDiff(cwd);
10212
10212
  }
10213
- async function untrackedFileDiff(cwd, path71) {
10214
- return execGit(cwd, ["diff", "--no-index", "--", "/dev/null", path71], {
10213
+ async function untrackedFileDiff(cwd, path73) {
10214
+ return execGit(cwd, ["diff", "--no-index", "--", "/dev/null", path73], {
10215
10215
  maxBuffer: MAX_DIFF_BYTES,
10216
10216
  allowFailure: true
10217
10217
  });
@@ -10224,7 +10224,7 @@ async function untrackedDiff(cwd) {
10224
10224
  ]);
10225
10225
  const paths = list5.split("\n").filter(Boolean);
10226
10226
  const diffs = await Promise.all(
10227
- paths.map((path71) => untrackedFileDiff(cwd, path71))
10227
+ paths.map((path73) => untrackedFileDiff(cwd, path73))
10228
10228
  );
10229
10229
  return diffs.join("");
10230
10230
  }
@@ -10317,9 +10317,9 @@ import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve10
10317
10317
  function repoRoot(cwd) {
10318
10318
  return resolve10(toGitCwd(cwd));
10319
10319
  }
10320
- function resolveWithinCwd(cwd, path71) {
10320
+ function resolveWithinCwd(cwd, path73) {
10321
10321
  const root = repoRoot(cwd);
10322
- const target = resolve10(root, path71);
10322
+ const target = resolve10(root, path73);
10323
10323
  const rel = relative2(root, target);
10324
10324
  if (rel === "" || rel.startsWith("..") || isAbsolute2(rel)) return null;
10325
10325
  return target;
@@ -10329,14 +10329,14 @@ function resolveWithinCwd(cwd, path71) {
10329
10329
  function getFileTarget(req, res) {
10330
10330
  const cwd = getCwdParam(req, res);
10331
10331
  if (!cwd) return null;
10332
- const path71 = new URL(req.url ?? "/", "http://localhost").searchParams.get(
10332
+ const path73 = new URL(req.url ?? "/", "http://localhost").searchParams.get(
10333
10333
  "path"
10334
10334
  );
10335
- if (!path71) {
10335
+ if (!path73) {
10336
10336
  respondJson(res, 400, { error: "Missing path" });
10337
10337
  return null;
10338
10338
  }
10339
- const target = resolveWithinCwd(cwd, path71);
10339
+ const target = resolveWithinCwd(cwd, path73);
10340
10340
  if (!target) {
10341
10341
  respondJson(res, 400, { error: "Path outside cwd" });
10342
10342
  return null;
@@ -10405,35 +10405,35 @@ function isPlainRecord(value) {
10405
10405
  }
10406
10406
 
10407
10407
  // src/shared/mapConfigSecrets.ts
10408
- function mapChildren(value, path71, childNode, map) {
10408
+ function mapChildren(value, path73, childNode, map) {
10409
10409
  if (!isPlainRecord(value)) return value;
10410
10410
  return Object.fromEntries(
10411
10411
  Object.entries(value).map(([name, child]) => [
10412
10412
  name,
10413
- walk(child, [...path71, name], childNode(name), map)
10413
+ walk(child, [...path73, name], childNode(name), map)
10414
10414
  ])
10415
10415
  );
10416
10416
  }
10417
- function mapItems(value, path71, item, map) {
10417
+ function mapItems(value, path73, item, map) {
10418
10418
  if (!Array.isArray(value)) return value;
10419
- return value.map((entry, index3) => walk(entry, [...path71, index3], item, map));
10419
+ return value.map((entry, index3) => walk(entry, [...path73, index3], item, map));
10420
10420
  }
10421
- function walk(value, path71, node, map) {
10421
+ function walk(value, path73, node, map) {
10422
10422
  if (!node || value === void 0 || value === null) return value;
10423
- if (node.secret) return map(value, path71);
10423
+ if (node.secret) return map(value, path73);
10424
10424
  switch (node.kind) {
10425
10425
  case "object":
10426
10426
  case "unionOfObjects":
10427
10427
  return mapChildren(
10428
10428
  value,
10429
- path71,
10429
+ path73,
10430
10430
  (name) => configNodeField(node, name),
10431
10431
  map
10432
10432
  );
10433
10433
  case "objectList":
10434
- return mapItems(value, path71, node.item, map);
10434
+ return mapItems(value, path73, node.item, map);
10435
10435
  case "record":
10436
- return mapChildren(value, path71, () => node.value, map);
10436
+ return mapChildren(value, path73, () => node.value, map);
10437
10437
  default:
10438
10438
  return value;
10439
10439
  }
@@ -10465,9 +10465,9 @@ function isTraversable(value) {
10465
10465
  function stepInto(current, key) {
10466
10466
  return isTraversable(current) ? current[key] : void 0;
10467
10467
  }
10468
- function getNestedValue(obj, path71) {
10468
+ function getNestedValue(obj, path73) {
10469
10469
  let current = obj;
10470
- for (const key of path71.split(".")) current = stepInto(current, key);
10470
+ for (const key of path73.split(".")) current = stepInto(current, key);
10471
10471
  return current;
10472
10472
  }
10473
10473
 
@@ -10552,9 +10552,9 @@ function step(node, segment) {
10552
10552
  return void 0;
10553
10553
  }
10554
10554
  }
10555
- function findConfigNode(root, path71) {
10555
+ function findConfigNode(root, path73) {
10556
10556
  let current = root;
10557
- for (const segment of path71) {
10557
+ for (const segment of path73) {
10558
10558
  if (!current) return void 0;
10559
10559
  current = step(current, segment);
10560
10560
  }
@@ -10571,34 +10571,34 @@ function nameSegment(name) {
10571
10571
  return name === RECORD_ENTRY_TOKEN ? { kind: "entry" } : { kind: "key", name };
10572
10572
  }
10573
10573
  function parseConfigPath(text17) {
10574
- const path71 = [];
10574
+ const path73 = [];
10575
10575
  let at2 = 0;
10576
10576
  while (at2 < text17.length) {
10577
10577
  if (text17[at2] === "[") {
10578
10578
  const close = text17.indexOf("]", at2);
10579
10579
  const segment = close === -1 ? void 0 : bracketSegment(text17.slice(at2 + 1, close));
10580
10580
  if (!segment) return void 0;
10581
- path71.push(segment);
10581
+ path73.push(segment);
10582
10582
  at2 = close + 1;
10583
10583
  continue;
10584
10584
  }
10585
10585
  if (text17[at2] === ".") {
10586
- if (path71.length === 0) return void 0;
10586
+ if (path73.length === 0) return void 0;
10587
10587
  at2 += 1;
10588
10588
  }
10589
10589
  const start3 = at2;
10590
10590
  while (at2 < text17.length && text17[at2] !== "." && text17[at2] !== "[") at2 += 1;
10591
10591
  const name = text17.slice(start3, at2);
10592
10592
  if (!name) return void 0;
10593
- path71.push(nameSegment(name));
10593
+ path73.push(nameSegment(name));
10594
10594
  }
10595
- return path71;
10595
+ return path73;
10596
10596
  }
10597
10597
 
10598
10598
  // src/commands/config/configEntryNode.ts
10599
10599
  function configEntryNode(root, key) {
10600
- const path71 = parseConfigPath(key);
10601
- return path71 ? findConfigNode(root, path71) : void 0;
10600
+ const path73 = parseConfigPath(key);
10601
+ return path73 ? findConfigNode(root, path73) : void 0;
10602
10602
  }
10603
10603
 
10604
10604
  // src/commands/config/readConfigEntries.ts
@@ -10703,7 +10703,7 @@ function findSynthesisForBranch(repoReviewsDir, branch2) {
10703
10703
  const parent = dirname21(branchKeyPath);
10704
10704
  const branchPrefix = basename7(branchKeyPath);
10705
10705
  if (!existsSync29(parent)) return null;
10706
- const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join27(parent, name, "synthesis.md")).filter((path71) => existsSync29(path71)).map((path71) => ({ path: path71, mtime: statSync4(path71).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
10706
+ const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join27(parent, name, "synthesis.md")).filter((path73) => existsSync29(path73)).map((path73) => ({ path: path73, mtime: statSync4(path73).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
10707
10707
  return synthesisFiles[0]?.path ?? null;
10708
10708
  }
10709
10709
 
@@ -10733,12 +10733,12 @@ async function getReviewSynthesis(req, res) {
10733
10733
  const cwd = getCwdParam(req, res);
10734
10734
  if (!cwd) return;
10735
10735
  try {
10736
- const path71 = await resolveSynthesisPath(cwd);
10737
- if (!path71) {
10736
+ const path73 = await resolveSynthesisPath(cwd);
10737
+ if (!path73) {
10738
10738
  respondJson(res, 404, { error: "No synthesis found" });
10739
10739
  return;
10740
10740
  }
10741
- respondJson(res, 200, { synthesis: readFileSync21(path71, "utf8") });
10741
+ respondJson(res, 200, { synthesis: readFileSync21(path73, "utf8") });
10742
10742
  } catch {
10743
10743
  respondJson(res, 404, { error: "No synthesis found" });
10744
10744
  }
@@ -10821,8 +10821,8 @@ function parseDiffNameStatus(output) {
10821
10821
  if (!status3 || fields.length < 2) continue;
10822
10822
  const category = categorize(status3[0]);
10823
10823
  if (!category) continue;
10824
- const path71 = fields[fields.length - 1];
10825
- if (path71) result[category].push(path71);
10824
+ const path73 = fields[fields.length - 1];
10825
+ if (path73) result[category].push(path73);
10826
10826
  }
10827
10827
  return result;
10828
10828
  }
@@ -10958,21 +10958,21 @@ function subsequenceScore(text17, query) {
10958
10958
  }
10959
10959
  return score - Math.min(text17.length, MAX_LENGTH_PENALTY);
10960
10960
  }
10961
- function scoreFilePath(path71, query) {
10961
+ function scoreFilePath(path73, query) {
10962
10962
  const needle = query.trim().toLowerCase();
10963
10963
  if (!needle) return 0;
10964
- const basename21 = path71.slice(path71.lastIndexOf("/") + 1);
10965
- const inBasename = subsequenceScore(basename21, needle);
10964
+ const basename23 = path73.slice(path73.lastIndexOf("/") + 1);
10965
+ const inBasename = subsequenceScore(basename23, needle);
10966
10966
  if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
10967
- return subsequenceScore(path71, needle);
10967
+ return subsequenceScore(path73, needle);
10968
10968
  }
10969
10969
 
10970
10970
  // src/commands/sessions/web/rankFilePaths.ts
10971
10971
  function rankFilePaths(paths, query, limit) {
10972
10972
  const scored = [];
10973
- for (const path71 of paths) {
10974
- const score = scoreFilePath(path71, query);
10975
- if (score !== null) scored.push({ path: path71, score });
10973
+ for (const path73 of paths) {
10974
+ const score = scoreFilePath(path73, query);
10975
+ if (score !== null) scored.push({ path: path73, score });
10976
10976
  }
10977
10977
  scored.sort((a, b) => b.score - a.score || a.path.localeCompare(b.path));
10978
10978
  return scored.slice(0, limit).map((entry) => entry.path);
@@ -11437,38 +11437,38 @@ async function restartWeb(req, res, deps2 = {}) {
11437
11437
  import { relative as relative3 } from "path";
11438
11438
 
11439
11439
  // src/commands/sessions/web/revertPathChanges.ts
11440
- async function isTracked(cwd, path71) {
11440
+ async function isTracked(cwd, path73) {
11441
11441
  try {
11442
- await execGit(cwd, ["ls-files", "--error-unmatch", "--", path71]);
11442
+ await execGit(cwd, ["ls-files", "--error-unmatch", "--", path73]);
11443
11443
  return true;
11444
11444
  } catch {
11445
11445
  return false;
11446
11446
  }
11447
11447
  }
11448
- async function isInHead(cwd, path71) {
11449
- const listing = await execGit(cwd, ["ls-tree", "HEAD", "--", path71]);
11448
+ async function isInHead(cwd, path73) {
11449
+ const listing = await execGit(cwd, ["ls-tree", "HEAD", "--", path73]);
11450
11450
  return listing.trim().length > 0;
11451
11451
  }
11452
- async function revertPathChanges(cwd, path71) {
11453
- if (!await isTracked(cwd, path71)) {
11454
- await execGit(cwd, ["clean", "-f", "--", path71]);
11452
+ async function revertPathChanges(cwd, path73) {
11453
+ if (!await isTracked(cwd, path73)) {
11454
+ await execGit(cwd, ["clean", "-f", "--", path73]);
11455
11455
  return;
11456
11456
  }
11457
- if (await isInHead(cwd, path71)) {
11458
- await execGit(cwd, ["checkout", "HEAD", "--", path71]);
11457
+ if (await isInHead(cwd, path73)) {
11458
+ await execGit(cwd, ["checkout", "HEAD", "--", path73]);
11459
11459
  return;
11460
11460
  }
11461
- await execGit(cwd, ["rm", "-f", "--", path71]);
11461
+ await execGit(cwd, ["rm", "-f", "--", path73]);
11462
11462
  }
11463
11463
 
11464
11464
  // src/commands/sessions/web/revertDiffFile.ts
11465
11465
  async function revertDiffFile(req, res) {
11466
11466
  const resolved = getFileTarget(req, res);
11467
11467
  if (!resolved) return;
11468
- const path71 = relative3(repoRoot(resolved.cwd), resolved.target);
11468
+ const path73 = relative3(repoRoot(resolved.cwd), resolved.target);
11469
11469
  try {
11470
- await revertPathChanges(resolved.cwd, path71);
11471
- respondJson(res, 200, { reverted: path71 });
11470
+ await revertPathChanges(resolved.cwd, path73);
11471
+ respondJson(res, 200, { reverted: path73 });
11472
11472
  } catch (error) {
11473
11473
  respondJson(res, 500, {
11474
11474
  error: error instanceof Error ? error.message : "Failed to revert file"
@@ -11549,11 +11549,11 @@ function coerceStructuredConfigValue(key, raw) {
11549
11549
  };
11550
11550
  }
11551
11551
  function formatIssue(key, issue) {
11552
- const path71 = formatConfigPath([
11552
+ const path73 = formatConfigPath([
11553
11553
  { kind: "key", name: key },
11554
11554
  ...issue.path.map(toSegment)
11555
11555
  ]);
11556
- return `${path71}: ${issue.message}`;
11556
+ return `${path73}: ${issue.message}`;
11557
11557
  }
11558
11558
  function toSegment(part) {
11559
11559
  return typeof part === "number" ? { kind: "index", index: part } : { kind: "key", name: String(part) };
@@ -11648,9 +11648,9 @@ function coerceUnion(key, raw, types) {
11648
11648
  }
11649
11649
 
11650
11650
  // src/shared/valueAtConfigPath.ts
11651
- function valueAtConfigPath(value, path71) {
11651
+ function valueAtConfigPath(value, path73) {
11652
11652
  let current = value;
11653
- for (const key of path71) {
11653
+ for (const key of path73) {
11654
11654
  if (typeof key === "number") {
11655
11655
  if (!Array.isArray(current)) return void 0;
11656
11656
  current = current[key];
@@ -11667,7 +11667,7 @@ function restoreConfigSecrets(value, stored, node) {
11667
11667
  return mapConfigSecrets(
11668
11668
  value,
11669
11669
  node,
11670
- (secret, path71) => isRedactedSecret(secret) ? valueAtConfigPath(stored, path71) : secret
11670
+ (secret, path73) => isRedactedSecret(secret) ? valueAtConfigPath(stored, path73) : secret
11671
11671
  );
11672
11672
  }
11673
11673
 
@@ -11716,8 +11716,8 @@ function stepIntoNested(container, key, nextKey) {
11716
11716
  }
11717
11717
  return ensureObject(container, resolved);
11718
11718
  }
11719
- function setNestedValue(obj, path71, value) {
11720
- const keys = path71.split(".");
11719
+ function setNestedValue(obj, path73, value) {
11720
+ const keys = path73.split(".");
11721
11721
  const result = { ...obj };
11722
11722
  let current = result;
11723
11723
  for (let i = 0; i < keys.length - 1; i++) {
@@ -11738,8 +11738,8 @@ function validateConfig(updated, key, schema2 = assistConfigSchema) {
11738
11738
  };
11739
11739
  }
11740
11740
  function formatIssue2(issue, key) {
11741
- const path71 = issue.path.length > 0 ? issue.path.join(".") : key;
11742
- return `${path71}: ${issue.message}`;
11741
+ const path73 = issue.path.length > 0 ? issue.path.join(".") : key;
11742
+ return `${path73}: ${issue.message}`;
11743
11743
  }
11744
11744
 
11745
11745
  // src/commands/config/applyConfigSet.ts
@@ -11970,8 +11970,8 @@ function removeAt(container, keys) {
11970
11970
  }
11971
11971
  return removeFromChild(container, key, rest);
11972
11972
  }
11973
- function unsetNestedValue(obj, path71) {
11974
- const { container, removed } = removeAt(obj, path71.split("."));
11973
+ function unsetNestedValue(obj, path73) {
11974
+ const { container, removed } = removeAt(obj, path73.split("."));
11975
11975
  return { config: container, removed };
11976
11976
  }
11977
11977
 
@@ -12963,9 +12963,9 @@ function originToSshUrl(origin) {
12963
12963
  const firstSlash = origin.indexOf("/");
12964
12964
  if (firstSlash <= 0) return null;
12965
12965
  const host = origin.slice(0, firstSlash);
12966
- const path71 = origin.slice(firstSlash + 1);
12967
- if (!path71) return null;
12968
- return `git@${host}:${path71}.git`;
12966
+ const path73 = origin.slice(firstSlash + 1);
12967
+ if (!path73) return null;
12968
+ return `git@${host}:${path73}.git`;
12969
12969
  }
12970
12970
 
12971
12971
  // src/commands/backlog/cloneRepo.ts
@@ -15937,9 +15937,9 @@ var __dirname4 = dirname23(__filename3);
15937
15937
  function packageRoot() {
15938
15938
  return __dirname4;
15939
15939
  }
15940
- function readLines(path71) {
15941
- if (!existsSync32(path71)) return [];
15942
- return readFileSync25(path71, "utf8").split("\n").filter((line) => line.trim() !== "");
15940
+ function readLines(path73) {
15941
+ if (!existsSync32(path73)) return [];
15942
+ return readFileSync25(path73, "utf8").split("\n").filter((line) => line.trim() !== "");
15943
15943
  }
15944
15944
  var cachedReads;
15945
15945
  var cachedWrites;
@@ -16433,14 +16433,14 @@ function showProgress(p, label2) {
16433
16433
  const pct = Math.round(p.done / p.total * 100);
16434
16434
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
16435
16435
  }
16436
- async function resolveCommand(cli, path71, description, depth, p) {
16437
- showProgress(p, path71.join(" "));
16438
- const subHelp = await runHelp([cli, ...path71]);
16436
+ async function resolveCommand(cli, path73, description, depth, p) {
16437
+ showProgress(p, path73.join(" "));
16438
+ const subHelp = await runHelp([cli, ...path73]);
16439
16439
  if (!subHelp || !hasSubcommands(subHelp)) {
16440
- return [{ path: path71, description }];
16440
+ return [{ path: path73, description }];
16441
16441
  }
16442
- const children = await discoverAt(cli, path71, depth + 1, p);
16443
- return children.length > 0 ? children : [{ path: path71, description }];
16442
+ const children = await discoverAt(cli, path73, depth + 1, p);
16443
+ return children.length > 0 ? children : [{ path: path73, description }];
16444
16444
  }
16445
16445
  async function discoverAt(cli, parentPath, depth, p) {
16446
16446
  if (depth > SAFETY_DEPTH) return [];
@@ -16588,9 +16588,9 @@ function logPath(cli) {
16588
16588
  return join34(homedir16(), ".assist", `cli-discover-${safeName}.log`);
16589
16589
  }
16590
16590
  function readCache(cli) {
16591
- const path71 = logPath(cli);
16592
- if (!existsSync34(path71)) return void 0;
16593
- return readFileSync27(path71, "utf8");
16591
+ const path73 = logPath(cli);
16592
+ if (!existsSync34(path73)) return void 0;
16593
+ return readFileSync27(path73, "utf8");
16594
16594
  }
16595
16595
  function writeCache(cli, output) {
16596
16596
  const dir = join34(homedir16(), ".assist");
@@ -16750,9 +16750,9 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
16750
16750
  }
16751
16751
  const cutoff = Date.now() - STALE_AFTER_MS;
16752
16752
  for (const entry of entries) {
16753
- const path71 = join36(dir, entry);
16753
+ const path73 = join36(dir, entry);
16754
16754
  try {
16755
- if (statSync5(path71).mtimeMs < cutoff) unlinkSync7(path71);
16755
+ if (statSync5(path73).mtimeMs < cutoff) unlinkSync7(path73);
16756
16756
  } catch {
16757
16757
  continue;
16758
16758
  }
@@ -16762,10 +16762,10 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
16762
16762
  // src/commands/codeComment/readPinState.ts
16763
16763
  import { existsSync as existsSync35, readFileSync as readFileSync28 } from "fs";
16764
16764
  function readPinState(pin) {
16765
- const path71 = getPinStatePath(pin);
16766
- if (!existsSync35(path71)) return void 0;
16765
+ const path73 = getPinStatePath(pin);
16766
+ if (!existsSync35(path73)) return void 0;
16767
16767
  try {
16768
- const state = JSON.parse(readFileSync28(path71, "utf8"));
16768
+ const state = JSON.parse(readFileSync28(path73, "utf8"));
16769
16769
  if (state.pin !== pin) return void 0;
16770
16770
  return state;
16771
16771
  } catch {
@@ -17850,10 +17850,10 @@ function getMigrationApprovalPath(migrationId) {
17850
17850
  // src/commands/dbMigration/readMigrationPinState.ts
17851
17851
  import { existsSync as existsSync37, readFileSync as readFileSync30 } from "fs";
17852
17852
  function readMigrationPinState(pin) {
17853
- const path71 = getMigrationPinPath(pin);
17854
- if (!existsSync37(path71)) return void 0;
17853
+ const path73 = getMigrationPinPath(pin);
17854
+ if (!existsSync37(path73)) return void 0;
17855
17855
  try {
17856
- const state = JSON.parse(readFileSync30(path71, "utf8"));
17856
+ const state = JSON.parse(readFileSync30(path73, "utf8"));
17857
17857
  if (state.pin !== pin) return void 0;
17858
17858
  if (!Number.isInteger(state.migrationId)) return void 0;
17859
17859
  return state;
@@ -19251,10 +19251,10 @@ function decideCommentGuard(input, existingContent) {
19251
19251
  import { existsSync as existsSync43, unlinkSync as unlinkSync11 } from "fs";
19252
19252
  function consumeMigrationApproval(migrationId) {
19253
19253
  sweepRestrictedDir();
19254
- const path71 = getMigrationApprovalPath(migrationId);
19255
- if (!existsSync43(path71)) return false;
19254
+ const path73 = getMigrationApprovalPath(migrationId);
19255
+ if (!existsSync43(path73)) return false;
19256
19256
  try {
19257
- unlinkSync11(path71);
19257
+ unlinkSync11(path73);
19258
19258
  return true;
19259
19259
  } catch {
19260
19260
  return false;
@@ -20061,22 +20061,22 @@ function createWorktree(clone, strategy, boundTreeRoots2, preferredPath) {
20061
20061
  const registered = new Set(listWorktreePaths(clone));
20062
20062
  const branches = new Set(listLocalBranches(clone));
20063
20063
  const isTaken = (candidate) => registered.has(candidate) || existsSync45(candidate) || boundTreeRoots2.has(candidate) || branches.has(basename14(candidate));
20064
- const path71 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
20064
+ const path73 = preferredPath && !isTaken(preferredPath) ? preferredPath : nextWorktreePath(clone, base, isTaken);
20065
20065
  const start3 = worktreeStartPoint(clone, strategy.trunk);
20066
20066
  gitSync(clone, [
20067
20067
  "worktree",
20068
20068
  "add",
20069
20069
  start3.track ? "--track" : "--no-track",
20070
20070
  "-b",
20071
- basename14(path71),
20072
- path71,
20071
+ basename14(path73),
20072
+ path73,
20073
20073
  start3.ref
20074
20074
  ]);
20075
- recordWorktree(path71, clone, getCurrentOrigin(clone));
20075
+ recordWorktree(path73, clone, getCurrentOrigin(clone));
20076
20076
  daemonLog(
20077
- start3.track ? `worktree allocated ${path71} (branch ${basename14(path71)} tracking ${start3.ref}) for clone ${clone}` : `worktree allocated ${path71} (branch ${basename14(path71)} off ${start3.ref}, no mainline tracking) for clone ${clone}`
20077
+ start3.track ? `worktree allocated ${path73} (branch ${basename14(path73)} tracking ${start3.ref}) for clone ${clone}` : `worktree allocated ${path73} (branch ${basename14(path73)} off ${start3.ref}, no mainline tracking) for clone ${clone}`
20078
20078
  );
20079
- return path71;
20079
+ return path73;
20080
20080
  }
20081
20081
 
20082
20082
  // src/commands/sessions/daemon/worktree/treeDurability.ts
@@ -20188,13 +20188,13 @@ function allocateTree(requestedCwd, boundTreeRoots2, options2 = {}) {
20188
20188
  if (forcedSpill) daemonLog(forcedSpill);
20189
20189
  else if (reusesClone(clone, boundTreeRoots2, reuse))
20190
20190
  return { cwd: clone, kind: "primary", created: false, clone };
20191
- const path71 = createWorktree(
20191
+ const path73 = createWorktree(
20192
20192
  clone,
20193
20193
  { root: cfg.root, trunk: cfg.trunk },
20194
20194
  boundTreeRoots2,
20195
20195
  options2.replacesTree
20196
20196
  );
20197
- return { cwd: path71, kind: "worktree", created: true, clone };
20197
+ return { cwd: path73, kind: "worktree", created: true, clone };
20198
20198
  }
20199
20199
  function keptInPlace(cwd) {
20200
20200
  daemonLog(
@@ -20525,13 +20525,13 @@ function worktreeHoldingBranch(cwd, branch2) {
20525
20525
  const listing = gitSyncOrNull(cwd, ["worktree", "list", "--porcelain"]);
20526
20526
  if (!listing) return null;
20527
20527
  const here = gitSyncOrNull(cwd, ["rev-parse", "--show-toplevel"]);
20528
- let path71 = null;
20528
+ let path73 = null;
20529
20529
  for (const line of listing.split("\n")) {
20530
20530
  const trimmed = line.trim();
20531
20531
  if (trimmed.startsWith("worktree "))
20532
- path71 = trimmed.slice("worktree ".length).trim();
20532
+ path73 = trimmed.slice("worktree ".length).trim();
20533
20533
  else if (trimmed === `branch refs/heads/${branch2}`)
20534
- return path71 && path71 !== here ? path71 : null;
20534
+ return path73 && path73 !== here ? path73 : null;
20535
20535
  }
20536
20536
  return null;
20537
20537
  }
@@ -20988,9 +20988,9 @@ function parseRscRows(flight) {
20988
20988
  }
20989
20989
  function makeRscResolver(rows) {
20990
20990
  return (ref) => {
20991
- const [id, ...path71] = ref.slice(1).replace(/^[L@]/, "").split(":");
20991
+ const [id, ...path73] = ref.slice(1).replace(/^[L@]/, "").split(":");
20992
20992
  let v = rows[id];
20993
- for (const key of path71) {
20993
+ for (const key of path73) {
20994
20994
  if (v == null || typeof v !== "object") return void 0;
20995
20995
  v = v[key];
20996
20996
  }
@@ -21676,15 +21676,15 @@ function postComment(vars) {
21676
21676
  const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
21677
21677
  assertThreadCreated(stdout);
21678
21678
  }
21679
- function comment2(path71, line, body, startLine) {
21679
+ function comment2(path73, line, body, startLine) {
21680
21680
  validateBody(body);
21681
21681
  validateLine(line);
21682
21682
  if (startLine !== void 0) validateLine(startLine);
21683
21683
  try {
21684
21684
  const prId = getCurrentPrNodeId();
21685
- postComment({ prId, body, path: path71, line, startLine });
21685
+ postComment({ prId, body, path: path73, line, startLine });
21686
21686
  const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
21687
- console.log(`Added review comment on ${path71}:${range}`);
21687
+ console.log(`Added review comment on ${path73}:${range}`);
21688
21688
  } catch (error) {
21689
21689
  if (isGhNotInstalled(error)) {
21690
21690
  console.error("Error: GitHub CLI (gh) is not installed.");
@@ -22939,8 +22939,8 @@ function registerPrs(program2) {
22939
22939
  prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
22940
22940
  reply(Number.parseInt(commentId, 10), body);
22941
22941
  });
22942
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path71, line, body) => {
22943
- comment2(path71, Number.parseInt(line, 10), body);
22942
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path73, line, body) => {
22943
+ comment2(path73, Number.parseInt(line, 10), body);
22944
22944
  });
22945
22945
  configHelp(prsCommand, prsConfigHelp);
22946
22946
  }
@@ -23193,10 +23193,10 @@ function resolveOpSecret(reference) {
23193
23193
  }
23194
23194
 
23195
23195
  // src/commands/ravendb/ravenFetch.ts
23196
- async function ravenFetch(connection, path71) {
23196
+ async function ravenFetch(connection, path73) {
23197
23197
  const apiKey = resolveOpSecret(connection.apiKeyRef);
23198
23198
  let accessToken = await getAccessToken(apiKey);
23199
- const url = `${connection.url}${path71}`;
23199
+ const url = `${connection.url}${path73}`;
23200
23200
  const headers = {
23201
23201
  Authorization: `Bearer ${accessToken}`,
23202
23202
  "Content-Type": "application/json"
@@ -23286,16 +23286,16 @@ import chalk182 from "chalk";
23286
23286
  // src/commands/ravendb/buildQueryPath.ts
23287
23287
  function buildQueryPath(opts) {
23288
23288
  const db = encodeURIComponent(opts.db);
23289
- let path71;
23289
+ let path73;
23290
23290
  if (opts.collection) {
23291
- path71 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
23291
+ path73 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
23292
23292
  } else {
23293
- path71 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
23293
+ path73 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
23294
23294
  }
23295
23295
  if (opts.query) {
23296
- path71 += `&query=${encodeURIComponent(opts.query)}`;
23296
+ path73 += `&query=${encodeURIComponent(opts.query)}`;
23297
23297
  }
23298
- return path71;
23298
+ return path73;
23299
23299
  }
23300
23300
 
23301
23301
  // src/commands/ravendb/fetchAllPages.ts
@@ -23304,7 +23304,7 @@ async function fetchAllPages(connection, opts) {
23304
23304
  let start3 = 0;
23305
23305
  while (true) {
23306
23306
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
23307
- const path71 = buildQueryPath({
23307
+ const path73 = buildQueryPath({
23308
23308
  db: connection.database,
23309
23309
  collection: opts.collection,
23310
23310
  start: start3,
@@ -23312,7 +23312,7 @@ async function fetchAllPages(connection, opts) {
23312
23312
  sort: opts.sort,
23313
23313
  query: opts.query
23314
23314
  });
23315
- const data = await ravenFetch(connection, path71);
23315
+ const data = await ravenFetch(connection, path73);
23316
23316
  const results = data.Results ?? [];
23317
23317
  const totalResults = data.TotalResults ?? 0;
23318
23318
  if (results.length === 0) break;
@@ -24753,8 +24753,8 @@ function findRootParent(file, importedBy, visited) {
24753
24753
  function clusterFiles(graph) {
24754
24754
  const clusters = /* @__PURE__ */ new Map();
24755
24755
  for (const file of graph.files) {
24756
- const basename21 = path52.basename(file, path52.extname(file));
24757
- if (basename21 === "index") continue;
24756
+ const basename23 = path52.basename(file, path52.extname(file));
24757
+ if (basename23 === "index") continue;
24758
24758
  const importers = graph.importedBy.get(file);
24759
24759
  if (!importers || importers.size !== 1) continue;
24760
24760
  const parent = [...importers][0];
@@ -25907,8 +25907,8 @@ async function handlePostSynthesis(synthesisPath, prInfo, options2) {
25907
25907
  // src/commands/review/prepareReviewDir.ts
25908
25908
  import { existsSync as existsSync50, mkdirSync as mkdirSync19, unlinkSync as unlinkSync17, writeFileSync as writeFileSync36 } from "fs";
25909
25909
  function clearReviewFiles(paths) {
25910
- for (const path71 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
25911
- if (existsSync50(path71)) unlinkSync17(path71);
25910
+ for (const path73 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
25911
+ if (existsSync50(path73)) unlinkSync17(path73);
25912
25912
  }
25913
25913
  }
25914
25914
  function prepareReviewDir(paths, requestBody, force) {
@@ -26998,8 +26998,8 @@ import chalk203 from "chalk";
26998
26998
 
26999
26999
  // src/commands/seq/fetchSeq.ts
27000
27000
  import chalk200 from "chalk";
27001
- async function fetchSeq(conn, path71, params) {
27002
- const url = `${conn.url}${path71}?${params}`;
27001
+ async function fetchSeq(conn, path73, params) {
27002
+ const url = `${conn.url}${path73}?${params}`;
27003
27003
  const response = await fetch(url, {
27004
27004
  headers: {
27005
27005
  Accept: "application/json",
@@ -27548,6 +27548,438 @@ function registerSql(program2) {
27548
27548
  configHelp(cmd, sqlConfigHelp);
27549
27549
  }
27550
27550
 
27551
+ // src/commands/sync.ts
27552
+ import * as fs43 from "fs";
27553
+ import * as os4 from "os";
27554
+ import * as path68 from "path";
27555
+ import { fileURLToPath as fileURLToPath7 } from "url";
27556
+
27557
+ // src/commands/sync/pruneCommands.ts
27558
+ import * as path59 from "path";
27559
+
27560
+ // src/commands/sync/pruneTarget.ts
27561
+ import * as fs35 from "fs";
27562
+ import * as path58 from "path";
27563
+ function pruneTarget(targetDir, keepNames, shape, options2) {
27564
+ const result = {
27565
+ orphans: [],
27566
+ removed: [],
27567
+ skipped: [],
27568
+ unmanaged: []
27569
+ };
27570
+ if (!fs35.existsSync(targetDir)) return result;
27571
+ const keep = new Set(keepNames);
27572
+ for (const entry of fs35.readdirSync(targetDir, { withFileTypes: true })) {
27573
+ const name = shape.nameOf(entry);
27574
+ if (name === void 0) {
27575
+ result.unmanaged.push(entry.name);
27576
+ continue;
27577
+ }
27578
+ if (keep.has(name)) continue;
27579
+ result.orphans.push(entry.name);
27580
+ const entryPath = path58.join(targetDir, entry.name);
27581
+ const reason4 = shape.blockedBy?.(entryPath);
27582
+ if (reason4) {
27583
+ result.skipped.push({ name: entry.name, reason: reason4 });
27584
+ continue;
27585
+ }
27586
+ if (options2.force) {
27587
+ fs35.rmSync(entryPath, { recursive: true });
27588
+ result.removed.push(entry.name);
27589
+ }
27590
+ }
27591
+ return result;
27592
+ }
27593
+
27594
+ // src/commands/sync/pruneCommands.ts
27595
+ function pruneCommands(targetDir, commandNames, options2) {
27596
+ return pruneTarget(
27597
+ targetDir,
27598
+ commandNames,
27599
+ {
27600
+ nameOf: (entry) => entry.isFile() && entry.name.endsWith(".md") ? path59.basename(entry.name, ".md") : void 0
27601
+ },
27602
+ options2
27603
+ );
27604
+ }
27605
+
27606
+ // src/commands/sync/reportPrune.ts
27607
+ function reportPrune(label2, result, force) {
27608
+ if (result.orphans.length === 0) {
27609
+ console.log(`No orphaned commands in ${label2}`);
27610
+ } else if (force) {
27611
+ for (const name of result.removed) {
27612
+ console.log(`Removed ${name} from ${label2}`);
27613
+ }
27614
+ } else {
27615
+ console.log(`Orphaned commands in ${label2} (run with --force to remove):`);
27616
+ for (const name of result.orphans) {
27617
+ console.log(` ${name}`);
27618
+ }
27619
+ }
27620
+ if (result.skipped.length > 0) {
27621
+ console.log(`Left in place in ${label2} (not written by sync):`);
27622
+ for (const { name, reason: reason4 } of result.skipped) {
27623
+ console.log(` ${name} - ${reason4}`);
27624
+ }
27625
+ }
27626
+ if (result.unmanaged.length === 0) return;
27627
+ console.log(`Not managed by sync in ${label2} (never removed):`);
27628
+ for (const name of result.unmanaged) {
27629
+ console.log(` ${name}`);
27630
+ }
27631
+ }
27632
+
27633
+ // src/commands/sync/syncClaudeMd.ts
27634
+ import * as fs36 from "fs";
27635
+ import * as path60 from "path";
27636
+ import chalk210 from "chalk";
27637
+ async function syncClaudeMd(claudeDir, targetBase, options2) {
27638
+ const source = path60.join(claudeDir, "CLAUDE.md");
27639
+ const target = path60.join(targetBase, "CLAUDE.md");
27640
+ const sourceContent = fs36.readFileSync(source, "utf8");
27641
+ if (fs36.existsSync(target)) {
27642
+ const targetContent = fs36.readFileSync(target, "utf8");
27643
+ if (sourceContent !== targetContent) {
27644
+ console.log(
27645
+ chalk210.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
27646
+ );
27647
+ console.log();
27648
+ printDiff(targetContent, sourceContent);
27649
+ if (!options2?.yes) {
27650
+ printAutoConfirmHint();
27651
+ const confirm = await promptConfirm(
27652
+ chalk210.red("Overwrite existing CLAUDE.md?"),
27653
+ false
27654
+ );
27655
+ if (!confirm) {
27656
+ console.log("Skipped CLAUDE.md");
27657
+ return;
27658
+ }
27659
+ }
27660
+ }
27661
+ }
27662
+ fs36.copyFileSync(source, target);
27663
+ console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
27664
+ }
27665
+
27666
+ // src/commands/sync/syncCodex.ts
27667
+ import * as path63 from "path";
27668
+
27669
+ // src/commands/sync/installHarnessCommands.ts
27670
+ import * as fs37 from "fs";
27671
+ import * as path61 from "path";
27672
+ function installHarnessCommands(claudeDir, harness, transform) {
27673
+ const commandsSource = path61.join(claudeDir, "commands");
27674
+ const files = fs37.readdirSync(commandsSource);
27675
+ const names = [];
27676
+ let synced = 0;
27677
+ for (const file of files) {
27678
+ if (!file.endsWith(".md")) continue;
27679
+ const name = file.replace(/\.md$/, "");
27680
+ names.push(name);
27681
+ const content = fs37.readFileSync(path61.join(commandsSource, file), "utf8");
27682
+ const target = path61.join(harness.homeDir, harness.sync.commandDest(name));
27683
+ fs37.mkdirSync(path61.dirname(target), { recursive: true });
27684
+ fs37.writeFileSync(target, transform(name, content));
27685
+ synced++;
27686
+ }
27687
+ const agentsTarget = path61.join(harness.homeDir, harness.sync.agentsFile);
27688
+ fs37.mkdirSync(path61.dirname(agentsTarget), { recursive: true });
27689
+ fs37.copyFileSync(path61.join(claudeDir, "CLAUDE.md"), agentsTarget);
27690
+ return { total: files.length, synced, names };
27691
+ }
27692
+
27693
+ // src/commands/sync/pruneSkills.ts
27694
+ import * as fs38 from "fs";
27695
+ function pruneSkills(targetDir, skillNames, options2) {
27696
+ return pruneTarget(
27697
+ targetDir,
27698
+ skillNames,
27699
+ {
27700
+ nameOf: (entry) => entry.isDirectory() ? entry.name : void 0,
27701
+ blockedBy: unexpectedContent
27702
+ },
27703
+ options2
27704
+ );
27705
+ }
27706
+ function unexpectedContent(skillDir) {
27707
+ const entries = fs38.readdirSync(skillDir);
27708
+ const others = entries.filter((entry) => entry !== "SKILL.md");
27709
+ if (others.length > 0) return `contains ${others.sort().join(", ")}`;
27710
+ return entries.length === 0 ? "no SKILL.md" : void 0;
27711
+ }
27712
+
27713
+ // src/commands/sync/syncCodexHooks.ts
27714
+ import * as fs39 from "fs";
27715
+ import * as path62 from "path";
27716
+ var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
27717
+ var END = "# <<< assist codex hooks (managed) <<<";
27718
+ function upsertManagedBlock(existing, body) {
27719
+ const block = `${BEGIN}
27720
+ ${body.trim()}
27721
+ ${END}`;
27722
+ const begin = existing.indexOf(BEGIN);
27723
+ if (begin === -1) {
27724
+ const base = existing.replace(/\s*$/, "");
27725
+ return base ? `${base}
27726
+
27727
+ ${block}
27728
+ ` : `${block}
27729
+ `;
27730
+ }
27731
+ const endMarker = existing.indexOf(END, begin);
27732
+ const after = endMarker === -1 ? existing.length : endMarker + END.length;
27733
+ const before = existing.slice(0, begin).replace(/\s*$/, "");
27734
+ const rest = existing.slice(after).replace(/^\s*/, "");
27735
+ const head = before ? `${before}
27736
+
27737
+ ${block}` : block;
27738
+ return rest ? `${head}
27739
+
27740
+ ${rest}
27741
+ ` : `${head}
27742
+ `;
27743
+ }
27744
+ function syncCodexHooks(sourcePath) {
27745
+ const body = fs39.readFileSync(sourcePath, "utf8");
27746
+ const configPath = path62.join(harnesses.codex.homeDir, "config.toml");
27747
+ const existing = fs39.existsSync(configPath) ? fs39.readFileSync(configPath, "utf8") : "";
27748
+ fs39.mkdirSync(path62.dirname(configPath), { recursive: true });
27749
+ fs39.writeFileSync(configPath, upsertManagedBlock(existing, body));
27750
+ console.log(
27751
+ "Registered assist codex-hook in ~/.codex/config.toml (PreToolUse, PermissionRequest)"
27752
+ );
27753
+ }
27754
+
27755
+ // src/commands/sync/syncCodex.ts
27756
+ function quoteYaml(value) {
27757
+ return `"${value.replace(/\\/g, String.raw`\\`).replace(/"/g, String.raw`\"`)}"`;
27758
+ }
27759
+ function commandToSkill(name, content) {
27760
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
27761
+ const frontmatter = match ? match[1] : "";
27762
+ const body = match ? content.slice(match[0].length) : content;
27763
+ const descriptionMatch = frontmatter.match(/^description:\s*(.*)$/m);
27764
+ const description = descriptionMatch ? descriptionMatch[1].trim().replace(/^["']|["']$/g, "") : name;
27765
+ const header = `---
27766
+ name: ${name}
27767
+ description: ${quoteYaml(description)}
27768
+ ---
27769
+
27770
+ `;
27771
+ return header + body.replace(/^\r?\n+/, "");
27772
+ }
27773
+ function syncCodex(claudeDir, options2) {
27774
+ if (!isHarnessAvailable("codex")) return;
27775
+ const { total, names } = installHarnessCommands(
27776
+ claudeDir,
27777
+ harnesses.codex,
27778
+ commandToSkill
27779
+ );
27780
+ syncCodexHooks(path63.join(claudeDir, "..", "codex", "config.toml"));
27781
+ console.log(
27782
+ `Synced ${total} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
27783
+ );
27784
+ if (!options2?.prune) return;
27785
+ const force = options2.force ?? false;
27786
+ reportPrune(
27787
+ "~/.codex/skills",
27788
+ pruneSkills(path63.join(harnesses.codex.homeDir, "skills"), names, { force }),
27789
+ force
27790
+ );
27791
+ }
27792
+
27793
+ // src/commands/sync/syncDesign.ts
27794
+ import * as fs40 from "fs";
27795
+ import * as path64 from "path";
27796
+ function syncDesign(claudeDir, targetBase) {
27797
+ const systemPromptSource = path64.join(claudeDir, "design-system-prompt.md");
27798
+ const systemPromptTarget = path64.join(targetBase, "design-system-prompt.md");
27799
+ fs40.copyFileSync(systemPromptSource, systemPromptTarget);
27800
+ console.log(
27801
+ "Copied design-system-prompt.md to ~/.claude/design-system-prompt.md"
27802
+ );
27803
+ const skillsSource = path64.join(claudeDir, "skills");
27804
+ const skillsTarget = path64.join(targetBase, "skills");
27805
+ fs40.mkdirSync(skillsTarget, { recursive: true });
27806
+ const files = fs40.readdirSync(skillsSource);
27807
+ for (const file of files) {
27808
+ fs40.copyFileSync(
27809
+ path64.join(skillsSource, file),
27810
+ path64.join(skillsTarget, file)
27811
+ );
27812
+ }
27813
+ console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
27814
+ }
27815
+
27816
+ // src/commands/sync/syncPi.ts
27817
+ import * as path66 from "path";
27818
+
27819
+ // src/commands/sync/syncPiHooks.ts
27820
+ import * as fs41 from "fs";
27821
+ import * as path65 from "path";
27822
+ function piExtensionsDir() {
27823
+ return path65.join(harnesses.pi.homeDir, "extensions");
27824
+ }
27825
+ function syncPiHooks(sourceDir) {
27826
+ const target = piExtensionsDir();
27827
+ fs41.mkdirSync(target, { recursive: true });
27828
+ const files = fs41.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
27829
+ for (const file of files) {
27830
+ fs41.copyFileSync(
27831
+ path65.join(sourceDir, file),
27832
+ path65.join(target, `assist-${file}`)
27833
+ );
27834
+ }
27835
+ console.log(
27836
+ `Registered ${files.length} assist extension(s) in ~/.pi/agent/extensions`
27837
+ );
27838
+ }
27839
+
27840
+ // src/commands/sync/syncPi.ts
27841
+ function unquote(value) {
27842
+ return value.trim().replace(/^["']|["']$/g, "");
27843
+ }
27844
+ function commandToPrompt(name, content) {
27845
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
27846
+ const frontmatter = match ? match[1] : "";
27847
+ const body = match ? content.slice(match[0].length) : content;
27848
+ const descriptionMatch = frontmatter.match(/^description:\s*(.*)$/m);
27849
+ const description = descriptionMatch ? unquote(descriptionMatch[1]) : name;
27850
+ const argsMatch = frontmatter.match(/^allowed_args:\s*(.*)$/m);
27851
+ const argumentHint = argsMatch ? unquote(argsMatch[1]) : void 0;
27852
+ const header = [
27853
+ "---",
27854
+ `description: ${description}`,
27855
+ ...argumentHint ? [`argument-hint: ${argumentHint}`] : [],
27856
+ "---",
27857
+ "",
27858
+ ""
27859
+ ].join("\n");
27860
+ return header + body.replace(/^\r?\n+/, "");
27861
+ }
27862
+ function syncPi(claudeDir, options2) {
27863
+ if (!isHarnessAvailable("pi")) return;
27864
+ const { synced, names } = installHarnessCommands(
27865
+ claudeDir,
27866
+ harnesses.pi,
27867
+ commandToPrompt
27868
+ );
27869
+ syncPiHooks(path66.join(claudeDir, "..", "pi"));
27870
+ console.log(
27871
+ `Synced ${synced} prompt(s) to ~/.pi/agent/prompts and CLAUDE.md to ~/.pi/agent/AGENTS.md`
27872
+ );
27873
+ if (!options2?.prune) return;
27874
+ const force = options2.force ?? false;
27875
+ reportPrune(
27876
+ "~/.pi/agent/prompts",
27877
+ pruneCommands(path66.join(harnesses.pi.homeDir, "prompts"), names, { force }),
27878
+ force
27879
+ );
27880
+ }
27881
+
27882
+ // src/commands/sync/syncSettings.ts
27883
+ import * as fs42 from "fs";
27884
+ import * as path67 from "path";
27885
+ import chalk211 from "chalk";
27886
+ async function syncSettings(claudeDir, targetBase, options2) {
27887
+ const source = path67.join(claudeDir, "settings.json");
27888
+ const target = path67.join(targetBase, "settings.json");
27889
+ const sourceContent = fs42.readFileSync(source, "utf8");
27890
+ const sourceSettings = JSON.parse(sourceContent);
27891
+ const targetExists = fs42.existsSync(target);
27892
+ const targetContent = targetExists ? fs42.readFileSync(target, "utf8") : "";
27893
+ const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
27894
+ const mergedContent = JSON.stringify(
27895
+ { ...preservedUserSettings, ...sourceSettings },
27896
+ null,
27897
+ " "
27898
+ );
27899
+ if (targetExists) {
27900
+ const normalizedTarget = JSON.stringify(preservedUserSettings, null, " ");
27901
+ if (mergedContent !== normalizedTarget) {
27902
+ if (!options2?.yes) {
27903
+ console.log(
27904
+ chalk211.yellow(
27905
+ "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
27906
+ )
27907
+ );
27908
+ console.log();
27909
+ printDiff(targetContent, mergedContent);
27910
+ printAutoConfirmHint();
27911
+ const confirm = await promptConfirm(
27912
+ chalk211.red("Overwrite existing settings.json?"),
27913
+ false
27914
+ );
27915
+ if (!confirm) {
27916
+ console.log("Skipped settings.json");
27917
+ return;
27918
+ }
27919
+ }
27920
+ }
27921
+ }
27922
+ fs42.writeFileSync(target, mergedContent);
27923
+ console.log("Copied settings.json to ~/.claude/settings.json");
27924
+ }
27925
+
27926
+ // src/commands/sync.ts
27927
+ var __filename4 = fileURLToPath7(import.meta.url);
27928
+ var __dirname5 = path68.dirname(__filename4);
27929
+ async function sync(options2) {
27930
+ const config = loadConfig();
27931
+ const yes = options2?.yes ?? config.sync.autoConfirm;
27932
+ const prune = { prune: options2?.prune, force: options2?.force };
27933
+ const claudeDir = path68.join(__dirname5, "..", "claude");
27934
+ const targetBase = path68.join(os4.homedir(), ".claude");
27935
+ const commandFiles = syncCommands(claudeDir, targetBase);
27936
+ syncDesign(claudeDir, targetBase);
27937
+ await syncSettings(claudeDir, targetBase, { yes });
27938
+ await syncClaudeMd(claudeDir, targetBase, { yes });
27939
+ syncCodex(claudeDir, prune);
27940
+ syncPi(claudeDir, prune);
27941
+ if (!options2?.prune) return;
27942
+ const commandNames = commandFiles.filter((file) => file.endsWith(".md")).map((file) => path68.basename(file, ".md"));
27943
+ const force = options2.force ?? false;
27944
+ reportPrune(
27945
+ "~/.claude/commands",
27946
+ pruneCommands(path68.join(targetBase, "commands"), commandNames, { force }),
27947
+ force
27948
+ );
27949
+ }
27950
+ function syncCommands(claudeDir, targetBase) {
27951
+ const sourceDir = path68.join(claudeDir, "commands");
27952
+ const targetDir = path68.join(targetBase, "commands");
27953
+ fs43.mkdirSync(targetDir, { recursive: true });
27954
+ const files = fs43.readdirSync(sourceDir);
27955
+ for (const file of files) {
27956
+ fs43.copyFileSync(path68.join(sourceDir, file), path68.join(targetDir, file));
27957
+ console.log(`Copied ${file} to ${targetDir}`);
27958
+ }
27959
+ console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
27960
+ return files;
27961
+ }
27962
+
27963
+ // src/commands/registerSync.ts
27964
+ function registerSync(program2) {
27965
+ const syncCommand = program2.command("sync").description(
27966
+ "Copy command files to ~/.claude/commands; when codex is detected, also install commands as ~/.codex/skills/<name>/SKILL.md, CLAUDE.md as ~/.codex/AGENTS.md, and register the assist codex-hook auto-approval hook in ~/.codex/config.toml; when pi is detected, also install commands as ~/.pi/agent/prompts/<name>.md, CLAUDE.md as ~/.pi/agent/AGENTS.md, and register the assist pi-hook permission-gate extension in ~/.pi/agent/extensions. With --prune, also report commands in those target dirs that sync did not write, and with --prune --force remove them"
27967
+ ).option("-y, --yes", "Overwrite settings.json without prompting").option(
27968
+ "--prune",
27969
+ "After syncing, list commands in the target dirs whose name is not in the repo's claude/commands/*.md set; subdirectories and non-.md files are listed separately and never removed"
27970
+ ).option(
27971
+ "--force",
27972
+ "With --prune, remove the listed orphaned commands; a codex skill directory is removed only when SKILL.md is its sole content. Errors without --prune"
27973
+ ).action((options2) => {
27974
+ if (options2.force && !options2.prune) {
27975
+ console.error("--force requires --prune.");
27976
+ process.exit(1);
27977
+ }
27978
+ return sync(options2);
27979
+ });
27980
+ configHelp(syncCommand, rootConfigHelp.sync);
27981
+ }
27982
+
27551
27983
  // src/commands/transcript/shared.ts
27552
27984
  import * as readline2 from "readline";
27553
27985
  function createReadlineInterface() {
@@ -27619,27 +28051,27 @@ async function configure() {
27619
28051
  }
27620
28052
 
27621
28053
  // src/commands/transcript/list.ts
27622
- import { existsSync as existsSync53, readdirSync as readdirSync11, statSync as statSync9 } from "fs";
27623
- import { join as join61 } from "path";
28054
+ import { existsSync as existsSync57, readdirSync as readdirSync17, statSync as statSync9 } from "fs";
28055
+ import { join as join71 } from "path";
27624
28056
  function list4() {
27625
28057
  const { vttDir } = getTranscriptConfig();
27626
- if (!existsSync53(vttDir)) return;
27627
- for (const entry of readdirSync11(vttDir)) {
28058
+ if (!existsSync57(vttDir)) return;
28059
+ for (const entry of readdirSync17(vttDir)) {
27628
28060
  if (!entry.endsWith(".vtt")) continue;
27629
- if (statSync9(join61(vttDir, entry)).isDirectory()) continue;
28061
+ if (statSync9(join71(vttDir, entry)).isDirectory()) continue;
27630
28062
  console.log(entry);
27631
28063
  }
27632
28064
  }
27633
28065
 
27634
28066
  // src/commands/transcript/move.ts
27635
28067
  import {
27636
- existsSync as existsSync54,
27637
- mkdirSync as mkdirSync20,
27638
- readFileSync as readFileSync43,
28068
+ existsSync as existsSync58,
28069
+ mkdirSync as mkdirSync25,
28070
+ readFileSync as readFileSync47,
27639
28071
  renameSync as renameSync2,
27640
- writeFileSync as writeFileSync38
28072
+ writeFileSync as writeFileSync41
27641
28073
  } from "fs";
27642
- import { basename as basename17, join as join62 } from "path";
28074
+ import { basename as basename19, join as join72 } from "path";
27643
28075
 
27644
28076
  // src/commands/transcript/cleanText.ts
27645
28077
  function cleanText(text17) {
@@ -27847,14 +28279,14 @@ function formatChatLog(messages) {
27847
28279
  // src/commands/transcript/move.ts
27848
28280
  var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
27849
28281
  function convertVttToMarkdown(inputPath) {
27850
- const cues = parseVtt(readFileSync43(inputPath, "utf8"));
28282
+ const cues = parseVtt(readFileSync47(inputPath, "utf8"));
27851
28283
  const messages = cuesToChatMessages(deduplicateCues(cues));
27852
28284
  return formatChatLog(messages);
27853
28285
  }
27854
28286
  function archiveRawVtt(vttDir, sourcePath, filename) {
27855
- const processedDir = join62(vttDir, "processed");
27856
- mkdirSync20(processedDir, { recursive: true });
27857
- renameSync2(sourcePath, join62(processedDir, filename));
28287
+ const processedDir = join72(vttDir, "processed");
28288
+ mkdirSync25(processedDir, { recursive: true });
28289
+ renameSync2(sourcePath, join72(processedDir, filename));
27858
28290
  }
27859
28291
  function move(file, options2) {
27860
28292
  const { date, client } = options2;
@@ -27863,20 +28295,20 @@ function move(file, options2) {
27863
28295
  process.exit(1);
27864
28296
  }
27865
28297
  const { vttDir, transcriptsDir, summaryDir } = getTranscriptConfig();
27866
- const filename = basename17(file);
27867
- const sourcePath = join62(vttDir, filename);
27868
- if (!existsSync54(sourcePath)) {
28298
+ const filename = basename19(file);
28299
+ const sourcePath = join72(vttDir, filename);
28300
+ if (!existsSync58(sourcePath)) {
27869
28301
  console.error(`Error: VTT file not found: ${sourcePath}`);
27870
28302
  process.exit(1);
27871
28303
  }
27872
- const base = basename17(filename, ".vtt").replace(/ Transcription$/, "");
28304
+ const base = basename19(filename, ".vtt").replace(/ Transcription$/, "");
27873
28305
  const outputName = `${date} ${base}.md`;
27874
- const formattedDir = join62(transcriptsDir, client);
27875
- mkdirSync20(formattedDir, { recursive: true });
27876
- const formattedPath = join62(formattedDir, outputName);
27877
- writeFileSync38(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
28306
+ const formattedDir = join72(transcriptsDir, client);
28307
+ mkdirSync25(formattedDir, { recursive: true });
28308
+ const formattedPath = join72(formattedDir, outputName);
28309
+ writeFileSync41(formattedPath, convertVttToMarkdown(sourcePath), "utf8");
27878
28310
  archiveRawVtt(vttDir, sourcePath, filename);
27879
- const summaryPath = join62(summaryDir, client, outputName);
28311
+ const summaryPath = join72(summaryDir, client, outputName);
27880
28312
  console.log(`Formatted transcript: ${formattedPath}`);
27881
28313
  console.log(`Summary target: ${summaryPath}`);
27882
28314
  }
@@ -27958,50 +28390,50 @@ function registerVerify(program2) {
27958
28390
 
27959
28391
  // src/commands/voice/devices.ts
27960
28392
  import { spawnSync as spawnSync6 } from "child_process";
27961
- import { join as join64 } from "path";
28393
+ import { join as join74 } from "path";
27962
28394
 
27963
28395
  // src/commands/voice/shared.ts
27964
- import { homedir as homedir22 } from "os";
27965
- import { dirname as dirname31, join as join63 } from "path";
27966
- import { fileURLToPath as fileURLToPath7 } from "url";
27967
- var __dirname5 = dirname31(fileURLToPath7(import.meta.url));
27968
- var VOICE_DIR = join63(homedir22(), ".assist", "voice");
28396
+ import { homedir as homedir23 } from "os";
28397
+ import { dirname as dirname34, join as join73 } from "path";
28398
+ import { fileURLToPath as fileURLToPath8 } from "url";
28399
+ var __dirname6 = dirname34(fileURLToPath8(import.meta.url));
28400
+ var VOICE_DIR = join73(homedir23(), ".assist", "voice");
27969
28401
  var voicePaths = {
27970
28402
  dir: VOICE_DIR,
27971
- pid: join63(VOICE_DIR, "voice.pid"),
27972
- log: join63(VOICE_DIR, "voice.log"),
27973
- venv: join63(VOICE_DIR, ".venv"),
27974
- lock: join63(VOICE_DIR, "voice.lock")
28403
+ pid: join73(VOICE_DIR, "voice.pid"),
28404
+ log: join73(VOICE_DIR, "voice.log"),
28405
+ venv: join73(VOICE_DIR, ".venv"),
28406
+ lock: join73(VOICE_DIR, "voice.lock")
27975
28407
  };
27976
28408
  function getPythonDir() {
27977
- return join63(__dirname5, "commands", "voice", "python");
28409
+ return join73(__dirname6, "commands", "voice", "python");
27978
28410
  }
27979
28411
  function getVenvPython() {
27980
- return process.platform === "win32" ? join63(voicePaths.venv, "Scripts", "python.exe") : join63(voicePaths.venv, "bin", "python");
28412
+ return process.platform === "win32" ? join73(voicePaths.venv, "Scripts", "python.exe") : join73(voicePaths.venv, "bin", "python");
27981
28413
  }
27982
28414
  function getLockDir() {
27983
28415
  const config = loadConfig();
27984
28416
  return config.voice?.lockDir ?? VOICE_DIR;
27985
28417
  }
27986
28418
  function getLockFile() {
27987
- return join63(getLockDir(), "voice.lock");
28419
+ return join73(getLockDir(), "voice.lock");
27988
28420
  }
27989
28421
 
27990
28422
  // src/commands/voice/devices.ts
27991
28423
  function devices() {
27992
- const script = join64(getPythonDir(), "list_devices.py");
28424
+ const script = join74(getPythonDir(), "list_devices.py");
27993
28425
  spawnSync6(getVenvPython(), [script], { stdio: "inherit" });
27994
28426
  }
27995
28427
 
27996
28428
  // src/commands/voice/logs.ts
27997
- import { existsSync as existsSync55, readFileSync as readFileSync44 } from "fs";
28429
+ import { existsSync as existsSync59, readFileSync as readFileSync48 } from "fs";
27998
28430
  function logs(options2) {
27999
- if (!existsSync55(voicePaths.log)) {
28431
+ if (!existsSync59(voicePaths.log)) {
28000
28432
  console.log("No voice log file found");
28001
28433
  return;
28002
28434
  }
28003
28435
  const count8 = Number.parseInt(options2.lines ?? "150", 10);
28004
- const content = readFileSync44(voicePaths.log, "utf8").trim();
28436
+ const content = readFileSync48(voicePaths.log, "utf8").trim();
28005
28437
  if (!content) {
28006
28438
  console.log("Voice log is empty");
28007
28439
  return;
@@ -28023,13 +28455,13 @@ function logs(options2) {
28023
28455
 
28024
28456
  // src/commands/voice/setup.ts
28025
28457
  import { spawnSync as spawnSync7 } from "child_process";
28026
- import { mkdirSync as mkdirSync22 } from "fs";
28027
- import { join as join66 } from "path";
28458
+ import { mkdirSync as mkdirSync27 } from "fs";
28459
+ import { join as join76 } from "path";
28028
28460
 
28029
28461
  // src/commands/voice/checkLockFile.ts
28030
28462
  import { execSync as execSync59 } from "child_process";
28031
- import { existsSync as existsSync56, mkdirSync as mkdirSync21, readFileSync as readFileSync45, writeFileSync as writeFileSync39 } from "fs";
28032
- import { join as join65 } from "path";
28463
+ import { existsSync as existsSync60, mkdirSync as mkdirSync26, readFileSync as readFileSync49, writeFileSync as writeFileSync42 } from "fs";
28464
+ import { join as join75 } from "path";
28033
28465
  function isProcessAlive2(pid) {
28034
28466
  try {
28035
28467
  process.kill(pid, 0);
@@ -28040,9 +28472,9 @@ function isProcessAlive2(pid) {
28040
28472
  }
28041
28473
  function checkLockFile() {
28042
28474
  const lockFile = getLockFile();
28043
- if (!existsSync56(lockFile)) return;
28475
+ if (!existsSync60(lockFile)) return;
28044
28476
  try {
28045
- const lock2 = JSON.parse(readFileSync45(lockFile, "utf8"));
28477
+ const lock2 = JSON.parse(readFileSync49(lockFile, "utf8"));
28046
28478
  if (lock2.pid && isProcessAlive2(lock2.pid)) {
28047
28479
  console.error(
28048
28480
  `Voice daemon already running (PID ${lock2.pid}, env: ${lock2.env}). Stop it first with: assist voice stop`
@@ -28053,7 +28485,7 @@ function checkLockFile() {
28053
28485
  }
28054
28486
  }
28055
28487
  function bootstrapVenv() {
28056
- if (existsSync56(getVenvPython())) return;
28488
+ if (existsSync60(getVenvPython())) return;
28057
28489
  console.log("Setting up Python environment...");
28058
28490
  const pythonDir = getPythonDir();
28059
28491
  execSync59(
@@ -28066,8 +28498,8 @@ function bootstrapVenv() {
28066
28498
  }
28067
28499
  function writeLockFile(pid) {
28068
28500
  const lockFile = getLockFile();
28069
- mkdirSync21(join65(lockFile, ".."), { recursive: true });
28070
- writeFileSync39(
28501
+ mkdirSync26(join75(lockFile, ".."), { recursive: true });
28502
+ writeFileSync42(
28071
28503
  lockFile,
28072
28504
  JSON.stringify({
28073
28505
  pid,
@@ -28079,10 +28511,10 @@ function writeLockFile(pid) {
28079
28511
 
28080
28512
  // src/commands/voice/setup.ts
28081
28513
  function setup() {
28082
- mkdirSync22(voicePaths.dir, { recursive: true });
28514
+ mkdirSync27(voicePaths.dir, { recursive: true });
28083
28515
  bootstrapVenv();
28084
28516
  console.log("\nDownloading models...\n");
28085
- const script = join66(getPythonDir(), "setup_models.py");
28517
+ const script = join76(getPythonDir(), "setup_models.py");
28086
28518
  const result = spawnSync7(getVenvPython(), [script], {
28087
28519
  stdio: "inherit",
28088
28520
  env: { ...process.env, VOICE_LOG_FILE: voicePaths.log }
@@ -28095,8 +28527,8 @@ function setup() {
28095
28527
 
28096
28528
  // src/commands/voice/start.ts
28097
28529
  import { spawn as spawn8 } from "child_process";
28098
- import { mkdirSync as mkdirSync23, writeFileSync as writeFileSync40 } from "fs";
28099
- import { join as join67 } from "path";
28530
+ import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync43 } from "fs";
28531
+ import { join as join77 } from "path";
28100
28532
 
28101
28533
  // src/commands/voice/buildDaemonEnv.ts
28102
28534
  function buildDaemonEnv(options2) {
@@ -28124,17 +28556,17 @@ function spawnBackground(python, script, env) {
28124
28556
  console.error("Failed to start voice daemon");
28125
28557
  process.exit(1);
28126
28558
  }
28127
- writeFileSync40(voicePaths.pid, String(pid));
28559
+ writeFileSync43(voicePaths.pid, String(pid));
28128
28560
  writeLockFile(pid);
28129
28561
  console.log(`Voice daemon started (PID ${pid})`);
28130
28562
  }
28131
28563
  function start2(options2) {
28132
- mkdirSync23(voicePaths.dir, { recursive: true });
28564
+ mkdirSync28(voicePaths.dir, { recursive: true });
28133
28565
  checkLockFile();
28134
28566
  bootstrapVenv();
28135
28567
  const debug = options2.debug || options2.foreground || process.platform === "win32";
28136
28568
  const env = buildDaemonEnv({ debug });
28137
- const script = join67(getPythonDir(), "voice_daemon.py");
28569
+ const script = join77(getPythonDir(), "voice_daemon.py");
28138
28570
  const python = getVenvPython();
28139
28571
  if (options2.foreground) {
28140
28572
  spawnForeground(python, script, env);
@@ -28144,7 +28576,7 @@ function start2(options2) {
28144
28576
  }
28145
28577
 
28146
28578
  // src/commands/voice/status.ts
28147
- import { existsSync as existsSync57, readFileSync as readFileSync46 } from "fs";
28579
+ import { existsSync as existsSync61, readFileSync as readFileSync50 } from "fs";
28148
28580
  function isProcessAlive3(pid) {
28149
28581
  try {
28150
28582
  process.kill(pid, 0);
@@ -28154,16 +28586,16 @@ function isProcessAlive3(pid) {
28154
28586
  }
28155
28587
  }
28156
28588
  function readRecentLogs(count8) {
28157
- if (!existsSync57(voicePaths.log)) return [];
28158
- const lines2 = readFileSync46(voicePaths.log, "utf8").trim().split("\n");
28589
+ if (!existsSync61(voicePaths.log)) return [];
28590
+ const lines2 = readFileSync50(voicePaths.log, "utf8").trim().split("\n");
28159
28591
  return lines2.slice(-count8);
28160
28592
  }
28161
28593
  function status2() {
28162
- if (!existsSync57(voicePaths.pid)) {
28594
+ if (!existsSync61(voicePaths.pid)) {
28163
28595
  console.log("Voice daemon: not running (no PID file)");
28164
28596
  return;
28165
28597
  }
28166
- const pid = Number.parseInt(readFileSync46(voicePaths.pid, "utf8").trim(), 10);
28598
+ const pid = Number.parseInt(readFileSync50(voicePaths.pid, "utf8").trim(), 10);
28167
28599
  const alive = isProcessAlive3(pid);
28168
28600
  console.log(`Voice daemon: ${alive ? "running" : "dead"} (PID ${pid})`);
28169
28601
  const recent = readRecentLogs(5);
@@ -28182,13 +28614,13 @@ function status2() {
28182
28614
  }
28183
28615
 
28184
28616
  // src/commands/voice/stop.ts
28185
- import { existsSync as existsSync58, readFileSync as readFileSync47, unlinkSync as unlinkSync20 } from "fs";
28617
+ import { existsSync as existsSync62, readFileSync as readFileSync51, unlinkSync as unlinkSync20 } from "fs";
28186
28618
  function stop2() {
28187
- if (!existsSync58(voicePaths.pid)) {
28619
+ if (!existsSync62(voicePaths.pid)) {
28188
28620
  console.log("Voice daemon is not running (no PID file)");
28189
28621
  return;
28190
28622
  }
28191
- const pid = Number.parseInt(readFileSync47(voicePaths.pid, "utf8").trim(), 10);
28623
+ const pid = Number.parseInt(readFileSync51(voicePaths.pid, "utf8").trim(), 10);
28192
28624
  try {
28193
28625
  process.kill(pid, "SIGTERM");
28194
28626
  console.log(`Sent SIGTERM to voice daemon (PID ${pid})`);
@@ -28201,7 +28633,7 @@ function stop2() {
28201
28633
  }
28202
28634
  try {
28203
28635
  const lockFile = getLockFile();
28204
- if (existsSync58(lockFile)) unlinkSync20(lockFile);
28636
+ if (existsSync62(lockFile)) unlinkSync20(lockFile);
28205
28637
  } catch {
28206
28638
  }
28207
28639
  console.log("Voice daemon stopped");
@@ -28220,7 +28652,7 @@ function registerVoice(program2) {
28220
28652
  }
28221
28653
 
28222
28654
  // src/commands/watch/readBuiltVersion.ts
28223
- import { join as join68 } from "path";
28655
+ import { join as join78 } from "path";
28224
28656
 
28225
28657
  // src/commands/watch/resolveUpstream.ts
28226
28658
  import { execFileSync as execFileSync10 } from "child_process";
@@ -28266,7 +28698,7 @@ function resolveUpstream(cwd) {
28266
28698
  function readBuiltVersion(cwd) {
28267
28699
  try {
28268
28700
  const root = runGit2(["rev-parse", "--show-toplevel"], cwd);
28269
- return readPackageJson(join68(root, "package.json")).version ?? "unknown";
28701
+ return readPackageJson(join78(root, "package.json")).version ?? "unknown";
28270
28702
  } catch {
28271
28703
  return "unknown";
28272
28704
  }
@@ -28318,11 +28750,11 @@ var webUiPrefix = "src/commands/sessions/web/ui/";
28318
28750
  var sessionsPrefix = "src/commands/sessions/";
28319
28751
  var rules = [
28320
28752
  {
28321
- matches: (path71) => path71.startsWith(webUiPrefix),
28753
+ matches: (path73) => path73.startsWith(webUiPrefix),
28322
28754
  advice: "restart the web server, then hard-reload the browser tab"
28323
28755
  },
28324
28756
  {
28325
- matches: (path71) => path71.startsWith(sessionsPrefix) && !path71.startsWith(webUiPrefix),
28757
+ matches: (path73) => path73.startsWith(sessionsPrefix) && !path73.startsWith(webUiPrefix),
28326
28758
  advice: "restart the daemon"
28327
28759
  }
28328
28760
  ];
@@ -28564,7 +28996,7 @@ function resolveParams(params, cliArgs) {
28564
28996
  }
28565
28997
 
28566
28998
  // src/commands/run/resolveRunCwd.ts
28567
- import { existsSync as existsSync59 } from "fs";
28999
+ import { existsSync as existsSync63 } from "fs";
28568
29000
  import { resolve as resolve17 } from "path";
28569
29001
  var MissingRunCwdError = class extends Error {
28570
29002
  constructor(runName, cwd) {
@@ -28577,25 +29009,25 @@ var MissingRunCwdError = class extends Error {
28577
29009
  function resolveRunCwd(config, baseDir = runConfigBaseDir()) {
28578
29010
  if (!config.cwd) return void 0;
28579
29011
  const cwd = resolve17(baseDir, config.cwd);
28580
- if (!existsSync59(cwd)) throw new MissingRunCwdError(config.name, cwd);
29012
+ if (!existsSync63(cwd)) throw new MissingRunCwdError(config.name, cwd);
28581
29013
  return cwd;
28582
29014
  }
28583
29015
 
28584
29016
  // src/commands/run/runCommandToCompletion.ts
28585
29017
  import { spawn as spawn9 } from "child_process";
28586
- import { existsSync as existsSync61 } from "fs";
29018
+ import { existsSync as existsSync65 } from "fs";
28587
29019
 
28588
29020
  // src/commands/run/resolveCommand.ts
28589
29021
  import { execFileSync as execFileSync11 } from "child_process";
28590
- import { existsSync as existsSync60 } from "fs";
28591
- import { dirname as dirname32, join as join69, resolve as resolve18 } from "path";
29022
+ import { existsSync as existsSync64 } from "fs";
29023
+ import { dirname as dirname35, join as join79, resolve as resolve18 } from "path";
28592
29024
  function resolveCommand2(command) {
28593
29025
  if (process.platform !== "win32" || command !== "bash") return command;
28594
29026
  try {
28595
29027
  const gitPath = execFileSync11("where", ["git"], { encoding: "utf8" }).trim().split("\r\n")[0];
28596
- const gitRoot = resolve18(dirname32(gitPath), "..");
28597
- const gitBash = join69(gitRoot, "bin", "bash.exe");
28598
- if (existsSync60(gitBash)) return gitBash;
29028
+ const gitRoot = resolve18(dirname35(gitPath), "..");
29029
+ const gitBash = join79(gitRoot, "bin", "bash.exe");
29030
+ if (existsSync64(gitBash)) return gitBash;
28599
29031
  } catch {
28600
29032
  return command;
28601
29033
  }
@@ -28605,7 +29037,7 @@ function resolveCommand2(command) {
28605
29037
  // src/commands/run/runCommandToCompletion.ts
28606
29038
  function runCommandToCompletion(command, args, env, cwd, quiet) {
28607
29039
  return new Promise((resolveResult) => {
28608
- if (cwd && !existsSync61(cwd)) {
29040
+ if (cwd && !existsSync65(cwd)) {
28609
29041
  resolveResult({
28610
29042
  kind: "failed",
28611
29043
  message: `Failed to execute command: cwd ${cwd} does not exist`
@@ -28835,7 +29267,7 @@ function registerWatch(program2) {
28835
29267
 
28836
29268
  // src/commands/roam/auth.ts
28837
29269
  import { randomBytes } from "crypto";
28838
- import chalk210 from "chalk";
29270
+ import chalk212 from "chalk";
28839
29271
 
28840
29272
  // src/commands/roam/waitForCallback.ts
28841
29273
  import { createServer as createServer3 } from "http";
@@ -28966,13 +29398,13 @@ async function auth() {
28966
29398
  saveGlobalConfig(config);
28967
29399
  const state = randomBytes(16).toString("hex");
28968
29400
  console.log(
28969
- chalk210.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
29401
+ chalk212.yellow("\nEnsure this Redirect URI is set in your Roam OAuth app:")
28970
29402
  );
28971
- console.log(chalk210.white("http://localhost:14523/callback\n"));
28972
- console.log(chalk210.blue("Opening browser for authorization..."));
28973
- console.log(chalk210.dim("Waiting for authorization callback..."));
29403
+ console.log(chalk212.white("http://localhost:14523/callback\n"));
29404
+ console.log(chalk212.blue("Opening browser for authorization..."));
29405
+ console.log(chalk212.dim("Waiting for authorization callback..."));
28974
29406
  const { code, redirectUri } = await authorizeInBrowser(clientId, state);
28975
- console.log(chalk210.dim("Exchanging code for tokens..."));
29407
+ console.log(chalk212.dim("Exchanging code for tokens..."));
28976
29408
  const tokens = await exchangeToken({
28977
29409
  code,
28978
29410
  clientId,
@@ -28988,25 +29420,25 @@ async function auth() {
28988
29420
  };
28989
29421
  saveGlobalConfig(config);
28990
29422
  console.log(
28991
- chalk210.green("Roam credentials and tokens saved to ~/.assist.yml")
29423
+ chalk212.green("Roam credentials and tokens saved to ~/.assist.yml")
28992
29424
  );
28993
29425
  }
28994
29426
 
28995
29427
  // src/commands/roam/postRoamActivity.ts
28996
29428
  import { execFileSync as execFileSync13 } from "child_process";
28997
- import { readdirSync as readdirSync12, readFileSync as readFileSync48, statSync as statSync10 } from "fs";
28998
- import { join as join70 } from "path";
29429
+ import { readdirSync as readdirSync18, readFileSync as readFileSync52, statSync as statSync10 } from "fs";
29430
+ import { join as join80 } from "path";
28999
29431
  function findPortFile(roamDir) {
29000
29432
  let entries;
29001
29433
  try {
29002
- entries = readdirSync12(roamDir);
29434
+ entries = readdirSync18(roamDir);
29003
29435
  } catch {
29004
29436
  return void 0;
29005
29437
  }
29006
29438
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
29007
- const path71 = join70(roamDir, name);
29439
+ const path73 = join80(roamDir, name);
29008
29440
  try {
29009
- return { path: path71, mtimeMs: statSync10(path71).mtimeMs };
29441
+ return { path: path73, mtimeMs: statSync10(path73).mtimeMs };
29010
29442
  } catch {
29011
29443
  return void 0;
29012
29444
  }
@@ -29016,11 +29448,11 @@ function findPortFile(roamDir) {
29016
29448
  function postRoamActivity(app, event) {
29017
29449
  const appData = process.env.APPDATA;
29018
29450
  if (!appData) return;
29019
- const portFile = findPortFile(join70(appData, "Roam"));
29451
+ const portFile = findPortFile(join80(appData, "Roam"));
29020
29452
  if (!portFile) return;
29021
29453
  let port;
29022
29454
  try {
29023
- port = readFileSync48(portFile, "utf8").trim();
29455
+ port = readFileSync52(portFile, "utf8").trim();
29024
29456
  } catch {
29025
29457
  return;
29026
29458
  }
@@ -29148,8 +29580,8 @@ async function run3(name, args) {
29148
29580
  }
29149
29581
 
29150
29582
  // src/commands/run/add.ts
29151
- import { mkdirSync as mkdirSync24, writeFileSync as writeFileSync41 } from "fs";
29152
- import { join as join71 } from "path";
29583
+ import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync44 } from "fs";
29584
+ import { join as join81 } from "path";
29153
29585
 
29154
29586
  // src/commands/run/extractOption.ts
29155
29587
  function extractOption(args, flag) {
@@ -29210,16 +29642,16 @@ function saveNewRunConfig(name, command, args, cwd) {
29210
29642
  saveConfig(config);
29211
29643
  }
29212
29644
  function createCommandFile(name) {
29213
- const dir = join71(".claude", "commands");
29214
- mkdirSync24(dir, { recursive: true });
29645
+ const dir = join81(".claude", "commands");
29646
+ mkdirSync29(dir, { recursive: true });
29215
29647
  const content = `---
29216
29648
  description: Run ${name}
29217
29649
  ---
29218
29650
 
29219
29651
  Run \`assist run ${name} $ARGUMENTS 2>&1\`.
29220
29652
  `;
29221
- const filePath = join71(dir, `${name}.md`);
29222
- writeFileSync41(filePath, content);
29653
+ const filePath = join81(dir, `${name}.md`);
29654
+ writeFileSync44(filePath, content);
29223
29655
  console.log(`Created command file: ${filePath}`);
29224
29656
  }
29225
29657
  function add3() {
@@ -29242,11 +29674,11 @@ function findLinkIndex() {
29242
29674
  function parseLinkArgs() {
29243
29675
  const idx = findLinkIndex();
29244
29676
  if (idx === -1) return null;
29245
- const path71 = process.argv[idx + 1];
29677
+ const path73 = process.argv[idx + 1];
29246
29678
  const rest = process.argv.slice(idx + 2);
29247
29679
  const { value: prefix2 } = extractOption(rest, "--prefix");
29248
29680
  if (!prefix2) return null;
29249
- return { path: path71, prefix: prefix2 };
29681
+ return { path: path73, prefix: prefix2 };
29250
29682
  }
29251
29683
  function hasDuplicateLink(runList, linkPath) {
29252
29684
  return runList.some(
@@ -29274,8 +29706,8 @@ function link2() {
29274
29706
  }
29275
29707
 
29276
29708
  // src/commands/run/remove.ts
29277
- import { existsSync as existsSync62, unlinkSync as unlinkSync21 } from "fs";
29278
- import { join as join72 } from "path";
29709
+ import { existsSync as existsSync66, unlinkSync as unlinkSync21 } from "fs";
29710
+ import { join as join82 } from "path";
29279
29711
  function findRemoveIndex() {
29280
29712
  const idx = process.argv.indexOf("remove");
29281
29713
  if (idx === -1 || idx + 1 >= process.argv.length) return -1;
@@ -29290,8 +29722,8 @@ function parseRemoveName() {
29290
29722
  return process.argv[idx + 1];
29291
29723
  }
29292
29724
  function deleteCommandFile(name) {
29293
- const filePath = join72(".claude", "commands", `${name}.md`);
29294
- if (existsSync62(filePath)) {
29725
+ const filePath = join82(".claude", "commands", `${name}.md`);
29726
+ if (existsSync66(filePath)) {
29295
29727
  unlinkSync21(filePath);
29296
29728
  console.log(`Deleted command file: ${filePath}`);
29297
29729
  }
@@ -29336,10 +29768,10 @@ function registerRun(program2) {
29336
29768
 
29337
29769
  // src/commands/screenshot/index.ts
29338
29770
  import { execSync as execSync61 } from "child_process";
29339
- import { existsSync as existsSync63, mkdirSync as mkdirSync25, unlinkSync as unlinkSync22, writeFileSync as writeFileSync42 } from "fs";
29771
+ import { existsSync as existsSync67, mkdirSync as mkdirSync30, unlinkSync as unlinkSync22, writeFileSync as writeFileSync45 } from "fs";
29340
29772
  import { tmpdir as tmpdir8 } from "os";
29341
- import { join as join73, resolve as resolve19 } from "path";
29342
- import chalk211 from "chalk";
29773
+ import { join as join83, resolve as resolve19 } from "path";
29774
+ import chalk213 from "chalk";
29343
29775
 
29344
29776
  // src/commands/screenshot/captureWindowPs1.ts
29345
29777
  var captureWindowPs1 = `
@@ -29468,15 +29900,15 @@ Write-Output $OutputPath
29468
29900
 
29469
29901
  // src/commands/screenshot/index.ts
29470
29902
  function buildOutputPath(outputDir, processName) {
29471
- if (!existsSync63(outputDir)) {
29472
- mkdirSync25(outputDir, { recursive: true });
29903
+ if (!existsSync67(outputDir)) {
29904
+ mkdirSync30(outputDir, { recursive: true });
29473
29905
  }
29474
29906
  const timestamp6 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
29475
29907
  return resolve19(outputDir, `${processName}-${timestamp6}.png`);
29476
29908
  }
29477
29909
  function runPowerShellScript(processName, outputPath) {
29478
- const scriptPath = join73(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
29479
- writeFileSync42(scriptPath, captureWindowPs1, "utf8");
29910
+ const scriptPath = join83(tmpdir8(), `assist-screenshot-${Date.now()}.ps1`);
29911
+ writeFileSync45(scriptPath, captureWindowPs1, "utf8");
29480
29912
  try {
29481
29913
  execSync61(
29482
29914
  `powershell -NoProfile -ExecutionPolicy Bypass -File "${scriptPath}" -ProcessName "${processName}" -OutputPath "${outputPath}"`,
@@ -29490,13 +29922,13 @@ function screenshot(processName) {
29490
29922
  const config = loadConfig();
29491
29923
  const outputDir = resolve19(config.screenshot.outputDir);
29492
29924
  const outputPath = buildOutputPath(outputDir, processName);
29493
- console.log(chalk211.gray(`Capturing window for process "${processName}" ...`));
29925
+ console.log(chalk213.gray(`Capturing window for process "${processName}" ...`));
29494
29926
  try {
29495
29927
  runPowerShellScript(processName, outputPath);
29496
- console.log(chalk211.green(`Screenshot saved: ${outputPath}`));
29928
+ console.log(chalk213.green(`Screenshot saved: ${outputPath}`));
29497
29929
  } catch (error) {
29498
29930
  const msg = error instanceof Error ? error.message : String(error);
29499
- console.error(chalk211.red(`Failed to capture screenshot: ${msg}`));
29931
+ console.error(chalk213.red(`Failed to capture screenshot: ${msg}`));
29500
29932
  process.exit(1);
29501
29933
  }
29502
29934
  }
@@ -29552,7 +29984,7 @@ function applyLine(result, pending, line) {
29552
29984
  }
29553
29985
 
29554
29986
  // src/commands/sessions/daemon/reportStolenSocket.ts
29555
- import { readFileSync as readFileSync49 } from "fs";
29987
+ import { readFileSync as readFileSync53 } from "fs";
29556
29988
  function reportStolenSocket(socketPid) {
29557
29989
  if (!socketPid) return;
29558
29990
  const filePid = readPidFile();
@@ -29564,7 +29996,7 @@ function reportStolenSocket(socketPid) {
29564
29996
  function readPidFile() {
29565
29997
  try {
29566
29998
  const pid = Number.parseInt(
29567
- readFileSync49(daemonPaths.pid, "utf8").trim(),
29999
+ readFileSync53(daemonPaths.pid, "utf8").trim(),
29568
30000
  10
29569
30001
  );
29570
30002
  return Number.isInteger(pid) ? pid : void 0;
@@ -29699,7 +30131,7 @@ function requestDrain(socket, lines2) {
29699
30131
  }
29700
30132
 
29701
30133
  // src/commands/sessions/daemon/runDaemon.ts
29702
- import { mkdirSync as mkdirSync29 } from "fs";
30134
+ import { mkdirSync as mkdirSync34 } from "fs";
29703
30135
 
29704
30136
  // src/commands/sessions/daemon/createAutoExit.ts
29705
30137
  var DEFAULT_GRACE_MS = 6e4;
@@ -29962,42 +30394,42 @@ function serverRunMeta(runName, cwd) {
29962
30394
  }
29963
30395
 
29964
30396
  // src/commands/sessions/daemon/readDesignSystemPrompt.ts
29965
- import * as fs35 from "fs";
29966
- import * as path58 from "path";
29967
- import { fileURLToPath as fileURLToPath8 } from "url";
29968
- var __filename4 = fileURLToPath8(import.meta.url);
29969
- var __dirname6 = path58.dirname(__filename4);
30397
+ import * as fs44 from "fs";
30398
+ import * as path69 from "path";
30399
+ import { fileURLToPath as fileURLToPath9 } from "url";
30400
+ var __filename5 = fileURLToPath9(import.meta.url);
30401
+ var __dirname7 = path69.dirname(__filename5);
29970
30402
  function readDesignSystemPrompt() {
29971
- const promptPath = path58.join(
29972
- __dirname6,
30403
+ const promptPath = path69.join(
30404
+ __dirname7,
29973
30405
  "..",
29974
30406
  "claude",
29975
30407
  "design-system-prompt.md"
29976
30408
  );
29977
- return fs35.readFileSync(promptPath, "utf8");
30409
+ return fs44.readFileSync(promptPath, "utf8");
29978
30410
  }
29979
30411
 
29980
30412
  // src/commands/sessions/daemon/spawnPty.ts
29981
- import { existsSync as existsSync65 } from "fs";
30413
+ import { existsSync as existsSync69 } from "fs";
29982
30414
  import * as pty from "node-pty";
29983
30415
 
29984
30416
  // src/commands/sessions/daemon/ensureSpawnHelperExecutable.ts
29985
- import { chmodSync, existsSync as existsSync64, statSync as statSync11 } from "fs";
30417
+ import { chmodSync, existsSync as existsSync68, statSync as statSync11 } from "fs";
29986
30418
  import { createRequire as createRequire3 } from "module";
29987
- import path59 from "path";
30419
+ import path70 from "path";
29988
30420
  var require4 = createRequire3(import.meta.url);
29989
30421
  var ensured = false;
29990
30422
  function ensureSpawnHelperExecutable() {
29991
30423
  if (ensured || process.platform !== "darwin") return;
29992
30424
  ensured = true;
29993
- const ptyRoot = path59.join(path59.dirname(require4.resolve("node-pty")), "..");
29994
- const helper = path59.join(
30425
+ const ptyRoot = path70.join(path70.dirname(require4.resolve("node-pty")), "..");
30426
+ const helper = path70.join(
29995
30427
  ptyRoot,
29996
30428
  "prebuilds",
29997
30429
  `${process.platform}-${process.arch}`,
29998
30430
  "spawn-helper"
29999
30431
  );
30000
- if (!existsSync64(helper)) return;
30432
+ if (!existsSync68(helper)) return;
30001
30433
  const mode = statSync11(helper).mode;
30002
30434
  if ((mode & 73) === 0) chmodSync(helper, mode | 493);
30003
30435
  }
@@ -30033,7 +30465,7 @@ function spawnPty(args, cwd, sessionId, extraEnv) {
30033
30465
  });
30034
30466
  }
30035
30467
  function refuseMissingCwd(cwd, sessionId) {
30036
- if (!cwd || existsSync65(cwd)) return;
30468
+ if (!cwd || existsSync69(cwd)) return;
30037
30469
  daemonLog(
30038
30470
  `${sessionId ? `session ${sessionId}` : "pty"} not spawned: working directory ${cwd} no longer exists`
30039
30471
  );
@@ -30164,17 +30596,17 @@ function setStatus2(session, newStatus) {
30164
30596
  }
30165
30597
 
30166
30598
  // src/commands/sessions/daemon/worktree/reapWorktree.ts
30167
- import { existsSync as existsSync67 } from "fs";
30168
- import { basename as basename18 } from "path";
30599
+ import { existsSync as existsSync71 } from "fs";
30600
+ import { basename as basename20 } from "path";
30169
30601
 
30170
30602
  // src/commands/sessions/daemon/worktree/deleteStrandedTree.ts
30171
- import { existsSync as existsSync66 } from "fs";
30172
- import { join as join76 } from "path";
30603
+ import { existsSync as existsSync70 } from "fs";
30604
+ import { join as join86 } from "path";
30173
30605
 
30174
30606
  // src/commands/sessions/daemon/worktree/deleteTreeDirectly.ts
30175
30607
  import { statSync as statSync12 } from "fs";
30176
30608
  import { rm as rm2 } from "fs/promises";
30177
- import { join as join75 } from "path";
30609
+ import { join as join85 } from "path";
30178
30610
  async function deleteTreeDirectly(clone, worktreePath, why) {
30179
30611
  if (holdsAGitDirectoryRatherThanALink(worktreePath)) {
30180
30612
  const refusal = "it is a clone of its own, not a linked worktree";
@@ -30202,7 +30634,7 @@ async function deleteTreeDirectly(clone, worktreePath, why) {
30202
30634
  return { removed: true };
30203
30635
  }
30204
30636
  function holdsAGitDirectoryRatherThanALink(worktreePath) {
30205
- return statSync12(join75(worktreePath, ".git"), {
30637
+ return statSync12(join85(worktreePath, ".git"), {
30206
30638
  throwIfNoEntry: false
30207
30639
  })?.isDirectory() === true;
30208
30640
  }
@@ -30238,7 +30670,7 @@ async function deleteStrandedTree(clone, worktreePath, cause) {
30238
30670
  );
30239
30671
  }
30240
30672
  function strandedReason(worktreePath, cause) {
30241
- if (!existsSync66(join76(worktreePath, ".git")))
30673
+ if (!existsSync70(join86(worktreePath, ".git")))
30242
30674
  return "its .git link is already gone";
30243
30675
  if (/not a working tree|not a git repository/i.test(reason2(cause)))
30244
30676
  return "git no longer recognises it as a working tree";
@@ -30290,7 +30722,7 @@ function reason3(error) {
30290
30722
 
30291
30723
  // src/commands/sessions/daemon/worktree/reapWorktree.ts
30292
30724
  async function reapWorktree(worktreePath, force = false) {
30293
- if (!existsSync67(worktreePath)) {
30725
+ if (!existsSync71(worktreePath)) {
30294
30726
  forgetWorktree(worktreePath);
30295
30727
  daemonLog(
30296
30728
  `worktree ${worktreePath} already gone; its record was forgotten`
@@ -30308,14 +30740,14 @@ async function reapWorktree(worktreePath, force = false) {
30308
30740
  const clone = owningClone(worktreePath);
30309
30741
  const removal = await removeTree(clone, worktreePath, force);
30310
30742
  if (!removal.removed) return removal;
30311
- await deleteWorktreeBranch(clone, basename18(worktreePath));
30743
+ await deleteWorktreeBranch(clone, basename20(worktreePath));
30312
30744
  forgetWorktree(worktreePath);
30313
30745
  daemonLog(`worktree ${worktreePath} reaped${force ? " (forced)" : ""}`);
30314
30746
  return removal;
30315
30747
  }
30316
30748
  function owningClone(worktreePath) {
30317
30749
  const recorded = worktreeAttributionIncludingReaped(worktreePath)?.clone;
30318
- if (recorded && existsSync67(recorded)) return recorded;
30750
+ if (recorded && existsSync71(recorded)) return recorded;
30319
30751
  const detected = mainWorktree(worktreePath);
30320
30752
  if (detected) return detected;
30321
30753
  daemonLog(
@@ -30443,12 +30875,12 @@ function closeGateApplies(sessions, session) {
30443
30875
  }
30444
30876
 
30445
30877
  // src/commands/sessions/daemon/worktree/watchGitState.ts
30446
- import { existsSync as existsSync68, watch } from "fs";
30878
+ import { existsSync as existsSync72, watch } from "fs";
30447
30879
  var DEBOUNCE_MS = 500;
30448
30880
  var POLL_MS = 3e4;
30449
30881
  function watchGitState(cwd, onChange) {
30450
30882
  const common = gitCommonDir(cwd);
30451
- if (!common || !existsSync68(common)) return void 0;
30883
+ if (!common || !existsSync72(common)) return void 0;
30452
30884
  const watchers = [
30453
30885
  watchGitDir(common, onChange),
30454
30886
  pollGitState(cwd, onChange)
@@ -30893,10 +31325,10 @@ function emitSessionOutput(session, clients, data) {
30893
31325
  }
30894
31326
 
30895
31327
  // src/commands/sessions/daemon/exitReason.ts
30896
- import { existsSync as existsSync69 } from "fs";
31328
+ import { existsSync as existsSync73 } from "fs";
30897
31329
  import { resolve as resolve20 } from "path";
30898
31330
  function exitDetail(session) {
30899
- if (session.cwd && !existsSync69(session.cwd))
31331
+ if (session.cwd && !existsSync73(session.cwd))
30900
31332
  return `working directory ${session.cwd} no longer exists`;
30901
31333
  return missingRunConfigCwd(session);
30902
31334
  }
@@ -30910,7 +31342,7 @@ function missingRunConfigCwd(session) {
30910
31342
  const config = resolveRunConfig(session.runName, dir);
30911
31343
  if (!config?.cwd) return void 0;
30912
31344
  const configured = resolve20(runConfigBaseDirFrom(dir), config.cwd);
30913
- if (existsSync69(configured)) return void 0;
31345
+ if (existsSync73(configured)) return void 0;
30914
31346
  return `run config "${config.name}": cwd ${configured} does not exist`;
30915
31347
  }
30916
31348
 
@@ -30927,8 +31359,8 @@ function handleFailedResume(session, exitCode, onStatusChange) {
30927
31359
  }
30928
31360
 
30929
31361
  // src/commands/sessions/daemon/watchActivity.ts
30930
- import { existsSync as existsSync70, mkdirSync as mkdirSync26, watch as watch2 } from "fs";
30931
- import { dirname as dirname34 } from "path";
31362
+ import { existsSync as existsSync74, mkdirSync as mkdirSync31, watch as watch2 } from "fs";
31363
+ import { dirname as dirname37 } from "path";
30932
31364
 
30933
31365
  // src/commands/sessions/daemon/applyReviewPause.ts
30934
31366
  function applyReviewPause(session, activity2) {
@@ -30981,10 +31413,10 @@ async function seedRunningMsFromUsage(session, notify2) {
30981
31413
  var DEBOUNCE_MS2 = 50;
30982
31414
  function watchActivity(session, notify2, onClaudeSessionId) {
30983
31415
  if (session.commandType !== "assist" || !session.cwd) return;
30984
- const path71 = activityPath(session.id);
30985
- const dir = dirname34(path71);
31416
+ const path73 = activityPath(session.id);
31417
+ const dir = dirname37(path73);
30986
31418
  try {
30987
- mkdirSync26(dir, { recursive: true });
31419
+ mkdirSync31(dir, { recursive: true });
30988
31420
  } catch {
30989
31421
  return;
30990
31422
  }
@@ -30992,7 +31424,7 @@ function watchActivity(session, notify2, onClaudeSessionId) {
30992
31424
  let timer = null;
30993
31425
  const read = () => {
30994
31426
  timer = null;
30995
- const activity2 = readActivity(path71);
31427
+ const activity2 = readActivity(path73);
30996
31428
  if (!activity2) return;
30997
31429
  session.activity = activity2;
30998
31430
  if (activity2.claudeSessionId) {
@@ -31004,11 +31436,11 @@ function watchActivity(session, notify2, onClaudeSessionId) {
31004
31436
  notify2();
31005
31437
  };
31006
31438
  session.activityWatcher = watch2(dir, (_event, filename) => {
31007
- if (filename && !path71.endsWith(filename)) return;
31439
+ if (filename && !path73.endsWith(filename)) return;
31008
31440
  if (timer) clearTimeout(timer);
31009
31441
  timer = setTimeout(read, DEBOUNCE_MS2);
31010
31442
  });
31011
- if (existsSync70(path71)) read();
31443
+ if (existsSync74(path73)) read();
31012
31444
  }
31013
31445
  function refreshActivity(session) {
31014
31446
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -31097,56 +31529,56 @@ function reportSilentFailure(session, clients) {
31097
31529
  import { watch as watch3 } from "fs";
31098
31530
 
31099
31531
  // src/commands/sessions/shared/findTranscriptPathSync.ts
31100
- import * as fs36 from "fs";
31101
- import * as os4 from "os";
31102
- import * as path60 from "path";
31532
+ import * as fs45 from "fs";
31533
+ import * as os5 from "os";
31534
+ import * as path71 from "path";
31103
31535
  function projectDirForCwd(cwd) {
31104
- return path60.join(
31105
- os4.homedir(),
31536
+ return path71.join(
31537
+ os5.homedir(),
31106
31538
  ".claude",
31107
31539
  "projects",
31108
31540
  cwd.replace(/[^a-zA-Z0-9]/g, "-")
31109
31541
  );
31110
31542
  }
31111
31543
  function transcriptPathFor(cwd, claudeSessionId) {
31112
- return path60.join(projectDirForCwd(cwd), `${claudeSessionId}.jsonl`);
31544
+ return path71.join(projectDirForCwd(cwd), `${claudeSessionId}.jsonl`);
31113
31545
  }
31114
31546
  function findTranscriptPathSync(cwd, claudeSessionId) {
31115
31547
  const direct = transcriptPathFor(cwd, claudeSessionId);
31116
- if (fs36.existsSync(direct)) return direct;
31548
+ if (fs45.existsSync(direct)) return direct;
31117
31549
  const dir = projectDirForCwd(cwd);
31118
31550
  let files;
31119
31551
  try {
31120
- files = fs36.readdirSync(dir);
31552
+ files = fs45.readdirSync(dir);
31121
31553
  } catch {
31122
31554
  return null;
31123
31555
  }
31124
31556
  for (const file of files) {
31125
31557
  if (!file.endsWith(".jsonl")) continue;
31126
- if (headContainsSessionId(path60.join(dir, file), claudeSessionId))
31127
- return path60.join(dir, file);
31558
+ if (headContainsSessionId(path71.join(dir, file), claudeSessionId))
31559
+ return path71.join(dir, file);
31128
31560
  }
31129
31561
  return null;
31130
31562
  }
31131
31563
  function headContainsSessionId(filePath, claudeSessionId) {
31132
31564
  let fd;
31133
31565
  try {
31134
- fd = fs36.openSync(filePath, "r");
31566
+ fd = fs45.openSync(filePath, "r");
31135
31567
  const buf = Buffer.alloc(16384);
31136
- const bytesRead = fs36.readSync(fd, buf, 0, buf.length, 0);
31568
+ const bytesRead = fs45.readSync(fd, buf, 0, buf.length, 0);
31137
31569
  return buf.toString("utf8", 0, bytesRead).includes(claudeSessionId);
31138
31570
  } catch {
31139
31571
  return false;
31140
31572
  } finally {
31141
- if (fd !== void 0) fs36.closeSync(fd);
31573
+ if (fd !== void 0) fs45.closeSync(fd);
31142
31574
  }
31143
31575
  }
31144
31576
 
31145
31577
  // src/commands/sessions/daemon/ensureProjectDirExists.ts
31146
- import { mkdirSync as mkdirSync27 } from "fs";
31578
+ import { mkdirSync as mkdirSync32 } from "fs";
31147
31579
  function ensureProjectDirExists(dir, sessionId) {
31148
31580
  try {
31149
- mkdirSync27(dir, { recursive: true });
31581
+ mkdirSync32(dir, { recursive: true });
31150
31582
  return true;
31151
31583
  } catch (error) {
31152
31584
  daemonLog(
@@ -31253,7 +31685,7 @@ function resolvedToolUseIds(events, afterIdx) {
31253
31685
  }
31254
31686
 
31255
31687
  // src/commands/sessions/shared/readTranscriptTail.ts
31256
- import * as fs37 from "fs";
31688
+ import * as fs46 from "fs";
31257
31689
  var DEFAULT_MAX_BYTES = 256 * 1024;
31258
31690
  function parseTailEntries(raw) {
31259
31691
  const entries = [];
@@ -31277,7 +31709,7 @@ function dropPartialFirstLine(raw, sliced) {
31277
31709
  async function readTranscriptTail(filePath, maxBytes = DEFAULT_MAX_BYTES) {
31278
31710
  let handle;
31279
31711
  try {
31280
- handle = await fs37.promises.open(filePath, "r");
31712
+ handle = await fs46.promises.open(filePath, "r");
31281
31713
  const { size } = await handle.stat();
31282
31714
  const start3 = Math.max(0, size - maxBytes);
31283
31715
  const length = size - start3;
@@ -31296,20 +31728,20 @@ async function readTranscriptTail(filePath, maxBytes = DEFAULT_MAX_BYTES) {
31296
31728
  function readTranscriptTailSync(filePath, maxBytes = DEFAULT_MAX_BYTES) {
31297
31729
  let fd;
31298
31730
  try {
31299
- fd = fs37.openSync(filePath, "r");
31300
- const { size } = fs37.fstatSync(fd);
31731
+ fd = fs46.openSync(filePath, "r");
31732
+ const { size } = fs46.fstatSync(fd);
31301
31733
  const start3 = Math.max(0, size - maxBytes);
31302
31734
  const length = size - start3;
31303
31735
  if (length === 0) return [];
31304
31736
  const buf = Buffer.alloc(length);
31305
- fs37.readSync(fd, buf, 0, length, start3);
31737
+ fs46.readSync(fd, buf, 0, length, start3);
31306
31738
  return parseTailEntries(
31307
31739
  dropPartialFirstLine(buf.toString("utf8"), start3 > 0)
31308
31740
  );
31309
31741
  } catch {
31310
31742
  return [];
31311
31743
  } finally {
31312
- if (fd !== void 0) fs37.closeSync(fd);
31744
+ if (fd !== void 0) fs46.closeSync(fd);
31313
31745
  }
31314
31746
  }
31315
31747
 
@@ -31674,7 +32106,7 @@ async function recordWindowTokens(db, window, resetsAt, tokensUp, tokensDown) {
31674
32106
  }
31675
32107
 
31676
32108
  // src/commands/sessions/shared/transcriptUsage.ts
31677
- import * as fs38 from "fs";
32109
+ import * as fs47 from "fs";
31678
32110
  function transcriptUsage(lines2) {
31679
32111
  const byId = /* @__PURE__ */ new Map();
31680
32112
  for (const line of lines2) {
@@ -31698,7 +32130,7 @@ function transcriptUsage(lines2) {
31698
32130
  return [...byId.values()];
31699
32131
  }
31700
32132
  async function readTranscriptUsage(transcriptPath2) {
31701
- const content = await fs38.promises.readFile(transcriptPath2, "utf8");
32133
+ const content = await fs47.promises.readFile(transcriptPath2, "utf8");
31702
32134
  return transcriptUsage(content.split("\n"));
31703
32135
  }
31704
32136
 
@@ -32365,8 +32797,8 @@ function rearmStoppedSessions(sessions, notify2) {
32365
32797
  }
32366
32798
 
32367
32799
  // src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
32368
- import { existsSync as existsSync73 } from "fs";
32369
- import { basename as basename20 } from "path";
32800
+ import { existsSync as existsSync77 } from "fs";
32801
+ import { basename as basename22 } from "path";
32370
32802
 
32371
32803
  // src/commands/sessions/daemon/worktree/accountedTrees.ts
32372
32804
  function accountedTrees(sessions) {
@@ -32421,21 +32853,21 @@ function bindResumedWorktree(session, cwd, notify2) {
32421
32853
 
32422
32854
  // src/commands/sessions/daemon/worktree/describeHeldWork.ts
32423
32855
  var MAX_ITEMS = 20;
32424
- async function describeHeldWork(path71, reason4) {
32425
- if (reason4.startsWith("uncommitted")) return await changedFiles(path71);
32426
- if (reason4.startsWith("unpushed")) return await unpushedCommits(path71, reason4);
32856
+ async function describeHeldWork(path73, reason4) {
32857
+ if (reason4.startsWith("uncommitted")) return await changedFiles(path73);
32858
+ if (reason4.startsWith("unpushed")) return await unpushedCommits(path73, reason4);
32427
32859
  return { summary: reason4, items: [] };
32428
32860
  }
32429
- async function changedFiles(path71) {
32430
- const status3 = await gitResult(path71, ["status", "--porcelain"]);
32861
+ async function changedFiles(path73) {
32862
+ const status3 = await gitResult(path73, ["status", "--porcelain"]);
32431
32863
  const lines2 = status3.ok ? nonEmptyLines(status3.out) : [];
32432
32864
  return {
32433
32865
  summary: `${lines2.length} uncommitted ${lines2.length === 1 ? "file" : "files"}`,
32434
32866
  items: capped(lines2)
32435
32867
  };
32436
32868
  }
32437
- async function unpushedCommits(path71, reason4) {
32438
- const log2 = await gitResult(path71, ["log", "--oneline", "@{upstream}..HEAD"]);
32869
+ async function unpushedCommits(path73, reason4) {
32870
+ const log2 = await gitResult(path73, ["log", "--oneline", "@{upstream}..HEAD"]);
32439
32871
  if (!log2.ok) return { summary: reason4, items: [] };
32440
32872
  const lines2 = nonEmptyLines(log2.out);
32441
32873
  return {
@@ -32455,18 +32887,18 @@ function capped(lines2) {
32455
32887
  }
32456
32888
 
32457
32889
  // src/commands/sessions/daemon/worktree/reclaimVanishedWorktrees.ts
32458
- import { existsSync as existsSync72 } from "fs";
32890
+ import { existsSync as existsSync76 } from "fs";
32459
32891
  async function reclaimVanishedWorktrees(clone, paths) {
32460
- if (!existsSync72(clone)) {
32461
- for (const { path: path71 } of paths) forgetWorktree(path71);
32892
+ if (!existsSync76(clone)) {
32893
+ for (const { path: path73 } of paths) forgetWorktree(path73);
32462
32894
  daemonLog(
32463
32895
  `clone ${clone} is gone; forgot ${paths.length} worktree record(s) it owned`
32464
32896
  );
32465
32897
  return;
32466
32898
  }
32467
32899
  await pruneBookkeeping2(clone);
32468
- for (const { path: path71, branch: branch2 } of paths)
32469
- if (await reclaimBranch(clone, branch2)) forgetWorktree(path71);
32900
+ for (const { path: path73, branch: branch2 } of paths)
32901
+ if (await reclaimBranch(clone, branch2)) forgetWorktree(path73);
32470
32902
  }
32471
32903
  async function pruneBookkeeping2(clone) {
32472
32904
  try {
@@ -32493,7 +32925,7 @@ async function reclaimBranch(clone, branch2) {
32493
32925
  }
32494
32926
 
32495
32927
  // src/commands/sessions/daemon/worktree/resurfaceOrphanedWorktree.ts
32496
- import { basename as basename19 } from "path";
32928
+ import { basename as basename21 } from "path";
32497
32929
  function resurfaceOrphanedWorktree(sessions, spawnWith, recovered, notify2) {
32498
32930
  const { orphan, reason: reason4, held } = recovered;
32499
32931
  let id;
@@ -32516,7 +32948,7 @@ function orphanedSession(id, recovered) {
32516
32948
  const { orphan, reason: reason4, held } = recovered;
32517
32949
  return {
32518
32950
  ...sessionBase(id, "stopped"),
32519
- name: `recovered ${basename19(orphan.path)}`,
32951
+ name: `recovered ${basename21(orphan.path)}`,
32520
32952
  subtitle: `${held.summary} in ${orphan.path}`,
32521
32953
  commandType: "claude",
32522
32954
  pty: null,
@@ -32541,17 +32973,17 @@ function recoveryNotice({ orphan, held }) {
32541
32973
  }
32542
32974
 
32543
32975
  // src/commands/sessions/daemon/worktree/logVanishedTree.ts
32544
- function logVanishedTree(sessions, path71) {
32976
+ function logVanishedTree(sessions, path73) {
32545
32977
  const claimants = [...sessions.values()].filter(
32546
- (s) => s.cwd === path71 || s.worktree?.path === path71
32978
+ (s) => s.cwd === path73 || s.worktree?.path === path73
32547
32979
  );
32548
32980
  if (claimants.length === 0) {
32549
- daemonLog(`worktree ${path71} gone from disk and unclaimed; reclaiming it`);
32981
+ daemonLog(`worktree ${path73} gone from disk and unclaimed; reclaiming it`);
32550
32982
  return;
32551
32983
  }
32552
32984
  for (const s of claimants)
32553
32985
  daemonLog(
32554
- `session ${s.id} ("${s.name}") claims worktree ${path71}, which is gone from disk; reclaiming it`
32986
+ `session ${s.id} ("${s.name}") claims worktree ${path73}, which is gone from disk; reclaiming it`
32555
32987
  );
32556
32988
  }
32557
32989
 
@@ -32563,17 +32995,17 @@ function reconcileWorktreesOnRestore(sessions, spawnWith, notify2) {
32563
32995
  async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
32564
32996
  const accounted = accountedTrees(sessions);
32565
32997
  const vanished = /* @__PURE__ */ new Map();
32566
- for (const { path: path71, clone } of readWorktreeRegistry()) {
32567
- if (!existsSync73(path71)) {
32568
- logVanishedTree(sessions, path71);
32998
+ for (const { path: path73, clone } of readWorktreeRegistry()) {
32999
+ if (!existsSync77(path73)) {
33000
+ logVanishedTree(sessions, path73);
32569
33001
  vanished.set(clone, [
32570
33002
  ...vanished.get(clone) ?? [],
32571
- { path: path71, branch: basename20(path71) }
33003
+ { path: path73, branch: basename22(path73) }
32572
33004
  ]);
32573
33005
  continue;
32574
33006
  }
32575
- if (accounted.has(path71)) continue;
32576
- await recoverOrphan(sessions, spawnWith, { path: path71, clone }, notify2);
33007
+ if (accounted.has(path73)) continue;
33008
+ await recoverOrphan(sessions, spawnWith, { path: path73, clone }, notify2);
32577
33009
  }
32578
33010
  for (const [clone, paths] of vanished)
32579
33011
  await reclaimVanishedWorktrees(clone, paths);
@@ -33152,14 +33584,14 @@ async function defaultConnect() {
33152
33584
  }
33153
33585
 
33154
33586
  // src/commands/sessions/daemon/hasPersistedWindowsSessions.ts
33155
- import { existsSync as existsSync74, readFileSync as readFileSync51 } from "fs";
33587
+ import { existsSync as existsSync78, readFileSync as readFileSync55 } from "fs";
33156
33588
  import { posix } from "path";
33157
33589
  function hasPersistedWindowsSessions() {
33158
33590
  const sessionsFile = windowsSessionsFileFromWsl();
33159
33591
  if (!sessionsFile) return false;
33160
33592
  try {
33161
- if (!existsSync74(sessionsFile)) return false;
33162
- const data = JSON.parse(readFileSync51(sessionsFile, "utf8"));
33593
+ if (!existsSync78(sessionsFile)) return false;
33594
+ const data = JSON.parse(readFileSync55(sessionsFile, "utf8"));
33163
33595
  return Array.isArray(data) && data.length > 0;
33164
33596
  } catch (error) {
33165
33597
  const message3 = error instanceof Error ? error.message : String(error);
@@ -33737,7 +34169,7 @@ function addAgentToStream(ctx, targetId, prompt, harness) {
33737
34169
  }
33738
34170
 
33739
34171
  // src/commands/sessions/daemon/worktree/spawnInTree.ts
33740
- import { existsSync as existsSync77 } from "fs";
34172
+ import { existsSync as existsSync81 } from "fs";
33741
34173
 
33742
34174
  // src/commands/sessions/daemon/createAssistSession.ts
33743
34175
  function createAssistSession(id, assistArgs, cwd, meta, holdPty) {
@@ -33790,11 +34222,11 @@ function resumeSession(id, sessionId, cwd, name, holdPty) {
33790
34222
  }
33791
34223
 
33792
34224
  // src/commands/sessions/daemon/worktree/resumeInReplacementTree.ts
33793
- import { existsSync as existsSync76 } from "fs";
34225
+ import { existsSync as existsSync80 } from "fs";
33794
34226
 
33795
34227
  // src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
33796
- import { copyFileSync as copyFileSync2, existsSync as existsSync75, mkdirSync as mkdirSync28 } from "fs";
33797
- import { join as join78 } from "path";
34228
+ import { copyFileSync as copyFileSync7, existsSync as existsSync79, mkdirSync as mkdirSync33 } from "fs";
34229
+ import { join as join88 } from "path";
33798
34230
  function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
33799
34231
  const dir = projectDirForCwd(toCwd);
33800
34232
  if (dir === projectDirForCwd(fromCwd)) {
@@ -33803,8 +34235,8 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
33803
34235
  );
33804
34236
  return;
33805
34237
  }
33806
- const dest = join78(dir, `${claudeSessionId}.jsonl`);
33807
- if (existsSync75(dest)) {
34238
+ const dest = join88(dir, `${claudeSessionId}.jsonl`);
34239
+ if (existsSync79(dest)) {
33808
34240
  daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
33809
34241
  return;
33810
34242
  }
@@ -33816,8 +34248,8 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
33816
34248
  return;
33817
34249
  }
33818
34250
  try {
33819
- mkdirSync28(dir, { recursive: true });
33820
- copyFileSync2(source, dest);
34251
+ mkdirSync33(dir, { recursive: true });
34252
+ copyFileSync7(source, dest);
33821
34253
  daemonLog(
33822
34254
  `transcript ${source} copied to ${dest} so ${toCwd} can resume it`
33823
34255
  );
@@ -33848,7 +34280,7 @@ function resumeInReplacementTree(ctx, claudeSessionId, missingCwd, name) {
33848
34280
  }
33849
34281
  function cloneForReapedTree(missingCwd) {
33850
34282
  const clone = worktreeAttributionIncludingReaped(missingCwd)?.clone;
33851
- if (!clone || !existsSync76(clone))
34283
+ if (!clone || !existsSync80(clone))
33852
34284
  throw new Error(
33853
34285
  `working directory no longer exists and no clone is recorded to re-allocate from: ${missingCwd}`
33854
34286
  );
@@ -33880,7 +34312,7 @@ function spawnAssistInTree(ctx, assistArgs, cwd, meta) {
33880
34312
  return id;
33881
34313
  }
33882
34314
  function resumeInTree(ctx, sessionId, cwd, name) {
33883
- if (!existsSync77(cwd))
34315
+ if (!existsSync81(cwd))
33884
34316
  return resumeInReplacementTree(ctx, sessionId, cwd, name);
33885
34317
  const id = ctx.spawnWith((sid) => resumeSession(sid, sessionId, cwd, name));
33886
34318
  daemonLog(`session ${id} resuming ${sessionId} in ${cwd}`);
@@ -34172,12 +34604,12 @@ function handleSetStatus(client, m, d) {
34172
34604
  }
34173
34605
 
34174
34606
  // src/commands/sessions/shared/parseTranscript.ts
34175
- import * as fs39 from "fs";
34607
+ import * as fs48 from "fs";
34176
34608
  async function parseTranscript(sessionId) {
34177
34609
  const filePath = await findSessionJsonlPath(sessionId);
34178
34610
  if (!filePath) return [];
34179
34611
  try {
34180
- const raw = await fs39.promises.readFile(filePath, "utf8");
34612
+ const raw = await fs48.promises.readFile(filePath, "utf8");
34181
34613
  return parseTranscriptLines(raw.split("\n"));
34182
34614
  } catch {
34183
34615
  return [];
@@ -34201,9 +34633,9 @@ function safeParse2(line) {
34201
34633
  }
34202
34634
 
34203
34635
  // src/commands/sessions/daemon/repoDirExists.ts
34204
- import { existsSync as existsSync78 } from "fs";
34636
+ import { existsSync as existsSync82 } from "fs";
34205
34637
  function repoDirExists(cwd) {
34206
- return existsSync78(toGitCwd(cwd));
34638
+ return existsSync82(toGitCwd(cwd));
34207
34639
  }
34208
34640
 
34209
34641
  // src/commands/sessions/daemon/withRepoGroups.ts
@@ -34404,10 +34836,10 @@ function handleConnection(socket, manager) {
34404
34836
  }
34405
34837
 
34406
34838
  // src/commands/sessions/daemon/onListening.ts
34407
- import { unlinkSync as unlinkSync23, writeFileSync as writeFileSync43 } from "fs";
34839
+ import { unlinkSync as unlinkSync23, writeFileSync as writeFileSync46 } from "fs";
34408
34840
 
34409
34841
  // src/commands/sessions/daemon/startPidFileWatchdog.ts
34410
- import { readFileSync as readFileSync52 } from "fs";
34842
+ import { readFileSync as readFileSync56 } from "fs";
34411
34843
  var WATCHDOG_INTERVAL_MS = 5e3;
34412
34844
  function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
34413
34845
  const timer = setInterval(() => {
@@ -34418,7 +34850,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
34418
34850
  }
34419
34851
  function ownsPidFile() {
34420
34852
  try {
34421
- return readFileSync52(daemonPaths.pid, "utf8").trim() === String(process.pid);
34853
+ return readFileSync56(daemonPaths.pid, "utf8").trim() === String(process.pid);
34422
34854
  } catch {
34423
34855
  return false;
34424
34856
  }
@@ -34426,7 +34858,7 @@ function ownsPidFile() {
34426
34858
 
34427
34859
  // src/commands/sessions/daemon/onListening.ts
34428
34860
  function onListening(manager, checkAutoExit) {
34429
- writeFileSync43(daemonPaths.pid, String(process.pid));
34861
+ writeFileSync46(daemonPaths.pid, String(process.pid));
34430
34862
  startPidFileWatchdog(() => {
34431
34863
  daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
34432
34864
  void manager.flushActiveMs().finally(() => {
@@ -34508,7 +34940,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
34508
34940
 
34509
34941
  // src/commands/sessions/daemon/runDaemon.ts
34510
34942
  async function runDaemon() {
34511
- mkdirSync29(daemonPaths.dir, { recursive: true });
34943
+ mkdirSync34(daemonPaths.dir, { recursive: true });
34512
34944
  daemonLog(
34513
34945
  `starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
34514
34946
  );
@@ -34562,17 +34994,17 @@ function registerSetStatusCommand(cmd) {
34562
34994
  }
34563
34995
 
34564
34996
  // src/commands/sessions/summarise/index.ts
34565
- import * as fs41 from "fs";
34566
- import chalk212 from "chalk";
34997
+ import * as fs50 from "fs";
34998
+ import chalk214 from "chalk";
34567
34999
 
34568
35000
  // src/commands/sessions/summarise/shared.ts
34569
- import * as fs40 from "fs";
35001
+ import * as fs49 from "fs";
34570
35002
  function writeSummary(jsonlPath2, summary) {
34571
- fs40.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
35003
+ fs49.writeFileSync(summaryPathFor(jsonlPath2), `${summary.trim()}
34572
35004
  `, "utf8");
34573
35005
  }
34574
35006
  function hasSummary(jsonlPath2) {
34575
- return fs40.existsSync(summaryPathFor(jsonlPath2));
35007
+ return fs49.existsSync(summaryPathFor(jsonlPath2));
34576
35008
  }
34577
35009
  function summaryPathFor(jsonlPath2) {
34578
35010
  return jsonlPath2.replace(/\.jsonl$/, ".summary");
@@ -34622,29 +35054,29 @@ ${firstMessage}`);
34622
35054
  async function summarise2(options2) {
34623
35055
  const files = await discoverSessionFiles();
34624
35056
  if (files.length === 0) {
34625
- console.log(chalk212.yellow("No sessions found."));
35057
+ console.log(chalk214.yellow("No sessions found."));
34626
35058
  return;
34627
35059
  }
34628
35060
  const toProcess = selectCandidates(files, options2);
34629
35061
  if (toProcess.length === 0) {
34630
- console.log(chalk212.green("All sessions already summarised."));
35062
+ console.log(chalk214.green("All sessions already summarised."));
34631
35063
  return;
34632
35064
  }
34633
35065
  console.log(
34634
- chalk212.cyan(
35066
+ chalk214.cyan(
34635
35067
  `Summarising ${toProcess.length} session(s) (${files.length} total)\u2026`
34636
35068
  )
34637
35069
  );
34638
35070
  const { succeeded, failed: failed2 } = processSessions(toProcess);
34639
35071
  console.log(
34640
- chalk212.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk212.yellow(`, ${failed2} skipped`) : "")
35072
+ chalk214.green(`Done: ${succeeded} summarised`) + (failed2 > 0 ? chalk214.yellow(`, ${failed2} skipped`) : "")
34641
35073
  );
34642
35074
  }
34643
35075
  function selectCandidates(files, options2) {
34644
35076
  const candidates = options2.force ? files : files.filter((f) => !hasSummary(f));
34645
35077
  candidates.sort((a, b) => {
34646
35078
  try {
34647
- return fs41.statSync(b).mtimeMs - fs41.statSync(a).mtimeMs;
35079
+ return fs50.statSync(b).mtimeMs - fs50.statSync(a).mtimeMs;
34648
35080
  } catch {
34649
35081
  return 0;
34650
35082
  }
@@ -34657,16 +35089,16 @@ function processSessions(files) {
34657
35089
  let failed2 = 0;
34658
35090
  for (let i = 0; i < files.length; i++) {
34659
35091
  const file = files[i];
34660
- process.stdout.write(chalk212.dim(` [${i + 1}/${files.length}] `));
35092
+ process.stdout.write(chalk214.dim(` [${i + 1}/${files.length}] `));
34661
35093
  const summary = summariseSession(file);
34662
35094
  if (summary) {
34663
35095
  writeSummary(file, summary);
34664
35096
  succeeded++;
34665
- process.stdout.write(`${chalk212.green("\u2713")} ${summary}
35097
+ process.stdout.write(`${chalk214.green("\u2713")} ${summary}
34666
35098
  `);
34667
35099
  } else {
34668
35100
  failed2++;
34669
- process.stdout.write(` ${chalk212.yellow("skip")}
35101
+ process.stdout.write(` ${chalk214.yellow("skip")}
34670
35102
  `);
34671
35103
  }
34672
35104
  }
@@ -34687,7 +35119,7 @@ function registerSessions(program2) {
34687
35119
  }
34688
35120
 
34689
35121
  // src/commands/statusLine.ts
34690
- import chalk214 from "chalk";
35122
+ import chalk216 from "chalk";
34691
35123
 
34692
35124
  // src/shared/contextLevel.ts
34693
35125
  function contextLevel(pct) {
@@ -34697,7 +35129,7 @@ function contextLevel(pct) {
34697
35129
  }
34698
35130
 
34699
35131
  // src/commands/buildLimitsSegment.ts
34700
- import chalk213 from "chalk";
35132
+ import chalk215 from "chalk";
34701
35133
 
34702
35134
  // src/shared/rateLimitLevel.ts
34703
35135
  var FIVE_HOUR_SECONDS = 5 * 3600;
@@ -34733,9 +35165,9 @@ function rateLimitLevel(pct, resetsAt, windowSeconds, now) {
34733
35165
 
34734
35166
  // src/commands/buildLimitsSegment.ts
34735
35167
  var LEVEL_COLOR = {
34736
- ok: chalk213.green,
34737
- warn: chalk213.yellow,
34738
- over: chalk213.red
35168
+ ok: chalk215.green,
35169
+ warn: chalk215.yellow,
35170
+ over: chalk215.red
34739
35171
  };
34740
35172
  function formatLimit(pct, resetsAt, windowSeconds, fallbackLabel, now) {
34741
35173
  const level = rateLimitLevel(pct, resetsAt, windowSeconds, now);
@@ -34766,10 +35198,10 @@ function buildLimitsSegment(rateLimits) {
34766
35198
  }
34767
35199
 
34768
35200
  // src/commands/readGitBranch.ts
34769
- import { readFileSync as readFileSync54, statSync as statSync14 } from "fs";
34770
- import { isAbsolute as isAbsolute4, join as join79, resolve as resolve21 } from "path";
35201
+ import { readFileSync as readFileSync58, statSync as statSync14 } from "fs";
35202
+ import { isAbsolute as isAbsolute4, join as join89, resolve as resolve21 } from "path";
34771
35203
  function resolveGitDir(cwd) {
34772
- const dotGit = join79(cwd, ".git");
35204
+ const dotGit = join89(cwd, ".git");
34773
35205
  let stat4;
34774
35206
  try {
34775
35207
  stat4 = statSync14(dotGit);
@@ -34781,7 +35213,7 @@ function resolveGitDir(cwd) {
34781
35213
  }
34782
35214
  let contents;
34783
35215
  try {
34784
- contents = readFileSync54(dotGit, "utf8");
35216
+ contents = readFileSync58(dotGit, "utf8");
34785
35217
  } catch {
34786
35218
  return null;
34787
35219
  }
@@ -34799,7 +35231,7 @@ function readGitBranch(cwd) {
34799
35231
  }
34800
35232
  let head;
34801
35233
  try {
34802
- head = readFileSync54(join79(gitDir, "HEAD"), "utf8");
35234
+ head = readFileSync58(join89(gitDir, "HEAD"), "utf8");
34803
35235
  } catch {
34804
35236
  return null;
34805
35237
  }
@@ -34831,7 +35263,7 @@ async function relayUsage(claudeSessionId, transcriptPath2, usedPct) {
34831
35263
  }
34832
35264
 
34833
35265
  // src/commands/statusLine.ts
34834
- chalk214.level = 3;
35266
+ chalk216.level = 3;
34835
35267
  function formatNumber(num) {
34836
35268
  return num.toLocaleString("en-US");
34837
35269
  }
@@ -34839,9 +35271,9 @@ function colorizePercent(pct) {
34839
35271
  const label2 = `${Math.round(pct)}%`;
34840
35272
  switch (contextLevel(pct)) {
34841
35273
  case "red":
34842
- return chalk214.red(label2);
35274
+ return chalk216.red(label2);
34843
35275
  case "yellow":
34844
- return chalk214.yellow(label2);
35276
+ return chalk216.yellow(label2);
34845
35277
  default:
34846
35278
  return label2;
34847
35279
  }
@@ -34854,7 +35286,7 @@ async function statusLine() {
34854
35286
  const usedPct = data.context_window.used_percentage ?? 0;
34855
35287
  const dir = data.workspace?.current_dir ?? data.cwd;
34856
35288
  const branch2 = dir ? readGitBranch(toGitCwd(dir)) : null;
34857
- const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk214.cyan(branch2)} | ` : "";
35289
+ const branchSegment = branch2 ? `\u{1F33F}\uFE0F ${chalk216.cyan(branch2)} | ` : "";
34858
35290
  console.log(
34859
35291
  `${branchSegment}${model} | Tokens - ${formatNumber(totalIn)} \u2191 : ${formatNumber(totalOut)} \u2193 | Context - ${colorizePercent(usedPct)}${buildLimitsSegment(data.rate_limits)}`
34860
35292
  );
@@ -34866,299 +35298,9 @@ async function statusLine() {
34866
35298
  );
34867
35299
  }
34868
35300
 
34869
- // src/commands/sync.ts
34870
- import * as fs48 from "fs";
34871
- import * as os5 from "os";
34872
- import * as path69 from "path";
34873
- import { fileURLToPath as fileURLToPath9 } from "url";
34874
-
34875
- // src/commands/sync/syncClaudeMd.ts
34876
- import * as fs42 from "fs";
34877
- import * as path61 from "path";
34878
- import chalk215 from "chalk";
34879
- async function syncClaudeMd(claudeDir, targetBase, options2) {
34880
- const source = path61.join(claudeDir, "CLAUDE.md");
34881
- const target = path61.join(targetBase, "CLAUDE.md");
34882
- const sourceContent = fs42.readFileSync(source, "utf8");
34883
- if (fs42.existsSync(target)) {
34884
- const targetContent = fs42.readFileSync(target, "utf8");
34885
- if (sourceContent !== targetContent) {
34886
- console.log(
34887
- chalk215.yellow("\n\u26A0\uFE0F Warning: CLAUDE.md differs from existing file")
34888
- );
34889
- console.log();
34890
- printDiff(targetContent, sourceContent);
34891
- if (!options2?.yes) {
34892
- printAutoConfirmHint();
34893
- const confirm = await promptConfirm(
34894
- chalk215.red("Overwrite existing CLAUDE.md?"),
34895
- false
34896
- );
34897
- if (!confirm) {
34898
- console.log("Skipped CLAUDE.md");
34899
- return;
34900
- }
34901
- }
34902
- }
34903
- }
34904
- fs42.copyFileSync(source, target);
34905
- console.log("Copied CLAUDE.md to ~/.claude/CLAUDE.md");
34906
- }
34907
-
34908
- // src/commands/sync/syncCodex.ts
34909
- import * as path64 from "path";
34910
-
34911
- // src/commands/sync/installHarnessCommands.ts
34912
- import * as fs43 from "fs";
34913
- import * as path62 from "path";
34914
- function installHarnessCommands(claudeDir, harness, transform) {
34915
- const commandsSource = path62.join(claudeDir, "commands");
34916
- const files = fs43.readdirSync(commandsSource);
34917
- let synced = 0;
34918
- for (const file of files) {
34919
- if (!file.endsWith(".md")) continue;
34920
- const name = file.replace(/\.md$/, "");
34921
- const content = fs43.readFileSync(path62.join(commandsSource, file), "utf8");
34922
- const target = path62.join(harness.homeDir, harness.sync.commandDest(name));
34923
- fs43.mkdirSync(path62.dirname(target), { recursive: true });
34924
- fs43.writeFileSync(target, transform(name, content));
34925
- synced++;
34926
- }
34927
- const agentsTarget = path62.join(harness.homeDir, harness.sync.agentsFile);
34928
- fs43.mkdirSync(path62.dirname(agentsTarget), { recursive: true });
34929
- fs43.copyFileSync(path62.join(claudeDir, "CLAUDE.md"), agentsTarget);
34930
- return { total: files.length, synced };
34931
- }
34932
-
34933
- // src/commands/sync/syncCodexHooks.ts
34934
- import * as fs44 from "fs";
34935
- import * as path63 from "path";
34936
- var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
34937
- var END = "# <<< assist codex hooks (managed) <<<";
34938
- function upsertManagedBlock(existing, body) {
34939
- const block = `${BEGIN}
34940
- ${body.trim()}
34941
- ${END}`;
34942
- const begin = existing.indexOf(BEGIN);
34943
- if (begin === -1) {
34944
- const base = existing.replace(/\s*$/, "");
34945
- return base ? `${base}
34946
-
34947
- ${block}
34948
- ` : `${block}
34949
- `;
34950
- }
34951
- const endMarker = existing.indexOf(END, begin);
34952
- const after = endMarker === -1 ? existing.length : endMarker + END.length;
34953
- const before = existing.slice(0, begin).replace(/\s*$/, "");
34954
- const rest = existing.slice(after).replace(/^\s*/, "");
34955
- const head = before ? `${before}
34956
-
34957
- ${block}` : block;
34958
- return rest ? `${head}
34959
-
34960
- ${rest}
34961
- ` : `${head}
34962
- `;
34963
- }
34964
- function syncCodexHooks(sourcePath) {
34965
- const body = fs44.readFileSync(sourcePath, "utf8");
34966
- const configPath = path63.join(harnesses.codex.homeDir, "config.toml");
34967
- const existing = fs44.existsSync(configPath) ? fs44.readFileSync(configPath, "utf8") : "";
34968
- fs44.mkdirSync(path63.dirname(configPath), { recursive: true });
34969
- fs44.writeFileSync(configPath, upsertManagedBlock(existing, body));
34970
- console.log(
34971
- "Registered assist codex-hook in ~/.codex/config.toml (PreToolUse, PermissionRequest)"
34972
- );
34973
- }
34974
-
34975
- // src/commands/sync/syncCodex.ts
34976
- function quoteYaml(value) {
34977
- return `"${value.replace(/\\/g, String.raw`\\`).replace(/"/g, String.raw`\"`)}"`;
34978
- }
34979
- function commandToSkill(name, content) {
34980
- const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
34981
- const frontmatter = match ? match[1] : "";
34982
- const body = match ? content.slice(match[0].length) : content;
34983
- const descriptionMatch = frontmatter.match(/^description:\s*(.*)$/m);
34984
- const description = descriptionMatch ? descriptionMatch[1].trim().replace(/^["']|["']$/g, "") : name;
34985
- const header = `---
34986
- name: ${name}
34987
- description: ${quoteYaml(description)}
34988
- ---
34989
-
34990
- `;
34991
- return header + body.replace(/^\r?\n+/, "");
34992
- }
34993
- function syncCodex(claudeDir) {
34994
- if (!isHarnessAvailable("codex")) return;
34995
- const { total } = installHarnessCommands(
34996
- claudeDir,
34997
- harnesses.codex,
34998
- commandToSkill
34999
- );
35000
- syncCodexHooks(path64.join(claudeDir, "..", "codex", "config.toml"));
35001
- console.log(
35002
- `Synced ${total} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
35003
- );
35004
- }
35005
-
35006
- // src/commands/sync/syncDesign.ts
35007
- import * as fs45 from "fs";
35008
- import * as path65 from "path";
35009
- function syncDesign(claudeDir, targetBase) {
35010
- const systemPromptSource = path65.join(claudeDir, "design-system-prompt.md");
35011
- const systemPromptTarget = path65.join(targetBase, "design-system-prompt.md");
35012
- fs45.copyFileSync(systemPromptSource, systemPromptTarget);
35013
- console.log(
35014
- "Copied design-system-prompt.md to ~/.claude/design-system-prompt.md"
35015
- );
35016
- const skillsSource = path65.join(claudeDir, "skills");
35017
- const skillsTarget = path65.join(targetBase, "skills");
35018
- fs45.mkdirSync(skillsTarget, { recursive: true });
35019
- const files = fs45.readdirSync(skillsSource);
35020
- for (const file of files) {
35021
- fs45.copyFileSync(
35022
- path65.join(skillsSource, file),
35023
- path65.join(skillsTarget, file)
35024
- );
35025
- }
35026
- console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
35027
- }
35028
-
35029
- // src/commands/sync/syncPi.ts
35030
- import * as path67 from "path";
35031
-
35032
- // src/commands/sync/syncPiHooks.ts
35033
- import * as fs46 from "fs";
35034
- import * as path66 from "path";
35035
- function piExtensionsDir() {
35036
- return path66.join(harnesses.pi.homeDir, "extensions");
35037
- }
35038
- function syncPiHooks(sourceDir) {
35039
- const target = piExtensionsDir();
35040
- fs46.mkdirSync(target, { recursive: true });
35041
- const files = fs46.readdirSync(sourceDir).filter((f) => f.endsWith(".ts"));
35042
- for (const file of files) {
35043
- fs46.copyFileSync(
35044
- path66.join(sourceDir, file),
35045
- path66.join(target, `assist-${file}`)
35046
- );
35047
- }
35048
- console.log(
35049
- `Registered ${files.length} assist extension(s) in ~/.pi/agent/extensions`
35050
- );
35051
- }
35052
-
35053
- // src/commands/sync/syncPi.ts
35054
- function unquote(value) {
35055
- return value.trim().replace(/^["']|["']$/g, "");
35056
- }
35057
- function commandToPrompt(name, content) {
35058
- const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
35059
- const frontmatter = match ? match[1] : "";
35060
- const body = match ? content.slice(match[0].length) : content;
35061
- const descriptionMatch = frontmatter.match(/^description:\s*(.*)$/m);
35062
- const description = descriptionMatch ? unquote(descriptionMatch[1]) : name;
35063
- const argsMatch = frontmatter.match(/^allowed_args:\s*(.*)$/m);
35064
- const argumentHint = argsMatch ? unquote(argsMatch[1]) : void 0;
35065
- const header = [
35066
- "---",
35067
- `description: ${description}`,
35068
- ...argumentHint ? [`argument-hint: ${argumentHint}`] : [],
35069
- "---",
35070
- "",
35071
- ""
35072
- ].join("\n");
35073
- return header + body.replace(/^\r?\n+/, "");
35074
- }
35075
- function syncPi(claudeDir) {
35076
- if (!isHarnessAvailable("pi")) return;
35077
- const { synced } = installHarnessCommands(
35078
- claudeDir,
35079
- harnesses.pi,
35080
- commandToPrompt
35081
- );
35082
- syncPiHooks(path67.join(claudeDir, "..", "pi"));
35083
- console.log(
35084
- `Synced ${synced} prompt(s) to ~/.pi/agent/prompts and CLAUDE.md to ~/.pi/agent/AGENTS.md`
35085
- );
35086
- }
35087
-
35088
- // src/commands/sync/syncSettings.ts
35089
- import * as fs47 from "fs";
35090
- import * as path68 from "path";
35091
- import chalk216 from "chalk";
35092
- async function syncSettings(claudeDir, targetBase, options2) {
35093
- const source = path68.join(claudeDir, "settings.json");
35094
- const target = path68.join(targetBase, "settings.json");
35095
- const sourceContent = fs47.readFileSync(source, "utf8");
35096
- const sourceSettings = JSON.parse(sourceContent);
35097
- const targetExists = fs47.existsSync(target);
35098
- const targetContent = targetExists ? fs47.readFileSync(target, "utf8") : "";
35099
- const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
35100
- const mergedContent = JSON.stringify(
35101
- { ...preservedUserSettings, ...sourceSettings },
35102
- null,
35103
- " "
35104
- );
35105
- if (targetExists) {
35106
- const normalizedTarget = JSON.stringify(preservedUserSettings, null, " ");
35107
- if (mergedContent !== normalizedTarget) {
35108
- if (!options2?.yes) {
35109
- console.log(
35110
- chalk216.yellow(
35111
- "\n\u26A0\uFE0F Warning: settings.json differs from existing file"
35112
- )
35113
- );
35114
- console.log();
35115
- printDiff(targetContent, mergedContent);
35116
- printAutoConfirmHint();
35117
- const confirm = await promptConfirm(
35118
- chalk216.red("Overwrite existing settings.json?"),
35119
- false
35120
- );
35121
- if (!confirm) {
35122
- console.log("Skipped settings.json");
35123
- return;
35124
- }
35125
- }
35126
- }
35127
- }
35128
- fs47.writeFileSync(target, mergedContent);
35129
- console.log("Copied settings.json to ~/.claude/settings.json");
35130
- }
35131
-
35132
- // src/commands/sync.ts
35133
- var __filename5 = fileURLToPath9(import.meta.url);
35134
- var __dirname7 = path69.dirname(__filename5);
35135
- async function sync(options2) {
35136
- const config = loadConfig();
35137
- const yes = options2?.yes ?? config.sync.autoConfirm;
35138
- const claudeDir = path69.join(__dirname7, "..", "claude");
35139
- const targetBase = path69.join(os5.homedir(), ".claude");
35140
- syncCommands(claudeDir, targetBase);
35141
- syncDesign(claudeDir, targetBase);
35142
- await syncSettings(claudeDir, targetBase, { yes });
35143
- await syncClaudeMd(claudeDir, targetBase, { yes });
35144
- syncCodex(claudeDir);
35145
- syncPi(claudeDir);
35146
- }
35147
- function syncCommands(claudeDir, targetBase) {
35148
- const sourceDir = path69.join(claudeDir, "commands");
35149
- const targetDir = path69.join(targetBase, "commands");
35150
- fs48.mkdirSync(targetDir, { recursive: true });
35151
- const files = fs48.readdirSync(sourceDir);
35152
- for (const file of files) {
35153
- fs48.copyFileSync(path69.join(sourceDir, file), path69.join(targetDir, file));
35154
- console.log(`Copied ${file} to ${targetDir}`);
35155
- }
35156
- console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
35157
- }
35158
-
35159
35301
  // src/commands/update.ts
35160
35302
  import { execSync as execSync62 } from "child_process";
35161
- import * as path70 from "path";
35303
+ import * as path72 from "path";
35162
35304
 
35163
35305
  // src/commands/restartDaemonAfterUpdate.ts
35164
35306
  async function restartDaemonAfterUpdate() {
@@ -35177,12 +35319,12 @@ async function restartDaemonAfterUpdate() {
35177
35319
  // src/commands/update.ts
35178
35320
  function isGlobalNpmInstall(dir) {
35179
35321
  try {
35180
- const resolved = path70.resolve(dir);
35181
- if (resolved.split(path70.sep).includes("node_modules")) {
35322
+ const resolved = path72.resolve(dir);
35323
+ if (resolved.split(path72.sep).includes("node_modules")) {
35182
35324
  return true;
35183
35325
  }
35184
35326
  const globalPrefix = execSync62("npm prefix -g", { stdio: "pipe" }).toString().trim();
35185
- return resolved.toLowerCase().startsWith(path70.resolve(globalPrefix).toLowerCase());
35327
+ return resolved.toLowerCase().startsWith(path72.resolve(globalPrefix).toLowerCase());
35186
35328
  } catch {
35187
35329
  return false;
35188
35330
  }
@@ -35227,10 +35369,7 @@ function reportCliError(error) {
35227
35369
  // src/index.ts
35228
35370
  var program = new Command();
35229
35371
  program.name("assist").description("CLI application").version(package_default.version).option("--no-open", "Do not open a browser on startup").action((options2) => web({ port: "3100", open: options2.open }));
35230
- var syncCommand = program.command("sync").description(
35231
- "Copy command files to ~/.claude/commands; when codex is detected, also install commands as ~/.codex/skills/<name>/SKILL.md, CLAUDE.md as ~/.codex/AGENTS.md, and register the assist codex-hook auto-approval hook in ~/.codex/config.toml; when pi is detected, also install commands as ~/.pi/agent/prompts/<name>.md, CLAUDE.md as ~/.pi/agent/AGENTS.md, and register the assist pi-hook permission-gate extension in ~/.pi/agent/extensions"
35232
- ).option("-y, --yes", "Overwrite settings.json without prompting").action((options2) => sync(options2));
35233
- configHelp(syncCommand, rootConfigHelp.sync);
35372
+ registerSync(program);
35234
35373
  program.command("init").description("Initialize VS Code and verify configurations").action(init5);
35235
35374
  var commitCommand = program.command("commit").description("Create a git commit with validation").argument("<args...>", "status | <message> [files...]").action(commit);
35236
35375
  configHelp(commitCommand, rootConfigHelp.commit);