@staff0rd/assist 0.391.4 → 0.392.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.391.4",
9
+ version: "0.392.0",
10
10
  type: "module",
11
11
  main: "dist/index.js",
12
12
  bin: {
@@ -17,6 +17,7 @@ var package_default = {
17
17
  files: [
18
18
  "dist",
19
19
  "claude",
20
+ "codex",
20
21
  "allowed.cli-reads",
21
22
  "allowed.cli-writes"
22
23
  ],
@@ -140,10 +141,10 @@ import { stringify as stringifyYaml } from "yaml";
140
141
  // src/shared/loadRawYaml.ts
141
142
  import { existsSync, readFileSync } from "fs";
142
143
  import { parse as parseYaml } from "yaml";
143
- function loadRawYaml(path63) {
144
- if (!existsSync(path63)) return {};
144
+ function loadRawYaml(path64) {
145
+ if (!existsSync(path64)) return {};
145
146
  try {
146
- const content = readFileSync(path63, "utf8");
147
+ const content = readFileSync(path64, "utf8");
147
148
  return parseYaml(content) || {};
148
149
  } catch {
149
150
  return {};
@@ -1360,8 +1361,8 @@ function findUnmergedPaths() {
1360
1361
  }
1361
1362
  const found = /* @__PURE__ */ new Set();
1362
1363
  for (const line of output.split("\n")) {
1363
- const path63 = line.split(" ")[1];
1364
- if (path63) found.add(path63.trim());
1364
+ const path64 = line.split(" ")[1];
1365
+ if (path64) found.add(path64.trim());
1365
1366
  }
1366
1367
  return [...found];
1367
1368
  }
@@ -1460,8 +1461,8 @@ function getPreferredRemoteRepo(cwd) {
1460
1461
  function gitRefUrl(kind, ref, cwd) {
1461
1462
  const repo = getPreferredRemoteRepo(cwd);
1462
1463
  if (!repo) return void 0;
1463
- const path63 = kind === "branch" ? "tree" : "commit";
1464
- return `https://github.com/${repo.org}/${repo.repo}/${path63}/${ref}`;
1464
+ const path64 = kind === "branch" ? "tree" : "commit";
1465
+ return `https://github.com/${repo.org}/${repo.repo}/${path64}/${ref}`;
1465
1466
  }
1466
1467
 
1467
1468
  // src/commands/commit/collectCommitRefs.ts
@@ -3232,9 +3233,9 @@ import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
3232
3233
 
3233
3234
  // src/commands/verify/forbiddenStrings/findForbiddenStrings.ts
3234
3235
  import { minimatch as minimatch2 } from "minimatch";
3235
- function resolveStringsAtPath(data, path63) {
3236
+ function resolveStringsAtPath(data, path64) {
3236
3237
  let current = data;
3237
- for (const segment of path63.split(".")) {
3238
+ for (const segment of path64.split(".")) {
3238
3239
  if (current === null || typeof current !== "object") return [];
3239
3240
  current = current[segment];
3240
3241
  }
@@ -3247,10 +3248,10 @@ function resolveStringsAtPath(data, path63) {
3247
3248
  }
3248
3249
  function findRuleViolations(data, rule) {
3249
3250
  const violations = [];
3250
- for (const path63 of rule.paths) {
3251
- for (const value of resolveStringsAtPath(data, path63)) {
3251
+ for (const path64 of rule.paths) {
3252
+ for (const value of resolveStringsAtPath(data, path64)) {
3252
3253
  if (minimatch2(value, rule.disallowed))
3253
- violations.push({ file: rule.file, path: path63, value });
3254
+ violations.push({ file: rule.file, path: path64, value });
3254
3255
  }
3255
3256
  }
3256
3257
  return violations;
@@ -3289,8 +3290,8 @@ function forbiddenStrings() {
3289
3290
  process.exit(0);
3290
3291
  }
3291
3292
  console.log("Forbidden strings found:\n");
3292
- for (const { file, path: path63, value } of violations) {
3293
- console.log(` ${file} ${path63}: ${value}`);
3293
+ for (const { file, path: path64, value } of violations) {
3294
+ console.log(` ${file} ${path64}: ${value}`);
3294
3295
  }
3295
3296
  console.log(`
3296
3297
  Total: ${violations.length} forbidden string(s).`);
@@ -3582,15 +3583,15 @@ function readBaselineMigrations(repoRelativeDir, ref) {
3582
3583
  } catch {
3583
3584
  return baseline;
3584
3585
  }
3585
- const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path63) => MIGRATION_FILE3.test(basename(path63)));
3586
- for (const path63 of paths) {
3586
+ const paths = listing.split("\n").map((line) => line.trim()).filter(Boolean).filter((path64) => MIGRATION_FILE3.test(basename(path64)));
3587
+ for (const path64 of paths) {
3587
3588
  try {
3588
- const content = execSync12(`git show "${ref}:${path63}"`, {
3589
+ const content = execSync12(`git show "${ref}:${path64}"`, {
3589
3590
  encoding: "utf8",
3590
3591
  maxBuffer: 16 * 1024 * 1024,
3591
3592
  stdio: ["pipe", "pipe", "pipe"]
3592
3593
  });
3593
- baseline.set(basename(path63), content);
3594
+ baseline.set(basename(path64), content);
3594
3595
  } catch {
3595
3596
  }
3596
3597
  }
@@ -4955,10 +4956,10 @@ var hooksSettings = {
4955
4956
  }
4956
4957
  };
4957
4958
  function ensureHooksSettings() {
4958
- const path63 = daemonPaths.hooksSettings;
4959
- mkdirSync5(dirname12(path63), { recursive: true });
4960
- writeFileSync15(path63, JSON.stringify(hooksSettings, null, 2));
4961
- return path63;
4959
+ const path64 = daemonPaths.hooksSettings;
4960
+ mkdirSync5(dirname12(path64), { recursive: true });
4961
+ writeFileSync15(path64, JSON.stringify(hooksSettings, null, 2));
4962
+ return path64;
4962
4963
  }
4963
4964
 
4964
4965
  // src/shared/spawnInherit.ts
@@ -5222,9 +5223,9 @@ var LOCAL_FILES = ["backlog.jsonl", "backlog.db"];
5222
5223
  function backupLocalBacklogFiles(dir) {
5223
5224
  const moved = [];
5224
5225
  for (const name of LOCAL_FILES) {
5225
- const path63 = join15(dir, ".assist", name);
5226
- if (existsSync18(path63)) {
5227
- renameSync(path63, `${path63}.bak`);
5226
+ const path64 = join15(dir, ".assist", name);
5227
+ if (existsSync18(path64)) {
5228
+ renameSync(path64, `${path64}.bak`);
5228
5229
  moved.push(`${name} \u2192 ${name}.bak`);
5229
5230
  }
5230
5231
  }
@@ -5663,8 +5664,8 @@ var backlogItemSchema = z3.strictObject({
5663
5664
  var backlogFileSchema = z3.array(backlogItemSchema);
5664
5665
 
5665
5666
  // src/commands/backlog/parseBacklogJsonl.ts
5666
- function parseBacklogJsonl(path63) {
5667
- const content = readFileSync14(path63, "utf8").trim();
5667
+ function parseBacklogJsonl(path64) {
5668
+ const content = readFileSync14(path64, "utf8").trim();
5668
5669
  if (content.length === 0) return [];
5669
5670
  return content.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => backlogItemSchema.parse(JSON.parse(line)));
5670
5671
  }
@@ -5746,8 +5747,8 @@ function findBacklogUp(startDir) {
5746
5747
 
5747
5748
  // src/commands/backlog/getCurrentOrigin.ts
5748
5749
  import { execFileSync } from "child_process";
5749
- function stripLeadingSlashes(path63) {
5750
- return path63.replace(/^\/+/, "");
5750
+ function stripLeadingSlashes(path64) {
5751
+ return path64.replace(/^\/+/, "");
5751
5752
  }
5752
5753
  function normalizeOrigin(raw) {
5753
5754
  const trimmed = raw.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
@@ -6287,24 +6288,24 @@ function getOwnerPath(itemId2) {
6287
6288
  function recordSignalOwner(itemId2) {
6288
6289
  const sessionId = process.env.ASSIST_SESSION_ID;
6289
6290
  if (!sessionId) return;
6290
- const path63 = getOwnerPath(itemId2);
6291
- mkdirSync7(dirname14(path63), { recursive: true });
6292
- writeFileSync17(path63, JSON.stringify({ sessionId }));
6291
+ const path64 = getOwnerPath(itemId2);
6292
+ mkdirSync7(dirname14(path64), { recursive: true });
6293
+ writeFileSync17(path64, JSON.stringify({ sessionId }));
6293
6294
  }
6294
6295
  function readSignalOwner(itemId2) {
6295
- const path63 = getOwnerPath(itemId2);
6296
- if (!existsSync21(path63)) return void 0;
6296
+ const path64 = getOwnerPath(itemId2);
6297
+ if (!existsSync21(path64)) return void 0;
6297
6298
  try {
6298
- const parsed = JSON.parse(readFileSync15(path63, "utf8"));
6299
+ const parsed = JSON.parse(readFileSync15(path64, "utf8"));
6299
6300
  return parsed.sessionId;
6300
6301
  } catch {
6301
6302
  return void 0;
6302
6303
  }
6303
6304
  }
6304
6305
  function clearSignalOwner(itemId2) {
6305
- const path63 = getOwnerPath(itemId2);
6306
+ const path64 = getOwnerPath(itemId2);
6306
6307
  try {
6307
- rmSync(path63);
6308
+ rmSync(path64);
6308
6309
  } catch {
6309
6310
  }
6310
6311
  }
@@ -6341,19 +6342,19 @@ function resolveSignalTarget(event, data) {
6341
6342
  function writeSignal(event, data) {
6342
6343
  const target = resolveSignalTarget(event, data);
6343
6344
  if (!target) return;
6344
- const path63 = getSignalPath(target);
6345
- if (!path63) return;
6345
+ const path64 = getSignalPath(target);
6346
+ if (!path64) return;
6346
6347
  const signal = { event, sessionId: target, ...data };
6347
- mkdirSync8(dirname15(path63), { recursive: true });
6348
- writeFileSync18(path63, JSON.stringify(signal));
6348
+ mkdirSync8(dirname15(path64), { recursive: true });
6349
+ writeFileSync18(path64, JSON.stringify(signal));
6349
6350
  }
6350
6351
 
6351
6352
  // src/commands/backlog/readSignal.ts
6352
6353
  function readSignal() {
6353
- const path63 = getSignalPath();
6354
- if (!path63 || !existsSync22(path63)) return void 0;
6354
+ const path64 = getSignalPath();
6355
+ if (!path64 || !existsSync22(path64)) return void 0;
6355
6356
  try {
6356
- return JSON.parse(readFileSync16(path63, "utf8"));
6357
+ return JSON.parse(readFileSync16(path64, "utf8"));
6357
6358
  } catch {
6358
6359
  return void 0;
6359
6360
  }
@@ -6448,13 +6449,13 @@ function activityPath(sessionId) {
6448
6449
  function emitActivity(activity2) {
6449
6450
  const sessionId = process.env.ASSIST_ACTIVITY_ID;
6450
6451
  if (!sessionId) return;
6451
- const path63 = activityPath(sessionId);
6452
- mkdirSync9(dirname16(path63), { recursive: true });
6453
- writeFileSync19(path63, JSON.stringify({ ...activity2, startedAt: Date.now() }));
6452
+ const path64 = activityPath(sessionId);
6453
+ mkdirSync9(dirname16(path64), { recursive: true });
6454
+ writeFileSync19(path64, JSON.stringify({ ...activity2, startedAt: Date.now() }));
6454
6455
  }
6455
- function readActivity(path63) {
6456
+ function readActivity(path64) {
6456
6457
  try {
6457
- return JSON.parse(readFileSync17(path63, "utf8"));
6458
+ return JSON.parse(readFileSync17(path64, "utf8"));
6458
6459
  } catch {
6459
6460
  return void 0;
6460
6461
  }
@@ -6464,9 +6465,9 @@ function reconcileActivity(sessionId, activity2) {
6464
6465
  removeActivity(sessionId);
6465
6466
  return;
6466
6467
  }
6467
- const path63 = activityPath(sessionId);
6468
- mkdirSync9(dirname16(path63), { recursive: true });
6469
- writeFileSync19(path63, JSON.stringify(activity2));
6468
+ const path64 = activityPath(sessionId);
6469
+ mkdirSync9(dirname16(path64), { recursive: true });
6470
+ writeFileSync19(path64, JSON.stringify(activity2));
6470
6471
  }
6471
6472
  function removeActivity(sessionId) {
6472
6473
  try {
@@ -7697,8 +7698,8 @@ async function getBacklogExists(req, res) {
7697
7698
  // src/commands/backlog/originDisplayName.ts
7698
7699
  function originDisplayName(origin) {
7699
7700
  if (origin.startsWith("local:")) {
7700
- const path63 = origin.slice("local:".length).replace(/\/+$/, "");
7701
- const segments = path63.split("/").filter(Boolean);
7701
+ const path64 = origin.slice("local:".length).replace(/\/+$/, "");
7702
+ const segments = path64.split("/").filter(Boolean);
7702
7703
  return segments[segments.length - 1] ?? origin;
7703
7704
  }
7704
7705
  const firstSlash = origin.indexOf("/");
@@ -8089,7 +8090,7 @@ function findSynthesisForBranch(repoReviewsDir, branch2) {
8089
8090
  const parent = dirname20(branchKeyPath);
8090
8091
  const branchPrefix = basename5(branchKeyPath);
8091
8092
  if (!existsSync25(parent)) return null;
8092
- const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join23(parent, name, "synthesis.md")).filter((path63) => existsSync25(path63)).map((path63) => ({ path: path63, mtime: statSync2(path63).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
8093
+ const synthesisFiles = readdirSync2(parent).filter((name) => name.startsWith(branchPrefix)).map((name) => join23(parent, name, "synthesis.md")).filter((path64) => existsSync25(path64)).map((path64) => ({ path: path64, mtime: statSync2(path64).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
8093
8094
  return synthesisFiles[0]?.path ?? null;
8094
8095
  }
8095
8096
 
@@ -8143,12 +8144,12 @@ async function getReviewSynthesis(req, res) {
8143
8144
  const cwd = getCwdParam(req, res);
8144
8145
  if (!cwd) return;
8145
8146
  try {
8146
- const path63 = await resolveSynthesisPath(cwd);
8147
- if (!path63) {
8147
+ const path64 = await resolveSynthesisPath(cwd);
8148
+ if (!path64) {
8148
8149
  respondJson(res, 404, { error: "No synthesis found" });
8149
8150
  return;
8150
8151
  }
8151
- respondJson(res, 200, { synthesis: readFileSync19(path63, "utf8") });
8152
+ respondJson(res, 200, { synthesis: readFileSync19(path64, "utf8") });
8152
8153
  } catch {
8153
8154
  respondJson(res, 404, { error: "No synthesis found" });
8154
8155
  }
@@ -8283,10 +8284,10 @@ function getStorePath(filename) {
8283
8284
  return join26(getStoreDir(), filename);
8284
8285
  }
8285
8286
  function loadJson(filename) {
8286
- const path63 = getStorePath(filename);
8287
- if (existsSync26(path63)) {
8287
+ const path64 = getStorePath(filename);
8288
+ if (existsSync26(path64)) {
8288
8289
  try {
8289
- return JSON.parse(readFileSync20(path63, "utf8"));
8290
+ return JSON.parse(readFileSync20(path64, "utf8"));
8290
8291
  } catch {
8291
8292
  return {};
8292
8293
  }
@@ -11440,52 +11441,6 @@ function findBuiltinDenyRaw(rawCommand) {
11440
11441
  return toDecision(matchBuiltinDeny(rawCommand));
11441
11442
  }
11442
11443
 
11443
- // src/commands/cliHook/logDeniedToolCall.ts
11444
- import { mkdirSync as mkdirSync12 } from "fs";
11445
- import { homedir as homedir14 } from "os";
11446
- import { join as join28 } from "path";
11447
- import Database from "better-sqlite3";
11448
- var _db;
11449
- function getDbDir() {
11450
- return join28(homedir14(), ".assist");
11451
- }
11452
- function initSchema(db) {
11453
- db.exec(`
11454
- CREATE TABLE IF NOT EXISTS denied_tool_calls (
11455
- id INTEGER PRIMARY KEY AUTOINCREMENT,
11456
- tool TEXT NOT NULL,
11457
- command TEXT NOT NULL,
11458
- repo TEXT NOT NULL,
11459
- session_id TEXT,
11460
- deny_reason TEXT NOT NULL,
11461
- timestamp TEXT NOT NULL DEFAULT (datetime('now'))
11462
- );
11463
- `);
11464
- }
11465
- function openPromptsDb(dir) {
11466
- if (_db) return _db;
11467
- const dbDir = dir ?? getDbDir();
11468
- mkdirSync12(dbDir, { recursive: true });
11469
- const db = new Database(join28(dbDir, "assist.db"));
11470
- db.pragma("journal_mode = WAL");
11471
- initSchema(db);
11472
- _db = db;
11473
- return db;
11474
- }
11475
- function logDeniedToolCall(entry) {
11476
- const db = openPromptsDb();
11477
- db.prepare(
11478
- `INSERT INTO denied_tool_calls (tool, command, repo, session_id, deny_reason)
11479
- VALUES (@tool, @command, @repo, @sessionId, @denyReason)`
11480
- ).run({
11481
- tool: entry.tool,
11482
- command: entry.command,
11483
- repo: entry.repo,
11484
- sessionId: entry.sessionId ?? null,
11485
- denyReason: entry.denyReason
11486
- });
11487
- }
11488
-
11489
11444
  // src/shared/isApprovedRead.ts
11490
11445
  import { resolve as resolve9, sep } from "path";
11491
11446
 
@@ -11576,9 +11531,9 @@ var __dirname4 = dirname21(__filename3);
11576
11531
  function packageRoot() {
11577
11532
  return __dirname4;
11578
11533
  }
11579
- function readLines(path63) {
11580
- if (!existsSync27(path63)) return [];
11581
- return readFileSync23(path63, "utf8").split("\n").filter((line) => line.trim() !== "");
11534
+ function readLines(path64) {
11535
+ if (!existsSync27(path64)) return [];
11536
+ return readFileSync23(path64, "utf8").split("\n").filter((line) => line.trim() !== "");
11582
11537
  }
11583
11538
  var cachedReads;
11584
11539
  var cachedWrites;
@@ -11625,13 +11580,13 @@ function findCliWrite(command) {
11625
11580
 
11626
11581
  // src/shared/readSettingsPerms.ts
11627
11582
  import { existsSync as existsSync28, readFileSync as readFileSync24 } from "fs";
11628
- import { homedir as homedir15 } from "os";
11629
- import { join as join29 } from "path";
11583
+ import { homedir as homedir14 } from "os";
11584
+ import { join as join28 } from "path";
11630
11585
  function readSettingsPerms(key) {
11631
11586
  const paths = [
11632
- join29(homedir15(), ".claude", "settings.json"),
11633
- join29(process.cwd(), ".claude", "settings.json"),
11634
- join29(process.cwd(), ".claude", "settings.local.json")
11587
+ join28(homedir14(), ".claude", "settings.json"),
11588
+ join28(process.cwd(), ".claude", "settings.json"),
11589
+ join28(process.cwd(), ".claude", "settings.local.json")
11635
11590
  ];
11636
11591
  const entries = [];
11637
11592
  for (const p of paths) {
@@ -11823,6 +11778,59 @@ function resolvePermission(toolName, parts) {
11823
11778
  };
11824
11779
  }
11825
11780
 
11781
+ // src/commands/cliHook/decideCommand.ts
11782
+ function decideCommand(toolName, rawCommand) {
11783
+ const result = splitCompound(rawCommand);
11784
+ if (result.ok) return resolvePermission(toolName, result.parts);
11785
+ return findBuiltinDenyRaw(rawCommand) ?? findDeny(toolName, [rawCommand]);
11786
+ }
11787
+
11788
+ // src/commands/cliHook/logDeniedToolCall.ts
11789
+ import { mkdirSync as mkdirSync12 } from "fs";
11790
+ import { homedir as homedir15 } from "os";
11791
+ import { join as join29 } from "path";
11792
+ import Database from "better-sqlite3";
11793
+ var _db;
11794
+ function getDbDir() {
11795
+ return join29(homedir15(), ".assist");
11796
+ }
11797
+ function initSchema(db) {
11798
+ db.exec(`
11799
+ CREATE TABLE IF NOT EXISTS denied_tool_calls (
11800
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
11801
+ tool TEXT NOT NULL,
11802
+ command TEXT NOT NULL,
11803
+ repo TEXT NOT NULL,
11804
+ session_id TEXT,
11805
+ deny_reason TEXT NOT NULL,
11806
+ timestamp TEXT NOT NULL DEFAULT (datetime('now'))
11807
+ );
11808
+ `);
11809
+ }
11810
+ function openPromptsDb(dir) {
11811
+ if (_db) return _db;
11812
+ const dbDir = dir ?? getDbDir();
11813
+ mkdirSync12(dbDir, { recursive: true });
11814
+ const db = new Database(join29(dbDir, "assist.db"));
11815
+ db.pragma("journal_mode = WAL");
11816
+ initSchema(db);
11817
+ _db = db;
11818
+ return db;
11819
+ }
11820
+ function logDeniedToolCall(entry) {
11821
+ const db = openPromptsDb();
11822
+ db.prepare(
11823
+ `INSERT INTO denied_tool_calls (tool, command, repo, session_id, deny_reason)
11824
+ VALUES (@tool, @command, @repo, @sessionId, @denyReason)`
11825
+ ).run({
11826
+ tool: entry.tool,
11827
+ command: entry.command,
11828
+ repo: entry.repo,
11829
+ sessionId: entry.sessionId ?? null,
11830
+ denyReason: entry.denyReason
11831
+ });
11832
+ }
11833
+
11826
11834
  // src/commands/cliHook/index.ts
11827
11835
  var SUPPORTED_TOOLS = /* @__PURE__ */ new Set(["Bash", "PowerShell"]);
11828
11836
  function tryParseInput(raw) {
@@ -11838,15 +11846,10 @@ function tryParseInput(raw) {
11838
11846
  return void 0;
11839
11847
  }
11840
11848
  }
11841
- function decide(toolName, rawCommand) {
11842
- const result = splitCompound(rawCommand);
11843
- if (result.ok) return resolvePermission(toolName, result.parts);
11844
- return findBuiltinDenyRaw(rawCommand) ?? findDeny(toolName, [rawCommand]);
11845
- }
11846
11849
  async function cliHook() {
11847
11850
  const input = tryParseInput(await readStdin());
11848
11851
  if (!input) return;
11849
- const decision = decide(input.toolName, input.command);
11852
+ const decision = decideCommand(input.toolName, input.command);
11850
11853
  if (!decision) return;
11851
11854
  console.log(
11852
11855
  JSON.stringify({
@@ -12022,14 +12025,14 @@ function showProgress(p, label2) {
12022
12025
  const pct = Math.round(p.done / p.total * 100);
12023
12026
  process.stderr.write(`\r\x1B[K[${pct}%] Scanning ${label2}...`);
12024
12027
  }
12025
- async function resolveCommand(cli, path63, description, depth, p) {
12026
- showProgress(p, path63.join(" "));
12027
- const subHelp = await runHelp([cli, ...path63]);
12028
+ async function resolveCommand(cli, path64, description, depth, p) {
12029
+ showProgress(p, path64.join(" "));
12030
+ const subHelp = await runHelp([cli, ...path64]);
12028
12031
  if (!subHelp || !hasSubcommands(subHelp)) {
12029
- return [{ path: path63, description }];
12032
+ return [{ path: path64, description }];
12030
12033
  }
12031
- const children = await discoverAt(cli, path63, depth + 1, p);
12032
- return children.length > 0 ? children : [{ path: path63, description }];
12034
+ const children = await discoverAt(cli, path64, depth + 1, p);
12035
+ return children.length > 0 ? children : [{ path: path64, description }];
12033
12036
  }
12034
12037
  async function discoverAt(cli, parentPath, depth, p) {
12035
12038
  if (depth > SAFETY_DEPTH) return [];
@@ -12177,9 +12180,9 @@ function logPath(cli) {
12177
12180
  return join30(homedir16(), ".assist", `cli-discover-${safeName}.log`);
12178
12181
  }
12179
12182
  function readCache(cli) {
12180
- const path63 = logPath(cli);
12181
- if (!existsSync29(path63)) return void 0;
12182
- return readFileSync25(path63, "utf8");
12183
+ const path64 = logPath(cli);
12184
+ if (!existsSync29(path64)) return void 0;
12185
+ return readFileSync25(path64, "utf8");
12183
12186
  }
12184
12187
  function writeCache(cli, output) {
12185
12188
  const dir = join30(homedir16(), ".assist");
@@ -12351,9 +12354,9 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
12351
12354
  }
12352
12355
  const cutoff = Date.now() - STALE_AFTER_MS;
12353
12356
  for (const entry of entries) {
12354
- const path63 = join32(dir, entry);
12357
+ const path64 = join32(dir, entry);
12355
12358
  try {
12356
- if (statSync3(path63).mtimeMs < cutoff) unlinkSync7(path63);
12359
+ if (statSync3(path64).mtimeMs < cutoff) unlinkSync7(path64);
12357
12360
  } catch {
12358
12361
  continue;
12359
12362
  }
@@ -12363,10 +12366,10 @@ function sweepRestrictedDir(dir = getRestrictedDir()) {
12363
12366
  // src/commands/codeComment/readPinState.ts
12364
12367
  import { existsSync as existsSync30, readFileSync as readFileSync26 } from "fs";
12365
12368
  function readPinState(pin) {
12366
- const path63 = getPinStatePath(pin);
12367
- if (!existsSync30(path63)) return void 0;
12369
+ const path64 = getPinStatePath(pin);
12370
+ if (!existsSync30(path64)) return void 0;
12368
12371
  try {
12369
- const state = JSON.parse(readFileSync26(path63, "utf8"));
12372
+ const state = JSON.parse(readFileSync26(path64, "utf8"));
12370
12373
  if (state.pin !== pin) return void 0;
12371
12374
  return state;
12372
12375
  } catch {
@@ -12515,6 +12518,65 @@ function registerCodeComment(parent) {
12515
12518
  codeComment.command("confirm").description("Confirm a pin to insert its comment and clear the pin state").argument("<pin>", "Pin issued by 'code-comment set'").action(codeCommentConfirm);
12516
12519
  }
12517
12520
 
12521
+ // src/commands/codexHook/index.ts
12522
+ var SUPPORTED_TOOLS2 = /* @__PURE__ */ new Set(["Bash", "PowerShell"]);
12523
+ function parseInput(raw) {
12524
+ try {
12525
+ const data = JSON.parse(raw);
12526
+ const command = data.tool_input?.command;
12527
+ if (typeof command !== "string" || !command.trim()) return void 0;
12528
+ if (!data.tool_name || !SUPPORTED_TOOLS2.has(data.tool_name))
12529
+ return void 0;
12530
+ return {
12531
+ event: data.hook_event_name ?? "PreToolUse",
12532
+ toolName: data.tool_name,
12533
+ command: command.trim()
12534
+ };
12535
+ } catch {
12536
+ return void 0;
12537
+ }
12538
+ }
12539
+ function preToolUseOutput(decision) {
12540
+ if (decision.permissionDecision === "allow") {
12541
+ return {
12542
+ hookSpecificOutput: {
12543
+ hookEventName: "PreToolUse",
12544
+ permissionDecision: "allow",
12545
+ permissionDecisionReason: decision.permissionDecisionReason
12546
+ }
12547
+ };
12548
+ }
12549
+ return { decision: "block", reason: decision.permissionDecisionReason };
12550
+ }
12551
+ function permissionRequestOutput(decision) {
12552
+ return {
12553
+ hookSpecificOutput: {
12554
+ hookEventName: "PermissionRequest",
12555
+ decision: {
12556
+ behavior: decision.permissionDecision === "allow" ? "allow" : "deny",
12557
+ message: decision.permissionDecisionReason
12558
+ }
12559
+ }
12560
+ };
12561
+ }
12562
+ async function codexHook() {
12563
+ const input = parseInput(await readStdin());
12564
+ if (!input) return;
12565
+ const decision = decideCommand(input.toolName, input.command);
12566
+ if (!decision) return;
12567
+ const output = input.event === "PermissionRequest" ? permissionRequestOutput(decision) : preToolUseOutput(decision);
12568
+ console.log(JSON.stringify(output));
12569
+ }
12570
+
12571
+ // src/commands/registerCodexHook.ts
12572
+ function registerCodexHook(program2) {
12573
+ program2.command("codex-hook").description(
12574
+ "Codex PreToolUse/PermissionRequest hook for auto-approving read-only CLI commands"
12575
+ ).action(() => {
12576
+ codexHook();
12577
+ });
12578
+ }
12579
+
12518
12580
  // src/commands/complexity/analyze.ts
12519
12581
  import chalk119 from "chalk";
12520
12582
 
@@ -13132,8 +13194,8 @@ function stepIntoNested(container, key, nextKey) {
13132
13194
  }
13133
13195
  return ensureObject(container, resolved);
13134
13196
  }
13135
- function setNestedValue(obj, path63, value) {
13136
- const keys = path63.split(".");
13197
+ function setNestedValue(obj, path64, value) {
13198
+ const keys = path64.split(".");
13137
13199
  const result = { ...obj };
13138
13200
  let current = result;
13139
13201
  for (let i = 0; i < keys.length - 1; i++) {
@@ -13213,9 +13275,9 @@ function isTraversable(value) {
13213
13275
  function stepInto(current, key) {
13214
13276
  return isTraversable(current) ? current[key] : void 0;
13215
13277
  }
13216
- function getNestedValue(obj, path63) {
13278
+ function getNestedValue(obj, path64) {
13217
13279
  let current = obj;
13218
- for (const key of path63.split(".")) current = stepInto(current, key);
13280
+ for (const key of path64.split(".")) current = stepInto(current, key);
13219
13281
  return current;
13220
13282
  }
13221
13283
 
@@ -15801,9 +15863,9 @@ function parseRscRows(flight) {
15801
15863
  }
15802
15864
  function makeRscResolver(rows) {
15803
15865
  return (ref) => {
15804
- const [id, ...path63] = ref.slice(1).replace(/^[L@]/, "").split(":");
15866
+ const [id, ...path64] = ref.slice(1).replace(/^[L@]/, "").split(":");
15805
15867
  let v = rows[id];
15806
- for (const key of path63) {
15868
+ for (const key of path64) {
15807
15869
  if (v == null || typeof v !== "object") return void 0;
15808
15870
  v = v[key];
15809
15871
  }
@@ -16450,15 +16512,15 @@ function postComment(vars) {
16450
16512
  const stdout = startLine === void 0 ? runGhGraphql(MUTATION_SINGLE, base) : runGhGraphql(MUTATION_MULTI, { ...base, startLine });
16451
16513
  assertThreadCreated(stdout);
16452
16514
  }
16453
- function comment2(path63, line, body, startLine) {
16515
+ function comment2(path64, line, body, startLine) {
16454
16516
  validateBody(body);
16455
16517
  validateLine(line);
16456
16518
  if (startLine !== void 0) validateLine(startLine);
16457
16519
  try {
16458
16520
  const prId = getCurrentPrNodeId();
16459
- postComment({ prId, body, path: path63, line, startLine });
16521
+ postComment({ prId, body, path: path64, line, startLine });
16460
16522
  const range = startLine !== void 0 ? `${startLine}-${line}` : `${line}`;
16461
- console.log(`Added review comment on ${path63}:${range}`);
16523
+ console.log(`Added review comment on ${path64}:${range}`);
16462
16524
  } catch (error) {
16463
16525
  if (isGhNotInstalled(error)) {
16464
16526
  console.error("Error: GitHub CLI (gh) is not installed.");
@@ -17319,8 +17381,8 @@ function registerPrs(program2) {
17319
17381
  prsCommand.command("reply <comment-id> <body>").description("Reply to a comment thread without resolving it").action((commentId, body) => {
17320
17382
  reply(Number.parseInt(commentId, 10), body);
17321
17383
  });
17322
- prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path63, line, body) => {
17323
- comment2(path63, Number.parseInt(line, 10), body);
17384
+ prsCommand.command("comment <path> <line> <body>").description("Add a line comment to the pending review").action((path64, line, body) => {
17385
+ comment2(path64, Number.parseInt(line, 10), body);
17324
17386
  });
17325
17387
  configHelp(prsCommand, prsConfigHelp);
17326
17388
  }
@@ -17573,10 +17635,10 @@ function resolveOpSecret(reference) {
17573
17635
  }
17574
17636
 
17575
17637
  // src/commands/ravendb/ravenFetch.ts
17576
- async function ravenFetch(connection, path63) {
17638
+ async function ravenFetch(connection, path64) {
17577
17639
  const apiKey = resolveOpSecret(connection.apiKeyRef);
17578
17640
  let accessToken = await getAccessToken(apiKey);
17579
- const url = `${connection.url}${path63}`;
17641
+ const url = `${connection.url}${path64}`;
17580
17642
  const headers = {
17581
17643
  Authorization: `Bearer ${accessToken}`,
17582
17644
  "Content-Type": "application/json"
@@ -17680,16 +17742,16 @@ import chalk166 from "chalk";
17680
17742
  // src/commands/ravendb/buildQueryPath.ts
17681
17743
  function buildQueryPath(opts) {
17682
17744
  const db = encodeURIComponent(opts.db);
17683
- let path63;
17745
+ let path64;
17684
17746
  if (opts.collection) {
17685
- path63 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
17747
+ path64 = `/databases/${db}/indexes/dynamic/${encodeURIComponent(opts.collection)}?start=${opts.start}&pageSize=${opts.pageSize}&sort=${encodeURIComponent(opts.sort)}`;
17686
17748
  } else {
17687
- path63 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
17749
+ path64 = `/databases/${db}/queries?start=${opts.start}&pageSize=${opts.pageSize}`;
17688
17750
  }
17689
17751
  if (opts.query) {
17690
- path63 += `&query=${encodeURIComponent(opts.query)}`;
17752
+ path64 += `&query=${encodeURIComponent(opts.query)}`;
17691
17753
  }
17692
- return path63;
17754
+ return path64;
17693
17755
  }
17694
17756
 
17695
17757
  // src/commands/ravendb/fetchAllPages.ts
@@ -17698,7 +17760,7 @@ async function fetchAllPages(connection, opts) {
17698
17760
  let start3 = 0;
17699
17761
  while (true) {
17700
17762
  const effectivePageSize = opts.limit !== void 0 ? Math.min(opts.pageSize, opts.limit - allResults.length) : opts.pageSize;
17701
- const path63 = buildQueryPath({
17763
+ const path64 = buildQueryPath({
17702
17764
  db: connection.database,
17703
17765
  collection: opts.collection,
17704
17766
  start: start3,
@@ -17706,7 +17768,7 @@ async function fetchAllPages(connection, opts) {
17706
17768
  sort: opts.sort,
17707
17769
  query: opts.query
17708
17770
  });
17709
- const data = await ravenFetch(connection, path63);
17771
+ const data = await ravenFetch(connection, path64);
17710
17772
  const results = data.Results ?? [];
17711
17773
  const totalResults = data.TotalResults ?? 0;
17712
17774
  if (results.length === 0) break;
@@ -20094,8 +20156,8 @@ async function handlePostSynthesis(synthesisPath, options2) {
20094
20156
  // src/commands/review/prepareReviewDir.ts
20095
20157
  import { existsSync as existsSync41, mkdirSync as mkdirSync17, unlinkSync as unlinkSync14, writeFileSync as writeFileSync34 } from "fs";
20096
20158
  function clearReviewFiles(paths) {
20097
- for (const path63 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
20098
- if (existsSync41(path63)) unlinkSync14(path63);
20159
+ for (const path64 of [paths.claudePath, paths.codexPath, paths.synthesisPath]) {
20160
+ if (existsSync41(path64)) unlinkSync14(path64);
20099
20161
  }
20100
20162
  }
20101
20163
  function prepareReviewDir(paths, requestBody, force) {
@@ -21243,8 +21305,8 @@ import chalk187 from "chalk";
21243
21305
 
21244
21306
  // src/commands/seq/fetchSeq.ts
21245
21307
  import chalk184 from "chalk";
21246
- async function fetchSeq(conn, path63, params) {
21247
- const url = `${conn.url}${path63}?${params}`;
21308
+ async function fetchSeq(conn, path64, params) {
21309
+ const url = `${conn.url}${path64}?${params}`;
21248
21310
  const response = await fetch(url, {
21249
21311
  headers: {
21250
21312
  Accept: "application/json",
@@ -22731,9 +22793,9 @@ function findPortFile(roamDir) {
22731
22793
  return void 0;
22732
22794
  }
22733
22795
  const candidates = entries.filter((name) => /^roam-local-api(-[^.]+)?\.port$/.test(name)).map((name) => {
22734
- const path63 = join60(roamDir, name);
22796
+ const path64 = join60(roamDir, name);
22735
22797
  try {
22736
- return { path: path63, mtimeMs: statSync8(path63).mtimeMs };
22798
+ return { path: path64, mtimeMs: statSync8(path64).mtimeMs };
22737
22799
  } catch {
22738
22800
  return void 0;
22739
22801
  }
@@ -23152,11 +23214,11 @@ function findLinkIndex() {
23152
23214
  function parseLinkArgs() {
23153
23215
  const idx = findLinkIndex();
23154
23216
  if (idx === -1) return null;
23155
- const path63 = process.argv[idx + 1];
23217
+ const path64 = process.argv[idx + 1];
23156
23218
  const rest = process.argv.slice(idx + 2);
23157
23219
  const { value: prefix2 } = extractOption(rest, "--prefix");
23158
23220
  if (!prefix2) return null;
23159
- return { path: path63, prefix: prefix2 };
23221
+ return { path: path64, prefix: prefix2 };
23160
23222
  }
23161
23223
  function hasDuplicateLink(runList, linkPath) {
23162
23224
  return runList.some(
@@ -24436,8 +24498,8 @@ async function seedRunningMsFromUsage(session, notify2) {
24436
24498
  var DEBOUNCE_MS = 50;
24437
24499
  function watchActivity(session, notify2) {
24438
24500
  if (session.commandType !== "assist" || !session.cwd) return;
24439
- const path63 = activityPath(session.id);
24440
- const dir = dirname29(path63);
24501
+ const path64 = activityPath(session.id);
24502
+ const dir = dirname29(path64);
24441
24503
  try {
24442
24504
  mkdirSync24(dir, { recursive: true });
24443
24505
  } catch {
@@ -24447,7 +24509,7 @@ function watchActivity(session, notify2) {
24447
24509
  let timer = null;
24448
24510
  const read = () => {
24449
24511
  timer = null;
24450
- const activity2 = readActivity(path63);
24512
+ const activity2 = readActivity(path64);
24451
24513
  if (!activity2) return;
24452
24514
  session.activity = activity2;
24453
24515
  if (activity2.claudeSessionId)
@@ -24457,11 +24519,11 @@ function watchActivity(session, notify2) {
24457
24519
  notify2();
24458
24520
  };
24459
24521
  session.activityWatcher = watch(dir, (_event, filename) => {
24460
- if (filename && !path63.endsWith(filename)) return;
24522
+ if (filename && !path64.endsWith(filename)) return;
24461
24523
  if (timer) clearTimeout(timer);
24462
24524
  timer = setTimeout(read, DEBOUNCE_MS);
24463
24525
  });
24464
- if (existsSync54(path63)) read();
24526
+ if (existsSync54(path64)) read();
24465
24527
  }
24466
24528
  function refreshActivity(session) {
24467
24529
  if (session.commandType !== "assist" || !session.cwd) return;
@@ -26550,9 +26612,9 @@ async function statusLine() {
26550
26612
  }
26551
26613
 
26552
26614
  // src/commands/sync.ts
26553
- import * as fs43 from "fs";
26615
+ import * as fs44 from "fs";
26554
26616
  import * as os3 from "os";
26555
- import * as path61 from "path";
26617
+ import * as path62 from "path";
26556
26618
  import { fileURLToPath as fileURLToPath9 } from "url";
26557
26619
 
26558
26620
  // src/commands/sync/syncClaudeMd.ts
@@ -26586,8 +26648,52 @@ async function syncClaudeMd(claudeDir, targetBase, options2) {
26586
26648
  }
26587
26649
 
26588
26650
  // src/commands/sync/syncCodex.ts
26651
+ import * as fs41 from "fs";
26652
+ import * as path59 from "path";
26653
+
26654
+ // src/commands/sync/syncCodexHooks.ts
26589
26655
  import * as fs40 from "fs";
26590
26656
  import * as path58 from "path";
26657
+ var BEGIN = "# >>> assist codex hooks (managed) \u2014 do not edit >>>";
26658
+ var END = "# <<< assist codex hooks (managed) <<<";
26659
+ function upsertManagedBlock(existing, body) {
26660
+ const block = `${BEGIN}
26661
+ ${body.trim()}
26662
+ ${END}`;
26663
+ const begin = existing.indexOf(BEGIN);
26664
+ if (begin === -1) {
26665
+ const base = existing.replace(/\s*$/, "");
26666
+ return base ? `${base}
26667
+
26668
+ ${block}
26669
+ ` : `${block}
26670
+ `;
26671
+ }
26672
+ const endMarker = existing.indexOf(END, begin);
26673
+ const after = endMarker === -1 ? existing.length : endMarker + END.length;
26674
+ const before = existing.slice(0, begin).replace(/\s*$/, "");
26675
+ const rest = existing.slice(after).replace(/^\s*/, "");
26676
+ const head = before ? `${before}
26677
+
26678
+ ${block}` : block;
26679
+ return rest ? `${head}
26680
+
26681
+ ${rest}
26682
+ ` : `${head}
26683
+ `;
26684
+ }
26685
+ function syncCodexHooks(sourcePath) {
26686
+ const body = fs40.readFileSync(sourcePath, "utf8");
26687
+ const configPath = path58.join(harnesses.codex.homeDir, "config.toml");
26688
+ const existing = fs40.existsSync(configPath) ? fs40.readFileSync(configPath, "utf8") : "";
26689
+ fs40.mkdirSync(path58.dirname(configPath), { recursive: true });
26690
+ fs40.writeFileSync(configPath, upsertManagedBlock(existing, body));
26691
+ console.log(
26692
+ "Registered assist codex-hook in ~/.codex/config.toml (PreToolUse, PermissionRequest)"
26693
+ );
26694
+ }
26695
+
26696
+ // src/commands/sync/syncCodex.ts
26591
26697
  function quoteYaml(value) {
26592
26698
  return `"${value.replace(/\\/g, String.raw`\\`).replace(/"/g, String.raw`\"`)}"`;
26593
26699
  }
@@ -26608,56 +26714,57 @@ description: ${quoteYaml(description)}
26608
26714
  function syncCodex(claudeDir) {
26609
26715
  if (!isHarnessAvailable("codex")) return;
26610
26716
  const codex = harnesses.codex;
26611
- const commandsSource = path58.join(claudeDir, "commands");
26612
- const files = fs40.readdirSync(commandsSource);
26717
+ const commandsSource = path59.join(claudeDir, "commands");
26718
+ const files = fs41.readdirSync(commandsSource);
26613
26719
  for (const file of files) {
26614
26720
  if (!file.endsWith(".md")) continue;
26615
26721
  const name = file.replace(/\.md$/, "");
26616
- const content = fs40.readFileSync(path58.join(commandsSource, file), "utf8");
26617
- const target = path58.join(codex.homeDir, codex.sync.commandDest(name));
26618
- fs40.mkdirSync(path58.dirname(target), { recursive: true });
26619
- fs40.writeFileSync(target, commandToSkill(name, content));
26620
- }
26621
- const agentsTarget = path58.join(codex.homeDir, codex.sync.agentsFile);
26622
- fs40.mkdirSync(path58.dirname(agentsTarget), { recursive: true });
26623
- fs40.copyFileSync(path58.join(claudeDir, "CLAUDE.md"), agentsTarget);
26722
+ const content = fs41.readFileSync(path59.join(commandsSource, file), "utf8");
26723
+ const target = path59.join(codex.homeDir, codex.sync.commandDest(name));
26724
+ fs41.mkdirSync(path59.dirname(target), { recursive: true });
26725
+ fs41.writeFileSync(target, commandToSkill(name, content));
26726
+ }
26727
+ const agentsTarget = path59.join(codex.homeDir, codex.sync.agentsFile);
26728
+ fs41.mkdirSync(path59.dirname(agentsTarget), { recursive: true });
26729
+ fs41.copyFileSync(path59.join(claudeDir, "CLAUDE.md"), agentsTarget);
26730
+ syncCodexHooks(path59.join(claudeDir, "..", "codex", "config.toml"));
26624
26731
  console.log(
26625
26732
  `Synced ${files.length} skill(s) to ~/.codex/skills and CLAUDE.md to ~/.codex/AGENTS.md`
26626
26733
  );
26627
26734
  }
26628
26735
 
26629
26736
  // src/commands/sync/syncDesign.ts
26630
- import * as fs41 from "fs";
26631
- import * as path59 from "path";
26737
+ import * as fs42 from "fs";
26738
+ import * as path60 from "path";
26632
26739
  function syncDesign(claudeDir, targetBase) {
26633
- const systemPromptSource = path59.join(claudeDir, "system-prompt.md");
26634
- const systemPromptTarget = path59.join(targetBase, "system-prompt.md");
26635
- fs41.copyFileSync(systemPromptSource, systemPromptTarget);
26740
+ const systemPromptSource = path60.join(claudeDir, "system-prompt.md");
26741
+ const systemPromptTarget = path60.join(targetBase, "system-prompt.md");
26742
+ fs42.copyFileSync(systemPromptSource, systemPromptTarget);
26636
26743
  console.log("Copied system-prompt.md to ~/.claude/system-prompt.md");
26637
- const skillsSource = path59.join(claudeDir, "skills");
26638
- const skillsTarget = path59.join(targetBase, "skills");
26639
- fs41.mkdirSync(skillsTarget, { recursive: true });
26640
- const files = fs41.readdirSync(skillsSource);
26744
+ const skillsSource = path60.join(claudeDir, "skills");
26745
+ const skillsTarget = path60.join(targetBase, "skills");
26746
+ fs42.mkdirSync(skillsTarget, { recursive: true });
26747
+ const files = fs42.readdirSync(skillsSource);
26641
26748
  for (const file of files) {
26642
- fs41.copyFileSync(
26643
- path59.join(skillsSource, file),
26644
- path59.join(skillsTarget, file)
26749
+ fs42.copyFileSync(
26750
+ path60.join(skillsSource, file),
26751
+ path60.join(skillsTarget, file)
26645
26752
  );
26646
26753
  }
26647
26754
  console.log(`Synced ${files.length} design skill(s) to ~/.claude/skills`);
26648
26755
  }
26649
26756
 
26650
26757
  // src/commands/sync/syncSettings.ts
26651
- import * as fs42 from "fs";
26652
- import * as path60 from "path";
26758
+ import * as fs43 from "fs";
26759
+ import * as path61 from "path";
26653
26760
  import chalk200 from "chalk";
26654
26761
  async function syncSettings(claudeDir, targetBase, options2) {
26655
- const source = path60.join(claudeDir, "settings.json");
26656
- const target = path60.join(targetBase, "settings.json");
26657
- const sourceContent = fs42.readFileSync(source, "utf8");
26762
+ const source = path61.join(claudeDir, "settings.json");
26763
+ const target = path61.join(targetBase, "settings.json");
26764
+ const sourceContent = fs43.readFileSync(source, "utf8");
26658
26765
  const sourceSettings = JSON.parse(sourceContent);
26659
- const targetExists = fs42.existsSync(target);
26660
- const targetContent = targetExists ? fs42.readFileSync(target, "utf8") : "";
26766
+ const targetExists = fs43.existsSync(target);
26767
+ const targetContent = targetExists ? fs43.readFileSync(target, "utf8") : "";
26661
26768
  const preservedUserSettings = targetExists ? JSON.parse(targetContent) : {};
26662
26769
  const mergedContent = JSON.stringify(
26663
26770
  { ...preservedUserSettings, ...sourceSettings },
@@ -26686,18 +26793,18 @@ async function syncSettings(claudeDir, targetBase, options2) {
26686
26793
  }
26687
26794
  }
26688
26795
  }
26689
- fs42.writeFileSync(target, mergedContent);
26796
+ fs43.writeFileSync(target, mergedContent);
26690
26797
  console.log("Copied settings.json to ~/.claude/settings.json");
26691
26798
  }
26692
26799
 
26693
26800
  // src/commands/sync.ts
26694
26801
  var __filename5 = fileURLToPath9(import.meta.url);
26695
- var __dirname7 = path61.dirname(__filename5);
26802
+ var __dirname7 = path62.dirname(__filename5);
26696
26803
  async function sync(options2) {
26697
26804
  const config = loadConfig();
26698
26805
  const yes = options2?.yes ?? config.sync.autoConfirm;
26699
- const claudeDir = path61.join(__dirname7, "..", "claude");
26700
- const targetBase = path61.join(os3.homedir(), ".claude");
26806
+ const claudeDir = path62.join(__dirname7, "..", "claude");
26807
+ const targetBase = path62.join(os3.homedir(), ".claude");
26701
26808
  syncCommands(claudeDir, targetBase);
26702
26809
  syncDesign(claudeDir, targetBase);
26703
26810
  await syncSettings(claudeDir, targetBase, { yes });
@@ -26705,12 +26812,12 @@ async function sync(options2) {
26705
26812
  syncCodex(claudeDir);
26706
26813
  }
26707
26814
  function syncCommands(claudeDir, targetBase) {
26708
- const sourceDir = path61.join(claudeDir, "commands");
26709
- const targetDir = path61.join(targetBase, "commands");
26710
- fs43.mkdirSync(targetDir, { recursive: true });
26711
- const files = fs43.readdirSync(sourceDir);
26815
+ const sourceDir = path62.join(claudeDir, "commands");
26816
+ const targetDir = path62.join(targetBase, "commands");
26817
+ fs44.mkdirSync(targetDir, { recursive: true });
26818
+ const files = fs44.readdirSync(sourceDir);
26712
26819
  for (const file of files) {
26713
- fs43.copyFileSync(path61.join(sourceDir, file), path61.join(targetDir, file));
26820
+ fs44.copyFileSync(path62.join(sourceDir, file), path62.join(targetDir, file));
26714
26821
  console.log(`Copied ${file} to ${targetDir}`);
26715
26822
  }
26716
26823
  console.log(`Synced ${files.length} command(s) to ~/.claude/commands`);
@@ -26718,7 +26825,7 @@ function syncCommands(claudeDir, targetBase) {
26718
26825
 
26719
26826
  // src/commands/update.ts
26720
26827
  import { execSync as execSync57 } from "child_process";
26721
- import * as path62 from "path";
26828
+ import * as path63 from "path";
26722
26829
 
26723
26830
  // src/commands/restartDaemonAfterUpdate.ts
26724
26831
  async function restartDaemonAfterUpdate() {
@@ -26737,12 +26844,12 @@ async function restartDaemonAfterUpdate() {
26737
26844
  // src/commands/update.ts
26738
26845
  function isGlobalNpmInstall(dir) {
26739
26846
  try {
26740
- const resolved = path62.resolve(dir);
26741
- if (resolved.split(path62.sep).includes("node_modules")) {
26847
+ const resolved = path63.resolve(dir);
26848
+ if (resolved.split(path63.sep).includes("node_modules")) {
26742
26849
  return true;
26743
26850
  }
26744
26851
  const globalPrefix = execSync57("npm prefix -g", { stdio: "pipe" }).toString().trim();
26745
- return resolved.toLowerCase().startsWith(path62.resolve(globalPrefix).toLowerCase());
26852
+ return resolved.toLowerCase().startsWith(path63.resolve(globalPrefix).toLowerCase());
26746
26853
  } catch {
26747
26854
  return false;
26748
26855
  }
@@ -26788,7 +26895,7 @@ function reportCliError(error) {
26788
26895
  var program = new Command();
26789
26896
  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 }));
26790
26897
  var syncCommand = program.command("sync").description(
26791
- "Copy command files to ~/.claude/commands; when codex is detected, also install commands as ~/.codex/skills/<name>/SKILL.md and CLAUDE.md as ~/.codex/AGENTS.md"
26898
+ "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"
26792
26899
  ).option("-y, --yes", "Overwrite settings.json without prompting").action((options2) => sync(options2));
26793
26900
  configHelp(syncCommand, rootConfigHelp.sync);
26794
26901
  program.command("init").description("Initialize VS Code and verify configurations").action(init5);
@@ -26815,6 +26922,7 @@ registerBackup(program);
26815
26922
  registerDb(program);
26816
26923
  registerCliHook(program);
26817
26924
  registerCodeComment(program);
26925
+ registerCodexHook(program);
26818
26926
  registerEditHook(program);
26819
26927
  registerGithub(program);
26820
26928
  registerHandover(program);