@sunasteriskrnd/takumi 1.0.0-dev.24 → 1.0.0-dev.26

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.
Files changed (2) hide show
  1. package/dist/index.js +2187 -575
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8539,7 +8539,7 @@ var package_default;
8539
8539
  var init_package = __esm(() => {
8540
8540
  package_default = {
8541
8541
  name: "@sunasteriskrnd/takumi",
8542
- version: "1.0.0-dev.24",
8542
+ version: "1.0.0-dev.26",
8543
8543
  description: "CLI tool for bootstrapping and managing Takumi projects",
8544
8544
  type: "module",
8545
8545
  repository: {
@@ -13598,6 +13598,7 @@ function globalSetupToInfo(g2) {
13598
13598
  };
13599
13599
  }
13600
13600
  async function getTakumiSetup(projectDir = process.cwd()) {
13601
+ const { getInstaller, listSupportedProviders } = await Promise.resolve().then(() => (init_registry(), exports_registry));
13601
13602
  const globalResults = await Promise.all(listSupportedProviders().map(async (p) => {
13602
13603
  const inst = getInstaller(p);
13603
13604
  return inst ? await inst.detectGlobalSetup() : null;
@@ -13622,7 +13623,6 @@ async function getTakumiSetup(projectDir = process.cwd()) {
13622
13623
  var import_fs_extra5;
13623
13624
  var init_takumi_scanner = __esm(() => {
13624
13625
  init_paths();
13625
- init_registry();
13626
13626
  init_skip_directories();
13627
13627
  init_manifest_path_resolver();
13628
13628
  import_fs_extra5 = __toESM(require_lib(), 1);
@@ -33539,10 +33539,16 @@ function mergeHooksObject(current, incoming) {
33539
33539
  const merged = deduplicateMerge(existingHooks, incoming);
33540
33540
  return { ...current, hooks: merged };
33541
33541
  }
33542
+ function isMalformedHookCommand(command) {
33543
+ return /(\$HOME|\$\{HOME\}|\$CLAUDE_PROJECT_DIR|\$\{CLAUDE_PROJECT_DIR\}|%USERPROFILE%|%CLAUDE_PROJECT_DIR%)\/\//.test(command);
33544
+ }
33542
33545
  function deduplicateMerge(existing, incoming) {
33543
33546
  const merged = {};
33544
33547
  for (const [event, groups] of Object.entries(existing)) {
33545
- merged[event] = groups.map((g2) => ({ ...g2, hooks: [...g2.hooks] }));
33548
+ merged[event] = groups.map((g2) => ({
33549
+ ...g2,
33550
+ hooks: g2.hooks.filter((h2) => !isMalformedHookCommand(h2.command))
33551
+ }));
33546
33552
  }
33547
33553
  for (const [event, incomingGroups] of Object.entries(incoming)) {
33548
33554
  const existingGroups = merged[event] ?? [];
@@ -33562,7 +33568,13 @@ function deduplicateMerge(existing, incoming) {
33562
33568
  }
33563
33569
  merged[event] = existingGroups;
33564
33570
  }
33565
- return merged;
33571
+ const cleaned = {};
33572
+ for (const [event, groups] of Object.entries(merged)) {
33573
+ const nonEmpty = groups.filter((g2) => g2.hooks.length > 0);
33574
+ if (nonEmpty.length > 0)
33575
+ cleaned[event] = nonEmpty;
33576
+ }
33577
+ return cleaned;
33566
33578
  }
33567
33579
  var init_hooks_settings_merger = __esm(() => {
33568
33580
  init_provider_registry();
@@ -33755,6 +33767,9 @@ function scrubHookEntry(entry, event, capabilities, pathRewrite) {
33755
33767
  if (pathRewrite) {
33756
33768
  scrubbed.command = rewriteCommandPath(scrubbed.command, pathRewrite);
33757
33769
  }
33770
+ if (typeof scrubbed.timeout === "number" && scrubbed.timeout < MIN_CODEX_HOOK_TIMEOUT_SECONDS) {
33771
+ scrubbed.timeout = MIN_CODEX_HOOK_TIMEOUT_SECONDS;
33772
+ }
33758
33773
  const eventCaps = capabilities.events[event];
33759
33774
  if (eventCaps?.permissionDecisionValues) {
33760
33775
  const allowed = new Set(eventCaps.permissionDecisionValues);
@@ -33773,14 +33788,17 @@ function rewriteCommandPath(command, pathRewrite) {
33773
33788
  if (pathRewrite.commandSubstitutions && pathRewrite.commandSubstitutions.size > 0) {
33774
33789
  const home4 = homedir12();
33775
33790
  const homeForward = normalizeSlashes(home4);
33791
+ const projectDirForward = pathRewrite.projectDir != null ? normalizeSlashes(pathRewrite.projectDir) : null;
33792
+ const relFrom = (absForward, baseForward) => {
33793
+ if (absForward.startsWith(`${baseForward}/`))
33794
+ return absForward.slice(baseForward.length + 1);
33795
+ if (absForward === baseForward)
33796
+ return "";
33797
+ return null;
33798
+ };
33776
33799
  for (const [originalAbsPath, wrapperAbsPath] of pathRewrite.commandSubstitutions) {
33777
33800
  const originalAbsForward = normalizeSlashes(originalAbsPath);
33778
- let relFromHome = null;
33779
- if (originalAbsForward.startsWith(`${homeForward}/`)) {
33780
- relFromHome = originalAbsForward.slice(homeForward.length + 1);
33781
- } else if (originalAbsForward === homeForward) {
33782
- relFromHome = "";
33783
- }
33801
+ const relFromHome = relFrom(originalAbsForward, homeForward);
33784
33802
  const candidates = [originalAbsForward, originalAbsPath];
33785
33803
  if (relFromHome !== null && relFromHome !== "") {
33786
33804
  candidates.push(`$HOME/${relFromHome}`);
@@ -33788,6 +33806,12 @@ function rewriteCommandPath(command, pathRewrite) {
33788
33806
  candidates.push(`%USERPROFILE%/${relFromHome}`);
33789
33807
  candidates.push(`\${HOME}/${relFromHome}`);
33790
33808
  }
33809
+ const relFromProject = projectDirForward !== null ? relFrom(originalAbsForward, projectDirForward) : null;
33810
+ if (relFromProject !== null && relFromProject !== "") {
33811
+ candidates.push(`$CLAUDE_PROJECT_DIR/${relFromProject}`);
33812
+ candidates.push(`\${CLAUDE_PROJECT_DIR}/${relFromProject}`);
33813
+ candidates.push(`%CLAUDE_PROJECT_DIR%/${relFromProject}`);
33814
+ }
33791
33815
  const wrapperForward = normalizeSlashes(wrapperAbsPath);
33792
33816
  for (const candidate of candidates) {
33793
33817
  const candidateNorm = normalizeSlashes(candidate);
@@ -33820,6 +33844,7 @@ function isRelativeCommandCandidate(candidate) {
33820
33844
  function escapeRegExp(value) {
33821
33845
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
33822
33846
  }
33847
+ var MIN_CODEX_HOOK_TIMEOUT_SECONDS = 10;
33823
33848
  var init_claude_to_codex_hooks = () => {};
33824
33849
 
33825
33850
  // src/domains/installers/codex/path-safety.ts
@@ -34371,7 +34396,8 @@ async function migrateCodexHooksSettings(options2) {
34371
34396
  const wrapperPaths = [];
34372
34397
  const commandSubstitutions = new Map;
34373
34398
  if (targetHooksDir) {
34374
- const absSourceHooksDir = sourceHooksDir ? isAbsolute2(sourceHooksDir) ? sourceHooksDir : resolve12(projectBase, sourceHooksDir) : "";
34399
+ const sourceHooksDirBase = isGlobal ? homedir14() : projectBase;
34400
+ const absSourceHooksDir = sourceHooksDir ? isAbsolute2(sourceHooksDir) ? sourceHooksDir : resolve12(sourceHooksDirBase, sourceHooksDir) : "";
34375
34401
  const absTargetHooksDir = isAbsolute2(targetHooksDir) ? targetHooksDir : resolve12(projectBase, targetHooksDir);
34376
34402
  const targetAbsolutePaths = installedHookAbsolutePaths && installedHookAbsolutePaths.length > 0 ? installedHookAbsolutePaths.filter(isCodexWrappableHookPath) : installedHookFiles.filter(isCodexWrappableHookPath).map((basenameOrPath) => basenameOrPath.includes("/") || basenameOrPath.includes("\\") ? basenameOrPath : join55(absTargetHooksDir, basenameOrPath));
34377
34403
  const wrapperResults = generateCodexHookWrappers(targetAbsolutePaths, absTargetHooksDir, capabilities);
@@ -34395,7 +34421,8 @@ async function migrateCodexHooksSettings(options2) {
34395
34421
  const converted = convertClaudeHooksToCodex(filtered, capabilities, {
34396
34422
  sourceDir: sourceHooksDir,
34397
34423
  targetDir: targetHooksDir || sourceHooksDir,
34398
- commandSubstitutions: commandSubstitutions.size > 0 ? commandSubstitutions : undefined
34424
+ commandSubstitutions: commandSubstitutions.size > 0 ? commandSubstitutions : undefined,
34425
+ projectDir: isGlobal ? homedir14() : projectBase
34399
34426
  });
34400
34427
  let hooksRegistered = 0;
34401
34428
  for (const groups of Object.values(converted)) {
@@ -34418,7 +34445,7 @@ async function migrateCodexHooksSettings(options2) {
34418
34445
  }
34419
34446
  let backupPath = null;
34420
34447
  try {
34421
- const mergeResult = await mergeHooksIntoSettings(resolvedTargetPath, converted);
34448
+ const mergeResult = await withCodexTargetLock2(resolvedTargetPath, () => mergeHooksIntoSettings(resolvedTargetPath, converted));
34422
34449
  backupPath = mergeResult.backupPath;
34423
34450
  } catch (err) {
34424
34451
  return {
@@ -34436,7 +34463,13 @@ async function migrateCodexHooksSettings(options2) {
34436
34463
  if (capabilities.requiresFeatureFlag) {
34437
34464
  const configTomlPath = isGlobal ? join55(homedir14(), ".codex", "config.toml") : join55(projectBase, ".codex", "config.toml");
34438
34465
  const flagResult = await ensureCodexHooksFeatureFlag(configTomlPath, isGlobal);
34439
- featureFlagWritten = flagResult.status === "written" || flagResult.status === "updated";
34466
+ featureFlagWritten = flagResult.status === "written" || flagResult.status === "updated" || flagResult.status === "already-set";
34467
+ if (flagResult.status === "failed") {
34468
+ warnings.push({
34469
+ reason: "codex-feature-flag-write-failed",
34470
+ message: `Could not write \`[features] hooks = true\` to ${configTomlPath}${flagResult.error ? ` (${flagResult.error})` : ""}. Codex will ignore installed hooks until this flag is set. Add it manually or re-run \`tkm init -a codex\`.`
34471
+ });
34472
+ }
34440
34473
  }
34441
34474
  return {
34442
34475
  status: "registered",
@@ -34460,6 +34493,7 @@ var init_hooks_merger = __esm(() => {
34460
34493
  init_claude_to_codex_hooks();
34461
34494
  init_features_flag();
34462
34495
  init_hook_wrapper();
34496
+ init_path_safety();
34463
34497
  CODEX_WRAPPABLE_HOOK_EXTENSIONS = new Set([".js", ".cjs", ".mjs", ".ts"]);
34464
34498
  });
34465
34499
 
@@ -35985,12 +36019,25 @@ var init_installer2 = __esm(() => {
35985
36019
  });
35986
36020
 
35987
36021
  // src/domains/installers/registry.ts
36022
+ var exports_registry = {};
36023
+ __export(exports_registry, {
36024
+ unregisterInstaller: () => unregisterInstaller,
36025
+ registerInstaller: () => registerInstaller,
36026
+ listSupportedProviders: () => listSupportedProviders,
36027
+ getInstaller: () => getInstaller
36028
+ });
35988
36029
  function getInstaller(provider) {
35989
36030
  return installers[provider] ?? null;
35990
36031
  }
35991
36032
  function listSupportedProviders() {
35992
36033
  return Object.keys(installers);
35993
36034
  }
36035
+ function registerInstaller(installer) {
36036
+ installers[installer.provider] = installer;
36037
+ }
36038
+ function unregisterInstaller(provider) {
36039
+ delete installers[provider];
36040
+ }
35994
36041
  var installers;
35995
36042
  var init_registry = __esm(() => {
35996
36043
  init_installer();
@@ -37485,6 +37532,24 @@ var init_kit_version_checker = __esm(() => {
37485
37532
  });
37486
37533
 
37487
37534
  // src/domains/github/npm-registry.ts
37535
+ function validateRegistryUrl(url) {
37536
+ if (!url || typeof url !== "string" || url.trim() === "") {
37537
+ throw new Error("Invalid registry URL: must be a non-empty string");
37538
+ }
37539
+ if (SHELL_METACHARACTERS.test(url)) {
37540
+ throw new Error("Invalid registry URL: contains disallowed characters");
37541
+ }
37542
+ let parsed;
37543
+ try {
37544
+ parsed = new URL(url);
37545
+ } catch {
37546
+ throw new Error(`Invalid registry URL: not a valid URL (${redactRegistryUrlForLog(url)})`);
37547
+ }
37548
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
37549
+ throw new Error(`Invalid registry URL: unsupported protocol ${parsed.protocol}`);
37550
+ }
37551
+ return url;
37552
+ }
37488
37553
  function redactRegistryUrlForLog(url) {
37489
37554
  if (!url)
37490
37555
  return url;
@@ -37633,9 +37698,10 @@ class NpmRegistryClient {
37633
37698
  }
37634
37699
  }
37635
37700
  }
37636
- var DEFAULT_REGISTRY_URL = "https://registry.npmjs.org", REQUEST_TIMEOUT = 5000, REDACTED_VALUE = "***";
37701
+ var DEFAULT_REGISTRY_URL = "https://registry.npmjs.org", REQUEST_TIMEOUT = 5000, REDACTED_VALUE = "***", SHELL_METACHARACTERS;
37637
37702
  var init_npm_registry = __esm(() => {
37638
37703
  init_logger();
37704
+ SHELL_METACHARACTERS = /[\s;|&$`<>()'"\\\n\r]/;
37639
37705
  });
37640
37706
 
37641
37707
  // src/domains/versioning/checking/cli-version-checker.ts
@@ -50384,14 +50450,14 @@ var exports_monorepo_resolver = {};
50384
50450
  __export(exports_monorepo_resolver, {
50385
50451
  resolveMonorepoRoot: () => resolveMonorepoRoot
50386
50452
  });
50387
- import { existsSync as existsSync46, readFileSync as readFileSync15 } from "node:fs";
50388
- import { dirname as dirname26, join as join96, resolve as resolve20 } from "node:path";
50453
+ import { existsSync as existsSync49, readFileSync as readFileSync16 } from "node:fs";
50454
+ import { dirname as dirname27, join as join99, resolve as resolve22 } from "node:path";
50389
50455
  import { fileURLToPath as fileURLToPath3 } from "node:url";
50390
50456
  function parseMetadataAt(metadataPath) {
50391
- if (!existsSync46(metadataPath))
50457
+ if (!existsSync49(metadataPath))
50392
50458
  return null;
50393
50459
  try {
50394
- const raw = readFileSync15(metadataPath, "utf-8");
50460
+ const raw = readFileSync16(metadataPath, "utf-8");
50395
50461
  const parsed = JSON.parse(raw);
50396
50462
  if (typeof parsed.name !== "string" || typeof parsed.version !== "string" || !ACCEPTED_METADATA_NAMES.has(parsed.name)) {
50397
50463
  return null;
@@ -50402,11 +50468,11 @@ function parseMetadataAt(metadataPath) {
50402
50468
  }
50403
50469
  }
50404
50470
  function readSourceDirFromPackageJson(candidateRoot) {
50405
- const packageJsonPath = join96(candidateRoot, "package.json");
50406
- if (!existsSync46(packageJsonPath))
50471
+ const packageJsonPath = join99(candidateRoot, "package.json");
50472
+ if (!existsSync49(packageJsonPath))
50407
50473
  return null;
50408
50474
  try {
50409
- const parsed = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
50475
+ const parsed = JSON.parse(readFileSync16(packageJsonPath, "utf-8"));
50410
50476
  const kitCfg = parsed.takumi;
50411
50477
  if (kitCfg && typeof kitCfg.sourceDir === "string" && kitCfg.sourceDir.length > 0) {
50412
50478
  return kitCfg.sourceDir;
@@ -50425,7 +50491,7 @@ function tryReadAtCandidate(candidateRoot) {
50425
50491
  };
50426
50492
  }
50427
50493
  const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
50428
- const sourceRoot = join96(candidateRoot, sourceDir);
50494
+ const sourceRoot = join99(candidateRoot, sourceDir);
50429
50495
  const nestedMetadata = parseMetadataAt(getManifestPath(sourceRoot)) ?? parseMetadataAt(getLegacyManifestPath(sourceRoot));
50430
50496
  if (nestedMetadata) {
50431
50497
  return {
@@ -50438,12 +50504,12 @@ function tryReadAtCandidate(candidateRoot) {
50438
50504
  return null;
50439
50505
  }
50440
50506
  function walkUpForMetadata(startDir, maxDepth = 5) {
50441
- let current = resolve20(startDir);
50507
+ let current = resolve22(startDir);
50442
50508
  for (let i = 0;i < maxDepth; i++) {
50443
50509
  const result = tryReadAtCandidate(current);
50444
50510
  if (result)
50445
50511
  return result;
50446
- const parent = dirname26(current);
50512
+ const parent = dirname27(current);
50447
50513
  if (parent === current)
50448
50514
  break;
50449
50515
  current = parent;
@@ -50453,13 +50519,13 @@ function walkUpForMetadata(startDir, maxDepth = 5) {
50453
50519
  function resolveMonorepoRoot() {
50454
50520
  try {
50455
50521
  const thisFile = fileURLToPath3(import.meta.url);
50456
- const thisDir = dirname26(thisFile);
50522
+ const thisDir = dirname27(thisFile);
50457
50523
  const result2 = walkUpForMetadata(thisDir);
50458
50524
  if (result2)
50459
50525
  return result2;
50460
50526
  } catch {}
50461
50527
  if (process.argv[1]) {
50462
- const binDir = dirname26(resolve20(process.argv[1]));
50528
+ const binDir = dirname27(resolve22(process.argv[1]));
50463
50529
  const result2 = walkUpForMetadata(binDir);
50464
50530
  if (result2)
50465
50531
  return result2;
@@ -51039,7 +51105,7 @@ function getPagerArgs(pagerCmd) {
51039
51105
  return [];
51040
51106
  }
51041
51107
  async function trySystemPager(content) {
51042
- return new Promise((resolve29) => {
51108
+ return new Promise((resolve31) => {
51043
51109
  const pagerCmd = process.env.PAGER || "less";
51044
51110
  const pagerArgs = getPagerArgs(pagerCmd);
51045
51111
  try {
@@ -51049,20 +51115,20 @@ async function trySystemPager(content) {
51049
51115
  });
51050
51116
  const timeout = setTimeout(() => {
51051
51117
  pager.kill();
51052
- resolve29(false);
51118
+ resolve31(false);
51053
51119
  }, 30000);
51054
51120
  pager.stdin.write(content);
51055
51121
  pager.stdin.end();
51056
51122
  pager.on("close", (code) => {
51057
51123
  clearTimeout(timeout);
51058
- resolve29(code === 0);
51124
+ resolve31(code === 0);
51059
51125
  });
51060
51126
  pager.on("error", () => {
51061
51127
  clearTimeout(timeout);
51062
- resolve29(false);
51128
+ resolve31(false);
51063
51129
  });
51064
51130
  } catch {
51065
- resolve29(false);
51131
+ resolve31(false);
51066
51132
  }
51067
51133
  });
51068
51134
  }
@@ -51089,16 +51155,16 @@ async function basicPager(content) {
51089
51155
  break;
51090
51156
  }
51091
51157
  const remaining = lines.length - currentLine;
51092
- await new Promise((resolve29) => {
51158
+ await new Promise((resolve31) => {
51093
51159
  rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
51094
51160
  if (answer.toLowerCase() === "q") {
51095
51161
  rl.close();
51096
51162
  process.exitCode = 0;
51097
- resolve29();
51163
+ resolve31();
51098
51164
  return;
51099
51165
  }
51100
51166
  process.stdout.write("\x1B[1A\x1B[2K");
51101
- resolve29();
51167
+ resolve31();
51102
51168
  });
51103
51169
  });
51104
51170
  }
@@ -53692,6 +53758,1459 @@ async function configCommand(action, keyOrOptions, valueOrOptions, options2) {
53692
53758
  };
53693
53759
  return configUICommand(uiOpts);
53694
53760
  }
53761
+ // src/domains/sessions/browser-open.ts
53762
+ init_open();
53763
+ function tryOpenBrowser(target) {
53764
+ open_default(target).catch(() => {});
53765
+ }
53766
+
53767
+ // src/domains/sessions/server.ts
53768
+ import * as http from "node:http";
53769
+
53770
+ // src/domains/sessions/adapters/claude.ts
53771
+ import * as fs9 from "node:fs";
53772
+ import * as os4 from "node:os";
53773
+ import * as path7 from "node:path";
53774
+
53775
+ // src/domains/sessions/transcript-parser.ts
53776
+ import * as fs8 from "node:fs";
53777
+
53778
+ // src/domains/sessions/types.ts
53779
+ function emptyTokens() {
53780
+ return { input: 0, output: 0, cacheCreate: 0, cacheRead: 0 };
53781
+ }
53782
+
53783
+ // src/domains/sessions/transcript-parser.ts
53784
+ var MAX_READ_BYTES = 50 * 1024 * 1024;
53785
+ function safeJSON(line) {
53786
+ try {
53787
+ return JSON.parse(line);
53788
+ } catch {
53789
+ return null;
53790
+ }
53791
+ }
53792
+ function readNew(transcriptPath, fromOffset) {
53793
+ if (!transcriptPath || !fs8.existsSync(transcriptPath)) {
53794
+ return { records: [], newOffset: fromOffset || 0 };
53795
+ }
53796
+ if (transcriptPath.endsWith(".zst")) {
53797
+ return { records: [], newOffset: fromOffset || 0 };
53798
+ }
53799
+ const st = fs8.statSync(transcriptPath);
53800
+ const start = fromOffset || 0;
53801
+ if (st.size <= start) {
53802
+ return { records: [], newOffset: st.size };
53803
+ }
53804
+ let len = st.size - start;
53805
+ let truncated = false;
53806
+ if (len > MAX_READ_BYTES) {
53807
+ len = MAX_READ_BYTES;
53808
+ truncated = true;
53809
+ }
53810
+ const fd = fs8.openSync(transcriptPath, "r");
53811
+ try {
53812
+ const buf = Buffer.alloc(len);
53813
+ fs8.readSync(fd, buf, 0, len, start);
53814
+ const text = buf.toString("utf-8");
53815
+ const lines = text.split(`
53816
+ `).filter(Boolean);
53817
+ const records = lines.map(safeJSON).filter((r2) => r2 !== null);
53818
+ const newOffset = truncated ? start + len : st.size;
53819
+ return { records, newOffset };
53820
+ } finally {
53821
+ fs8.closeSync(fd);
53822
+ }
53823
+ }
53824
+ function addTokens(a3, b3) {
53825
+ return {
53826
+ input: (a3.input || 0) + (b3.input || 0),
53827
+ output: (a3.output || 0) + (b3.output || 0),
53828
+ cacheCreate: (a3.cacheCreate || 0) + (b3.cacheCreate || 0),
53829
+ cacheRead: (a3.cacheRead || 0) + (b3.cacheRead || 0)
53830
+ };
53831
+ }
53832
+ function tokensOfClaude(rec) {
53833
+ const r2 = rec;
53834
+ const u = r2?.message?.usage;
53835
+ if (!u)
53836
+ return null;
53837
+ return {
53838
+ input: u.input_tokens || 0,
53839
+ output: u.output_tokens || 0,
53840
+ cacheCreate: u.cache_creation_input_tokens || 0,
53841
+ cacheRead: u.cache_read_input_tokens || 0
53842
+ };
53843
+ }
53844
+ function tokensOfCodex(rec) {
53845
+ const r2 = rec;
53846
+ if (r2?.type !== "event_msg")
53847
+ return null;
53848
+ if (r2?.payload?.type !== "token_count")
53849
+ return null;
53850
+ const u = r2?.payload?.info?.last_token_usage;
53851
+ if (!u)
53852
+ return null;
53853
+ return {
53854
+ input: u.input_tokens || 0,
53855
+ output: (u.output_tokens || 0) + (u.reasoning_output_tokens || 0),
53856
+ cacheCreate: 0,
53857
+ cacheRead: u.cached_input_tokens || 0
53858
+ };
53859
+ }
53860
+ function peekFirstTimestamp(jsonlPath) {
53861
+ if (!fs8.existsSync(jsonlPath))
53862
+ return null;
53863
+ const { records } = readNew(jsonlPath, 0);
53864
+ for (const r2 of records) {
53865
+ const ts = r2?.timestamp;
53866
+ if (ts)
53867
+ return ts;
53868
+ }
53869
+ return null;
53870
+ }
53871
+ function peekLastTimestamp(jsonlPath) {
53872
+ if (!fs8.existsSync(jsonlPath))
53873
+ return null;
53874
+ const { records } = readNew(jsonlPath, 0);
53875
+ for (let i = records.length - 1;i >= 0; i--) {
53876
+ const ts = records[i]?.timestamp;
53877
+ if (ts)
53878
+ return ts;
53879
+ }
53880
+ return null;
53881
+ }
53882
+ function sumClaudeAgentTokens(jsonlPath) {
53883
+ const tot = emptyTokens();
53884
+ let model = null;
53885
+ if (!fs8.existsSync(jsonlPath))
53886
+ return { tokens: tot, model };
53887
+ const { records } = readNew(jsonlPath, 0);
53888
+ for (const rec of records) {
53889
+ const r2 = rec;
53890
+ if (r2?.type !== "assistant" && r2?.message?.role !== "assistant")
53891
+ continue;
53892
+ if (!model && r2?.message?.model)
53893
+ model = r2.message.model;
53894
+ const tok = tokensOfClaude(rec);
53895
+ if (!tok)
53896
+ continue;
53897
+ tot.input += tok.input;
53898
+ tot.output += tok.output;
53899
+ tot.cacheCreate += tok.cacheCreate;
53900
+ tot.cacheRead += tok.cacheRead;
53901
+ }
53902
+ return { tokens: tot, model };
53903
+ }
53904
+ function sumCodexAgentTokens(jsonlPath) {
53905
+ const tot = emptyTokens();
53906
+ if (!fs8.existsSync(jsonlPath))
53907
+ return tot;
53908
+ const { records } = readNew(jsonlPath, 0);
53909
+ for (const rec of records) {
53910
+ const tok = tokensOfCodex(rec);
53911
+ if (!tok)
53912
+ continue;
53913
+ tot.input += tok.input;
53914
+ tot.output += tok.output;
53915
+ tot.cacheCreate += tok.cacheCreate;
53916
+ tot.cacheRead += tok.cacheRead;
53917
+ }
53918
+ return tot;
53919
+ }
53920
+
53921
+ // src/domains/sessions/adapters/claude.ts
53922
+ var CLAUDE_ROOT = path7.join(os4.homedir(), ".claude", "projects");
53923
+ var MAX_PARSE_BYTES = 50 * 1024 * 1024;
53924
+ var HARNESS_TAGS = [
53925
+ "command-name",
53926
+ "command-message",
53927
+ "command-args",
53928
+ "ide_opened_file",
53929
+ "ide_selection",
53930
+ "task-notification",
53931
+ "local-command-stdout",
53932
+ "system-reminder"
53933
+ ];
53934
+ function decodeProjectDir(name) {
53935
+ if (!name)
53936
+ return name;
53937
+ let p = name.replace(/-/g, "/");
53938
+ if (!p.startsWith("/"))
53939
+ p = `/${p}`;
53940
+ return p.replace(/\/+/g, "/");
53941
+ }
53942
+ function peekText(c2) {
53943
+ if (typeof c2 === "string")
53944
+ return c2;
53945
+ if (Array.isArray(c2)) {
53946
+ return c2.filter((it) => it && it.type === "text").map((it) => it.text || "").join(`
53947
+ `);
53948
+ }
53949
+ return "";
53950
+ }
53951
+ function isInterruptText(s) {
53952
+ return /^\s*\[Request interrupted\b/.test(String(s || ""));
53953
+ }
53954
+ function stripCommandTags(s) {
53955
+ let out = String(s || "");
53956
+ for (const tag of HARNESS_TAGS) {
53957
+ const re2 = new RegExp(`<${tag}>[\\s\\S]*?</${tag}>`, "g");
53958
+ out = out.replace(re2, " ");
53959
+ }
53960
+ return out.replace(/\s+/g, " ").trim();
53961
+ }
53962
+ function extractUserText(rec) {
53963
+ const msg = rec?.message;
53964
+ if (!msg)
53965
+ return "";
53966
+ const c2 = msg.content;
53967
+ if (typeof c2 === "string")
53968
+ return stripCommandTags(c2);
53969
+ if (Array.isArray(c2)) {
53970
+ const parts = [];
53971
+ for (const it of c2) {
53972
+ const item = it;
53973
+ if (item?.type === "text" && typeof item.text === "string")
53974
+ parts.push(item.text);
53975
+ }
53976
+ return stripCommandTags(parts.join(`
53977
+ `));
53978
+ }
53979
+ return "";
53980
+ }
53981
+ function parseCommandFromUser(rec) {
53982
+ const msg = rec?.message;
53983
+ if (!msg)
53984
+ return { slashCommand: null, args: "" };
53985
+ let text = "";
53986
+ if (typeof msg.content === "string")
53987
+ text = msg.content;
53988
+ else if (Array.isArray(msg.content)) {
53989
+ for (const it of msg.content) {
53990
+ const item = it;
53991
+ if (item?.type === "text" && typeof item.text === "string")
53992
+ text += item.text;
53993
+ }
53994
+ }
53995
+ const nameMatch = text.match(/<command-name>\s*\/?([^<\s]+)\s*<\/command-name>/);
53996
+ const argsMatch = text.match(/<command-args>([\s\S]*?)<\/command-args>/);
53997
+ return {
53998
+ slashCommand: nameMatch?.[1] ?? null,
53999
+ args: argsMatch?.[1]?.trim() ?? ""
54000
+ };
54001
+ }
54002
+ function isPromptUser(rec) {
54003
+ if (!rec || rec.type !== "user")
54004
+ return false;
54005
+ if (rec.isSidechain)
54006
+ return false;
54007
+ if (rec.isMeta)
54008
+ return false;
54009
+ const msg = rec.message;
54010
+ if (!msg)
54011
+ return false;
54012
+ if (isInterruptText(peekText(msg.content)))
54013
+ return false;
54014
+ if (typeof msg.content === "string")
54015
+ return msg.content.length > 0;
54016
+ if (Array.isArray(msg.content)) {
54017
+ const arr = msg.content;
54018
+ if (arr.some((it) => it?.type === "tool_result"))
54019
+ return false;
54020
+ return arr.some((it) => it?.type === "text");
54021
+ }
54022
+ return false;
54023
+ }
54024
+ function readSessionSummary(filePath) {
54025
+ const out = {
54026
+ startedAt: null,
54027
+ firstUserText: "",
54028
+ cwd: null,
54029
+ aiTitle: null
54030
+ };
54031
+ try {
54032
+ const st = fs9.statSync(filePath);
54033
+ const len = Math.min(st.size, 64 * 1024);
54034
+ const buf = Buffer.alloc(len);
54035
+ const fd = fs9.openSync(filePath, "r");
54036
+ try {
54037
+ fs9.readSync(fd, buf, 0, len, 0);
54038
+ } finally {
54039
+ fs9.closeSync(fd);
54040
+ }
54041
+ const lines = buf.toString("utf-8").split(`
54042
+ `);
54043
+ for (const line of lines) {
54044
+ if (!line)
54045
+ continue;
54046
+ let r2 = null;
54047
+ try {
54048
+ r2 = JSON.parse(line);
54049
+ } catch {
54050
+ continue;
54051
+ }
54052
+ if (!r2)
54053
+ continue;
54054
+ if (!out.startedAt && r2.timestamp)
54055
+ out.startedAt = r2.timestamp;
54056
+ if (!out.cwd && r2.cwd)
54057
+ out.cwd = r2.cwd;
54058
+ if (r2.type === "ai-title" && typeof r2.aiTitle === "string" && r2.aiTitle.trim()) {
54059
+ out.aiTitle = r2.aiTitle.trim();
54060
+ }
54061
+ if (!out.firstUserText && r2.type === "user" && !r2.isMeta && !isInterruptText(peekText(r2.message?.content))) {
54062
+ const cmd = parseCommandFromUser(r2);
54063
+ if (cmd.slashCommand) {
54064
+ out.firstUserText = `/${cmd.slashCommand} ${cmd.args}`.replace(/\s+/g, " ").trim().slice(0, 120);
54065
+ } else {
54066
+ const text = extractUserText(r2);
54067
+ if (text)
54068
+ out.firstUserText = text.replace(/\s+/g, " ").trim().slice(0, 120);
54069
+ }
54070
+ }
54071
+ }
54072
+ } catch {}
54073
+ return out;
54074
+ }
54075
+ async function listSessions(rootDir) {
54076
+ const root = rootDir || CLAUDE_ROOT;
54077
+ const out = [];
54078
+ let projects;
54079
+ try {
54080
+ projects = fs9.readdirSync(root);
54081
+ } catch {
54082
+ return out;
54083
+ }
54084
+ for (const proj of projects) {
54085
+ const projDir = path7.join(root, proj);
54086
+ let entries;
54087
+ try {
54088
+ entries = fs9.readdirSync(projDir);
54089
+ } catch {
54090
+ continue;
54091
+ }
54092
+ for (const entry of entries) {
54093
+ if (!entry.endsWith(".jsonl"))
54094
+ continue;
54095
+ const full = path7.join(projDir, entry);
54096
+ let st;
54097
+ try {
54098
+ st = fs9.statSync(full);
54099
+ } catch {
54100
+ continue;
54101
+ }
54102
+ const sessionId = entry.replace(/\.jsonl$/, "");
54103
+ const summary = readSessionSummary(full);
54104
+ out.push({
54105
+ id: sessionId,
54106
+ adapterName: "claude",
54107
+ path: full,
54108
+ startedAt: summary.startedAt || new Date(st.mtimeMs).toISOString(),
54109
+ project: summary.cwd || decodeProjectDir(proj),
54110
+ title: summary.aiTitle || null,
54111
+ summary: summary.firstUserText,
54112
+ sizeBytes: st.size
54113
+ });
54114
+ }
54115
+ }
54116
+ return out;
54117
+ }
54118
+ function loadSubagentIndex(parentTranscriptPath, sessionId) {
54119
+ const subDir = path7.join(path7.dirname(parentTranscriptPath), sessionId, "subagents");
54120
+ const byToolUseId = new Map;
54121
+ const byAgentId = new Map;
54122
+ let names;
54123
+ try {
54124
+ names = fs9.readdirSync(subDir);
54125
+ } catch {
54126
+ return { byToolUseId, byAgentId };
54127
+ }
54128
+ for (const name of names) {
54129
+ if (!name.endsWith(".meta.json"))
54130
+ continue;
54131
+ const agentId = name.replace(/^agent-/, "").replace(/\.meta\.json$/, "");
54132
+ let meta = {};
54133
+ try {
54134
+ meta = JSON.parse(fs9.readFileSync(path7.join(subDir, name), "utf-8"));
54135
+ } catch {}
54136
+ const jsonlPath = path7.join(subDir, `agent-${agentId}.jsonl`);
54137
+ const { tokens, model } = sumClaudeAgentTokens(jsonlPath);
54138
+ const entry = {
54139
+ agentId,
54140
+ type: meta.agentType || "unknown",
54141
+ description: meta.description || "",
54142
+ toolUseId: meta.toolUseId || null,
54143
+ jsonlPath,
54144
+ tokens,
54145
+ model,
54146
+ startedAt: peekFirstTimestamp(jsonlPath),
54147
+ endedAt: peekLastTimestamp(jsonlPath)
54148
+ };
54149
+ byAgentId.set(agentId, entry);
54150
+ if (meta.toolUseId)
54151
+ byToolUseId.set(meta.toolUseId, entry);
54152
+ }
54153
+ return { byToolUseId, byAgentId };
54154
+ }
54155
+ function pushTurn(state, opts) {
54156
+ const last = state.turns[state.turns.length - 1];
54157
+ if (last && !last.endedAt)
54158
+ last.endedAt = opts.startedAt;
54159
+ const id = `T${state.turns.length}`;
54160
+ const turn = {
54161
+ id,
54162
+ startedAt: opts.startedAt,
54163
+ endedAt: null,
54164
+ source: opts.source,
54165
+ slashCommand: opts.slashCommand,
54166
+ args: String(opts.args || "").slice(0, 120),
54167
+ agentIds: [],
54168
+ skillIds: [],
54169
+ slashSkillId: null
54170
+ };
54171
+ state.turns.push(turn);
54172
+ if (opts.slashCommand) {
54173
+ state.skillCounter += 1;
54174
+ const skillId = `sk-slash-${id}`;
54175
+ const skill = {
54176
+ id: skillId,
54177
+ name: opts.slashCommand,
54178
+ source: "slash",
54179
+ prefix: "/",
54180
+ turnId: id,
54181
+ startedAt: opts.startedAt,
54182
+ endedAt: null,
54183
+ status: "running",
54184
+ args: turn.args,
54185
+ tokens: emptyTokens()
54186
+ };
54187
+ state.skills[skillId] = skill;
54188
+ turn.slashSkillId = skillId;
54189
+ turn.skillIds.push(skillId);
54190
+ }
54191
+ return turn;
54192
+ }
54193
+ function handleTaskUse(state, rec, toolUse, subIdx) {
54194
+ const turn = state.turns[state.turns.length - 1];
54195
+ if (!turn)
54196
+ return;
54197
+ const inp = toolUse.input || {};
54198
+ const toolUseId = toolUse.id;
54199
+ const match2 = toolUseId ? subIdx.byToolUseId.get(toolUseId) : null;
54200
+ const now = rec.timestamp || new Date().toISOString();
54201
+ if (!match2) {
54202
+ const aid = (toolUseId || `unknown-${turn.agentIds.length}`).replace(/^toolu_/, "");
54203
+ const agent2 = {
54204
+ id: aid,
54205
+ type: inp.subagent_type || "unknown",
54206
+ description: inp.description || "",
54207
+ promptPreview: String(inp.prompt || "").slice(0, 120),
54208
+ turnId: turn.id,
54209
+ startedAt: now,
54210
+ endedAt: now,
54211
+ status: "done",
54212
+ tokens: emptyTokens()
54213
+ };
54214
+ state.agents[aid] = agent2;
54215
+ turn.agentIds.push(aid);
54216
+ return;
54217
+ }
54218
+ const agentId = match2.agentId;
54219
+ const agent = {
54220
+ id: agentId,
54221
+ type: match2.type || inp.subagent_type || "unknown",
54222
+ description: inp.description || match2.description || "",
54223
+ promptPreview: String(inp.prompt || "").slice(0, 120),
54224
+ turnId: turn.id,
54225
+ startedAt: match2.startedAt || now,
54226
+ endedAt: match2.endedAt || now,
54227
+ status: "done",
54228
+ tokens: match2.tokens || emptyTokens(),
54229
+ model: match2.model || null
54230
+ };
54231
+ state.agents[agentId] = agent;
54232
+ turn.agentIds.push(agentId);
54233
+ if (match2.jsonlPath) {
54234
+ try {
54235
+ state.agentOffsets[agentId] = fs9.statSync(match2.jsonlPath).size;
54236
+ } catch {
54237
+ state.agentOffsets[agentId] = 0;
54238
+ }
54239
+ }
54240
+ }
54241
+ function handleSkillUse(state, rec, toolUse, openSkills) {
54242
+ const turn = state.turns[state.turns.length - 1];
54243
+ if (!turn)
54244
+ return null;
54245
+ const inp = toolUse.input || {};
54246
+ const name = inp.skill || "unknown";
54247
+ state.skillCounter += 1;
54248
+ const skillId = `sk-tool-${state.skillCounter}`;
54249
+ const startedAt = rec.timestamp || new Date().toISOString();
54250
+ const skill = {
54251
+ id: skillId,
54252
+ name,
54253
+ source: "tool",
54254
+ turnId: turn.id,
54255
+ startedAt,
54256
+ endedAt: null,
54257
+ status: "running",
54258
+ args: String(inp.args || "").slice(0, 80),
54259
+ tokens: emptyTokens()
54260
+ };
54261
+ state.skills[skillId] = skill;
54262
+ turn.skillIds.push(skillId);
54263
+ openSkills.set(toolUse.id, { skillId });
54264
+ return skill;
54265
+ }
54266
+ function closeSkill(state, open2, endedAt) {
54267
+ const sk = state.skills[open2.skillId];
54268
+ if (!sk)
54269
+ return;
54270
+ sk.endedAt = endedAt;
54271
+ sk.status = "done";
54272
+ }
54273
+ function pickTurnForTimestamp(state, ts) {
54274
+ if (!ts)
54275
+ return null;
54276
+ let chosen = null;
54277
+ for (const t of state.turns) {
54278
+ if (String(t.startedAt) <= String(ts))
54279
+ chosen = t;
54280
+ else
54281
+ break;
54282
+ }
54283
+ return chosen;
54284
+ }
54285
+ function lastNonStartupTurn(state) {
54286
+ for (let i = state.turns.length - 1;i >= 0; i--) {
54287
+ const turn = state.turns[i];
54288
+ if (turn && turn.source !== "startup")
54289
+ return turn;
54290
+ }
54291
+ return null;
54292
+ }
54293
+ async function parse2(filePath) {
54294
+ const sessionId = path7.basename(filePath, ".jsonl");
54295
+ try {
54296
+ const st = fs9.statSync(filePath);
54297
+ if (st.size > MAX_PARSE_BYTES) {
54298
+ const mb = (st.size / (1024 * 1024)).toFixed(0);
54299
+ const cap = MAX_PARSE_BYTES / (1024 * 1024);
54300
+ throw Object.assign(new Error(`Claude transcript ${path7.basename(filePath)} is ${mb}MB (> ${cap}MB cap).`), { code: "TRANSCRIPT_TOO_LARGE" });
54301
+ }
54302
+ } catch (e2) {
54303
+ if (e2.code === "TRANSCRIPT_TOO_LARGE")
54304
+ throw e2;
54305
+ }
54306
+ const { records } = readNew(filePath, 0);
54307
+ const recs = records;
54308
+ const subIdx = loadSubagentIndex(filePath, sessionId);
54309
+ const firstTs = recs.find((r2) => r2?.timestamp)?.timestamp || new Date().toISOString();
54310
+ const state = {
54311
+ sessionId,
54312
+ schemaVersion: 2,
54313
+ startedAt: firstTs,
54314
+ transcriptPath: filePath,
54315
+ transcriptOffset: 0,
54316
+ agentOffsets: {},
54317
+ cwd: null,
54318
+ turns: [],
54319
+ agents: {},
54320
+ skills: {},
54321
+ skillCounter: 0,
54322
+ tasks: {},
54323
+ taskOrder: [],
54324
+ todos: [],
54325
+ todosUpdatedAt: null,
54326
+ mainLoopTokens: emptyTokens(),
54327
+ totals: emptyTokens(),
54328
+ hookLog: []
54329
+ };
54330
+ pushTurn(state, {
54331
+ source: "startup",
54332
+ slashCommand: null,
54333
+ args: "startup",
54334
+ startedAt: firstTs
54335
+ });
54336
+ const openSkills = new Map;
54337
+ let activeToolSkillId = null;
54338
+ for (const rec of recs) {
54339
+ if (!rec || typeof rec !== "object")
54340
+ continue;
54341
+ if (rec.cwd && !state.cwd)
54342
+ state.cwd = rec.cwd;
54343
+ if (rec.type === "user" && !rec.isSidechain && !rec.isMeta && isInterruptText(peekText(rec.message?.content))) {
54344
+ const cur = state.turns[state.turns.length - 1];
54345
+ if (cur && cur.source !== "startup") {
54346
+ cur.interrupts = cur.interrupts || [];
54347
+ const txt = peekText(rec.message?.content).trim();
54348
+ cur.interrupts.push({
54349
+ at: rec.timestamp || new Date().toISOString(),
54350
+ label: txt.replace(/^\[|\]$/g, "").slice(0, 60)
54351
+ });
54352
+ }
54353
+ continue;
54354
+ }
54355
+ if (isPromptUser(rec)) {
54356
+ activeToolSkillId = null;
54357
+ const { slashCommand, args } = parseCommandFromUser(rec);
54358
+ const text = extractUserText(rec);
54359
+ const argsPreview = slashCommand ? args : text.slice(0, 120);
54360
+ pushTurn(state, {
54361
+ source: slashCommand ? "slash" : "prompt",
54362
+ slashCommand,
54363
+ args: argsPreview,
54364
+ startedAt: rec.timestamp || new Date().toISOString()
54365
+ });
54366
+ continue;
54367
+ }
54368
+ if (rec.type === "assistant" && !rec.isSidechain) {
54369
+ const tok = tokensOfClaude(rec);
54370
+ if (tok)
54371
+ state.mainLoopTokens = addTokens(state.mainLoopTokens, tok);
54372
+ const cur = state.turns[state.turns.length - 1];
54373
+ if (cur && cur.source !== "startup") {
54374
+ cur.assistant = cur.assistant || {
54375
+ model: null,
54376
+ tokens: emptyTokens(),
54377
+ startedAt: null,
54378
+ endedAt: null
54379
+ };
54380
+ if (rec.message?.model)
54381
+ cur.assistant.model = rec.message.model;
54382
+ if (tok)
54383
+ cur.assistant.tokens = addTokens(cur.assistant.tokens, tok);
54384
+ const ts = rec.timestamp;
54385
+ if (ts) {
54386
+ if (!cur.assistant.startedAt || String(ts) < String(cur.assistant.startedAt))
54387
+ cur.assistant.startedAt = ts;
54388
+ if (!cur.assistant.endedAt || String(ts) > String(cur.assistant.endedAt))
54389
+ cur.assistant.endedAt = ts;
54390
+ }
54391
+ }
54392
+ if (tok && activeToolSkillId && state.skills[activeToolSkillId]) {
54393
+ const sk = state.skills[activeToolSkillId];
54394
+ sk.tokens = addTokens(sk.tokens, tok);
54395
+ }
54396
+ const content = rec.message?.content;
54397
+ if (Array.isArray(content)) {
54398
+ for (const it of content) {
54399
+ const block = it;
54400
+ if (!block || block.type !== "tool_use")
54401
+ continue;
54402
+ if (block.name === "Task")
54403
+ handleTaskUse(state, rec, block, subIdx);
54404
+ else if (block.name === "Skill") {
54405
+ const opened = handleSkillUse(state, rec, block, openSkills);
54406
+ if (opened)
54407
+ activeToolSkillId = opened.id;
54408
+ }
54409
+ }
54410
+ }
54411
+ continue;
54412
+ }
54413
+ if (rec.type === "user" && Array.isArray(rec?.message?.content)) {
54414
+ for (const it of rec.message.content) {
54415
+ if (!it || it.type !== "tool_result" || !it.tool_use_id)
54416
+ continue;
54417
+ const open2 = openSkills.get(it.tool_use_id);
54418
+ if (!open2)
54419
+ continue;
54420
+ closeSkill(state, open2, rec.timestamp || new Date().toISOString());
54421
+ openSkills.delete(it.tool_use_id);
54422
+ }
54423
+ }
54424
+ }
54425
+ for (const open2 of openSkills.values()) {
54426
+ closeSkill(state, open2, new Date().toISOString());
54427
+ }
54428
+ for (const t of state.turns) {
54429
+ if (!t.assistant)
54430
+ continue;
54431
+ for (const aid of t.agentIds || []) {
54432
+ const ag = state.agents[aid];
54433
+ if (!ag?.tokens)
54434
+ continue;
54435
+ t.assistant.tokens = addTokens(t.assistant.tokens, ag.tokens);
54436
+ }
54437
+ }
54438
+ for (const t of state.turns) {
54439
+ if (!t.assistant || !t.skillIds)
54440
+ continue;
54441
+ for (const sid of t.skillIds) {
54442
+ const sk = state.skills[sid];
54443
+ if (sk && sk.source === "slash") {
54444
+ sk.tokens = { ...t.assistant.tokens };
54445
+ }
54446
+ }
54447
+ }
54448
+ for (const entry of subIdx.byAgentId.values()) {
54449
+ if (state.agents[entry.agentId])
54450
+ continue;
54451
+ const turn = pickTurnForTimestamp(state, entry.startedAt) || lastNonStartupTurn(state) || state.turns[state.turns.length - 1];
54452
+ if (!turn)
54453
+ continue;
54454
+ state.agents[entry.agentId] = {
54455
+ id: entry.agentId,
54456
+ type: entry.type,
54457
+ description: entry.description || "",
54458
+ promptPreview: "",
54459
+ turnId: turn.id,
54460
+ startedAt: entry.startedAt || turn.startedAt,
54461
+ endedAt: entry.endedAt || turn.endedAt || new Date().toISOString(),
54462
+ status: "done",
54463
+ tokens: entry.tokens || emptyTokens(),
54464
+ model: entry.model || null
54465
+ };
54466
+ turn.agentIds.push(entry.agentId);
54467
+ }
54468
+ state.totals = { ...state.mainLoopTokens };
54469
+ for (const ag of Object.values(state.agents)) {
54470
+ state.totals = addTokens(state.totals, ag.tokens || emptyTokens());
54471
+ }
54472
+ const last = state.turns[state.turns.length - 1];
54473
+ if (last && !last.endedAt)
54474
+ last.endedAt = new Date().toISOString();
54475
+ return state;
54476
+ }
54477
+ function matches(filePath) {
54478
+ if (!filePath)
54479
+ return false;
54480
+ const norm = path7.resolve(filePath);
54481
+ return norm.includes(`${path7.sep}.claude${path7.sep}projects${path7.sep}`) && norm.endsWith(".jsonl");
54482
+ }
54483
+ var claudeAdapter = {
54484
+ name: "claude",
54485
+ matches,
54486
+ listSessions,
54487
+ parse: parse2
54488
+ };
54489
+
54490
+ // src/domains/sessions/adapters/codex.ts
54491
+ import * as fs10 from "node:fs";
54492
+ import * as os5 from "node:os";
54493
+ import * as path8 from "node:path";
54494
+ var CODEX_ROOT = path8.join(os5.homedir(), ".codex", "sessions");
54495
+ function normalizeName(n) {
54496
+ return String(n || "").toLowerCase().replace(/[^a-z0-9]/g, "");
54497
+ }
54498
+ function skillDirs(cwd2) {
54499
+ const dirs = [path8.join(os5.homedir(), ".codex", "skills")];
54500
+ if (cwd2)
54501
+ dirs.push(path8.join(cwd2, ".codex", "skills"));
54502
+ return dirs;
54503
+ }
54504
+ function loadSkillCatalog(cwd2) {
54505
+ const out = [];
54506
+ const seen = new Set;
54507
+ for (const dir of skillDirs(cwd2)) {
54508
+ let names;
54509
+ try {
54510
+ names = fs10.readdirSync(dir);
54511
+ } catch {
54512
+ continue;
54513
+ }
54514
+ for (const name of names) {
54515
+ if (name.startsWith("."))
54516
+ continue;
54517
+ const entryPath = path8.join(dir, name);
54518
+ let st;
54519
+ try {
54520
+ st = fs10.statSync(entryPath);
54521
+ } catch {
54522
+ continue;
54523
+ }
54524
+ if (!st.isDirectory())
54525
+ continue;
54526
+ if (!fs10.existsSync(path8.join(entryPath, "SKILL.md")))
54527
+ continue;
54528
+ const key = normalizeName(name);
54529
+ if (!key || seen.has(key))
54530
+ continue;
54531
+ seen.add(key);
54532
+ out.push({ raw: name, normalized: key });
54533
+ }
54534
+ }
54535
+ return out;
54536
+ }
54537
+ function detectSkillsInPrompt(catalog, promptText) {
54538
+ if (!promptText || !catalog.length)
54539
+ return [];
54540
+ const matches2 = [];
54541
+ const seen = new Set;
54542
+ const re2 = /\$([A-Za-z0-9_-]+(?::[A-Za-z0-9_-]+)?)/g;
54543
+ for (let m2 = re2.exec(promptText);m2 !== null; m2 = re2.exec(promptText)) {
54544
+ const token = m2[1];
54545
+ if (!token)
54546
+ continue;
54547
+ const candidates = [token];
54548
+ const colonIdx = token.indexOf(":");
54549
+ if (colonIdx > -1)
54550
+ candidates.push(token.slice(colonIdx + 1));
54551
+ let hit;
54552
+ for (const cand of candidates) {
54553
+ const candNorm = normalizeName(cand);
54554
+ hit = catalog.find((c2) => c2.raw === cand) || catalog.find((c2) => c2.normalized === candNorm);
54555
+ if (hit)
54556
+ break;
54557
+ }
54558
+ if (!hit)
54559
+ continue;
54560
+ if (seen.has(hit.raw))
54561
+ continue;
54562
+ seen.add(hit.raw);
54563
+ matches2.push(hit.raw);
54564
+ }
54565
+ return matches2;
54566
+ }
54567
+ function safeJSON2(line) {
54568
+ try {
54569
+ return JSON.parse(line);
54570
+ } catch {
54571
+ return null;
54572
+ }
54573
+ }
54574
+ function extractUuidFromName(filePath) {
54575
+ const base = path8.basename(filePath, ".jsonl");
54576
+ const m2 = base.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/);
54577
+ return m2?.[1] ?? null;
54578
+ }
54579
+ function walkRolloutFiles(dir, depth, maxDepth, out) {
54580
+ let entries;
54581
+ try {
54582
+ entries = fs10.readdirSync(dir, { withFileTypes: true });
54583
+ } catch {
54584
+ return;
54585
+ }
54586
+ for (const e2 of entries) {
54587
+ const full = path8.join(dir, e2.name);
54588
+ if (e2.isDirectory()) {
54589
+ if (depth < maxDepth)
54590
+ walkRolloutFiles(full, depth + 1, maxDepth, out);
54591
+ continue;
54592
+ }
54593
+ if (!e2.isFile())
54594
+ continue;
54595
+ if (!e2.name.startsWith("rollout-") || !e2.name.endsWith(".jsonl"))
54596
+ continue;
54597
+ out.push(full);
54598
+ }
54599
+ }
54600
+ function collectRolloutFiles(root) {
54601
+ const files = [];
54602
+ if (!fs10.existsSync(root))
54603
+ return files;
54604
+ walkRolloutFiles(root, 0, 3, files);
54605
+ return files;
54606
+ }
54607
+ function readFirstSessionMeta(filePath) {
54608
+ try {
54609
+ const len = Math.min(fs10.statSync(filePath).size, 64 * 1024);
54610
+ const buf = Buffer.alloc(len);
54611
+ const fd = fs10.openSync(filePath, "r");
54612
+ try {
54613
+ fs10.readSync(fd, buf, 0, len, 0);
54614
+ } finally {
54615
+ fs10.closeSync(fd);
54616
+ }
54617
+ const firstLine = buf.toString("utf-8").split(`
54618
+ `)[0];
54619
+ const rec = firstLine ? safeJSON2(firstLine) : null;
54620
+ if (!rec || rec.type !== "session_meta")
54621
+ return null;
54622
+ return rec.payload || {};
54623
+ } catch {
54624
+ return null;
54625
+ }
54626
+ }
54627
+ function readFirstUserPrompt(filePath) {
54628
+ try {
54629
+ const len = Math.min(fs10.statSync(filePath).size, 128 * 1024);
54630
+ const buf = Buffer.alloc(len);
54631
+ const fd = fs10.openSync(filePath, "r");
54632
+ try {
54633
+ fs10.readSync(fd, buf, 0, len, 0);
54634
+ } finally {
54635
+ fs10.closeSync(fd);
54636
+ }
54637
+ const lines = buf.toString("utf-8").split(`
54638
+ `);
54639
+ for (const line of lines) {
54640
+ if (!line)
54641
+ continue;
54642
+ const r2 = safeJSON2(line);
54643
+ if (!r2)
54644
+ continue;
54645
+ if (r2.type === "event_msg" && r2.payload?.type === "user_message") {
54646
+ return String(r2.payload.message || "").replace(/\s+/g, " ").trim().slice(0, 120);
54647
+ }
54648
+ }
54649
+ } catch {}
54650
+ return "";
54651
+ }
54652
+ function readFirstChildModel(filePath) {
54653
+ try {
54654
+ const len = Math.min(fs10.statSync(filePath).size, 64 * 1024);
54655
+ const buf = Buffer.alloc(len);
54656
+ const fd = fs10.openSync(filePath, "r");
54657
+ try {
54658
+ fs10.readSync(fd, buf, 0, len, 0);
54659
+ } finally {
54660
+ fs10.closeSync(fd);
54661
+ }
54662
+ for (const line of buf.toString("utf-8").split(`
54663
+ `)) {
54664
+ if (!line)
54665
+ continue;
54666
+ const r2 = safeJSON2(line);
54667
+ if (!r2)
54668
+ continue;
54669
+ if (r2.type === "turn_context" && r2.payload?.model)
54670
+ return r2.payload.model;
54671
+ }
54672
+ } catch {}
54673
+ return null;
54674
+ }
54675
+ var _childIndex = null;
54676
+ function buildChildIndex(root) {
54677
+ if (_childIndex)
54678
+ return _childIndex;
54679
+ const map = new Map;
54680
+ const files = collectRolloutFiles(root);
54681
+ for (const f3 of files) {
54682
+ const id = extractUuidFromName(f3);
54683
+ if (id)
54684
+ map.set(id, f3);
54685
+ }
54686
+ _childIndex = map;
54687
+ return map;
54688
+ }
54689
+ function invalidateChildIndex() {
54690
+ _childIndex = null;
54691
+ }
54692
+ async function listSessions2(rootDir) {
54693
+ const root = rootDir || CODEX_ROOT;
54694
+ const out = [];
54695
+ const allFiles = collectRolloutFiles(root);
54696
+ for (const full of allFiles) {
54697
+ const meta = readFirstSessionMeta(full);
54698
+ if (!meta)
54699
+ continue;
54700
+ if (meta.thread_source && meta.thread_source !== "user")
54701
+ continue;
54702
+ let st;
54703
+ try {
54704
+ st = fs10.statSync(full);
54705
+ } catch {
54706
+ continue;
54707
+ }
54708
+ const summary = readFirstUserPrompt(full);
54709
+ const idFromName = extractUuidFromName(full);
54710
+ out.push({
54711
+ id: idFromName || meta.session_id || path8.basename(full, ".jsonl"),
54712
+ adapterName: "codex",
54713
+ path: full,
54714
+ startedAt: meta.timestamp || new Date(st.mtimeMs).toISOString(),
54715
+ project: meta.cwd || null,
54716
+ summary,
54717
+ sizeBytes: st.size
54718
+ });
54719
+ }
54720
+ return out;
54721
+ }
54722
+ function pushTurn2(state, opts) {
54723
+ const last = state.turns[state.turns.length - 1];
54724
+ if (last && !last.endedAt)
54725
+ last.endedAt = opts.startedAt;
54726
+ const id = `T${state.turns.length}`;
54727
+ const turn = {
54728
+ id,
54729
+ startedAt: opts.startedAt,
54730
+ endedAt: null,
54731
+ source: opts.source,
54732
+ slashCommand: null,
54733
+ args: String(opts.args || "").slice(0, 120),
54734
+ agentIds: [],
54735
+ skillIds: [],
54736
+ slashSkillId: null
54737
+ };
54738
+ state.turns.push(turn);
54739
+ return turn;
54740
+ }
54741
+ function addDollarSkill(state, name, ts) {
54742
+ const turn = state.turns[state.turns.length - 1];
54743
+ if (!turn)
54744
+ return null;
54745
+ state.skillCounter += 1;
54746
+ const id = `sk-slash-${turn.id}-${state.skillCounter}`;
54747
+ const startedAt = ts || new Date().toISOString();
54748
+ const skill = {
54749
+ id,
54750
+ name,
54751
+ source: "slash",
54752
+ prefix: "$",
54753
+ turnId: turn.id,
54754
+ startedAt,
54755
+ endedAt: null,
54756
+ status: "running",
54757
+ args: "",
54758
+ tokens: emptyTokens()
54759
+ };
54760
+ state.skills[id] = skill;
54761
+ if (!turn.slashSkillId)
54762
+ turn.slashSkillId = id;
54763
+ turn.skillIds.push(id);
54764
+ return skill;
54765
+ }
54766
+ function attachSubagent(state, info, childIndex) {
54767
+ const turn = state.turns[state.turns.length - 1] || pushTurn2(state, {
54768
+ source: "prompt",
54769
+ args: "spawned subagent",
54770
+ startedAt: info.spawnedAt
54771
+ });
54772
+ const cached = childIndex.get(info.agentId);
54773
+ const childPath = cached && fs10.existsSync(cached) ? cached : null;
54774
+ const transcriptMissing = !childPath;
54775
+ const description = info.nickname ? `${info.nickname}${transcriptMissing ? " (transcript missing)" : ""}` : transcriptMissing ? "(transcript missing)" : "";
54776
+ let tokens = emptyTokens();
54777
+ let model = null;
54778
+ if (childPath) {
54779
+ tokens = sumCodexAgentTokens(childPath);
54780
+ model = readFirstChildModel(childPath);
54781
+ }
54782
+ const ag = {
54783
+ id: info.agentId,
54784
+ type: info.agentType || "unknown",
54785
+ description,
54786
+ promptPreview: info.promptPreview || "",
54787
+ turnId: turn.id,
54788
+ startedAt: info.spawnedAt,
54789
+ endedAt: info.completedAt,
54790
+ status: "done",
54791
+ tokens,
54792
+ model,
54793
+ transcriptMissing
54794
+ };
54795
+ state.agents[info.agentId] = ag;
54796
+ turn.agentIds.push(info.agentId);
54797
+ }
54798
+ async function parse3(filePath) {
54799
+ const childIndex = buildChildIndex(CODEX_ROOT);
54800
+ const { records } = readNew(filePath, 0);
54801
+ const recs = records;
54802
+ const sessionMetaRec = recs.find((r2) => r2?.type === "session_meta");
54803
+ const sessionMeta = sessionMetaRec?.payload || {};
54804
+ const sessionId = extractUuidFromName(filePath) || sessionMeta.session_id || path8.basename(filePath, ".jsonl");
54805
+ const firstTs = sessionMeta.timestamp || recs.find((r2) => r2?.timestamp)?.timestamp || new Date().toISOString();
54806
+ const skillCatalog = loadSkillCatalog(sessionMeta.cwd || null);
54807
+ const state = {
54808
+ sessionId,
54809
+ schemaVersion: 2,
54810
+ startedAt: firstTs,
54811
+ transcriptPath: filePath,
54812
+ transcriptOffset: 0,
54813
+ agentOffsets: {},
54814
+ cwd: sessionMeta.cwd || null,
54815
+ turns: [],
54816
+ agents: {},
54817
+ skills: {},
54818
+ skillCounter: 0,
54819
+ tasks: {},
54820
+ taskOrder: [],
54821
+ todos: [],
54822
+ todosUpdatedAt: null,
54823
+ mainLoopTokens: emptyTokens(),
54824
+ totals: emptyTokens(),
54825
+ hookLog: []
54826
+ };
54827
+ const pendingSpawns = new Map;
54828
+ let lastModel = sessionMeta.model_provider || null;
54829
+ function attachAssistantTo(turn, rec) {
54830
+ if (!turn || turn.source === "startup")
54831
+ return;
54832
+ turn.assistant = turn.assistant || {
54833
+ model: null,
54834
+ tokens: emptyTokens(),
54835
+ startedAt: null,
54836
+ endedAt: null
54837
+ };
54838
+ if (lastModel)
54839
+ turn.assistant.model = lastModel;
54840
+ const tok = tokensOfCodex(rec);
54841
+ if (tok)
54842
+ turn.assistant.tokens = addTokens(turn.assistant.tokens, tok);
54843
+ const ts = rec.timestamp;
54844
+ if (ts) {
54845
+ if (!turn.assistant.startedAt || String(ts) < String(turn.assistant.startedAt))
54846
+ turn.assistant.startedAt = ts;
54847
+ if (!turn.assistant.endedAt || String(ts) > String(turn.assistant.endedAt))
54848
+ turn.assistant.endedAt = ts;
54849
+ }
54850
+ }
54851
+ for (const rec of recs) {
54852
+ if (!rec || typeof rec !== "object")
54853
+ continue;
54854
+ if (rec.type === "turn_context") {
54855
+ const p = rec.payload || {};
54856
+ if (p.model)
54857
+ lastModel = p.model;
54858
+ continue;
54859
+ }
54860
+ if (rec.type === "event_msg") {
54861
+ const p = rec.payload || {};
54862
+ if (p.type === "user_message") {
54863
+ const text = String(p.message || "");
54864
+ pushTurn2(state, {
54865
+ source: "prompt",
54866
+ args: text.slice(0, 120),
54867
+ startedAt: rec.timestamp || new Date().toISOString()
54868
+ });
54869
+ const hits = detectSkillsInPrompt(skillCatalog, text);
54870
+ for (const name of hits.slice(0, 3))
54871
+ addDollarSkill(state, name, rec.timestamp);
54872
+ } else if (p.type === "token_count") {
54873
+ const tok = tokensOfCodex(rec);
54874
+ if (tok)
54875
+ state.mainLoopTokens = addTokens(state.mainLoopTokens, tok);
54876
+ attachAssistantTo(state.turns[state.turns.length - 1], rec);
54877
+ } else if (p.type === "agent_message") {
54878
+ const cur = state.turns[state.turns.length - 1];
54879
+ if (cur && cur.source !== "startup") {
54880
+ cur.assistant = cur.assistant || {
54881
+ model: lastModel,
54882
+ tokens: emptyTokens(),
54883
+ startedAt: null,
54884
+ endedAt: null
54885
+ };
54886
+ if (lastModel)
54887
+ cur.assistant.model = lastModel;
54888
+ const ts = rec.timestamp;
54889
+ if (ts) {
54890
+ if (!cur.assistant.startedAt || String(ts) < String(cur.assistant.startedAt))
54891
+ cur.assistant.startedAt = ts;
54892
+ if (!cur.assistant.endedAt || String(ts) > String(cur.assistant.endedAt))
54893
+ cur.assistant.endedAt = ts;
54894
+ }
54895
+ }
54896
+ } else if (p.type === "task_complete") {
54897
+ const t = state.turns[state.turns.length - 1];
54898
+ if (t && !t.endedAt)
54899
+ t.endedAt = rec.timestamp || new Date().toISOString();
54900
+ }
54901
+ continue;
54902
+ }
54903
+ if (rec.type === "response_item") {
54904
+ const p = rec.payload || {};
54905
+ if (p.type === "function_call") {
54906
+ if (p.name === "spawn_agent" && p.call_id) {
54907
+ let argsParsed = {};
54908
+ try {
54909
+ argsParsed = JSON.parse(p.arguments || "{}");
54910
+ } catch {}
54911
+ pendingSpawns.set(p.call_id, {
54912
+ agentType: argsParsed.agent_type || "default",
54913
+ message: argsParsed.message || "",
54914
+ timestamp: rec.timestamp || new Date().toISOString()
54915
+ });
54916
+ }
54917
+ continue;
54918
+ }
54919
+ if (p.type === "function_call_output" && p.call_id) {
54920
+ const pending = pendingSpawns.get(p.call_id);
54921
+ if (!pending)
54922
+ continue;
54923
+ pendingSpawns.delete(p.call_id);
54924
+ let parsedOutput = {};
54925
+ try {
54926
+ parsedOutput = JSON.parse(p.output || "{}");
54927
+ } catch {}
54928
+ const agentId = parsedOutput.agent_id;
54929
+ const nickname = parsedOutput.nickname || "";
54930
+ if (!agentId)
54931
+ continue;
54932
+ attachSubagent(state, {
54933
+ agentId,
54934
+ agentType: pending.agentType,
54935
+ nickname,
54936
+ promptPreview: pending.message.slice(0, 120),
54937
+ spawnedAt: pending.timestamp,
54938
+ completedAt: rec.timestamp || pending.timestamp
54939
+ }, childIndex);
54940
+ }
54941
+ }
54942
+ }
54943
+ for (const t of state.turns) {
54944
+ if (!t.assistant)
54945
+ continue;
54946
+ for (const aid of t.agentIds || []) {
54947
+ const ag = state.agents[aid];
54948
+ if (!ag?.tokens)
54949
+ continue;
54950
+ t.assistant.tokens = addTokens(t.assistant.tokens, ag.tokens);
54951
+ }
54952
+ }
54953
+ for (const t of state.turns) {
54954
+ if (!t.assistant || !t.skillIds)
54955
+ continue;
54956
+ for (const sid of t.skillIds) {
54957
+ const sk = state.skills[sid];
54958
+ if (sk && sk.source === "slash") {
54959
+ sk.tokens = { ...t.assistant.tokens };
54960
+ }
54961
+ }
54962
+ }
54963
+ state.totals = { ...state.mainLoopTokens };
54964
+ for (const ag of Object.values(state.agents)) {
54965
+ state.totals = addTokens(state.totals, ag.tokens || emptyTokens());
54966
+ }
54967
+ const last = state.turns[state.turns.length - 1];
54968
+ if (last && !last.endedAt)
54969
+ last.endedAt = new Date().toISOString();
54970
+ return state;
54971
+ }
54972
+ function matches2(filePath) {
54973
+ if (!filePath)
54974
+ return false;
54975
+ const norm = path8.resolve(filePath);
54976
+ return norm.includes(`${path8.sep}.codex${path8.sep}sessions${path8.sep}`) && /rollout-.*\.jsonl$/.test(norm);
54977
+ }
54978
+ var codexAdapter = {
54979
+ name: "codex",
54980
+ matches: matches2,
54981
+ listSessions: listSessions2,
54982
+ parse: parse3,
54983
+ invalidateChildIndex
54984
+ };
54985
+
54986
+ // src/domains/sessions/adapters/index.ts
54987
+ var adapters = [claudeAdapter, codexAdapter];
54988
+ function resolveById(namespacedId) {
54989
+ if (!namespacedId)
54990
+ return null;
54991
+ const idx = namespacedId.indexOf(":");
54992
+ if (idx < 0)
54993
+ return null;
54994
+ const adapterName = namespacedId.slice(0, idx);
54995
+ const uuid = namespacedId.slice(idx + 1);
54996
+ const adapter = adapters.find((a3) => a3.name === adapterName);
54997
+ if (!adapter)
54998
+ return null;
54999
+ return { adapter, uuid, namespacedId };
55000
+ }
55001
+
55002
+ // src/domains/sessions/enumerate.ts
55003
+ var cache = null;
55004
+ async function list(opts = {}) {
55005
+ if (cache && !opts.refresh)
55006
+ return cache;
55007
+ const lists = await Promise.all(adapters.map((a3) => a3.listSessions().catch(() => [])));
55008
+ const merged = [];
55009
+ adapters.forEach((adapter, i) => {
55010
+ const list2 = lists[i] || [];
55011
+ for (const s of list2) {
55012
+ merged.push({ ...s, id: `${adapter.name}:${s.id}` });
55013
+ }
55014
+ });
55015
+ merged.sort((a3, b3) => String(b3.startedAt || "").localeCompare(String(a3.startedAt || "")));
55016
+ cache = merged;
55017
+ return cache;
55018
+ }
55019
+ function invalidate() {
55020
+ cache = null;
55021
+ for (const a3 of adapters) {
55022
+ if (typeof a3.invalidateChildIndex === "function")
55023
+ a3.invalidateChildIndex();
55024
+ }
55025
+ }
55026
+
55027
+ // src/domains/sessions/origin-allowlist.ts
55028
+ init_build_config();
55029
+ function originOf(url) {
55030
+ try {
55031
+ const u = new URL(url);
55032
+ return `${u.protocol}//${u.host}`;
55033
+ } catch {
55034
+ return url.replace(/\/+$/, "");
55035
+ }
55036
+ }
55037
+ var PLATFORM_ORIGIN = originOf(SERVER_URL);
55038
+ var DEFAULT_ORIGINS = [
55039
+ PLATFORM_ORIGIN,
55040
+ "http://localhost:5173",
55041
+ "http://localhost:4321"
55042
+ ];
55043
+ var LOOPBACK_HOST_PATTERN = /^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/;
55044
+ function isAllowedOrigin(origin) {
55045
+ if (!origin)
55046
+ return false;
55047
+ if (DEFAULT_ORIGINS.includes(origin))
55048
+ return true;
55049
+ return LOOPBACK_HOST_PATTERN.test(origin);
55050
+ }
55051
+
55052
+ // src/domains/sessions/server.ts
55053
+ var PORT_BUMP_MAX = 9;
55054
+ function applyCorsHeaders(req, res) {
55055
+ const origin = req.headers.origin;
55056
+ if (origin && isAllowedOrigin(origin)) {
55057
+ res.setHeader("Access-Control-Allow-Origin", origin);
55058
+ res.setHeader("Vary", "Origin");
55059
+ }
55060
+ }
55061
+ function sendJSON(res, code, body) {
55062
+ const buf = Buffer.from(JSON.stringify(body));
55063
+ res.writeHead(code, {
55064
+ "content-type": "application/json; charset=utf-8",
55065
+ "content-length": buf.length
55066
+ });
55067
+ res.end(buf);
55068
+ }
55069
+ function originGuard(req, res) {
55070
+ const origin = req.headers.origin;
55071
+ if (isAllowedOrigin(origin)) {
55072
+ applyCorsHeaders(req, res);
55073
+ return true;
55074
+ }
55075
+ sendJSON(res, 403, { error: "origin not allowed", origin: origin ?? null });
55076
+ return false;
55077
+ }
55078
+ async function route(req, res, version3) {
55079
+ const url = new URL(req.url || "/", "http://127.0.0.1");
55080
+ const pathname = url.pathname;
55081
+ applyCorsHeaders(req, res);
55082
+ if (req.method === "OPTIONS") {
55083
+ res.writeHead(204, {
55084
+ "Access-Control-Allow-Methods": "GET, OPTIONS",
55085
+ "Access-Control-Allow-Headers": "content-type",
55086
+ "Access-Control-Max-Age": "600"
55087
+ });
55088
+ res.end();
55089
+ return;
55090
+ }
55091
+ if (pathname === "/healthz") {
55092
+ sendJSON(res, 200, { ok: true, version: version3 });
55093
+ return;
55094
+ }
55095
+ if (!pathname.startsWith("/api/")) {
55096
+ sendJSON(res, 404, { error: "not found" });
55097
+ return;
55098
+ }
55099
+ if (!originGuard(req, res))
55100
+ return;
55101
+ if (pathname === "/api/sessions") {
55102
+ const refresh2 = url.searchParams.get("refresh") === "1";
55103
+ if (refresh2)
55104
+ invalidate();
55105
+ const list2 = await list({ refresh: refresh2 });
55106
+ sendJSON(res, 200, list2);
55107
+ return;
55108
+ }
55109
+ const m2 = pathname.match(/^\/api\/sessions\/([^/]+)\/state$/);
55110
+ if (m2?.[1]) {
55111
+ const id = decodeURIComponent(m2[1]);
55112
+ const resolved = resolveById(id);
55113
+ if (!resolved) {
55114
+ sendJSON(res, 404, { error: "unknown adapter or id", id });
55115
+ return;
55116
+ }
55117
+ const all = await list();
55118
+ const summary = all.find((s) => s.id === id);
55119
+ if (!summary) {
55120
+ sendJSON(res, 404, { error: "session not in list", id });
55121
+ return;
55122
+ }
55123
+ try {
55124
+ const state = await resolved.adapter.parse(summary.path);
55125
+ sendJSON(res, 200, state);
55126
+ } catch (e2) {
55127
+ sendJSON(res, 500, { error: String(e2.message || e2) });
55128
+ }
55129
+ return;
55130
+ }
55131
+ sendJSON(res, 404, { error: "not found" });
55132
+ }
55133
+ function start(options2 = {}) {
55134
+ const requested = options2.port ?? 8765;
55135
+ const version3 = options2.version ?? "unknown";
55136
+ return new Promise((resolve17, reject) => {
55137
+ let attempt = 0;
55138
+ const tryListen = (p) => {
55139
+ const server = http.createServer((req, res) => {
55140
+ Promise.resolve(route(req, res, version3)).catch((e2) => {
55141
+ if (res.headersSent) {
55142
+ try {
55143
+ res.end();
55144
+ } catch {}
55145
+ return;
55146
+ }
55147
+ sendJSON(res, 500, { error: String(e2.message || e2) });
55148
+ });
55149
+ });
55150
+ server.on("error", (err) => {
55151
+ if (err.code === "EADDRINUSE" && attempt < PORT_BUMP_MAX) {
55152
+ attempt += 1;
55153
+ tryListen(p + 1);
55154
+ return;
55155
+ }
55156
+ reject(err);
55157
+ });
55158
+ server.listen(p, "127.0.0.1", () => {
55159
+ const addr = server.address();
55160
+ const port = addr?.port ?? p;
55161
+ const handle = {
55162
+ server,
55163
+ port,
55164
+ close: () => new Promise((r2) => {
55165
+ server.close(() => r2());
55166
+ })
55167
+ };
55168
+ options2.onReady?.({ port, url: `http://127.0.0.1:${port}` });
55169
+ resolve17(handle);
55170
+ });
55171
+ };
55172
+ tryListen(requested);
55173
+ });
55174
+ }
55175
+
55176
+ // src/commands/console.ts
55177
+ init_build_config();
55178
+ init_package();
55179
+ function stripTrailingSlash(u) {
55180
+ return u.replace(/\/+$/, "");
55181
+ }
55182
+ async function consoleCommand(options2 = {}) {
55183
+ const requestedPort = options2.port ?? 8765;
55184
+ const openBrowser = !options2.noOpen;
55185
+ const handle = await start({
55186
+ port: requestedPort,
55187
+ version: package_default.version,
55188
+ onReady: ({ url }) => {
55189
+ console.log(`Bridge ready at ${url}`);
55190
+ const platformUrl = `${stripTrailingSlash(SERVER_URL)}/app/console#bridge=${url}`;
55191
+ if (openBrowser) {
55192
+ console.log(`Opening ${platformUrl}`);
55193
+ tryOpenBrowser(platformUrl);
55194
+ } else {
55195
+ console.log(`Open ${platformUrl} in your browser`);
55196
+ }
55197
+ }
55198
+ });
55199
+ await new Promise((resolve17) => {
55200
+ const shutdown = () => {
55201
+ console.log(`
55202
+ Shutting down bridge`);
55203
+ handle.close().finally(() => {
55204
+ resolve17();
55205
+ process.exit(0);
55206
+ });
55207
+ setTimeout(() => process.exit(0), 500).unref();
55208
+ };
55209
+ process.once("SIGINT", shutdown);
55210
+ process.once("SIGTERM", shutdown);
55211
+ });
55212
+ }
55213
+
53695
55214
  // src/domains/health-checks/types.ts
53696
55215
  init_zod();
53697
55216
  var CheckStatusSchema = exports_external.enum(["pass", "warn", "fail", "info"]);
@@ -53859,7 +55378,7 @@ import { promisify as promisify11 } from "node:util";
53859
55378
  // src/domains/github/gh-cli-utils.ts
53860
55379
  init_environment();
53861
55380
  init_logger();
53862
- import { readFileSync as readFileSync7 } from "node:fs";
55381
+ import { readFileSync as readFileSync8 } from "node:fs";
53863
55382
  var MIN_GH_CLI_VERSION = "2.20.0";
53864
55383
  var GH_COMMAND_TIMEOUT_MS = 1e4;
53865
55384
  function compareVersions4(a3, b3) {
@@ -53880,7 +55399,7 @@ function isWSL2() {
53880
55399
  if (process.platform !== "linux")
53881
55400
  return false;
53882
55401
  try {
53883
- const release = readFileSync7("/proc/version", "utf-8").toLowerCase();
55402
+ const release = readFileSync8("/proc/version", "utf-8").toLowerCase();
53884
55403
  return release.includes("microsoft") || release.includes("wsl");
53885
55404
  } catch (error) {
53886
55405
  logger.debug(`WSL detection skipped: ${error instanceof Error ? error.message : "unknown error"}`);
@@ -54044,10 +55563,10 @@ async function getCommandPath(command) {
54044
55563
  const whichCmd = process.platform === "win32" ? "where" : "which";
54045
55564
  logger.verbose(`Getting path for command: ${command}`);
54046
55565
  const { stdout } = await execAsync2(`${whichCmd} ${command}`);
54047
- const path7 = stdout.trim().split(`
55566
+ const path9 = stdout.trim().split(`
54048
55567
  `)[0] || null;
54049
- logger.verbose(`Command path resolved: ${command} -> ${path7}`);
54050
- return path7;
55568
+ logger.verbose(`Command path resolved: ${command} -> ${path9}`);
55569
+ return path9;
54051
55570
  } catch {
54052
55571
  logger.verbose(`Failed to get path for command: ${command}`);
54053
55572
  return null;
@@ -54102,7 +55621,7 @@ async function checkDependency(config) {
54102
55621
  const exists = await commandExists(command);
54103
55622
  if (exists) {
54104
55623
  logger.verbose(`Found ${config.name} via command: ${command}`);
54105
- const path7 = await getCommandPath(command);
55624
+ const path9 = await getCommandPath(command);
54106
55625
  const version3 = await getCommandVersion(command, config.versionFlag, config.versionRegex);
54107
55626
  let meetsRequirements = true;
54108
55627
  let message;
@@ -54116,7 +55635,7 @@ async function checkDependency(config) {
54116
55635
  name: config.name,
54117
55636
  installed: true,
54118
55637
  version: version3 || undefined,
54119
- path: path7 || undefined,
55638
+ path: path9 || undefined,
54120
55639
  minVersion: config.minVersion,
54121
55640
  meetsRequirements,
54122
55641
  message
@@ -54237,7 +55756,7 @@ var PYTHON_INSTALLERS = [
54237
55756
  // src/services/package-installer/dependencies/system-installer.ts
54238
55757
  init_logger();
54239
55758
  import { exec as exec3 } from "node:child_process";
54240
- import * as fs8 from "node:fs";
55759
+ import * as fs11 from "node:fs";
54241
55760
  import { promisify as promisify9 } from "node:util";
54242
55761
  var execAsync3 = promisify9(exec3);
54243
55762
  async function detectOS() {
@@ -54252,8 +55771,8 @@ async function detectOS() {
54252
55771
  }
54253
55772
  } else if (platform5 === "linux") {
54254
55773
  try {
54255
- if (fs8.existsSync("/etc/os-release")) {
54256
- const content = fs8.readFileSync("/etc/os-release", "utf-8");
55774
+ if (fs11.existsSync("/etc/os-release")) {
55775
+ const content = fs11.readFileSync("/etc/os-release", "utf-8");
54257
55776
  const idMatch = content.match(/^ID=(.+)$/m);
54258
55777
  info.distro = idMatch?.[1]?.replace(/"/g, "");
54259
55778
  }
@@ -54833,10 +56352,10 @@ function getPnpmUpdateCommand(packageName, version3, registryUrl) {
54833
56352
  init_logger();
54834
56353
  init_path_resolver();
54835
56354
  init_takumi_constants();
54836
- import { existsSync as existsSync33, realpathSync } from "node:fs";
56355
+ import { existsSync as existsSync35, realpathSync } from "node:fs";
54837
56356
  import { chmod as chmod2, mkdir as mkdir18, readFile as readFile32, writeFile as writeFile22 } from "node:fs/promises";
54838
56357
  import { platform as platform5 } from "node:os";
54839
- import { join as join71 } from "node:path";
56358
+ import { join as join73 } from "node:path";
54840
56359
  var CACHE_FILE = "install-info.json";
54841
56360
  var CACHE_TTL = 30 * 24 * 60 * 60 * 1000;
54842
56361
  function detectFromBinaryPath() {
@@ -54920,8 +56439,8 @@ function detectFromEnv() {
54920
56439
  }
54921
56440
  async function readCachedPm() {
54922
56441
  try {
54923
- const cacheFile = join71(PathResolver.getConfigDir(false), CACHE_FILE);
54924
- if (!existsSync33(cacheFile)) {
56442
+ const cacheFile = join73(PathResolver.getConfigDir(false), CACHE_FILE);
56443
+ if (!existsSync35(cacheFile)) {
54925
56444
  return null;
54926
56445
  }
54927
56446
  const content = await readFile32(cacheFile, "utf-8");
@@ -54951,8 +56470,8 @@ async function saveCachedPm(pm, getVersion) {
54951
56470
  return;
54952
56471
  try {
54953
56472
  const configDir = PathResolver.getConfigDir(false);
54954
- const cacheFile = join71(configDir, CACHE_FILE);
54955
- if (!existsSync33(configDir)) {
56473
+ const cacheFile = join73(configDir, CACHE_FILE);
56474
+ if (!existsSync35(configDir)) {
54956
56475
  await mkdir18(configDir, { recursive: true });
54957
56476
  if (platform5() !== "win32") {
54958
56477
  await chmod2(configDir, 448);
@@ -55014,8 +56533,8 @@ async function findOwningPm() {
55014
56533
  async function clearCache() {
55015
56534
  try {
55016
56535
  const { unlink: unlink7 } = await import("node:fs/promises");
55017
- const cacheFile = join71(PathResolver.getConfigDir(false), CACHE_FILE);
55018
- if (existsSync33(cacheFile)) {
56536
+ const cacheFile = join73(PathResolver.getConfigDir(false), CACHE_FILE);
56537
+ if (existsSync35(cacheFile)) {
55019
56538
  await unlink7(cacheFile);
55020
56539
  logger.debug("Package manager cache cleared");
55021
56540
  }
@@ -55275,23 +56794,23 @@ async function checkCliVersion() {
55275
56794
  // src/domains/health-checks/checkers/claude-md-checker.ts
55276
56795
  init_paths();
55277
56796
  init_registry();
55278
- import { existsSync as existsSync34, statSync as statSync2 } from "node:fs";
55279
- import { join as join72 } from "node:path";
56797
+ import { existsSync as existsSync36, statSync as statSync5 } from "node:fs";
56798
+ import { join as join74 } from "node:path";
55280
56799
  function checkClaudeMd(setup, projectDir) {
55281
56800
  const results = [];
55282
56801
  const claudeCodeInstaller2 = getInstaller("claude-code");
55283
56802
  if (claudeCodeInstaller2?.isInstalledGlobally()) {
55284
56803
  const claudeGlobal = setup.globals.find((g2) => g2.provider === "claude-code") ?? setup.globals[0];
55285
56804
  const globalPath = claudeGlobal?.path ?? claudeCodeInstaller2.globalRoot();
55286
- const globalClaudeMd = join72(globalPath, "CLAUDE.md");
56805
+ const globalClaudeMd = join74(globalPath, "CLAUDE.md");
55287
56806
  results.push(checkClaudeMdFile(globalClaudeMd, "Global CLAUDE.md", "sk-global-claude-md"));
55288
56807
  }
55289
- const projectClaudeMd = join72(getLocalClaudeDir(projectDir), "CLAUDE.md");
56808
+ const projectClaudeMd = join74(getLocalClaudeDir(projectDir), "CLAUDE.md");
55290
56809
  results.push(checkClaudeMdFile(projectClaudeMd, "Project CLAUDE.md", "sk-project-claude-md"));
55291
56810
  return results;
55292
56811
  }
55293
- function checkClaudeMdFile(path7, name, id) {
55294
- if (!existsSync34(path7)) {
56812
+ function checkClaudeMdFile(path9, name, id) {
56813
+ if (!existsSync36(path9)) {
55295
56814
  return {
55296
56815
  id,
55297
56816
  name,
@@ -55304,7 +56823,7 @@ function checkClaudeMdFile(path7, name, id) {
55304
56823
  };
55305
56824
  }
55306
56825
  try {
55307
- const stat8 = statSync2(path7);
56826
+ const stat8 = statSync5(path9);
55308
56827
  const sizeKB = (stat8.size / 1024).toFixed(1);
55309
56828
  if (stat8.size === 0) {
55310
56829
  return {
@@ -55314,7 +56833,7 @@ function checkClaudeMdFile(path7, name, id) {
55314
56833
  priority: "standard",
55315
56834
  status: "warn",
55316
56835
  message: "Empty (0 bytes)",
55317
- details: path7,
56836
+ details: path9,
55318
56837
  suggestion: "Add project instructions to CLAUDE.md",
55319
56838
  autoFixable: false
55320
56839
  };
@@ -55326,7 +56845,7 @@ function checkClaudeMdFile(path7, name, id) {
55326
56845
  priority: "standard",
55327
56846
  status: "pass",
55328
56847
  message: `Found (${sizeKB}KB)`,
55329
- details: path7,
56848
+ details: path9,
55330
56849
  autoFixable: false
55331
56850
  };
55332
56851
  } catch {
@@ -55337,18 +56856,18 @@ function checkClaudeMdFile(path7, name, id) {
55337
56856
  priority: "standard",
55338
56857
  status: "warn",
55339
56858
  message: "Unreadable",
55340
- details: path7,
56859
+ details: path9,
55341
56860
  suggestion: "Check file permissions",
55342
56861
  autoFixable: false
55343
56862
  };
55344
56863
  }
55345
56864
  }
55346
56865
  // src/domains/health-checks/checkers/active-plan-checker.ts
55347
- import { existsSync as existsSync35, readFileSync as readFileSync9 } from "node:fs";
55348
- import { join as join73 } from "node:path";
56866
+ import { existsSync as existsSync37, readFileSync as readFileSync10 } from "node:fs";
56867
+ import { join as join75 } from "node:path";
55349
56868
  function checkActivePlan(projectDir) {
55350
- const activePlanPath = join73(projectDir, ".claude", "active-plan");
55351
- if (!existsSync35(activePlanPath)) {
56869
+ const activePlanPath = join75(projectDir, ".claude", "active-plan");
56870
+ if (!existsSync37(activePlanPath)) {
55352
56871
  return {
55353
56872
  id: "sk-active-plan",
55354
56873
  name: "Active Plan",
@@ -55360,9 +56879,9 @@ function checkActivePlan(projectDir) {
55360
56879
  };
55361
56880
  }
55362
56881
  try {
55363
- const targetPath = readFileSync9(activePlanPath, "utf-8").trim();
55364
- const fullPath = join73(projectDir, targetPath);
55365
- if (!existsSync35(fullPath)) {
56882
+ const targetPath = readFileSync10(activePlanPath, "utf-8").trim();
56883
+ const fullPath = join75(projectDir, targetPath);
56884
+ if (!existsSync37(fullPath)) {
55366
56885
  return {
55367
56886
  id: "sk-active-plan",
55368
56887
  name: "Active Plan",
@@ -55427,7 +56946,7 @@ function checkComponentCounts(setup) {
55427
56946
  init_registry();
55428
56947
  init_logger();
55429
56948
  import { constants, access, unlink as unlink7, writeFile as writeFile23 } from "node:fs/promises";
55430
- import { join as join74 } from "node:path";
56949
+ import { join as join76 } from "node:path";
55431
56950
 
55432
56951
  // src/domains/health-checks/checkers/shared.ts
55433
56952
  init_registry();
@@ -55502,7 +57021,7 @@ async function checkGlobalDirWritable(provider) {
55502
57021
  }
55503
57022
  const timestamp = Date.now();
55504
57023
  const random = Math.random().toString(36).substring(2);
55505
- const testFile = join74(globalDir, `.sk-write-test-${timestamp}-${random}`);
57024
+ const testFile = join76(globalDir, `.sk-write-test-${timestamp}-${random}`);
55506
57025
  try {
55507
57026
  await writeFile23(testFile, "test", { encoding: "utf-8", flag: "wx" });
55508
57027
  } catch (_error) {
@@ -55537,9 +57056,9 @@ async function checkGlobalDirWritable(provider) {
55537
57056
  // src/domains/health-checks/checkers/hooks-checker.ts
55538
57057
  init_paths();
55539
57058
  init_registry();
55540
- import { existsSync as existsSync36 } from "node:fs";
57059
+ import { existsSync as existsSync38 } from "node:fs";
55541
57060
  import { readdir as readdir23 } from "node:fs/promises";
55542
- import { join as join75 } from "node:path";
57061
+ import { join as join77 } from "node:path";
55543
57062
 
55544
57063
  // src/domains/health-checks/utils/path-normalizer.ts
55545
57064
  import { normalize as normalize5 } from "node:path";
@@ -55551,17 +57070,17 @@ function normalizePath(filePath) {
55551
57070
 
55552
57071
  // src/domains/health-checks/checkers/hooks-checker.ts
55553
57072
  async function checkHooksExist(projectDir) {
55554
- const globalHooksDir = join75(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
55555
- const projectHooksDir = join75(getLocalClaudeDir(projectDir), "hooks");
55556
- const globalExists = existsSync36(globalHooksDir);
55557
- const projectExists = existsSync36(projectHooksDir);
57073
+ const globalHooksDir = join77(getInstaller("claude-code")?.globalRoot() ?? "", "hooks");
57074
+ const projectHooksDir = join77(getLocalClaudeDir(projectDir), "hooks");
57075
+ const globalExists = existsSync38(globalHooksDir);
57076
+ const projectExists = existsSync38(projectHooksDir);
55558
57077
  let hookCount = 0;
55559
57078
  const checkedFiles = new Set;
55560
57079
  if (globalExists) {
55561
57080
  const files = await readdir23(globalHooksDir, { withFileTypes: false });
55562
57081
  const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
55563
57082
  hooks.forEach((hook) => {
55564
- const fullPath = join75(globalHooksDir, hook);
57083
+ const fullPath = join77(globalHooksDir, hook);
55565
57084
  checkedFiles.add(normalizePath(fullPath));
55566
57085
  });
55567
57086
  }
@@ -55571,7 +57090,7 @@ async function checkHooksExist(projectDir) {
55571
57090
  const files = await readdir23(projectHooksDir, { withFileTypes: false });
55572
57091
  const hooks = files.filter((f3) => HOOK_EXTENSIONS2.some((ext2) => f3.endsWith(ext2)));
55573
57092
  hooks.forEach((hook) => {
55574
- const fullPath = join75(projectHooksDir, hook);
57093
+ const fullPath = join77(projectHooksDir, hook);
55575
57094
  checkedFiles.add(normalizePath(fullPath));
55576
57095
  });
55577
57096
  }
@@ -55598,17 +57117,102 @@ async function checkHooksExist(projectDir) {
55598
57117
  autoFixable: false
55599
57118
  };
55600
57119
  }
57120
+ // src/domains/health-checks/checkers/codex-hook-health-checker.ts
57121
+ init_registry();
57122
+ import { existsSync as existsSync39 } from "node:fs";
57123
+ import { readFile as readFile33 } from "node:fs/promises";
57124
+ import { join as join78 } from "node:path";
57125
+ async function checkCodexHooksHealth() {
57126
+ const codex = getInstaller("codex");
57127
+ if (!codex?.isInstalledGlobally())
57128
+ return [];
57129
+ const codexRoot = codex.globalRoot();
57130
+ const configTomlPath = join78(codexRoot, "config.toml");
57131
+ const hooksJsonPath = join78(codexRoot, "hooks.json");
57132
+ if (!existsSync39(hooksJsonPath))
57133
+ return [];
57134
+ const results = [];
57135
+ const flagPresent = existsSync39(configTomlPath) ? /(^|\n)\s*hooks\s*=\s*true/.test(await readFile33(configTomlPath, "utf8")) : false;
57136
+ results.push(flagPresent ? {
57137
+ id: "codex-hooks-feature-flag",
57138
+ name: "Codex hooks feature flag",
57139
+ group: "takumi",
57140
+ priority: "critical",
57141
+ status: "pass",
57142
+ message: "[features] hooks = true present",
57143
+ details: configTomlPath,
57144
+ autoFixable: false
57145
+ } : {
57146
+ id: "codex-hooks-feature-flag",
57147
+ name: "Codex hooks feature flag",
57148
+ group: "takumi",
57149
+ priority: "critical",
57150
+ status: "fail",
57151
+ message: "[features] hooks = true missing — Codex ignores all hooks. Add it to config.toml or run `tkm init -a codex`.",
57152
+ details: configTomlPath,
57153
+ autoFixable: false
57154
+ });
57155
+ const missing = await collectMissingWrapperTargets(hooksJsonPath);
57156
+ results.push(missing.length === 0 ? {
57157
+ id: "codex-hooks-command-targets",
57158
+ name: "Codex hook command targets",
57159
+ group: "takumi",
57160
+ priority: "standard",
57161
+ status: "pass",
57162
+ message: "All hook commands point to existing wrappers",
57163
+ details: hooksJsonPath,
57164
+ autoFixable: false
57165
+ } : {
57166
+ id: "codex-hooks-command-targets",
57167
+ name: "Codex hook command targets",
57168
+ group: "takumi",
57169
+ priority: "standard",
57170
+ status: "fail",
57171
+ message: `${missing.length} hook command(s) point to a missing wrapper. Re-run \`tkm init -a codex\` to regenerate.`,
57172
+ details: missing.join(", "),
57173
+ autoFixable: false
57174
+ });
57175
+ return results;
57176
+ }
57177
+ async function collectMissingWrapperTargets(hooksJsonPath) {
57178
+ let parsed;
57179
+ try {
57180
+ parsed = JSON.parse(await readFile33(hooksJsonPath, "utf8"));
57181
+ } catch {
57182
+ return [];
57183
+ }
57184
+ const hooks = parsed?.hooks;
57185
+ if (!hooks || typeof hooks !== "object")
57186
+ return [];
57187
+ const missing = [];
57188
+ const nodeCmd = /\bnode\s+"([^"]+\.cjs)"/;
57189
+ for (const groups of Object.values(hooks)) {
57190
+ if (!Array.isArray(groups))
57191
+ continue;
57192
+ for (const group of groups) {
57193
+ for (const entry of group?.hooks ?? []) {
57194
+ const command = entry?.command;
57195
+ if (typeof command !== "string")
57196
+ continue;
57197
+ const m2 = command.match(nodeCmd);
57198
+ if (m2 && !existsSync39(m2[1]))
57199
+ missing.push(m2[1]);
57200
+ }
57201
+ }
57202
+ }
57203
+ return missing;
57204
+ }
55601
57205
  // src/domains/health-checks/checkers/settings-checker.ts
55602
57206
  init_paths();
55603
57207
  init_registry();
55604
57208
  init_logger();
55605
- import { existsSync as existsSync37 } from "node:fs";
55606
- import { readFile as readFile33 } from "node:fs/promises";
55607
- import { join as join76 } from "node:path";
57209
+ import { existsSync as existsSync40 } from "node:fs";
57210
+ import { readFile as readFile34 } from "node:fs/promises";
57211
+ import { join as join79 } from "node:path";
55608
57212
  async function checkSettingsValid(projectDir) {
55609
- const globalSettings = join76(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
55610
- const projectSettings = join76(getLocalClaudeDir(projectDir), "settings.json");
55611
- const settingsPath = existsSync37(globalSettings) ? globalSettings : existsSync37(projectSettings) ? projectSettings : null;
57213
+ const globalSettings = join79(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
57214
+ const projectSettings = join79(getLocalClaudeDir(projectDir), "settings.json");
57215
+ const settingsPath = existsSync40(globalSettings) ? globalSettings : existsSync40(projectSettings) ? projectSettings : null;
55612
57216
  if (!settingsPath) {
55613
57217
  return {
55614
57218
  id: "sk-settings-valid",
@@ -55621,7 +57225,7 @@ async function checkSettingsValid(projectDir) {
55621
57225
  };
55622
57226
  }
55623
57227
  try {
55624
- const content = await readFile33(settingsPath, "utf-8");
57228
+ const content = await readFile34(settingsPath, "utf-8");
55625
57229
  JSON.parse(content);
55626
57230
  return {
55627
57231
  id: "sk-settings-valid",
@@ -55678,14 +57282,14 @@ async function checkSettingsValid(projectDir) {
55678
57282
  init_paths();
55679
57283
  init_registry();
55680
57284
  init_logger();
55681
- import { existsSync as existsSync38 } from "node:fs";
55682
- import { readFile as readFile34 } from "node:fs/promises";
55683
- import { homedir as homedir22 } from "node:os";
55684
- import { dirname as dirname18, join as join77, normalize as normalize6, resolve as resolve15 } from "node:path";
57285
+ import { existsSync as existsSync41 } from "node:fs";
57286
+ import { readFile as readFile35 } from "node:fs/promises";
57287
+ import { homedir as homedir24 } from "node:os";
57288
+ import { dirname as dirname19, join as join80, normalize as normalize6, resolve as resolve17 } from "node:path";
55685
57289
  async function checkPathRefsValid(projectDir) {
55686
- const globalClaudeMd = join77(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
55687
- const projectClaudeMd = join77(getLocalClaudeDir(projectDir), "CLAUDE.md");
55688
- const claudeMdPath = existsSync38(globalClaudeMd) ? globalClaudeMd : existsSync38(projectClaudeMd) ? projectClaudeMd : null;
57290
+ const globalClaudeMd = join80(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
57291
+ const projectClaudeMd = join80(getLocalClaudeDir(projectDir), "CLAUDE.md");
57292
+ const claudeMdPath = existsSync41(globalClaudeMd) ? globalClaudeMd : existsSync41(projectClaudeMd) ? projectClaudeMd : null;
55689
57293
  if (!claudeMdPath) {
55690
57294
  return {
55691
57295
  id: "sk-path-refs-valid",
@@ -55698,7 +57302,7 @@ async function checkPathRefsValid(projectDir) {
55698
57302
  };
55699
57303
  }
55700
57304
  try {
55701
- const content = await readFile34(claudeMdPath, "utf-8");
57305
+ const content = await readFile35(claudeMdPath, "utf-8");
55702
57306
  const refPattern = /@([^\s\)]+)/g;
55703
57307
  const refs = [...content.matchAll(refPattern)].map((m2) => m2[1]);
55704
57308
  if (refs.length === 0) {
@@ -55712,8 +57316,8 @@ async function checkPathRefsValid(projectDir) {
55712
57316
  autoFixable: false
55713
57317
  };
55714
57318
  }
55715
- const baseDir = dirname18(claudeMdPath);
55716
- const home6 = homedir22();
57319
+ const baseDir = dirname19(claudeMdPath);
57320
+ const home6 = homedir24();
55717
57321
  const broken = [];
55718
57322
  for (const ref of refs) {
55719
57323
  let refPath;
@@ -55728,7 +57332,7 @@ async function checkPathRefsValid(projectDir) {
55728
57332
  } else if (/^[A-Za-z]:/.test(ref)) {
55729
57333
  refPath = normalize6(ref);
55730
57334
  } else {
55731
- refPath = resolve15(baseDir, ref);
57335
+ refPath = resolve17(baseDir, ref);
55732
57336
  }
55733
57337
  const normalizedPath = normalize6(refPath);
55734
57338
  const isWithinHome = normalizedPath.startsWith(home6);
@@ -55738,7 +57342,7 @@ async function checkPathRefsValid(projectDir) {
55738
57342
  logger.verbose("Skipping potentially unsafe path reference", { ref, refPath });
55739
57343
  continue;
55740
57344
  }
55741
- if (!existsSync38(normalizedPath)) {
57345
+ if (!existsSync41(normalizedPath)) {
55742
57346
  broken.push(ref);
55743
57347
  }
55744
57348
  }
@@ -55778,9 +57382,9 @@ async function checkPathRefsValid(projectDir) {
55778
57382
  }
55779
57383
  // src/domains/health-checks/checkers/config-completeness-checker.ts
55780
57384
  init_paths();
55781
- import { existsSync as existsSync39 } from "node:fs";
57385
+ import { existsSync as existsSync42 } from "node:fs";
55782
57386
  import { readdir as readdir24 } from "node:fs/promises";
55783
- import { join as join78 } from "node:path";
57387
+ import { join as join81 } from "node:path";
55784
57388
  async function checkProjectConfigCompleteness(setup, projectDir) {
55785
57389
  if (setup.globals.some((g2) => g2.path === setup.project.path)) {
55786
57390
  return {
@@ -55797,12 +57401,12 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
55797
57401
  const requiredDirs = ["agents", "commands", "skills"];
55798
57402
  const missingDirs = [];
55799
57403
  for (const dir of requiredDirs) {
55800
- const dirPath = join78(projectClaudeDir, dir);
55801
- if (!existsSync39(dirPath)) {
57404
+ const dirPath = join81(projectClaudeDir, dir);
57405
+ if (!existsSync42(dirPath)) {
55802
57406
  missingDirs.push(dir);
55803
57407
  }
55804
57408
  }
55805
- const hasRulesOrWorkflows = existsSync39(join78(projectClaudeDir, "rules")) || existsSync39(join78(projectClaudeDir, "workflows"));
57409
+ const hasRulesOrWorkflows = existsSync42(join81(projectClaudeDir, "rules")) || existsSync42(join81(projectClaudeDir, "workflows"));
55806
57410
  if (!hasRulesOrWorkflows) {
55807
57411
  missingDirs.push("rules");
55808
57412
  }
@@ -55882,6 +57486,8 @@ class TakumiChecker {
55882
57486
  }
55883
57487
  logger.verbose("TakumiChecker: Checking hooks directory");
55884
57488
  results.push(await checkHooksExist(this.projectDir));
57489
+ logger.verbose("TakumiChecker: Checking Codex hook health");
57490
+ results.push(...await checkCodexHooksHealth());
55885
57491
  logger.verbose("TakumiChecker: Checking settings.json validity");
55886
57492
  results.push(await checkSettingsValid(this.projectDir));
55887
57493
  logger.verbose("TakumiChecker: Checking path references");
@@ -55899,16 +57505,16 @@ import { spawnSync as spawnSync3 } from "node:child_process";
55899
57505
  // src/domains/installation/git-clone-manager.ts
55900
57506
  init_logger();
55901
57507
  import { execSync as execSync3 } from "node:child_process";
55902
- import * as fs9 from "node:fs";
55903
- import * as os4 from "node:os";
55904
- import * as path7 from "node:path";
57508
+ import * as fs12 from "node:fs";
57509
+ import * as os6 from "node:os";
57510
+ import * as path9 from "node:path";
55905
57511
  var VALID_TAG_PATTERN = /^[a-zA-Z0-9._+\-]+$/;
55906
57512
 
55907
57513
  class GitCloneManager {
55908
57514
  tempBaseDir;
55909
57515
  constructor() {
55910
57516
  const homeDir = process.env.HOME || process.env.USERPROFILE;
55911
- this.tempBaseDir = process.env.TMPDIR || process.env.TEMP || process.env.TMP || (homeDir ? path7.join(homeDir, ".sunagentkit", "tmp") : null) || path7.join(os4.tmpdir(), ".sunagentkit", "tmp");
57517
+ this.tempBaseDir = process.env.TMPDIR || process.env.TEMP || process.env.TMP || (homeDir ? path9.join(homeDir, ".sunagentkit", "tmp") : null) || path9.join(os6.tmpdir(), ".sunagentkit", "tmp");
55912
57518
  }
55913
57519
  validateTag(tag) {
55914
57520
  if (!VALID_TAG_PATTERN.test(tag)) {
@@ -55921,7 +57527,7 @@ Tags must contain only letters, numbers, dots, hyphens, underscores, and plus si
55921
57527
  const { kit, tag, preferSsh = true, timeout = 60000 } = options2;
55922
57528
  this.validateTag(tag);
55923
57529
  try {
55924
- await fs9.promises.mkdir(this.tempBaseDir, { recursive: true });
57530
+ await fs12.promises.mkdir(this.tempBaseDir, { recursive: true });
55925
57531
  } catch (error) {
55926
57532
  const msg = error instanceof Error ? error.message : String(error);
55927
57533
  throw new Error(`Failed to create temp directory: ${this.tempBaseDir}
@@ -55929,7 +57535,7 @@ Error: ${msg}
55929
57535
 
55930
57536
  Check disk space and directory permissions.`);
55931
57537
  }
55932
- const tempDir = await fs9.promises.mkdtemp(path7.join(this.tempBaseDir, `sk-git-${kit.repo}-`));
57538
+ const tempDir = await fs12.promises.mkdtemp(path9.join(this.tempBaseDir, `sk-git-${kit.repo}-`));
55933
57539
  const url = preferSsh ? `git@github.com:${kit.owner}/${kit.repo}.git` : `https://github.com/${kit.owner}/${kit.repo}.git`;
55934
57540
  const method = preferSsh ? "ssh" : "https";
55935
57541
  logger.verbose("Git clone", { url, tag, tempDir, method });
@@ -55946,8 +57552,8 @@ Check disk space and directory permissions.`);
55946
57552
  const stderr = shallowError?.stderr || "";
55947
57553
  if (stderr.includes("Could not find remote branch") || stderr.includes("fatal: Remote branch") || stderr.includes("warning: Could not find remote branch")) {
55948
57554
  logger.debug(`Shallow clone failed for tag ${tag}, trying full clone...`);
55949
- await fs9.promises.rm(tempDir, { recursive: true, force: true }).catch(() => {});
55950
- await fs9.promises.mkdir(tempDir, { recursive: true });
57555
+ await fs12.promises.rm(tempDir, { recursive: true, force: true }).catch(() => {});
57556
+ await fs12.promises.mkdir(tempDir, { recursive: true });
55951
57557
  execSync3(`git clone --no-checkout ${quotedUrl} ${quotedDir}`, {
55952
57558
  stdio: ["pipe", "pipe", "pipe"],
55953
57559
  timeout,
@@ -55962,8 +57568,8 @@ Check disk space and directory permissions.`);
55962
57568
  throw shallowError;
55963
57569
  }
55964
57570
  }
55965
- const gitDir = path7.join(tempDir, ".git");
55966
- await fs9.promises.rm(gitDir, { recursive: true, force: true });
57571
+ const gitDir = path9.join(tempDir, ".git");
57572
+ await fs12.promises.rm(gitDir, { recursive: true, force: true });
55967
57573
  logger.debug(`Git clone successful: ${tempDir}`);
55968
57574
  return {
55969
57575
  cloneDir: tempDir,
@@ -55971,7 +57577,7 @@ Check disk space and directory permissions.`);
55971
57577
  method
55972
57578
  };
55973
57579
  } catch (error) {
55974
- await fs9.promises.rm(tempDir, { recursive: true, force: true }).catch((err) => logger.debug(`Failed to cleanup temp dir ${tempDir}: ${err.message}`));
57580
+ await fs12.promises.rm(tempDir, { recursive: true, force: true }).catch((err) => logger.debug(`Failed to cleanup temp dir ${tempDir}: ${err.message}`));
55975
57581
  const errorMessage = error instanceof Error ? error.message : String(error);
55976
57582
  const stderr = error?.stderr || "";
55977
57583
  const errorCode = error?.code;
@@ -56011,13 +57617,13 @@ Ensure you have access to the repository and your git credentials are configured
56011
57617
  const homeDir = process.env.HOME || process.env.USERPROFILE;
56012
57618
  if (!homeDir)
56013
57619
  return false;
56014
- const sshDir = path7.join(homeDir, ".ssh");
57620
+ const sshDir = path9.join(homeDir, ".ssh");
56015
57621
  const keyFiles = ["id_rsa", "id_ed25519", "id_ecdsa", "id_rsa.pub", "id_ed25519.pub"];
56016
57622
  try {
56017
- if (!fs9.existsSync(sshDir))
57623
+ if (!fs12.existsSync(sshDir))
56018
57624
  return false;
56019
57625
  for (const keyFile of keyFiles) {
56020
- if (fs9.existsSync(path7.join(sshDir, keyFile))) {
57626
+ if (fs12.existsSync(path9.join(sshDir, keyFile))) {
56021
57627
  return true;
56022
57628
  }
56023
57629
  }
@@ -56239,17 +57845,17 @@ import { platform as platform7 } from "node:os";
56239
57845
  // src/domains/health-checks/platform/environment-checker.ts
56240
57846
  init_registry();
56241
57847
  init_environment();
56242
- import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile35, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
56243
- import { arch as arch2, homedir as homedir23, platform as platform6 } from "node:os";
56244
- import { join as join80, normalize as normalize7 } from "node:path";
57848
+ import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile36, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
57849
+ import { arch as arch2, homedir as homedir25, platform as platform6 } from "node:os";
57850
+ import { join as join83, normalize as normalize7 } from "node:path";
56245
57851
  function shouldSkipExpensiveOperations4() {
56246
57852
  return shouldSkipExpensiveOperations();
56247
57853
  }
56248
57854
  async function checkPlatformDetect() {
56249
- const os5 = platform6();
57855
+ const os7 = platform6();
56250
57856
  const architecture = arch2();
56251
57857
  const wslDistro = process.env.WSL_DISTRO_NAME;
56252
- let message = `${os5} (${architecture})`;
57858
+ let message = `${os7} (${architecture})`;
56253
57859
  if (wslDistro)
56254
57860
  message += ` - WSL: ${wslDistro}`;
56255
57861
  return {
@@ -56263,7 +57869,7 @@ async function checkPlatformDetect() {
56263
57869
  };
56264
57870
  }
56265
57871
  async function checkHomeDirResolution() {
56266
- const nodeHome = normalize7(homedir23());
57872
+ const nodeHome = normalize7(homedir25());
56267
57873
  const rawEnvHome = getHomeDirectoryFromEnv(platform6());
56268
57874
  const envHome = rawEnvHome ? normalize7(rawEnvHome) : "";
56269
57875
  const match2 = nodeHome === envHome && envHome !== "";
@@ -56334,11 +57940,11 @@ async function checkGlobalDirAccess(provider) {
56334
57940
  autoFixable: false
56335
57941
  };
56336
57942
  }
56337
- const testFile = join80(globalDir, ".sk-doctor-access-test");
57943
+ const testFile = join83(globalDir, ".sk-doctor-access-test");
56338
57944
  try {
56339
57945
  await mkdir19(globalDir, { recursive: true });
56340
57946
  await writeFile24(testFile, "test", "utf-8");
56341
- const content = await readFile35(testFile, "utf-8");
57947
+ const content = await readFile36(testFile, "utf-8");
56342
57948
  await unlink8(testFile);
56343
57949
  if (content !== "test")
56344
57950
  throw new Error("Read mismatch");
@@ -56412,7 +58018,7 @@ async function checkWSLBoundary() {
56412
58018
  // src/domains/health-checks/platform/windows-checker.ts
56413
58019
  init_registry();
56414
58020
  import { mkdir as mkdir20, symlink as symlink2, unlink as unlink9, writeFile as writeFile25 } from "node:fs/promises";
56415
- import { join as join81 } from "node:path";
58021
+ import { join as join84 } from "node:path";
56416
58022
  async function checkLongPathSupport() {
56417
58023
  if (shouldSkipExpensiveOperations4()) {
56418
58024
  return {
@@ -56464,8 +58070,8 @@ async function checkSymlinkSupport() {
56464
58070
  };
56465
58071
  }
56466
58072
  const testDir = getInstaller("claude-code")?.globalRoot() ?? "";
56467
- const target = join81(testDir, ".sk-symlink-test-target");
56468
- const link = join81(testDir, ".sk-symlink-test-link");
58073
+ const target = join84(testDir, ".sk-symlink-test-target");
58074
+ const link = join84(testDir, ".sk-symlink-test-link");
56469
58075
  try {
56470
58076
  await mkdir20(testDir, { recursive: true });
56471
58077
  await writeFile25(target, "test", "utf-8");
@@ -56721,11 +58327,11 @@ class AutoHealer {
56721
58327
  duration: 0
56722
58328
  };
56723
58329
  }
56724
- const start = Date.now();
58330
+ const start2 = Date.now();
56725
58331
  try {
56726
58332
  const result = await Promise.race([fix.execute(), this.createTimeout()]);
56727
58333
  const attempt = this.buildAttempt(check, fix.id, result);
56728
- attempt.duration = Date.now() - start;
58334
+ attempt.duration = Date.now() - start2;
56729
58335
  return attempt;
56730
58336
  } catch (e2) {
56731
58337
  const err = e2 instanceof Error ? e2.message : "Unknown error";
@@ -56736,7 +58342,7 @@ class AutoHealer {
56736
58342
  success: false,
56737
58343
  message: "Fix failed",
56738
58344
  error: err,
56739
- duration: Date.now() - start
58345
+ duration: Date.now() - start2
56740
58346
  };
56741
58347
  }
56742
58348
  }
@@ -56759,18 +58365,18 @@ class AutoHealer {
56759
58365
  }
56760
58366
  // src/domains/health-checks/report-generator.ts
56761
58367
  import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
56762
- import { readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
58368
+ import { readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
56763
58369
  import { tmpdir as tmpdir2 } from "node:os";
56764
- import { dirname as dirname19, join as join82 } from "node:path";
58370
+ import { dirname as dirname20, join as join85 } from "node:path";
56765
58371
  import { fileURLToPath as fileURLToPath2 } from "node:url";
56766
58372
  init_environment();
56767
58373
  init_logger();
56768
58374
  init_dist2();
56769
58375
  function getCliVersion3() {
56770
58376
  try {
56771
- const __dirname3 = dirname19(fileURLToPath2(import.meta.url));
56772
- const pkgPath = join82(__dirname3, "../../../package.json");
56773
- const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
58377
+ const __dirname3 = dirname20(fileURLToPath2(import.meta.url));
58378
+ const pkgPath = join85(__dirname3, "../../../package.json");
58379
+ const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
56774
58380
  return pkg.version || "unknown";
56775
58381
  } catch (err) {
56776
58382
  logger.debug(`Failed to read CLI version: ${err}`);
@@ -56908,7 +58514,7 @@ class ReportGenerator {
56908
58514
  return null;
56909
58515
  }
56910
58516
  }
56911
- const tmpFile = join82(tmpdir2(), `sk-report-${Date.now()}.txt`);
58517
+ const tmpFile = join85(tmpdir2(), `sk-report-${Date.now()}.txt`);
56912
58518
  writeFileSync6(tmpFile, report);
56913
58519
  try {
56914
58520
  const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "Takumi Diagnostic Report"], {
@@ -56939,9 +58545,9 @@ class ReportGenerator {
56939
58545
  cliVersion: getCliVersion3()
56940
58546
  };
56941
58547
  }
56942
- scrubPath(path8) {
58548
+ scrubPath(path10) {
56943
58549
  const home6 = process.env.HOME || process.env.USERPROFILE || "";
56944
- return home6 ? path8.replace(home6, "~") : path8;
58550
+ return home6 ? path10.replace(home6, "~") : path10;
56945
58551
  }
56946
58552
  getStatusIcon(status2) {
56947
58553
  switch (status2) {
@@ -57054,14 +58660,14 @@ class DoctorUIRenderer {
57054
58660
  return message;
57055
58661
  }
57056
58662
  }
57057
- shortenPath(path8) {
58663
+ shortenPath(path10) {
57058
58664
  const home6 = process.env.HOME || process.env.USERPROFILE || "";
57059
- let shortened = home6 ? path8.replace(home6, "~") : path8;
58665
+ let shortened = home6 ? path10.replace(home6, "~") : path10;
57060
58666
  const maxLen = 50;
57061
58667
  if (shortened.length > maxLen) {
57062
- const start = shortened.slice(0, 20);
58668
+ const start2 = shortened.slice(0, 20);
57063
58669
  const end = shortened.slice(-27);
57064
- shortened = `${start}...${end}`;
58670
+ shortened = `${start2}...${end}`;
57065
58671
  }
57066
58672
  return shortened;
57067
58673
  }
@@ -57220,14 +58826,14 @@ async function authedFetch(url, init) {
57220
58826
 
57221
58827
  // src/commands/hooks/lib/detached-put.ts
57222
58828
  import { spawn as spawn2 } from "node:child_process";
57223
- import { openSync } from "node:fs";
57224
- import { dirname as dirname20, join as join83 } from "node:path";
58829
+ import { openSync as openSync4 } from "node:fs";
58830
+ import { dirname as dirname21, join as join86 } from "node:path";
57225
58831
 
57226
58832
  // src/commands/hooks/lib/hook-logger.ts
57227
58833
  import { appendFileSync } from "node:fs";
57228
58834
  var extraLogPath = null;
57229
- function setHookDebugLog(path8) {
57230
- extraLogPath = path8 && path8.trim().length > 0 ? path8 : null;
58835
+ function setHookDebugLog(path10) {
58836
+ extraLogPath = path10 && path10.trim().length > 0 ? path10 : null;
57231
58837
  }
57232
58838
  function formatValue(v2) {
57233
58839
  if (v2 === null || v2 === undefined)
@@ -57268,7 +58874,7 @@ function effectiveDetachMode(flags) {
57268
58874
  return flags.noDetach ? "inline" : "detached";
57269
58875
  }
57270
58876
  function sessionDebugLogPath(sessionDir) {
57271
- return join83(sessionDir, DETACH_DEBUG_LOG_NAME);
58877
+ return join86(sessionDir, DETACH_DEBUG_LOG_NAME);
57272
58878
  }
57273
58879
  var BUNFS_PREFIX = "/$bunfs/";
57274
58880
  function resolveInvocationPrefix() {
@@ -57296,9 +58902,9 @@ function resolveInvocationPrefix() {
57296
58902
  }
57297
58903
  function resolvePreloadScript(entryPath) {
57298
58904
  try {
57299
- const srcDir = dirname20(entryPath);
57300
- const repoRoot = dirname20(srcDir);
57301
- return join83(repoRoot, "scripts", "preload-config-override.ts");
58905
+ const srcDir = dirname21(entryPath);
58906
+ const repoRoot = dirname21(srcDir);
58907
+ return join86(repoRoot, "scripts", "preload-config-override.ts");
57302
58908
  } catch {
57303
58909
  return null;
57304
58910
  }
@@ -57322,7 +58928,7 @@ function buildChildStdio(job) {
57322
58928
  if (!job.debug)
57323
58929
  return "ignore";
57324
58930
  try {
57325
- const fd = openSync(sessionDebugLogPath(job.sessionDir), "a");
58931
+ const fd = openSync4(sessionDebugLogPath(job.sessionDir), "a");
57326
58932
  return ["ignore", fd, fd];
57327
58933
  } catch {
57328
58934
  return "ignore";
@@ -57366,17 +58972,17 @@ function decodeJobArgv(argv) {
57366
58972
  }
57367
58973
 
57368
58974
  // src/commands/hooks/lib/throttle.ts
57369
- import { promises as fs10 } from "node:fs";
58975
+ import { promises as fs13 } from "node:fs";
57370
58976
 
57371
58977
  // src/commands/hooks/lib/session-paths.ts
57372
58978
  init_paths2();
57373
- import { join as join85 } from "node:path";
58979
+ import { join as join88 } from "node:path";
57374
58980
 
57375
58981
  // src/commands/hooks/lib/project-paths.ts
57376
58982
  init_paths2();
57377
58983
  import { createHash as createHash8 } from "node:crypto";
57378
58984
  import { realpathSync as realpathSync2 } from "node:fs";
57379
- import { basename as basename10, join as join84 } from "node:path";
58985
+ import { basename as basename12, join as join87 } from "node:path";
57380
58986
  function encodeCwd(cwd2) {
57381
58987
  const stripped = cwd2.replace(/^\/+/, "");
57382
58988
  const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
@@ -57392,13 +58998,13 @@ function computeProjectHash(cwd2) {
57392
58998
  return createHash8("sha256").update(canonical).digest("hex").slice(0, 16);
57393
58999
  }
57394
59000
  function getProjectLabel(cwd2) {
57395
- return basename10(cwd2) || "";
59001
+ return basename12(cwd2) || "";
57396
59002
  }
57397
59003
  function getProjectsRoot() {
57398
- return join84(getConfigDir(), "projects");
59004
+ return join87(getConfigDir(), "projects");
57399
59005
  }
57400
59006
  function getProjectDir(args) {
57401
- return join84(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
59007
+ return join87(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
57402
59008
  }
57403
59009
 
57404
59010
  // src/commands/hooks/lib/session-paths.ts
@@ -57410,25 +59016,25 @@ function safeSessionSegment(sessionId) {
57410
59016
  return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
57411
59017
  }
57412
59018
  function getSessionsRoot() {
57413
- return join85(getConfigDir(), "sessions");
59019
+ return join88(getConfigDir(), "sessions");
57414
59020
  }
57415
59021
  function getSessionDirV2(args) {
57416
59022
  const segment = safeSessionSegment(args.sessionId);
57417
59023
  if (!segment)
57418
59024
  return null;
57419
- return join85(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
59025
+ return join88(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
57420
59026
  }
57421
59027
  function getEventsFile(sessionDir) {
57422
- return join85(sessionDir, "events.jsonl");
59028
+ return join88(sessionDir, "events.jsonl");
57423
59029
  }
57424
59030
  function getSummaryFile(sessionDir) {
57425
- return join85(sessionDir, "summary.json");
59031
+ return join88(sessionDir, "summary.json");
57426
59032
  }
57427
59033
  function getLastPushFile(sessionDir) {
57428
- return join85(sessionDir, "last_push.txt");
59034
+ return join88(sessionDir, "last_push.txt");
57429
59035
  }
57430
59036
  function getMetaFile(sessionDir) {
57431
- return join85(sessionDir, "meta.json");
59037
+ return join88(sessionDir, "meta.json");
57432
59038
  }
57433
59039
 
57434
59040
  // src/commands/hooks/lib/throttle.ts
@@ -57436,7 +59042,7 @@ var defaultNow = () => Date.now();
57436
59042
  async function readLastPush(sessionDir) {
57437
59043
  let raw;
57438
59044
  try {
57439
- raw = await fs10.readFile(getLastPushFile(sessionDir), "utf8");
59045
+ raw = await fs13.readFile(getLastPushFile(sessionDir), "utf8");
57440
59046
  } catch {
57441
59047
  return null;
57442
59048
  }
@@ -57444,11 +59050,11 @@ async function readLastPush(sessionDir) {
57444
59050
  return Number.isFinite(parsed) ? parsed : null;
57445
59051
  }
57446
59052
  async function writeLastPush(sessionDir, ts) {
57447
- await fs10.mkdir(sessionDir, { recursive: true });
59053
+ await fs13.mkdir(sessionDir, { recursive: true });
57448
59054
  const target = getLastPushFile(sessionDir);
57449
59055
  const tmp = `${target}.tmp`;
57450
- await fs10.writeFile(tmp, String(ts), "utf8");
57451
- await fs10.rename(tmp, target);
59056
+ await fs13.writeFile(tmp, String(ts), "utf8");
59057
+ await fs13.rename(tmp, target);
57452
59058
  }
57453
59059
  async function shouldFlush(args) {
57454
59060
  const now = args.now ?? defaultNow;
@@ -57458,7 +59064,7 @@ async function shouldFlush(args) {
57458
59064
  if (now() - last >= args.intervalMs)
57459
59065
  return true;
57460
59066
  try {
57461
- const stat8 = await fs10.stat(getEventsFile(args.sessionDir));
59067
+ const stat8 = await fs13.stat(getEventsFile(args.sessionDir));
57462
59068
  if (stat8.size >= args.sizeBytes)
57463
59069
  return true;
57464
59070
  } catch {}
@@ -57500,22 +59106,22 @@ async function handleDoPut() {
57500
59106
  }
57501
59107
 
57502
59108
  // src/commands/hooks/lib/buffer.ts
57503
- import { promises as fs11 } from "node:fs";
59109
+ import { promises as fs14 } from "node:fs";
57504
59110
  async function appendEvent(sessionDir, event) {
57505
59111
  try {
57506
- await fs11.mkdir(sessionDir, { recursive: true });
59112
+ await fs14.mkdir(sessionDir, { recursive: true });
57507
59113
  const line = `${JSON.stringify(event)}
57508
59114
  `;
57509
- await fs11.appendFile(getEventsFile(sessionDir), line, "utf8");
59115
+ await fs14.appendFile(getEventsFile(sessionDir), line, "utf8");
57510
59116
  } catch {}
57511
59117
  }
57512
59118
 
57513
59119
  // src/commands/hooks/lib/session-meta.ts
57514
- import { promises as fs12 } from "node:fs";
59120
+ import { promises as fs15 } from "node:fs";
57515
59121
  async function readMeta(sessionDir) {
57516
59122
  let raw;
57517
59123
  try {
57518
- raw = await fs12.readFile(getMetaFile(sessionDir), "utf8");
59124
+ raw = await fs15.readFile(getMetaFile(sessionDir), "utf8");
57519
59125
  } catch {
57520
59126
  return null;
57521
59127
  }
@@ -57528,17 +59134,17 @@ async function readMeta(sessionDir) {
57528
59134
  async function writeMetaIfAbsent(sessionDir, meta) {
57529
59135
  const target = getMetaFile(sessionDir);
57530
59136
  try {
57531
- await fs12.access(target);
59137
+ await fs15.access(target);
57532
59138
  return;
57533
59139
  } catch {}
57534
- await fs12.mkdir(sessionDir, { recursive: true });
59140
+ await fs15.mkdir(sessionDir, { recursive: true });
57535
59141
  const tmp = `${target}.tmp`;
57536
- await fs12.writeFile(tmp, JSON.stringify(meta), "utf8");
57537
- await fs12.rename(tmp, target);
59142
+ await fs15.writeFile(tmp, JSON.stringify(meta), "utf8");
59143
+ await fs15.rename(tmp, target);
57538
59144
  }
57539
59145
 
57540
59146
  // src/commands/hooks/lib/summary.ts
57541
- import { promises as fs13 } from "node:fs";
59147
+ import { promises as fs16 } from "node:fs";
57542
59148
  function zeroTokens() {
57543
59149
  return { input: 0, output: 0, cache_read: 0, cache_write: 0 };
57544
59150
  }
@@ -57573,7 +59179,7 @@ function initialSummary(args) {
57573
59179
  async function readSummary(sessionDir) {
57574
59180
  let raw;
57575
59181
  try {
57576
- raw = await fs13.readFile(getSummaryFile(sessionDir), "utf8");
59182
+ raw = await fs16.readFile(getSummaryFile(sessionDir), "utf8");
57577
59183
  } catch {
57578
59184
  return null;
57579
59185
  }
@@ -57584,11 +59190,11 @@ async function readSummary(sessionDir) {
57584
59190
  }
57585
59191
  }
57586
59192
  async function writeSummary(sessionDir, summary) {
57587
- await fs13.mkdir(sessionDir, { recursive: true });
59193
+ await fs16.mkdir(sessionDir, { recursive: true });
57588
59194
  const target = getSummaryFile(sessionDir);
57589
59195
  const tmp = `${target}.tmp`;
57590
- await fs13.writeFile(tmp, JSON.stringify(summary), "utf8");
57591
- await fs13.rename(tmp, target);
59196
+ await fs16.writeFile(tmp, JSON.stringify(summary), "utf8");
59197
+ await fs16.rename(tmp, target);
57592
59198
  }
57593
59199
  function isPlainObject2(value) {
57594
59200
  return typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
@@ -57665,14 +59271,14 @@ async function recordEvent(args) {
57665
59271
  }
57666
59272
 
57667
59273
  // src/commands/hooks/lib/transcript-reader.ts
57668
- import { promises as fs14 } from "node:fs";
59274
+ import { promises as fs17 } from "node:fs";
57669
59275
  function num(v2) {
57670
59276
  return typeof v2 === "number" && Number.isFinite(v2) ? v2 : 0;
57671
59277
  }
57672
59278
  function zeroTokens2() {
57673
59279
  return { input: 0, output: 0, cache_read: 0, cache_write: 0 };
57674
59280
  }
57675
- function addTokens(a3, b3) {
59281
+ function addTokens2(a3, b3) {
57676
59282
  return {
57677
59283
  input: a3.input + b3.input,
57678
59284
  output: a3.output + b3.output,
@@ -57694,7 +59300,7 @@ function extractTokens(record) {
57694
59300
  async function tailRead(args) {
57695
59301
  let stat8;
57696
59302
  try {
57697
- stat8 = await fs14.stat(args.transcriptPath);
59303
+ stat8 = await fs17.stat(args.transcriptPath);
57698
59304
  } catch {
57699
59305
  return { records: [], nextOffset: args.offset };
57700
59306
  }
@@ -57702,7 +59308,7 @@ async function tailRead(args) {
57702
59308
  if (currentSize <= args.offset) {
57703
59309
  return { records: [], nextOffset: currentSize };
57704
59310
  }
57705
- const handle = await fs14.open(args.transcriptPath, "r");
59311
+ const handle = await fs17.open(args.transcriptPath, "r");
57706
59312
  try {
57707
59313
  const length = currentSize - args.offset;
57708
59314
  const buf = Buffer.alloc(length);
@@ -57736,13 +59342,13 @@ function bucketTokens(records) {
57736
59342
  const key = record.agentId ?? record.toolUseID;
57737
59343
  if (!key) {
57738
59344
  const prev2 = mainLoopDelta;
57739
- Object.assign(mainLoopDelta, addTokens(prev2, tokens));
59345
+ Object.assign(mainLoopDelta, addTokens2(prev2, tokens));
57740
59346
  continue;
57741
59347
  }
57742
59348
  const prev = subagentDeltas.get(key) ?? zeroTokens2();
57743
- subagentDeltas.set(key, addTokens(prev, tokens));
59349
+ subagentDeltas.set(key, addTokens2(prev, tokens));
57744
59350
  } else {
57745
- Object.assign(mainLoopDelta, addTokens(mainLoopDelta, tokens));
59351
+ Object.assign(mainLoopDelta, addTokens2(mainLoopDelta, tokens));
57746
59352
  }
57747
59353
  }
57748
59354
  return { mainLoopDelta, subagentDeltas };
@@ -57752,7 +59358,7 @@ function bucketTokens(records) {
57752
59358
  function ensureTokens(t) {
57753
59359
  return t ?? { input: 0, output: 0, cache_read: 0, cache_write: 0 };
57754
59360
  }
57755
- function addTokens2(a3, b3) {
59361
+ function addTokens3(a3, b3) {
57756
59362
  return {
57757
59363
  input: a3.input + b3.input,
57758
59364
  output: a3.output + b3.output,
@@ -57775,12 +59381,12 @@ async function applyTranscriptDelta(args) {
57775
59381
  const { mainLoopDelta, subagentDeltas } = bucketTokens(records);
57776
59382
  const updated = {
57777
59383
  ...args.summary,
57778
- main_loop_tokens: addTokens2(args.summary.main_loop_tokens, mainLoopDelta),
59384
+ main_loop_tokens: addTokens3(args.summary.main_loop_tokens, mainLoopDelta),
57779
59385
  subagents: args.summary.subagents.map((rec) => {
57780
59386
  const delta = subagentDeltas.get(rec.id);
57781
59387
  if (!delta)
57782
59388
  return rec;
57783
- return { ...rec, tokens: addTokens2(ensureTokens(rec.tokens), delta) };
59389
+ return { ...rec, tokens: addTokens3(ensureTokens(rec.tokens), delta) };
57784
59390
  }),
57785
59391
  transcript_offset: nextOffset
57786
59392
  };
@@ -58035,25 +59641,25 @@ init_takumi_constants();
58035
59641
 
58036
59642
  // src/commands/hooks/lib/endpoint.ts
58037
59643
  init_build_config();
58038
- function stripTrailingSlash(u) {
59644
+ function stripTrailingSlash2(u) {
58039
59645
  return u.replace(/\/+$/, "");
58040
59646
  }
58041
59647
  function resolveEndpoint() {
58042
59648
  if (!SERVER_URL)
58043
59649
  return null;
58044
- return { url: stripTrailingSlash(SERVER_URL) };
59650
+ return { url: stripTrailingSlash2(SERVER_URL) };
58045
59651
  }
58046
59652
 
58047
59653
  // src/commands/hooks/lib/manifest-versions.ts
58048
59654
  init_manifest_path_resolver();
58049
- import { existsSync as existsSync41, readFileSync as readFileSync11 } from "node:fs";
58050
- import { homedir as homedir24 } from "node:os";
58051
- import { dirname as dirname21, join as join86, resolve as resolve16 } from "node:path";
59655
+ import { existsSync as existsSync44, readFileSync as readFileSync12 } from "node:fs";
59656
+ import { homedir as homedir26 } from "node:os";
59657
+ import { dirname as dirname22, join as join89, resolve as resolve18 } from "node:path";
58052
59658
  var PROVIDER_DIRS = [".claude", ".codex"];
58053
59659
  var MAX_WALK = 6;
58054
- function readManifestRaw(path8) {
59660
+ function readManifestRaw(path10) {
58055
59661
  try {
58056
- const raw = readFileSync11(path8, "utf8");
59662
+ const raw = readFileSync12(path10, "utf8");
58057
59663
  return JSON.parse(raw);
58058
59664
  } catch {
58059
59665
  return null;
@@ -58064,28 +59670,28 @@ function findManifestInProviderDir(providerRoot) {
58064
59670
  return resolved?.path ?? null;
58065
59671
  }
58066
59672
  function findManifest(cwd2) {
58067
- let dir = resolve16(cwd2);
59673
+ let dir = resolve18(cwd2);
58068
59674
  for (let i = 0;i < MAX_WALK; i++) {
58069
59675
  for (const provider of PROVIDER_DIRS) {
58070
- const providerRoot = join86(dir, provider);
58071
- if (existsSync41(providerRoot)) {
58072
- const path8 = findManifestInProviderDir(providerRoot);
58073
- if (path8)
58074
- return path8;
59676
+ const providerRoot = join89(dir, provider);
59677
+ if (existsSync44(providerRoot)) {
59678
+ const path10 = findManifestInProviderDir(providerRoot);
59679
+ if (path10)
59680
+ return path10;
58075
59681
  }
58076
59682
  }
58077
- const parent = dirname21(dir);
59683
+ const parent = dirname22(dir);
58078
59684
  if (parent === dir)
58079
59685
  break;
58080
59686
  dir = parent;
58081
59687
  }
58082
59688
  const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
58083
59689
  if (pluginRoot) {
58084
- const pluginPath = findManifestInProviderDir(join86(pluginRoot, ".claude"));
59690
+ const pluginPath = findManifestInProviderDir(join89(pluginRoot, ".claude"));
58085
59691
  if (pluginPath)
58086
59692
  return pluginPath;
58087
59693
  }
58088
- const globalPath = findManifestInProviderDir(join86(homedir24(), ".claude"));
59694
+ const globalPath = findManifestInProviderDir(join89(homedir26(), ".claude"));
58089
59695
  if (globalPath)
58090
59696
  return globalPath;
58091
59697
  return null;
@@ -58199,12 +59805,12 @@ async function handleSessionEnd(agent, flags = {}) {
58199
59805
  ...reason ? { session_end_reason: reason } : {},
58200
59806
  session_end_raw: data
58201
59807
  };
58202
- const { promises: fs15 } = await import("node:fs");
58203
- const { join: join87 } = await import("node:path");
58204
- const target = join87(sessionDir, "meta.json");
59808
+ const { promises: fs18 } = await import("node:fs");
59809
+ const { join: join90 } = await import("node:path");
59810
+ const target = join90(sessionDir, "meta.json");
58205
59811
  const tmp = `${target}.tmp`;
58206
- await fs15.writeFile(tmp, JSON.stringify(updated), "utf8");
58207
- await fs15.rename(tmp, target);
59812
+ await fs18.writeFile(tmp, JSON.stringify(updated), "utf8");
59813
+ await fs18.rename(tmp, target);
58208
59814
  } else if (!existingMeta) {
58209
59815
  await writeMetaIfAbsent(sessionDir, {
58210
59816
  agent,
@@ -58271,11 +59877,11 @@ async function handleSessionEnd(agent, flags = {}) {
58271
59877
  init_auth_client();
58272
59878
 
58273
59879
  // src/commands/hooks/lib/retention.ts
58274
- import { promises as fs15 } from "node:fs";
58275
- import { join as join87 } from "node:path";
59880
+ import { promises as fs18 } from "node:fs";
59881
+ import { join as join90 } from "node:path";
58276
59882
  async function hasLastPush(dir) {
58277
59883
  try {
58278
- await fs15.access(getLastPushFile(dir));
59884
+ await fs18.access(getLastPushFile(dir));
58279
59885
  return true;
58280
59886
  } catch {
58281
59887
  return false;
@@ -58284,7 +59890,7 @@ async function hasLastPush(dir) {
58284
59890
  async function decideDelete(dir, args) {
58285
59891
  let mtimeMs = 0;
58286
59892
  try {
58287
- const stat8 = await fs15.stat(dir);
59893
+ const stat8 = await fs18.stat(dir);
58288
59894
  if (!stat8.isDirectory())
58289
59895
  return false;
58290
59896
  mtimeMs = stat8.mtimeMs;
@@ -58301,8 +59907,8 @@ async function decideDelete(dir, args) {
58301
59907
  }
58302
59908
  async function listChildren(dir) {
58303
59909
  try {
58304
- const names = await fs15.readdir(dir);
58305
- return names.map((n) => join87(dir, n));
59910
+ const names = await fs18.readdir(dir);
59911
+ return names.map((n) => join90(dir, n));
58306
59912
  } catch {
58307
59913
  return [];
58308
59914
  }
@@ -58313,7 +59919,7 @@ async function collectV2Sessions() {
58313
59919
  const sessions = [];
58314
59920
  for (const projectDir of projects) {
58315
59921
  for (const agentDir of await listChildren(projectDir)) {
58316
- for (const sessionDir of await listChildren(join87(agentDir, "sessions"))) {
59922
+ for (const sessionDir of await listChildren(join90(agentDir, "sessions"))) {
58317
59923
  sessions.push(sessionDir);
58318
59924
  }
58319
59925
  }
@@ -58334,7 +59940,7 @@ async function sweepRetention(args) {
58334
59940
  continue;
58335
59941
  }
58336
59942
  try {
58337
- await fs15.rm(dir, { recursive: true, force: true });
59943
+ await fs18.rm(dir, { recursive: true, force: true });
58338
59944
  deleted.push(dir);
58339
59945
  } catch {}
58340
59946
  }
@@ -58359,8 +59965,8 @@ async function warmUpToken() {
58359
59965
  const token = await getValidToken();
58360
59966
  return token ? "ok" : "none";
58361
59967
  })(),
58362
- new Promise((resolve17) => {
58363
- timer = setTimeout(() => resolve17("timeout"), TOKEN_WARMUP_TIMEOUT_MS);
59968
+ new Promise((resolve19) => {
59969
+ timer = setTimeout(() => resolve19("timeout"), TOKEN_WARMUP_TIMEOUT_MS);
58364
59970
  })
58365
59971
  ]);
58366
59972
  return result;
@@ -58713,8 +60319,8 @@ init_hooks_settings_merger();
58713
60319
 
58714
60320
  // src/commands/portable/settings-write-with-confirm.ts
58715
60321
  init_safe_prompts();
58716
- import { existsSync as existsSync42, mkdirSync as mkdirSync4, readFileSync as readFileSync12, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "node:fs";
58717
- import { dirname as dirname22 } from "node:path";
60322
+ import { existsSync as existsSync45, mkdirSync as mkdirSync4, readFileSync as readFileSync13, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "node:fs";
60323
+ import { dirname as dirname23 } from "node:path";
58718
60324
 
58719
60325
  // node_modules/diff/libesm/diff/base.js
58720
60326
  class Diff {
@@ -58816,16 +60422,16 @@ class Diff {
58816
60422
  }
58817
60423
  }
58818
60424
  }
58819
- addToPath(path8, added, removed, oldPosInc, options2) {
58820
- const last = path8.lastComponent;
60425
+ addToPath(path10, added, removed, oldPosInc, options2) {
60426
+ const last = path10.lastComponent;
58821
60427
  if (last && !options2.oneChangePerToken && last.added === added && last.removed === removed) {
58822
60428
  return {
58823
- oldPos: path8.oldPos + oldPosInc,
60429
+ oldPos: path10.oldPos + oldPosInc,
58824
60430
  lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
58825
60431
  };
58826
60432
  } else {
58827
60433
  return {
58828
- oldPos: path8.oldPos + oldPosInc,
60434
+ oldPos: path10.oldPos + oldPosInc,
58829
60435
  lastComponent: { count: 1, added, removed, previousComponent: last }
58830
60436
  };
58831
60437
  }
@@ -59403,11 +61009,11 @@ function isWin(patch) {
59403
61009
 
59404
61010
  // node_modules/diff/libesm/patch/parse.js
59405
61011
  function parsePatch(uniDiff) {
59406
- const diffstr = uniDiff.split(/\n/), list = [];
61012
+ const diffstr = uniDiff.split(/\n/), list2 = [];
59407
61013
  let i = 0;
59408
61014
  function parseIndex() {
59409
61015
  const index = {};
59410
- list.push(index);
61016
+ list2.push(index);
59411
61017
  while (i < diffstr.length) {
59412
61018
  const line = diffstr[i];
59413
61019
  if (/^(---|\+\+\+|@@)\s/.test(line)) {
@@ -59503,11 +61109,11 @@ function parsePatch(uniDiff) {
59503
61109
  while (i < diffstr.length) {
59504
61110
  parseIndex();
59505
61111
  }
59506
- return list;
61112
+ return list2;
59507
61113
  }
59508
61114
 
59509
61115
  // node_modules/diff/libesm/util/distance-iterator.js
59510
- function distance_iterator_default(start, minLine, maxLine) {
61116
+ function distance_iterator_default(start2, minLine, maxLine) {
59511
61117
  let wantForward = true, backwardExhausted = false, forwardExhausted = false, localOffset = 1;
59512
61118
  return function iterator() {
59513
61119
  if (wantForward && !forwardExhausted) {
@@ -59516,8 +61122,8 @@ function distance_iterator_default(start, minLine, maxLine) {
59516
61122
  } else {
59517
61123
  wantForward = false;
59518
61124
  }
59519
- if (start + localOffset <= maxLine) {
59520
- return start + localOffset;
61125
+ if (start2 + localOffset <= maxLine) {
61126
+ return start2 + localOffset;
59521
61127
  }
59522
61128
  forwardExhausted = true;
59523
61129
  }
@@ -59525,8 +61131,8 @@ function distance_iterator_default(start, minLine, maxLine) {
59525
61131
  if (!forwardExhausted) {
59526
61132
  wantForward = true;
59527
61133
  }
59528
- if (minLine <= start - localOffset) {
59529
- return start - localOffset++;
61134
+ if (minLine <= start2 - localOffset) {
61135
+ return start2 - localOffset++;
59530
61136
  }
59531
61137
  backwardExhausted = true;
59532
61138
  return iterator();
@@ -59885,12 +61491,12 @@ var EMPTY_RESULT = (status2) => ({
59885
61491
  deletions: 0,
59886
61492
  backupPath: null
59887
61493
  });
59888
- function readCurrent(path8) {
59889
- if (!existsSync42(path8))
61494
+ function readCurrent(path10) {
61495
+ if (!existsSync45(path10))
59890
61496
  return { kind: "missing" };
59891
61497
  let raw = "";
59892
61498
  try {
59893
- raw = readFileSync12(path8, "utf8");
61499
+ raw = readFileSync13(path10, "utf8");
59894
61500
  const parsed = JSON.parse(raw);
59895
61501
  return { kind: "ok", raw, parsed };
59896
61502
  } catch {
@@ -59916,21 +61522,21 @@ function diffStats(diff) {
59916
61522
  }
59917
61523
  return { additions, deletions };
59918
61524
  }
59919
- function atomicWrite2(path8, contents, backupPath) {
59920
- mkdirSync4(dirname22(path8), { recursive: true });
59921
- const tmp = `${path8}.tmp`;
61525
+ function atomicWrite2(path10, contents, backupPath) {
61526
+ mkdirSync4(dirname23(path10), { recursive: true });
61527
+ const tmp = `${path10}.tmp`;
59922
61528
  try {
59923
61529
  writeFileSync7(tmp, contents);
59924
- renameSync2(tmp, path8);
61530
+ renameSync2(tmp, path10);
59925
61531
  } catch (err) {
59926
61532
  rmSync3(tmp, { force: true });
59927
61533
  const trailer = backupPath ? `. Backup preserved at: ${backupPath}` : "";
59928
- throw new Error(`Failed to write ${path8}: ${err instanceof Error ? err.message : String(err)}${trailer}`);
61534
+ throw new Error(`Failed to write ${path10}: ${err instanceof Error ? err.message : String(err)}${trailer}`);
59929
61535
  }
59930
61536
  }
59931
- function writeBackup(path8, raw) {
61537
+ function writeBackup(path10, raw) {
59932
61538
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
59933
- const backupPath = `${path8}.${timestamp}.bak`;
61539
+ const backupPath = `${path10}.${timestamp}.bak`;
59934
61540
  try {
59935
61541
  writeFileSync7(backupPath, raw);
59936
61542
  return backupPath;
@@ -59939,7 +61545,7 @@ function writeBackup(path8, raw) {
59939
61545
  }
59940
61546
  }
59941
61547
  async function resolveMissingFile(options2) {
59942
- const { missingFile, interactive, label, path: path8 } = options2;
61548
+ const { missingFile, interactive, label, path: path10 } = options2;
59943
61549
  if (missingFile === "create")
59944
61550
  return "proceed";
59945
61551
  if (missingFile === "skip")
@@ -59947,7 +61553,7 @@ async function resolveMissingFile(options2) {
59947
61553
  if (!interactive)
59948
61554
  return "skip";
59949
61555
  const result = await se({
59950
- message: `${label} does not exist at ${path8}. Create it?`,
61556
+ message: `${label} does not exist at ${path10}. Create it?`,
59951
61557
  initialValue: false
59952
61558
  });
59953
61559
  if (lD(result))
@@ -59955,9 +61561,9 @@ async function resolveMissingFile(options2) {
59955
61561
  return result ? "proceed" : "skip";
59956
61562
  }
59957
61563
  async function writeSettingsWithConfirm(options2) {
59958
- const { path: path8, transform, yes, dryRun, interactive, useStepUI } = options2;
61564
+ const { path: path10, transform, yes, dryRun, interactive, useStepUI } = options2;
59959
61565
  const diffPrint = useStepUI ? stepLine : undefined;
59960
- const current = readCurrent(path8);
61566
+ const current = readCurrent(path10);
59961
61567
  if (current.kind === "corrupt")
59962
61568
  return EMPTY_RESULT("skipped-corrupt");
59963
61569
  const fileMissing = current.kind === "missing";
@@ -59974,7 +61580,7 @@ async function writeSettingsWithConfirm(options2) {
59974
61580
  if (before === after) {
59975
61581
  return EMPTY_RESULT("no-changes");
59976
61582
  }
59977
- const diff = createPatch(path8, before, after, "", "", { context: 3 });
61583
+ const diff = createPatch(path10, before, after, "", "", { context: 3 });
59978
61584
  const { additions, deletions } = diffStats(diff);
59979
61585
  if (dryRun) {
59980
61586
  displayDiff(diff, { color: true, print: diffPrint });
@@ -59983,15 +61589,15 @@ async function writeSettingsWithConfirm(options2) {
59983
61589
  if (!yes && interactive) {
59984
61590
  displayDiff(diff, { color: true, print: diffPrint });
59985
61591
  const accepted = await se({
59986
- message: `Apply changes to ${path8}?`,
61592
+ message: `Apply changes to ${path10}?`,
59987
61593
  initialValue: false
59988
61594
  });
59989
61595
  if (lD(accepted) || !accepted) {
59990
61596
  return { status: "user-declined", diff, additions, deletions, backupPath: null };
59991
61597
  }
59992
61598
  }
59993
- const backupPath = fileMissing ? null : writeBackup(path8, raw);
59994
- atomicWrite2(path8, after, backupPath);
61599
+ const backupPath = fileMissing ? null : writeBackup(path10, raw);
61600
+ atomicWrite2(path10, after, backupPath);
59995
61601
  return { status: "wrote", diff, additions, deletions, backupPath };
59996
61602
  }
59997
61603
 
@@ -60003,18 +61609,18 @@ init_dist2();
60003
61609
  // src/commands/hooks/lib/agent-target-picker.ts
60004
61610
  init_safe_prompts();
60005
61611
  init_dist2();
60006
- import { existsSync as existsSync43 } from "node:fs";
61612
+ import { existsSync as existsSync46 } from "node:fs";
60007
61613
 
60008
61614
  // src/commands/hooks/lib/settings-path-resolver.ts
60009
61615
  import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "node:fs";
60010
- import { homedir as homedir25 } from "node:os";
60011
- import { join as join88 } from "node:path";
61616
+ import { homedir as homedir27 } from "node:os";
61617
+ import { join as join91 } from "node:path";
60012
61618
  function rawPath(agent, global3) {
60013
- const root = global3 ? homedir25() : process.cwd();
61619
+ const root = global3 ? homedir27() : process.cwd();
60014
61620
  if (agent === "claude") {
60015
- return join88(root, ".claude", "settings.json");
61621
+ return join91(root, ".claude", "settings.json");
60016
61622
  }
60017
- return join88(root, ".codex", "hooks.json");
61623
+ return join91(root, ".codex", "hooks.json");
60018
61624
  }
60019
61625
  function resolveSettingsPath(agent, options2 = {}) {
60020
61626
  const originalPath = rawPath(agent, Boolean(options2.global));
@@ -60042,7 +61648,7 @@ function probe(global3) {
60042
61648
  return {
60043
61649
  agent,
60044
61650
  path: location2.realPath,
60045
- exists: existsSync43(location2.realPath)
61651
+ exists: existsSync46(location2.realPath)
60046
61652
  };
60047
61653
  });
60048
61654
  }
@@ -60087,7 +61693,7 @@ async function promptHookAgentTargets(options2) {
60087
61693
 
60088
61694
  // src/commands/hooks/lib/entry-builder.ts
60089
61695
  init_capabilities();
60090
- var TIMEOUT_SECONDS = 2;
61696
+ var TIMEOUT_SECONDS = 10;
60091
61697
  var DEFAULT_HOOK_BIN = "tkm";
60092
61698
  var CLAUDE_SESSION_START_MATCHER = "startup|resume|clear|compact";
60093
61699
  var HOOK_EVENT_TO_CLAUDE_EVENT = {
@@ -60157,8 +61763,8 @@ function buildHookSection(agent, bin, flags = {}) {
60157
61763
 
60158
61764
  // src/commands/hooks/uninstall-handler.ts
60159
61765
  init_logger();
60160
- import { existsSync as existsSync44, mkdirSync as mkdirSync5, readFileSync as readFileSync13, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
60161
- import { dirname as dirname23 } from "node:path";
61766
+ import { existsSync as existsSync47, mkdirSync as mkdirSync5, readFileSync as readFileSync14, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
61767
+ import { dirname as dirname24 } from "node:path";
60162
61768
  var AGENT_DISPLAY2 = {
60163
61769
  claude: "Claude Code",
60164
61770
  codex: "Codex"
@@ -60193,12 +61799,12 @@ function pruneHooksSection(hooks, agent) {
60193
61799
  }
60194
61800
  return { pruned, removed };
60195
61801
  }
60196
- function writeAtomic(path8, contents) {
60197
- mkdirSync5(dirname23(path8), { recursive: true });
60198
- const tmp = `${path8}.tmp`;
61802
+ function writeAtomic(path10, contents) {
61803
+ mkdirSync5(dirname24(path10), { recursive: true });
61804
+ const tmp = `${path10}.tmp`;
60199
61805
  try {
60200
61806
  writeFileSync8(tmp, contents);
60201
- renameSync3(tmp, path8);
61807
+ renameSync3(tmp, path10);
60202
61808
  } catch (err) {
60203
61809
  rmSync4(tmp, { force: true });
60204
61810
  throw err;
@@ -60212,12 +61818,12 @@ async function uninstallForAgent(agent, options2) {
60212
61818
  removed: 0,
60213
61819
  dryRun: Boolean(options2.dryRun)
60214
61820
  };
60215
- if (!existsSync44(location2.realPath)) {
61821
+ if (!existsSync47(location2.realPath)) {
60216
61822
  return result;
60217
61823
  }
60218
61824
  let parsed;
60219
61825
  try {
60220
- parsed = JSON.parse(readFileSync13(location2.realPath, "utf8"));
61826
+ parsed = JSON.parse(readFileSync14(location2.realPath, "utf8"));
60221
61827
  } catch {
60222
61828
  logger.warning(`[hooks] could not parse ${location2.realPath}; uninstall skipped to avoid clobbering`);
60223
61829
  return result;
@@ -61684,8 +63290,8 @@ async function dispatchInstallers(ctx, targetAgents2, lifecycle) {
61684
63290
  init_logger();
61685
63291
  // src/domains/installation/download-extractor.ts
61686
63292
  init_auth_client();
61687
- import * as fs17 from "node:fs";
61688
- import * as path8 from "node:path";
63293
+ import * as fs20 from "node:fs";
63294
+ import * as path10 from "node:path";
61689
63295
 
61690
63296
  // src/domains/github/auth-prompt.ts
61691
63297
  init_dist2();
@@ -61766,7 +63372,7 @@ init_logger();
61766
63372
  init_safe_spinner();
61767
63373
  import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
61768
63374
  import { tmpdir as tmpdir3 } from "node:os";
61769
- import { join as join94 } from "node:path";
63375
+ import { join as join97 } from "node:path";
61770
63376
 
61771
63377
  // src/shared/temp-cleanup.ts
61772
63378
  init_logger();
@@ -61785,7 +63391,7 @@ init_logger();
61785
63391
  init_output_manager();
61786
63392
  import { createWriteStream as createWriteStream2, rmSync as rmSync5 } from "node:fs";
61787
63393
  import { mkdir as mkdir21 } from "node:fs/promises";
61788
- import { join as join89 } from "node:path";
63394
+ import { join as join92 } from "node:path";
61789
63395
 
61790
63396
  // src/shared/progress-bar.ts
61791
63397
  init_output_manager();
@@ -61950,10 +63556,10 @@ init_types2();
61950
63556
  // src/domains/installation/utils/path-security.ts
61951
63557
  init_types2();
61952
63558
  import { lstatSync as lstatSync4, realpathSync as realpathSync4 } from "node:fs";
61953
- import { relative as relative14, resolve as resolve17 } from "node:path";
63559
+ import { relative as relative14, resolve as resolve19 } from "node:path";
61954
63560
  var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
61955
63561
  function isPathSafe(basePath, targetPath) {
61956
- const resolvedBase = resolve17(basePath);
63562
+ const resolvedBase = resolve19(basePath);
61957
63563
  try {
61958
63564
  const stat8 = lstatSync4(targetPath);
61959
63565
  if (stat8.isSymbolicLink()) {
@@ -61963,7 +63569,7 @@ function isPathSafe(basePath, targetPath) {
61963
63569
  }
61964
63570
  }
61965
63571
  } catch {}
61966
- const resolvedTarget = resolve17(targetPath);
63572
+ const resolvedTarget = resolve19(targetPath);
61967
63573
  const relativePath = relative14(resolvedBase, resolvedTarget);
61968
63574
  return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
61969
63575
  }
@@ -61995,7 +63601,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
61995
63601
  class FileDownloader {
61996
63602
  async downloadAsset(asset, destDir) {
61997
63603
  try {
61998
- const destPath = join89(destDir, asset.name);
63604
+ const destPath = join92(destDir, asset.name);
61999
63605
  await mkdir21(destDir, { recursive: true });
62000
63606
  output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
62001
63607
  logger.verbose("Download details", {
@@ -62051,7 +63657,7 @@ class FileDownloader {
62051
63657
  }
62052
63658
  if (downloadedSize !== totalSize) {
62053
63659
  fileStream.end();
62054
- await new Promise((resolve18) => fileStream.once("close", resolve18));
63660
+ await new Promise((resolve20) => fileStream.once("close", resolve20));
62055
63661
  try {
62056
63662
  rmSync5(destPath, { force: true });
62057
63663
  } catch (cleanupError) {
@@ -62065,7 +63671,7 @@ class FileDownloader {
62065
63671
  return destPath;
62066
63672
  } catch (error) {
62067
63673
  fileStream.end();
62068
- await new Promise((resolve18) => fileStream.once("close", resolve18));
63674
+ await new Promise((resolve20) => fileStream.once("close", resolve20));
62069
63675
  try {
62070
63676
  rmSync5(destPath, { force: true });
62071
63677
  } catch (cleanupError) {
@@ -62080,7 +63686,7 @@ class FileDownloader {
62080
63686
  }
62081
63687
  async downloadFile(params) {
62082
63688
  const { url, name, size, destDir, token } = params;
62083
- const destPath = join89(destDir, name);
63689
+ const destPath = join92(destDir, name);
62084
63690
  await mkdir21(destDir, { recursive: true });
62085
63691
  output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
62086
63692
  const headers = {};
@@ -62148,7 +63754,7 @@ class FileDownloader {
62148
63754
  const expectedSize = Number(response.headers.get("content-length"));
62149
63755
  if (expectedSize > 0 && downloadedSize !== expectedSize) {
62150
63756
  fileStream.end();
62151
- await new Promise((resolve18) => fileStream.once("close", resolve18));
63757
+ await new Promise((resolve20) => fileStream.once("close", resolve20));
62152
63758
  try {
62153
63759
  rmSync5(destPath, { force: true });
62154
63760
  } catch (cleanupError) {
@@ -62166,7 +63772,7 @@ class FileDownloader {
62166
63772
  return destPath;
62167
63773
  } catch (error) {
62168
63774
  fileStream.end();
62169
- await new Promise((resolve18) => fileStream.once("close", resolve18));
63775
+ await new Promise((resolve20) => fileStream.once("close", resolve20));
62170
63776
  try {
62171
63777
  rmSync5(destPath, { force: true });
62172
63778
  } catch (cleanupError) {
@@ -62183,7 +63789,7 @@ init_logger();
62183
63789
  init_types2();
62184
63790
  import { constants as constants3 } from "node:fs";
62185
63791
  import { access as access3, readdir as readdir25 } from "node:fs/promises";
62186
- import { join as join90 } from "node:path";
63792
+ import { join as join93 } from "node:path";
62187
63793
  async function validateExtraction(extractDir) {
62188
63794
  try {
62189
63795
  const entries = await readdir25(extractDir, { encoding: "utf8" });
@@ -62193,13 +63799,13 @@ async function validateExtraction(extractDir) {
62193
63799
  }
62194
63800
  const criticalPaths = [".claude", "CLAUDE.md"];
62195
63801
  const missingPaths = [];
62196
- for (const path8 of criticalPaths) {
63802
+ for (const path10 of criticalPaths) {
62197
63803
  try {
62198
- await access3(join90(extractDir, path8), constants3.F_OK);
62199
- logger.debug(`Found: ${path8}`);
63804
+ await access3(join93(extractDir, path10), constants3.F_OK);
63805
+ logger.debug(`Found: ${path10}`);
62200
63806
  } catch {
62201
- logger.warning(`Expected path not found: ${path8}`);
62202
- missingPaths.push(path8);
63807
+ logger.warning(`Expected path not found: ${path10}`);
63808
+ missingPaths.push(path10);
62203
63809
  }
62204
63810
  }
62205
63811
  if (missingPaths.length > 0) {
@@ -62217,7 +63823,7 @@ async function validateExtraction(extractDir) {
62217
63823
  // src/domains/installation/extraction/tar-extractor.ts
62218
63824
  init_logger();
62219
63825
  import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat8 } from "node:fs/promises";
62220
- import { join as join92 } from "node:path";
63826
+ import { join as join95 } from "node:path";
62221
63827
 
62222
63828
  // node_modules/tar/dist/esm/index.min.js
62223
63829
  import Kr from "events";
@@ -64249,7 +65855,7 @@ var ls = Symbol("readdir");
64249
65855
  var ai = Symbol("onreaddir");
64250
65856
  var li = Symbol("pipe");
64251
65857
  var ir = Symbol("entry");
64252
- var os5 = Symbol("entryOpt");
65858
+ var os7 = Symbol("entryOpt");
64253
65859
  var ci = Symbol("writeEntryClass");
64254
65860
  var rr = Symbol("write");
64255
65861
  var hs = Symbol("ondrain");
@@ -64312,7 +65918,7 @@ var Et = class extends D {
64312
65918
  t.resume();
64313
65919
  else {
64314
65920
  let i = new di(t.path, e2);
64315
- i.entry = new ri(t, this[os5](i)), i.entry.on("end", () => this[ns](i)), this[G2] += 1, this[W2].push(i);
65921
+ i.entry = new ri(t, this[os7](i)), i.entry.on("end", () => this[ns](i)), this[G2] += 1, this[W2].push(i);
64316
65922
  }
64317
65923
  this[Ft]();
64318
65924
  }
@@ -64381,13 +65987,13 @@ var Et = class extends D {
64381
65987
  }
64382
65988
  }
64383
65989
  }
64384
- [os5](t) {
65990
+ [os7](t) {
64385
65991
  return { onwarn: (e2, i, r2) => this.warn(e2, i, r2), noPax: this.noPax, cwd: this.cwd, absolute: t.absolute, preservePaths: this.preservePaths, maxReadSize: this.maxReadSize, strict: this.strict, portable: this.portable, linkCache: this.linkCache, statCache: this.statCache, noMtime: this.noMtime, mtime: this.mtime, prefix: this.prefix, onWriteEntry: this.onWriteEntry };
64386
65992
  }
64387
65993
  [ir](t) {
64388
65994
  this[G2] += 1;
64389
65995
  try {
64390
- return new this[ci](t.path, this[os5](t)).on("end", () => this[ns](t)).on("error", (i) => this.emit("error", i));
65996
+ return new this[ci](t.path, this[os7](t)).on("end", () => this[ns](t)).on("error", (i) => this.emit("error", i));
64391
65997
  } catch (e2) {
64392
65998
  this.emit("error", e2);
64393
65999
  }
@@ -64489,7 +66095,7 @@ var Vn = 512 * 1024;
64489
66095
  var $n = pr | ur | dr | mr;
64490
66096
  var lr = !fr && typeof ar == "number" ? ar | ur | dr | mr : null;
64491
66097
  var cs = lr !== null ? () => lr : Kn ? (s3) => s3 < Vn ? $n : "w" : () => "w";
64492
- var fs16 = (s3, t, e2) => {
66098
+ var fs19 = (s3, t, e2) => {
64493
66099
  try {
64494
66100
  return mi.lchownSync(s3, t, e2);
64495
66101
  } catch (i) {
@@ -64538,7 +66144,7 @@ var ds = (s3, t, e2, i) => {
64538
66144
  });
64539
66145
  };
64540
66146
  var qn = (s3, t, e2, i) => {
64541
- t.isDirectory() && us(Ee.resolve(s3, t.name), e2, i), fs16(Ee.resolve(s3, t.name), e2, i);
66147
+ t.isDirectory() && us(Ee.resolve(s3, t.name), e2, i), fs19(Ee.resolve(s3, t.name), e2, i);
64542
66148
  };
64543
66149
  var us = (s3, t, e2) => {
64544
66150
  let i;
@@ -64549,12 +66155,12 @@ var us = (s3, t, e2) => {
64549
66155
  if (n?.code === "ENOENT")
64550
66156
  return;
64551
66157
  if (n?.code === "ENOTDIR" || n?.code === "ENOTSUP")
64552
- return fs16(s3, t, e2);
66158
+ return fs19(s3, t, e2);
64553
66159
  throw n;
64554
66160
  }
64555
66161
  for (let r2 of i)
64556
66162
  qn(s3, r2, t, e2);
64557
- return fs16(s3, t, e2);
66163
+ return fs19(s3, t, e2);
64558
66164
  };
64559
66165
  var we = class extends Error {
64560
66166
  path;
@@ -65409,20 +67015,20 @@ function normalizeZipEntryName(entryName) {
65409
67015
  }
65410
67016
  return String(entryName);
65411
67017
  }
65412
- function decodeFilePath(path8) {
65413
- if (!path8.includes("%")) {
65414
- return path8;
67018
+ function decodeFilePath(path10) {
67019
+ if (!path10.includes("%")) {
67020
+ return path10;
65415
67021
  }
65416
67022
  try {
65417
- if (/%[0-9A-F]{2}/i.test(path8)) {
65418
- const decoded = decodeURIComponent(path8);
65419
- logger.debug(`Decoded path: ${path8} -> ${decoded}`);
67023
+ if (/%[0-9A-F]{2}/i.test(path10)) {
67024
+ const decoded = decodeURIComponent(path10);
67025
+ logger.debug(`Decoded path: ${path10} -> ${decoded}`);
65420
67026
  return decoded;
65421
67027
  }
65422
- return path8;
67028
+ return path10;
65423
67029
  } catch (error) {
65424
- logger.warning(`Failed to decode path "${path8}": ${error instanceof Error ? error.message : "Unknown error"}`);
65425
- return path8;
67030
+ logger.warning(`Failed to decode path "${path10}": ${error instanceof Error ? error.message : "Unknown error"}`);
67031
+ return path10;
65426
67032
  }
65427
67033
  }
65428
67034
 
@@ -65430,7 +67036,7 @@ function decodeFilePath(path8) {
65430
67036
  init_logger();
65431
67037
  init_types2();
65432
67038
  import { copyFile as copyFile4, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
65433
- import { join as join91, relative as relative15 } from "node:path";
67039
+ import { join as join94, relative as relative15 } from "node:path";
65434
67040
  async function withRetry2(fn2, retries = 3) {
65435
67041
  for (let i = 0;i < retries; i++) {
65436
67042
  try {
@@ -65452,8 +67058,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
65452
67058
  await mkdir22(destDir, { recursive: true });
65453
67059
  const entries = await readdir26(sourceDir, { encoding: "utf8" });
65454
67060
  for (const entry of entries) {
65455
- const sourcePath = join91(sourceDir, entry);
65456
- const destPath = join91(destDir, entry);
67061
+ const sourcePath = join94(sourceDir, entry);
67062
+ const destPath = join94(destDir, entry);
65457
67063
  const relativePath = relative15(sourceDir, sourcePath);
65458
67064
  if (!isPathSafe(destDir, destPath)) {
65459
67065
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -65480,8 +67086,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
65480
67086
  await mkdir22(destDir, { recursive: true });
65481
67087
  const entries = await readdir26(sourceDir, { encoding: "utf8" });
65482
67088
  for (const entry of entries) {
65483
- const sourcePath = join91(sourceDir, entry);
65484
- const destPath = join91(destDir, entry);
67089
+ const sourcePath = join94(sourceDir, entry);
67090
+ const destPath = join94(destDir, entry);
65485
67091
  const relativePath = relative15(sourceDir, sourcePath);
65486
67092
  if (!isPathSafe(destDir, destPath)) {
65487
67093
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -65518,12 +67124,12 @@ class TarExtractor {
65518
67124
  onwarn: (code, message) => {
65519
67125
  logger.debug(`tar warning [${code}]: ${message}`);
65520
67126
  },
65521
- filter: (path8, entry) => {
67127
+ filter: (path10, entry) => {
65522
67128
  if ("type" in entry && (entry.type === "SymbolicLink" || entry.type === "Link")) {
65523
- logger.debug(`Skipping symlink: ${path8}`);
67129
+ logger.debug(`Skipping symlink: ${path10}`);
65524
67130
  return false;
65525
67131
  }
65526
- const decodedPath = decodeFilePath(path8);
67132
+ const decodedPath = decodeFilePath(path10);
65527
67133
  const shouldInclude = !shouldExclude(decodedPath);
65528
67134
  if (!shouldInclude) {
65529
67135
  logger.debug(`Excluding: ${decodedPath}`);
@@ -65536,7 +67142,7 @@ class TarExtractor {
65536
67142
  logger.debug(`Root entries: ${entries.join(", ")}`);
65537
67143
  if (entries.length === 1) {
65538
67144
  const rootEntry = entries[0];
65539
- const rootPath = join92(tempExtractDir, rootEntry);
67145
+ const rootPath = join95(tempExtractDir, rootEntry);
65540
67146
  const rootStat = await stat8(rootPath);
65541
67147
  if (rootStat.isDirectory()) {
65542
67148
  const rootContents = await readdir27(rootPath, { encoding: "utf8" });
@@ -65552,7 +67158,7 @@ class TarExtractor {
65552
67158
  }
65553
67159
  } else {
65554
67160
  await mkdir23(destDir, { recursive: true });
65555
- await copyFile5(rootPath, join92(destDir, rootEntry));
67161
+ await copyFile5(rootPath, join95(destDir, rootEntry));
65556
67162
  }
65557
67163
  } else {
65558
67164
  logger.debug("Multiple root entries - moving all");
@@ -65573,7 +67179,7 @@ class TarExtractor {
65573
67179
  init_logger();
65574
67180
  import { createWriteStream as createWriteStream3 } from "node:fs";
65575
67181
  import { chmod as chmod3, copyFile as copyFile6, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as stat9 } from "node:fs/promises";
65576
- import { dirname as dirname24, join as join93, resolve as resolve18 } from "node:path";
67182
+ import { dirname as dirname25, join as join96, resolve as resolve20 } from "node:path";
65577
67183
  import { pipeline } from "node:stream/promises";
65578
67184
  import yauzl from "yauzl-promise";
65579
67185
  class ZipExtractor {
@@ -65587,7 +67193,7 @@ class ZipExtractor {
65587
67193
  logger.debug(`Root entries: ${entries.join(", ")}`);
65588
67194
  if (entries.length === 1) {
65589
67195
  const rootEntry = entries[0];
65590
- const rootPath = join93(tempExtractDir, rootEntry);
67196
+ const rootPath = join96(tempExtractDir, rootEntry);
65591
67197
  const rootStat = await stat9(rootPath);
65592
67198
  if (rootStat.isDirectory()) {
65593
67199
  const rootContents = await readdir28(rootPath, { encoding: "utf8" });
@@ -65603,7 +67209,7 @@ class ZipExtractor {
65603
67209
  }
65604
67210
  } else {
65605
67211
  await mkdir24(destDir, { recursive: true });
65606
- await copyFile6(rootPath, join93(destDir, rootEntry));
67212
+ await copyFile6(rootPath, join96(destDir, rootEntry));
65607
67213
  }
65608
67214
  } else {
65609
67215
  logger.debug("Multiple root entries - moving all");
@@ -65620,13 +67226,13 @@ class ZipExtractor {
65620
67226
  }
65621
67227
  async extractToDir(archivePath, destDir) {
65622
67228
  const zip = await yauzl.open(archivePath, { decodeStrings: false });
65623
- const destRoot = resolve18(destDir);
67229
+ const destRoot = resolve20(destDir);
65624
67230
  let count = 0;
65625
67231
  try {
65626
67232
  for await (const entry of zip) {
65627
67233
  const rawName = entry.filename;
65628
67234
  const name = normalizeZipEntryName(rawName);
65629
- const outPath = resolve18(destRoot, name);
67235
+ const outPath = resolve20(destRoot, name);
65630
67236
  if (!isPathSafe(destRoot, outPath)) {
65631
67237
  throw new Error(`Unsafe zip entry path (zip-slip): ${name}`);
65632
67238
  }
@@ -65634,7 +67240,7 @@ class ZipExtractor {
65634
67240
  await mkdir24(outPath, { recursive: true });
65635
67241
  continue;
65636
67242
  }
65637
- await mkdir24(dirname24(outPath), { recursive: true });
67243
+ await mkdir24(dirname25(outPath), { recursive: true });
65638
67244
  const readStream = await entry.openReadStream();
65639
67245
  await pipeline(readStream, createWriteStream3(outPath));
65640
67246
  const unixMode = entry.externalFileAttributes >>> 16 & 511;
@@ -65732,7 +67338,7 @@ class DownloadManager {
65732
67338
  async createTempDir() {
65733
67339
  const timestamp = Date.now();
65734
67340
  const counter = DownloadManager.tempDirCounter++;
65735
- const primaryTempDir = join94(tmpdir3(), `takumi-${timestamp}-${counter}`);
67341
+ const primaryTempDir = join97(tmpdir3(), `takumi-${timestamp}-${counter}`);
65736
67342
  try {
65737
67343
  await mkdir25(primaryTempDir, { recursive: true });
65738
67344
  logger.debug(`Created temp directory: ${primaryTempDir}`);
@@ -65749,7 +67355,7 @@ Solutions:
65749
67355
  2. Set HOME environment variable
65750
67356
  3. Try running from a different directory`);
65751
67357
  }
65752
- const fallbackTempDir = join94(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
67358
+ const fallbackTempDir = join97(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
65753
67359
  try {
65754
67360
  await mkdir25(fallbackTempDir, { recursive: true });
65755
67361
  logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
@@ -65792,9 +67398,9 @@ function buildReleaseAllowlist(layout) {
65792
67398
  return [...new Set([layout.sourceDir, ...RELEASE_ROOT_ALLOWLIST])];
65793
67399
  }
65794
67400
  async function ensureLayoutSourceDir(projectRoot, layout, strict) {
65795
- const sourceDir = path8.join(projectRoot, layout.sourceDir);
67401
+ const sourceDir = path10.join(projectRoot, layout.sourceDir);
65796
67402
  try {
65797
- const stat11 = await fs17.promises.stat(sourceDir);
67403
+ const stat11 = await fs20.promises.stat(sourceDir);
65798
67404
  if (!stat11.isDirectory()) {
65799
67405
  throw new Error(`Expected source directory "${layout.sourceDir}" exists but is not a directory.`);
65800
67406
  }
@@ -65817,10 +67423,10 @@ async function materializeRuntimeLayoutInPlace(projectRoot, layout) {
65817
67423
  if (layout.sourceDir === layout.runtimeDir) {
65818
67424
  return;
65819
67425
  }
65820
- const sourceDir = path8.join(projectRoot, layout.sourceDir);
65821
- const runtimeDir = path8.join(projectRoot, layout.runtimeDir);
65822
- await fs17.promises.rm(runtimeDir, { recursive: true, force: true });
65823
- await fs17.promises.rename(sourceDir, runtimeDir);
67426
+ const sourceDir = path10.join(projectRoot, layout.sourceDir);
67427
+ const runtimeDir = path10.join(projectRoot, layout.runtimeDir);
67428
+ await fs20.promises.rm(runtimeDir, { recursive: true, force: true });
67429
+ await fs20.promises.rename(sourceDir, runtimeDir);
65824
67430
  }
65825
67431
  async function stageLocalKitPathForRuntimeLayout(kitRoot, layout) {
65826
67432
  const sourceDir = await ensureLayoutSourceDir(kitRoot, layout, false);
@@ -65830,20 +67436,20 @@ async function stageLocalKitPathForRuntimeLayout(kitRoot, layout) {
65830
67436
  const downloadManager = new DownloadManager;
65831
67437
  const tempDir = await downloadManager.createTempDir();
65832
67438
  const extractDir = `${tempDir}/extracted`;
65833
- await fs17.promises.mkdir(extractDir, { recursive: true });
65834
- const entries = await fs17.promises.readdir(kitRoot);
67439
+ await fs20.promises.mkdir(extractDir, { recursive: true });
67440
+ const entries = await fs20.promises.readdir(kitRoot);
65835
67441
  const allowlist = buildReleaseAllowlist(layout);
65836
67442
  for (const entry of entries) {
65837
67443
  if (!allowlist.includes(entry) || entry === layout.sourceDir) {
65838
67444
  continue;
65839
67445
  }
65840
- await fs17.promises.cp(path8.join(kitRoot, entry), path8.join(extractDir, entry), {
67446
+ await fs20.promises.cp(path10.join(kitRoot, entry), path10.join(extractDir, entry), {
65841
67447
  recursive: true
65842
67448
  });
65843
67449
  }
65844
- const runtimeDir = path8.join(extractDir, layout.runtimeDir);
65845
- await fs17.promises.mkdir(path8.dirname(runtimeDir), { recursive: true });
65846
- await fs17.promises.cp(sourceDir, runtimeDir, { recursive: true });
67450
+ const runtimeDir = path10.join(extractDir, layout.runtimeDir);
67451
+ await fs20.promises.mkdir(path10.dirname(runtimeDir), { recursive: true });
67452
+ await fs20.promises.cp(sourceDir, runtimeDir, { recursive: true });
65847
67453
  logger.verbose("Staged local kit path with runtime layout", {
65848
67454
  kitRoot,
65849
67455
  extractDir,
@@ -65870,14 +67476,14 @@ var MONOREPO_KIT_CONTENT = [
65870
67476
  ];
65871
67477
  function resolveRepoRootForKit(kitRoot) {
65872
67478
  try {
65873
- const parent = path8.dirname(kitRoot);
65874
- const parentPackageJson = path8.join(parent, "package.json");
65875
- if (!fs17.existsSync(parentPackageJson))
67479
+ const parent = path10.dirname(kitRoot);
67480
+ const parentPackageJson = path10.join(parent, "package.json");
67481
+ if (!fs20.existsSync(parentPackageJson))
65876
67482
  return kitRoot;
65877
- const pkg = JSON.parse(fs17.readFileSync(parentPackageJson, "utf-8"));
67483
+ const pkg = JSON.parse(fs20.readFileSync(parentPackageJson, "utf-8"));
65878
67484
  const kitCfg = pkg.takumi;
65879
67485
  const sourceDir = kitCfg?.sourceDir;
65880
- if (typeof sourceDir === "string" && path8.resolve(parent, sourceDir) === path8.resolve(kitRoot)) {
67486
+ if (typeof sourceDir === "string" && path10.resolve(parent, sourceDir) === path10.resolve(kitRoot)) {
65881
67487
  return parent;
65882
67488
  }
65883
67489
  } catch {}
@@ -65887,25 +67493,25 @@ async function stageMonorepoForInstallation(kitRoot) {
65887
67493
  const downloadManager = new DownloadManager;
65888
67494
  const tempDir = await downloadManager.createTempDir();
65889
67495
  const extractDir = `${tempDir}/extracted`;
65890
- const claudeDir = path8.join(extractDir, ".claude");
65891
- await fs17.promises.mkdir(claudeDir, { recursive: true });
67496
+ const claudeDir = path10.join(extractDir, ".claude");
67497
+ await fs20.promises.mkdir(claudeDir, { recursive: true });
65892
67498
  const repoRoot = resolveRepoRootForKit(kitRoot);
65893
- const kitEntries = await fs17.promises.readdir(kitRoot);
67499
+ const kitEntries = await fs20.promises.readdir(kitRoot);
65894
67500
  const skipLegacyManifest = kitEntries.includes(MANIFEST_FILENAME) && kitEntries.includes(LEGACY_MANIFEST_FILENAME);
65895
67501
  for (const entry of kitEntries) {
65896
67502
  if (!MONOREPO_KIT_CONTENT.includes(entry))
65897
67503
  continue;
65898
67504
  if (skipLegacyManifest && entry === LEGACY_MANIFEST_FILENAME)
65899
67505
  continue;
65900
- const srcPath = path8.join(kitRoot, entry);
65901
- await fs17.promises.cp(srcPath, path8.join(claudeDir, entry), { recursive: true });
67506
+ const srcPath = path10.join(kitRoot, entry);
67507
+ await fs20.promises.cp(srcPath, path10.join(claudeDir, entry), { recursive: true });
65902
67508
  }
65903
- const repoEntries = repoRoot === kitRoot ? kitEntries : await fs17.promises.readdir(repoRoot);
67509
+ const repoEntries = repoRoot === kitRoot ? kitEntries : await fs20.promises.readdir(repoRoot);
65904
67510
  for (const entry of repoEntries) {
65905
67511
  if (!RELEASE_ROOT_ALLOWLIST.includes(entry))
65906
67512
  continue;
65907
- const srcPath = path8.join(repoRoot, entry);
65908
- await fs17.promises.cp(srcPath, path8.join(extractDir, entry), { recursive: true });
67513
+ const srcPath = path10.join(repoRoot, entry);
67514
+ await fs20.promises.cp(srcPath, path10.join(extractDir, entry), { recursive: true });
65909
67515
  }
65910
67516
  logger.verbose("Staged monorepo for installation", {
65911
67517
  kitRoot,
@@ -65919,13 +67525,13 @@ async function stageMonorepoForInstallation(kitRoot) {
65919
67525
  async function normalizeFullRepoExtract(dir, strict) {
65920
67526
  const layout = resolveKitLayout(dir);
65921
67527
  await ensureLayoutSourceDir(dir, layout, strict);
65922
- const entries = await fs17.promises.readdir(dir);
67528
+ const entries = await fs20.promises.readdir(dir);
65923
67529
  const releaseAllowlist = buildReleaseAllowlist(layout);
65924
67530
  let removedCount = 0;
65925
67531
  for (const entry of entries) {
65926
67532
  if (!releaseAllowlist.includes(entry)) {
65927
- const fullPath = path8.join(dir, entry);
65928
- await fs17.promises.rm(fullPath, { recursive: true, force: true });
67533
+ const fullPath = path10.join(dir, entry);
67534
+ await fs20.promises.rm(fullPath, { recursive: true, force: true });
65929
67535
  removedCount++;
65930
67536
  }
65931
67537
  }
@@ -66038,9 +67644,9 @@ Or try: tkm init --use-git`);
66038
67644
  async function useLocalKitPath(kitPath, isMonorepo) {
66039
67645
  logger.verbose("Using local kit path", { kitPath });
66040
67646
  output.section("Using local kit");
66041
- const absolutePath = path8.resolve(kitPath);
67647
+ const absolutePath = path10.resolve(kitPath);
66042
67648
  try {
66043
- const stat11 = await fs17.promises.stat(absolutePath);
67649
+ const stat11 = await fs20.promises.stat(absolutePath);
66044
67650
  if (!stat11.isDirectory()) {
66045
67651
  throw new Error(`--kit-path must point to a directory, not a file.
66046
67652
 
@@ -66077,9 +67683,9 @@ Please verify the path exists and is accessible.`);
66077
67683
  };
66078
67684
  }
66079
67685
  }
66080
- const claudeDir = path8.join(absolutePath, DEFAULT_KIT_LAYOUT.runtimeDir);
67686
+ const claudeDir = path10.join(absolutePath, DEFAULT_KIT_LAYOUT.runtimeDir);
66081
67687
  try {
66082
- const stat11 = await fs17.promises.stat(claudeDir);
67688
+ const stat11 = await fs20.promises.stat(claudeDir);
66083
67689
  if (!stat11.isDirectory()) {
66084
67690
  logger.warning(`Warning: ${claudeDir} exists but is not a directory.
66085
67691
  This may not be a valid Takumi installation.`);
@@ -66102,7 +67708,7 @@ function validateArchiveFormat(archivePath) {
66102
67708
  const lowerPath = archivePath.toLowerCase();
66103
67709
  const isValid2 = VALID_ARCHIVE_FORMATS.some((ext2) => lowerPath.endsWith(ext2));
66104
67710
  if (!isValid2) {
66105
- const ext2 = path8.extname(archivePath) || "(no extension)";
67711
+ const ext2 = path10.extname(archivePath) || "(no extension)";
66106
67712
  throw new Error(`Unsupported archive format: ${ext2}
66107
67713
 
66108
67714
  ` + `Supported formats: ${VALID_ARCHIVE_FORMATS.join(", ")}`);
@@ -66111,10 +67717,10 @@ function validateArchiveFormat(archivePath) {
66111
67717
  async function extractLocalArchive(archivePath, exclude) {
66112
67718
  logger.verbose("Using local archive", { archivePath });
66113
67719
  output.section("Extracting local archive");
66114
- const absolutePath = path8.resolve(archivePath);
67720
+ const absolutePath = path10.resolve(archivePath);
66115
67721
  validateArchiveFormat(absolutePath);
66116
67722
  try {
66117
- const stat11 = await fs17.promises.stat(absolutePath);
67723
+ const stat11 = await fs20.promises.stat(absolutePath);
66118
67724
  if (!stat11.isFile()) {
66119
67725
  throw new Error(`--archive must point to a file, not a directory.
66120
67726
 
@@ -66245,9 +67851,9 @@ async function downloadViaWorker(release, kit, isNonInteractive2) {
66245
67851
  const res = await source.fetchAsset(release.tag_name, assetName);
66246
67852
  const downloadManager = new DownloadManager;
66247
67853
  const tempDir = await downloadManager.createTempDir();
66248
- const archivePath = path8.join(tempDir, assetName);
67854
+ const archivePath = path10.join(tempDir, assetName);
66249
67855
  const buf = Buffer.from(await res.arrayBuffer());
66250
- await fs17.promises.writeFile(archivePath, buf);
67856
+ await fs20.promises.writeFile(archivePath, buf);
66251
67857
  const extractDir = `${tempDir}/extracted`;
66252
67858
  logger.verbose("Extraction", { archivePath, extractDir });
66253
67859
  await downloadManager.extractArchive(archivePath, extractDir);
@@ -66455,7 +68061,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
66455
68061
  }
66456
68062
  // src/commands/init/phases/selection-handler.ts
66457
68063
  import { mkdir as mkdir26 } from "node:fs/promises";
66458
- import { join as join98, resolve as resolve22 } from "node:path";
68064
+ import { join as join101, resolve as resolve24 } from "node:path";
66459
68065
 
66460
68066
  // src/commands/shared/agent-selector.ts
66461
68067
  init_registry();
@@ -66608,8 +68214,8 @@ init_logger();
66608
68214
  init_safe_spinner();
66609
68215
  init_takumi_constants();
66610
68216
  var import_fs_extra31 = __toESM(require_lib(), 1);
66611
- import { existsSync as existsSync47, readdirSync as readdirSync4, rmSync as rmSync6, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
66612
- import { dirname as dirname27, join as join97, resolve as resolve21 } from "node:path";
68217
+ import { existsSync as existsSync50, readdirSync as readdirSync6, rmSync as rmSync6, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
68218
+ import { dirname as dirname28, join as join100, resolve as resolve23 } from "node:path";
66613
68219
  var TAKUMI_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
66614
68220
  async function analyzeFreshInstallation(claudeDir) {
66615
68221
  const metadata = await readManifest(claudeDir);
@@ -66654,15 +68260,15 @@ async function analyzeFreshInstallation(claudeDir) {
66654
68260
  };
66655
68261
  }
66656
68262
  function cleanupEmptyDirectories2(filePath, claudeDir) {
66657
- const normalizedClaudeDir = resolve21(claudeDir);
66658
- let currentDir = resolve21(dirname27(filePath));
68263
+ const normalizedClaudeDir = resolve23(claudeDir);
68264
+ let currentDir = resolve23(dirname28(filePath));
66659
68265
  while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
66660
68266
  try {
66661
- const entries = readdirSync4(currentDir);
68267
+ const entries = readdirSync6(currentDir);
66662
68268
  if (entries.length === 0) {
66663
68269
  rmdirSync2(currentDir);
66664
68270
  logger.debug(`Removed empty directory: ${currentDir}`);
66665
- currentDir = resolve21(dirname27(currentDir));
68271
+ currentDir = resolve23(dirname28(currentDir));
66666
68272
  } else {
66667
68273
  break;
66668
68274
  }
@@ -66679,9 +68285,9 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
66679
68285
  const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
66680
68286
  const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
66681
68287
  for (const file of filesToRemove) {
66682
- const fullPath = join97(claudeDir, file.path);
68288
+ const fullPath = join100(claudeDir, file.path);
66683
68289
  try {
66684
- if (existsSync47(fullPath)) {
68290
+ if (existsSync50(fullPath)) {
66685
68291
  unlinkSync5(fullPath);
66686
68292
  removedFiles.push(file.path);
66687
68293
  logger.debug(`Removed: ${file.path}`);
@@ -66753,7 +68359,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
66753
68359
  const removedFiles = [];
66754
68360
  let removedDirCount = 0;
66755
68361
  for (const subdir of TAKUMI_SUBDIRECTORIES) {
66756
- const subdirPath = join97(claudeDir, subdir);
68362
+ const subdirPath = join100(claudeDir, subdir);
66757
68363
  if (await import_fs_extra31.pathExists(subdirPath)) {
66758
68364
  rmSync6(subdirPath, { recursive: true, force: true });
66759
68365
  removedDirCount++;
@@ -66950,7 +68556,7 @@ async function handleSelection(ctx) {
66950
68556
  }
66951
68557
  }
66952
68558
  }
66953
- const resolvedDir = resolve22(targetDir);
68559
+ const resolvedDir = resolve24(targetDir);
66954
68560
  logger.info(`Target directory: ${resolvedDir}`);
66955
68561
  if (!ctx.options.global && isLocalSameAsGlobal(resolvedDir)) {
66956
68562
  logger.warning("You're at HOME directory. Installing here modifies your GLOBAL Takumi.");
@@ -66978,7 +68584,7 @@ async function handleSelection(ctx) {
66978
68584
  }
66979
68585
  if (!ctx.options.fresh) {
66980
68586
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
66981
- const claudeDir = prefix ? join98(resolvedDir, prefix) : resolvedDir;
68587
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
66982
68588
  try {
66983
68589
  const existingMetadata = await readManifest(claudeDir);
66984
68590
  if (existingMetadata?.kits) {
@@ -67011,7 +68617,7 @@ async function handleSelection(ctx) {
67011
68617
  }
67012
68618
  if (ctx.options.fresh) {
67013
68619
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
67014
- const claudeDir = prefix ? join98(resolvedDir, prefix) : resolvedDir;
68620
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
67015
68621
  const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
67016
68622
  if (!canProceed) {
67017
68623
  return { ...ctx, cancelled: true };
@@ -67031,7 +68637,7 @@ async function handleSelection(ctx) {
67031
68637
  let currentVersion = null;
67032
68638
  try {
67033
68639
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
67034
- const claudeDir = prefix ? join98(resolvedDir, prefix) : resolvedDir;
68640
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
67035
68641
  const existingMetadata = await readManifest(claudeDir);
67036
68642
  currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
67037
68643
  if (currentVersion) {
@@ -67119,7 +68725,7 @@ async function handleSelection(ctx) {
67119
68725
  if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
67120
68726
  try {
67121
68727
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
67122
- const claudeDir = prefix ? join98(resolvedDir, prefix) : resolvedDir;
68728
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
67123
68729
  const existingMetadata = await readManifest(claudeDir);
67124
68730
  const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
67125
68731
  if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
@@ -67142,7 +68748,7 @@ async function handleSelection(ctx) {
67142
68748
  let currentSecondaryVersion = null;
67143
68749
  try {
67144
68750
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
67145
- const claudeDir = prefix ? join98(resolvedDir, prefix) : resolvedDir;
68751
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
67146
68752
  const existingMetadata = await readManifest(claudeDir);
67147
68753
  currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
67148
68754
  } catch {}
@@ -67225,13 +68831,13 @@ function resolveGlobalTargetDir(targetAgents2) {
67225
68831
  }
67226
68832
  // src/commands/init/phases/sync-handler.ts
67227
68833
  init_paths();
67228
- import { copyFile as copyFile7, mkdir as mkdir28, open as open2, readFile as readFile39, rename as rename7, stat as stat12, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
67229
- import { dirname as dirname28, join as join101, resolve as resolve23 } from "node:path";
68834
+ import { copyFile as copyFile7, mkdir as mkdir28, open as open2, readFile as readFile40, rename as rename7, stat as stat12, unlink as unlink11, writeFile as writeFile28 } from "node:fs/promises";
68835
+ import { dirname as dirname29, join as join104, resolve as resolve25 } from "node:path";
67230
68836
 
67231
68837
  // src/domains/sync/config-version-checker.ts
67232
68838
  init_auth_client();
67233
- import { mkdir as mkdir27, readFile as readFile37, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
67234
- import { join as join99 } from "node:path";
68839
+ import { mkdir as mkdir27, readFile as readFile38, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
68840
+ import { join as join102 } from "node:path";
67235
68841
  init_version_utils();
67236
68842
  init_logger();
67237
68843
  init_path_resolver();
@@ -67267,12 +68873,12 @@ var CACHE_FILENAME = "config-update-cache.json";
67267
68873
  class ConfigVersionChecker {
67268
68874
  static getCacheFilePath(kitType, global3) {
67269
68875
  const cacheDir = PathResolver.getCacheDir(global3);
67270
- return join99(cacheDir, `${kitType}-${CACHE_FILENAME}`);
68876
+ return join102(cacheDir, `${kitType}-${CACHE_FILENAME}`);
67271
68877
  }
67272
68878
  static async loadCache(kitType, global3) {
67273
68879
  try {
67274
68880
  const cachePath = ConfigVersionChecker.getCacheFilePath(kitType, global3);
67275
- const data = await readFile37(cachePath, "utf8");
68881
+ const data = await readFile38(cachePath, "utf8");
67276
68882
  const parsed = JSON.parse(data);
67277
68883
  if (typeof parsed !== "object" || parsed === null || typeof parsed.lastCheck !== "number" || typeof parsed.latestVersion !== "string" || !parsed.latestVersion || parsed.lastCheck < 0 || parsed.lastCheck > Date.now() + 7 * 24 * 60 * 60 * 1000) {
67278
68884
  logger.debug("Invalid cache structure, ignoring");
@@ -67283,12 +68889,12 @@ class ConfigVersionChecker {
67283
68889
  return null;
67284
68890
  }
67285
68891
  }
67286
- static async saveCache(kitType, global3, cache) {
68892
+ static async saveCache(kitType, global3, cache2) {
67287
68893
  try {
67288
68894
  const cachePath = ConfigVersionChecker.getCacheFilePath(kitType, global3);
67289
68895
  const cacheDir = PathResolver.getCacheDir(global3);
67290
68896
  await mkdir27(cacheDir, { recursive: true });
67291
- await writeFile27(cachePath, JSON.stringify(cache, null, 2));
68897
+ await writeFile27(cachePath, JSON.stringify(cache2, null, 2));
67292
68898
  } catch (error) {
67293
68899
  logger.debug(`Cache write failed: ${error instanceof Error ? error.message : "Unknown error"}`);
67294
68900
  }
@@ -67323,21 +68929,21 @@ class ConfigVersionChecker {
67323
68929
  return null;
67324
68930
  }
67325
68931
  const delay3 = baseBackoff * 2 ** attempt2;
67326
- await new Promise((resolve23) => setTimeout(resolve23, delay3));
68932
+ await new Promise((resolve25) => setTimeout(resolve25, delay3));
67327
68933
  }
67328
68934
  }
67329
68935
  return null;
67330
68936
  }
67331
68937
  static async checkForUpdates(kitType, currentVersion, global3 = false) {
67332
68938
  const normalizedCurrent = currentVersion.replace(/^v/, "");
67333
- const cache = await ConfigVersionChecker.loadCache(kitType, global3);
68939
+ const cache2 = await ConfigVersionChecker.loadCache(kitType, global3);
67334
68940
  const now = Date.now();
67335
- if (cache && now - cache.lastCheck < CACHE_TTL_MS) {
67336
- const hasUpdates = isNewerVersion(normalizedCurrent, cache.latestVersion);
68941
+ if (cache2 && now - cache2.lastCheck < CACHE_TTL_MS) {
68942
+ const hasUpdates = isNewerVersion(normalizedCurrent, cache2.latestVersion);
67337
68943
  return {
67338
68944
  hasUpdates,
67339
68945
  currentVersion: normalizedCurrent,
67340
- latestVersion: cache.latestVersion,
68946
+ latestVersion: cache2.latestVersion,
67341
68947
  fromCache: true
67342
68948
  };
67343
68949
  }
@@ -67355,12 +68961,12 @@ class ConfigVersionChecker {
67355
68961
  fromCache: false
67356
68962
  };
67357
68963
  }
67358
- if (cache) {
67359
- const hasUpdates = isNewerVersion(normalizedCurrent, cache.latestVersion);
68964
+ if (cache2) {
68965
+ const hasUpdates = isNewerVersion(normalizedCurrent, cache2.latestVersion);
67360
68966
  return {
67361
68967
  hasUpdates,
67362
68968
  currentVersion: normalizedCurrent,
67363
- latestVersion: cache.latestVersion,
68969
+ latestVersion: cache2.latestVersion,
67364
68970
  fromCache: true
67365
68971
  };
67366
68972
  }
@@ -67386,12 +68992,12 @@ class ConfigVersionChecker {
67386
68992
  // src/domains/sync/sync-engine.ts
67387
68993
  init_ownership_checker();
67388
68994
  init_logger();
67389
- import { lstat as lstat7, readFile as readFile38, readlink, realpath as realpath3, stat as stat11 } from "node:fs/promises";
67390
- import { isAbsolute as isAbsolute3, join as join100, normalize as normalize8, relative as relative16 } from "node:path";
68995
+ import { lstat as lstat7, readFile as readFile39, readlink, realpath as realpath3, stat as stat11 } from "node:fs/promises";
68996
+ import { isAbsolute as isAbsolute3, join as join103, normalize as normalize8, relative as relative16 } from "node:path";
67391
68997
  var MAX_SYNC_FILE_SIZE = 10 * 1024 * 1024;
67392
68998
  var MAX_SYMLINK_DEPTH = 20;
67393
- async function validateSymlinkChain(path9, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
67394
- let current = path9;
68999
+ async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
69000
+ let current = path11;
67395
69001
  let depth = 0;
67396
69002
  while (depth < maxDepth) {
67397
69003
  try {
@@ -67399,11 +69005,11 @@ async function validateSymlinkChain(path9, basePath, maxDepth = MAX_SYMLINK_DEPT
67399
69005
  if (!stats.isSymbolicLink())
67400
69006
  break;
67401
69007
  const target = await readlink(current);
67402
- const resolvedTarget = isAbsolute3(target) ? target : join100(current, "..", target);
69008
+ const resolvedTarget = isAbsolute3(target) ? target : join103(current, "..", target);
67403
69009
  const normalizedTarget = normalize8(resolvedTarget);
67404
69010
  const rel = relative16(basePath, normalizedTarget);
67405
69011
  if (rel.startsWith("..") || isAbsolute3(rel)) {
67406
- throw new Error(`Symlink chain escapes base directory at depth ${depth}: ${path9}`);
69012
+ throw new Error(`Symlink chain escapes base directory at depth ${depth}: ${path11}`);
67407
69013
  }
67408
69014
  current = normalizedTarget;
67409
69015
  depth++;
@@ -67415,7 +69021,7 @@ async function validateSymlinkChain(path9, basePath, maxDepth = MAX_SYMLINK_DEPT
67415
69021
  }
67416
69022
  }
67417
69023
  if (depth >= maxDepth) {
67418
- throw new Error(`Symlink chain too deep (>${maxDepth}): ${path9}`);
69024
+ throw new Error(`Symlink chain too deep (>${maxDepth}): ${path11}`);
67419
69025
  }
67420
69026
  }
67421
69027
  async function validateSyncPath(basePath, filePath) {
@@ -67435,7 +69041,7 @@ async function validateSyncPath(basePath, filePath) {
67435
69041
  if (normalized.startsWith("..") || normalized.includes("/../")) {
67436
69042
  throw new Error(`Path traversal not allowed: ${filePath}`);
67437
69043
  }
67438
- const fullPath = join100(basePath, normalized);
69044
+ const fullPath = join103(basePath, normalized);
67439
69045
  const rel = relative16(basePath, fullPath);
67440
69046
  if (rel.startsWith("..") || isAbsolute3(rel)) {
67441
69047
  throw new Error(`Path escapes base directory: ${filePath}`);
@@ -67450,7 +69056,7 @@ async function validateSyncPath(basePath, filePath) {
67450
69056
  }
67451
69057
  } catch (error) {
67452
69058
  if (error.code === "ENOENT") {
67453
- const parentPath = join100(fullPath, "..");
69059
+ const parentPath = join103(fullPath, "..");
67454
69060
  try {
67455
69061
  const resolvedBase = await realpath3(basePath);
67456
69062
  const resolvedParent = await realpath3(parentPath);
@@ -67621,7 +69227,7 @@ class SyncEngine {
67621
69227
  if (lstats.size > MAX_SYNC_FILE_SIZE) {
67622
69228
  throw new Error(`File too large for sync (${Math.round(lstats.size / 1024 / 1024)}MB > ${MAX_SYNC_FILE_SIZE / 1024 / 1024}MB limit)`);
67623
69229
  }
67624
- const buffer = await readFile38(filePath);
69230
+ const buffer = await readFile39(filePath);
67625
69231
  if (buffer.includes(0)) {
67626
69232
  return { content: "", isBinary: true };
67627
69233
  }
@@ -67838,7 +69444,7 @@ async function handleSync(ctx) {
67838
69444
  logger.error(`Sync not yet supported for ${targetAgent}. Only --agent claude-code supports --sync.`);
67839
69445
  return { ...ctx, cancelled: true };
67840
69446
  }
67841
- const resolvedDir = ctx.options.global ? getClaudeDir() : resolve23(ctx.options.dir || ".");
69447
+ const resolvedDir = ctx.options.global ? getClaudeDir() : resolve25(ctx.options.dir || ".");
67842
69448
  const claudeDir = ctx.options.global ? resolvedDir : getLocalClaudeDir(resolvedDir);
67843
69449
  if (!await import_fs_extra33.pathExists(claudeDir)) {
67844
69450
  logger.error("Cannot sync: no .claude directory found");
@@ -67941,10 +69547,10 @@ function getLockTimeout() {
67941
69547
  var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
67942
69548
  async function acquireSyncLock(global3) {
67943
69549
  const cacheDir = PathResolver.getCacheDir(global3);
67944
- const lockPath = join101(cacheDir, ".sync-lock");
69550
+ const lockPath = join104(cacheDir, ".sync-lock");
67945
69551
  const startTime = Date.now();
67946
69552
  const lockTimeout = getLockTimeout();
67947
- await mkdir28(dirname28(lockPath), { recursive: true });
69553
+ await mkdir28(dirname29(lockPath), { recursive: true });
67948
69554
  while (Date.now() - startTime < lockTimeout) {
67949
69555
  try {
67950
69556
  const handle = await open2(lockPath, "wx");
@@ -67968,7 +69574,7 @@ async function acquireSyncLock(global3) {
67968
69574
  }
67969
69575
  logger.debug(`Lock stat failed: ${statError}`);
67970
69576
  }
67971
- await new Promise((resolve24) => setTimeout(resolve24, 100));
69577
+ await new Promise((resolve26) => setTimeout(resolve26, 100));
67972
69578
  continue;
67973
69579
  }
67974
69580
  throw err;
@@ -67992,7 +69598,7 @@ async function executeSyncMerge(ctx) {
67992
69598
  try {
67993
69599
  const sourceManifest = await findManifestPath(upstreamDir);
67994
69600
  if (sourceManifest) {
67995
- const content = await readFile39(sourceManifest.path, "utf-8");
69601
+ const content = await readFile40(sourceManifest.path, "utf-8");
67996
69602
  const sourceMetadata = JSON.parse(content);
67997
69603
  deletions = sourceMetadata.deletions || [];
67998
69604
  }
@@ -68022,7 +69628,7 @@ async function executeSyncMerge(ctx) {
68022
69628
  try {
68023
69629
  const sourcePath = await validateSyncPath(upstreamDir, file.path);
68024
69630
  const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
68025
- const targetDir = join101(targetPath, "..");
69631
+ const targetDir = join104(targetPath, "..");
68026
69632
  try {
68027
69633
  await mkdir28(targetDir, { recursive: true });
68028
69634
  } catch (mkdirError) {
@@ -68193,7 +69799,7 @@ async function createBackup(claudeDir, files, backupDir) {
68193
69799
  const sourcePath = await validateSyncPath(claudeDir, file.path);
68194
69800
  if (await import_fs_extra33.pathExists(sourcePath)) {
68195
69801
  const targetPath = await validateSyncPath(backupDir, file.path);
68196
- const targetDir = join101(targetPath, "..");
69802
+ const targetDir = join104(targetPath, "..");
68197
69803
  await mkdir28(targetDir, { recursive: true });
68198
69804
  await copyFile7(sourcePath, targetPath);
68199
69805
  }
@@ -68219,38 +69825,38 @@ init_logger();
68219
69825
  init_types2();
68220
69826
  var import_fs_extra34 = __toESM(require_lib(), 1);
68221
69827
  import { rename as rename8, rm as rm9 } from "node:fs/promises";
68222
- import { join as join102, relative as relative17 } from "node:path";
69828
+ import { join as join105, relative as relative17 } from "node:path";
68223
69829
  async function collectDirsToRename(extractDir, folders) {
68224
69830
  const dirsToRename = [];
68225
69831
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
68226
- const docsPath = join102(extractDir, DEFAULT_FOLDERS.docs);
69832
+ const docsPath = join105(extractDir, DEFAULT_FOLDERS.docs);
68227
69833
  if (await import_fs_extra34.pathExists(docsPath)) {
68228
69834
  dirsToRename.push({
68229
69835
  from: docsPath,
68230
- to: join102(extractDir, folders.docs)
69836
+ to: join105(extractDir, folders.docs)
68231
69837
  });
68232
69838
  }
68233
- const claudeDocsPath = join102(extractDir, ".claude", DEFAULT_FOLDERS.docs);
69839
+ const claudeDocsPath = join105(extractDir, ".claude", DEFAULT_FOLDERS.docs);
68234
69840
  if (await import_fs_extra34.pathExists(claudeDocsPath)) {
68235
69841
  dirsToRename.push({
68236
69842
  from: claudeDocsPath,
68237
- to: join102(extractDir, ".claude", folders.docs)
69843
+ to: join105(extractDir, ".claude", folders.docs)
68238
69844
  });
68239
69845
  }
68240
69846
  }
68241
69847
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
68242
- const plansPath = join102(extractDir, DEFAULT_FOLDERS.plans);
69848
+ const plansPath = join105(extractDir, DEFAULT_FOLDERS.plans);
68243
69849
  if (await import_fs_extra34.pathExists(plansPath)) {
68244
69850
  dirsToRename.push({
68245
69851
  from: plansPath,
68246
- to: join102(extractDir, folders.plans)
69852
+ to: join105(extractDir, folders.plans)
68247
69853
  });
68248
69854
  }
68249
- const claudePlansPath = join102(extractDir, ".claude", DEFAULT_FOLDERS.plans);
69855
+ const claudePlansPath = join105(extractDir, ".claude", DEFAULT_FOLDERS.plans);
68250
69856
  if (await import_fs_extra34.pathExists(claudePlansPath)) {
68251
69857
  dirsToRename.push({
68252
69858
  from: claudePlansPath,
68253
- to: join102(extractDir, ".claude", folders.plans)
69859
+ to: join105(extractDir, ".claude", folders.plans)
68254
69860
  });
68255
69861
  }
68256
69862
  }
@@ -68290,8 +69896,8 @@ async function renameFolders(dirsToRename, extractDir, options2) {
68290
69896
  // src/services/transformers/folder-transform/path-replacer.ts
68291
69897
  init_logger();
68292
69898
  init_types2();
68293
- import { readFile as readFile40, readdir as readdir29, writeFile as writeFile29 } from "node:fs/promises";
68294
- import { join as join103, relative as relative18 } from "node:path";
69899
+ import { readFile as readFile41, readdir as readdir29, writeFile as writeFile29 } from "node:fs/promises";
69900
+ import { join as join106, relative as relative18 } from "node:path";
68295
69901
  var TRANSFORMABLE_FILE_PATTERNS = [
68296
69902
  ".md",
68297
69903
  ".txt",
@@ -68344,7 +69950,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
68344
69950
  let replacementsCount = 0;
68345
69951
  const entries = await readdir29(dir, { withFileTypes: true });
68346
69952
  for (const entry of entries) {
68347
- const fullPath = join103(dir, entry.name);
69953
+ const fullPath = join106(dir, entry.name);
68348
69954
  if (entry.isDirectory()) {
68349
69955
  if (entry.name === "node_modules" || entry.name === ".git") {
68350
69956
  continue;
@@ -68357,14 +69963,14 @@ async function transformFileContents(dir, compiledReplacements, options2) {
68357
69963
  if (!shouldTransform)
68358
69964
  continue;
68359
69965
  try {
68360
- const content = await readFile40(fullPath, "utf-8");
69966
+ const content = await readFile41(fullPath, "utf-8");
68361
69967
  let newContent = content;
68362
69968
  let changeCount = 0;
68363
69969
  for (const { regex: regex2, replacement } of compiledReplacements) {
68364
69970
  regex2.lastIndex = 0;
68365
- const matches = newContent.match(regex2);
68366
- if (matches) {
68367
- changeCount += matches.length;
69971
+ const matches3 = newContent.match(regex2);
69972
+ if (matches3) {
69973
+ changeCount += matches3.length;
68368
69974
  regex2.lastIndex = 0;
68369
69975
  newContent = newContent.replace(regex2, replacement);
68370
69976
  }
@@ -68479,11 +70085,11 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
68479
70085
 
68480
70086
  // src/services/transformers/global-path-transformer.ts
68481
70087
  init_logger();
68482
- import { readFile as readFile41, readdir as readdir30, writeFile as writeFile30 } from "node:fs/promises";
70088
+ import { readFile as readFile42, readdir as readdir30, writeFile as writeFile30 } from "node:fs/promises";
68483
70089
  import { platform as platform9 } from "node:os";
68484
- import { extname as extname6, join as join104 } from "node:path";
70090
+ import { extname as extname6, join as join107 } from "node:path";
68485
70091
  var IS_WINDOWS3 = platform9() === "win32";
68486
- var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
70092
+ var HOME_PREFIX = "$HOME";
68487
70093
  function getHomeDirPrefix() {
68488
70094
  return HOME_PREFIX;
68489
70095
  }
@@ -68506,24 +70112,14 @@ function transformContent(content) {
68506
70112
  let transformed = content;
68507
70113
  const homePrefix = getHomeDirPrefix();
68508
70114
  const claudePath = `${homePrefix}/.claude/`;
68509
- if (IS_WINDOWS3) {
68510
- transformed = transformed.replace(/\$HOME\/\.claude\//g, () => {
68511
- changes++;
68512
- return claudePath;
68513
- });
68514
- transformed = transformed.replace(/\$\{HOME\}\/\.claude\//g, () => {
68515
- changes++;
68516
- return claudePath;
68517
- });
68518
- transformed = transformed.replace(/\$HOME(?=\/|\\)/g, () => {
68519
- changes++;
68520
- return homePrefix;
68521
- });
68522
- transformed = transformed.replace(/\$\{HOME\}(?=\/|\\)/g, () => {
68523
- changes++;
68524
- return homePrefix;
68525
- });
68526
- }
70115
+ transformed = transformed.replace(/%USERPROFILE%\/\.claude\//g, () => {
70116
+ changes++;
70117
+ return claudePath;
70118
+ });
70119
+ transformed = transformed.replace(/%USERPROFILE%(?=\/|\\)/g, () => {
70120
+ changes++;
70121
+ return homePrefix;
70122
+ });
68527
70123
  transformed = transformed.replace(/\$CLAUDE_PROJECT_DIR\/\.claude\//g, () => {
68528
70124
  changes++;
68529
70125
  return claudePath;
@@ -68536,12 +70132,10 @@ function transformContent(content) {
68536
70132
  changes++;
68537
70133
  return claudePath;
68538
70134
  });
68539
- if (IS_WINDOWS3) {
68540
- transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%\/\.claude\//g, () => {
68541
- changes++;
68542
- return claudePath;
68543
- });
68544
- }
70135
+ transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%\/\.claude\//g, () => {
70136
+ changes++;
70137
+ return claudePath;
70138
+ });
68545
70139
  transformed = transformed.replace(/\.\/\.claude\//g, () => {
68546
70140
  changes++;
68547
70141
  return claudePath;
@@ -68582,8 +70176,8 @@ function transformContent(content) {
68582
70176
  }
68583
70177
  function shouldTransformFile3(filename) {
68584
70178
  const ext2 = extname6(filename).toLowerCase();
68585
- const basename11 = filename.split("/").pop() || filename;
68586
- return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename11);
70179
+ const basename13 = filename.split("/").pop() || filename;
70180
+ return TRANSFORMABLE_EXTENSIONS3.has(ext2) || ALWAYS_TRANSFORM_FILES.has(basename13);
68587
70181
  }
68588
70182
  async function transformPathsForGlobalInstall(directory, options2 = {}) {
68589
70183
  let filesTransformed = 0;
@@ -68593,7 +70187,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
68593
70187
  async function processDirectory2(dir) {
68594
70188
  const entries = await readdir30(dir, { withFileTypes: true });
68595
70189
  for (const entry of entries) {
68596
- const fullPath = join104(dir, entry.name);
70190
+ const fullPath = join107(dir, entry.name);
68597
70191
  if (entry.isDirectory()) {
68598
70192
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
68599
70193
  continue;
@@ -68601,7 +70195,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
68601
70195
  await processDirectory2(fullPath);
68602
70196
  } else if (entry.isFile() && shouldTransformFile3(entry.name)) {
68603
70197
  try {
68604
- const content = await readFile41(fullPath, "utf-8");
70198
+ const content = await readFile42(fullPath, "utf-8");
68605
70199
  const { transformed, changes } = transformContent(content);
68606
70200
  if (changes > 0) {
68607
70201
  await writeFile30(fullPath, transformed, "utf-8");
@@ -68860,20 +70454,20 @@ async function initCommand(options2) {
68860
70454
  }
68861
70455
  // src/commands/plan/plan-command.ts
68862
70456
  init_output_manager();
68863
- import { existsSync as existsSync52, statSync as statSync4 } from "node:fs";
68864
- import { dirname as dirname34, join as join108, parse as parse2, resolve as resolve27 } from "node:path";
70457
+ import { existsSync as existsSync55, statSync as statSync7 } from "node:fs";
70458
+ import { dirname as dirname35, join as join111, parse as parse4, resolve as resolve29 } from "node:path";
68865
70459
 
68866
70460
  // src/commands/plan/plan-read-handlers.ts
68867
- import { existsSync as existsSync51, statSync as statSync3 } from "node:fs";
68868
- import { basename as basename13, dirname as dirname33, join as join107, relative as relative19, resolve as resolve25 } from "node:path";
70461
+ import { existsSync as existsSync54, statSync as statSync6 } from "node:fs";
70462
+ import { basename as basename15, dirname as dirname34, join as join110, relative as relative19, resolve as resolve27 } from "node:path";
68869
70463
 
68870
70464
  // src/domains/plan-parser/index.ts
68871
- import { dirname as dirname32 } from "node:path";
70465
+ import { dirname as dirname33 } from "node:path";
68872
70466
 
68873
70467
  // src/domains/plan-parser/plan-table-parser.ts
68874
70468
  var import_gray_matter5 = __toESM(require_gray_matter(), 1);
68875
- import { readFileSync as readFileSync16 } from "node:fs";
68876
- import { dirname as dirname29, resolve as resolve24 } from "node:path";
70469
+ import { readFileSync as readFileSync17 } from "node:fs";
70470
+ import { dirname as dirname30, resolve as resolve26 } from "node:path";
68877
70471
  function normalizeStatus(raw) {
68878
70472
  const s3 = raw.toLowerCase().trim();
68879
70473
  if (s3.includes("complete") || s3.includes("done") || s3.includes("✓") || s3.includes("✅")) {
@@ -68957,7 +70551,7 @@ function parseHeaderAwareTable(content, dir, options2) {
68957
70551
  hasLinks = true;
68958
70552
  linkText = linkMatch[1].trim();
68959
70553
  name = filenameToTitle(linkText);
68960
- file = resolve24(dir, linkMatch[2]);
70554
+ file = resolve26(dir, linkMatch[2]);
68961
70555
  } else {
68962
70556
  name = nameRaw.replace(/\[.*?\]\(.*?\)/g, "").trim() || `Phase ${phaseId}`;
68963
70557
  linkText = name;
@@ -68997,7 +70591,7 @@ function parseFormat1(content, dir, options2) {
68997
70591
  phaseId,
68998
70592
  name: name.trim(),
68999
70593
  status: normalizeStatus(status2),
69000
- file: resolve24(dir, linkPath),
70594
+ file: resolve26(dir, linkPath),
69001
70595
  linkText: linkText.trim(),
69002
70596
  anchor
69003
70597
  });
@@ -69017,7 +70611,7 @@ function parseFormat2(content, dir, options2) {
69017
70611
  phaseId,
69018
70612
  name: name.trim(),
69019
70613
  status: normalizeStatus(status2),
69020
- file: resolve24(dir, linkPath),
70614
+ file: resolve26(dir, linkPath),
69021
70615
  linkText,
69022
70616
  anchor
69023
70617
  });
@@ -69036,7 +70630,7 @@ function parseFormat2b(content, dir, options2) {
69036
70630
  phaseId,
69037
70631
  name: name.trim(),
69038
70632
  status: normalizeStatus(status2),
69039
- file: resolve24(dir, linkPath),
70633
+ file: resolve26(dir, linkPath),
69040
70634
  linkText: name.trim(),
69041
70635
  anchor
69042
70636
  });
@@ -69134,8 +70728,8 @@ function parseFormat4(content, planFilePath, options2) {
69134
70728
  const hasCheck = /[✅✓]/.test(line);
69135
70729
  current = { name, status: hasCheck ? "completed" : "pending" };
69136
70730
  } else if (fileMatch && current) {
69137
- const planDir = dirname29(planFilePath);
69138
- current.file = resolve24(planDir, fileMatch[1].trim());
70731
+ const planDir = dirname30(planFilePath);
70732
+ current.file = resolve26(planDir, fileMatch[1].trim());
69139
70733
  } else if (statusMatch && current) {
69140
70734
  current.status = normalizeStatus(statusMatch[2]);
69141
70735
  }
@@ -69201,7 +70795,7 @@ function parseFormat6(content, dir, options2) {
69201
70795
  phaseId,
69202
70796
  name: phaseName,
69203
70797
  status: checked.toLowerCase() === "x" ? "completed" : "pending",
69204
- file: resolve24(dir, linkPath),
70798
+ file: resolve26(dir, linkPath),
69205
70799
  linkText: phaseName,
69206
70800
  anchor
69207
70801
  });
@@ -69238,31 +70832,31 @@ function parsePhasesFromBody(body, dir, options2) {
69238
70832
  return parseFormat6(normalizedBody, dir, options2);
69239
70833
  }
69240
70834
  function parsePlanFile(planFilePath, options2) {
69241
- const content = readFileSync16(planFilePath, "utf8");
69242
- const dir = dirname29(planFilePath);
70835
+ const content = readFileSync17(planFilePath, "utf8");
70836
+ const dir = dirname30(planFilePath);
69243
70837
  const { data: frontmatter, content: body } = import_gray_matter5.default(content);
69244
70838
  const phases = parsePhasesFromBody(body, dir, options2);
69245
70839
  return { frontmatter, phases };
69246
70840
  }
69247
70841
  // src/domains/plan-parser/plan-scanner.ts
69248
- import { existsSync as existsSync48, readdirSync as readdirSync5 } from "node:fs";
69249
- import { join as join105 } from "node:path";
70842
+ import { existsSync as existsSync51, readdirSync as readdirSync7 } from "node:fs";
70843
+ import { join as join108 } from "node:path";
69250
70844
  function scanPlanDir(dir) {
69251
- if (!existsSync48(dir))
70845
+ if (!existsSync51(dir))
69252
70846
  return [];
69253
70847
  try {
69254
- return readdirSync5(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join105(dir, entry.name, "plan.md")).filter(existsSync48);
70848
+ return readdirSync7(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join108(dir, entry.name, "plan.md")).filter(existsSync51);
69255
70849
  } catch {
69256
70850
  return [];
69257
70851
  }
69258
70852
  }
69259
70853
  // src/domains/plan-parser/plan-validator.ts
69260
70854
  var import_gray_matter6 = __toESM(require_gray_matter(), 1);
69261
- import { existsSync as existsSync49, readFileSync as readFileSync17 } from "node:fs";
69262
- import { basename as basename11, dirname as dirname30 } from "node:path";
70855
+ import { existsSync as existsSync52, readFileSync as readFileSync18 } from "node:fs";
70856
+ import { basename as basename13, dirname as dirname31 } from "node:path";
69263
70857
  function validatePlanFile(filePath, strict = false) {
69264
- const content = readFileSync17(filePath, "utf8");
69265
- const dir = dirname30(filePath);
70858
+ const content = readFileSync18(filePath, "utf8");
70859
+ const dir = dirname31(filePath);
69266
70860
  const issues = [];
69267
70861
  const lines = content.split(`
69268
70862
  `);
@@ -69298,14 +70892,14 @@ function validatePlanFile(filePath, strict = false) {
69298
70892
  });
69299
70893
  }
69300
70894
  for (const phase of phases) {
69301
- if (phase.file && !existsSync49(phase.file)) {
69302
- const fileBasename = basename11(phase.file);
70895
+ if (phase.file && !existsSync52(phase.file)) {
70896
+ const fileBasename = basename13(phase.file);
69303
70897
  const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
69304
70898
  issues.push({
69305
70899
  line: refLine >= 0 ? refLine + 1 : 1,
69306
70900
  severity: "warning",
69307
70901
  code: "missing-phase-file",
69308
- message: `Phase ${phase.phaseId} references '${basename11(phase.file)}' which doesn't exist`
70902
+ message: `Phase ${phase.phaseId} references '${basename13(phase.file)}' which doesn't exist`
69309
70903
  });
69310
70904
  }
69311
70905
  }
@@ -69318,9 +70912,9 @@ function validatePlanFile(filePath, strict = false) {
69318
70912
  }
69319
70913
  // src/domains/plan-parser/plan-writer.ts
69320
70914
  var import_gray_matter7 = __toESM(require_gray_matter(), 1);
69321
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync9 } from "node:fs";
69322
- import { existsSync as existsSync50 } from "node:fs";
69323
- import { basename as basename12, dirname as dirname31, join as join106 } from "node:path";
70915
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync19, writeFileSync as writeFileSync9 } from "node:fs";
70916
+ import { existsSync as existsSync53 } from "node:fs";
70917
+ import { basename as basename14, dirname as dirname32, join as join109 } from "node:path";
69324
70918
  function phaseNameToFilename(id, name) {
69325
70919
  const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
69326
70920
  const num3 = numMatch ? numMatch[1] : id;
@@ -69428,12 +71022,12 @@ function scaffoldPlan(options2) {
69428
71022
  mkdirSync6(dir, { recursive: true });
69429
71023
  const resolvedPhases = resolvePhaseIds(options2.phases);
69430
71024
  const optionsWithResolved = { ...options2, phases: resolvedPhases };
69431
- const planFile = join106(dir, "plan.md");
71025
+ const planFile = join109(dir, "plan.md");
69432
71026
  writeFileSync9(planFile, generatePlanMd(optionsWithResolved), "utf8");
69433
71027
  const phaseFiles = [];
69434
71028
  for (const phase of resolvedPhases) {
69435
71029
  const filename = phaseNameToFilename(phase.id, phase.name);
69436
- const phaseFile = join106(dir, filename);
71030
+ const phaseFile = join109(dir, filename);
69437
71031
  writeFileSync9(phaseFile, generatePhaseTemplate(phase), "utf8");
69438
71032
  phaseFiles.push(phaseFile);
69439
71033
  }
@@ -69458,7 +71052,7 @@ function isCanonicalFormat(content) {
69458
71052
  return /^\|\s*phase\s*\|\s*name\s*\|\s*status\s*\|/im.test(content);
69459
71053
  }
69460
71054
  function updatePhaseStatus(planFile, phaseId, newStatus) {
69461
- const raw = readFileSync18(planFile, "utf8").replace(/\r\n/g, `
71055
+ const raw = readFileSync19(planFile, "utf8").replace(/\r\n/g, `
69462
71056
  `);
69463
71057
  if (!isCanonicalFormat(raw)) {
69464
71058
  console.error("[!] plan.md is not in canonical format — skipping status update");
@@ -69499,9 +71093,9 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
69499
71093
  const updatedFrontmatter = { ...frontmatter, status: planStatus };
69500
71094
  const updatedContent = import_gray_matter7.default.stringify(updatedBody, updatedFrontmatter);
69501
71095
  writeFileSync9(planFile, updatedContent, "utf8");
69502
- const planDir = dirname31(planFile);
71096
+ const planDir = dirname32(planFile);
69503
71097
  const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
69504
- if (phaseFilename && existsSync50(phaseFilename)) {
71098
+ if (phaseFilename && existsSync53(phaseFilename)) {
69505
71099
  updatePhaseFileFrontmatter(phaseFilename, newStatus);
69506
71100
  }
69507
71101
  }
@@ -69513,25 +71107,25 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
69513
71107
  continue;
69514
71108
  const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
69515
71109
  if (linkMatch)
69516
- return join106(planDir, linkMatch[2]);
71110
+ return join109(planDir, linkMatch[2]);
69517
71111
  }
69518
71112
  return null;
69519
71113
  }
69520
71114
  function updatePhaseFileFrontmatter(phaseFile, newStatus) {
69521
- const raw = readFileSync18(phaseFile, "utf8");
71115
+ const raw = readFileSync19(phaseFile, "utf8");
69522
71116
  const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
69523
71117
  const updated = { ...frontmatter, status: newStatus };
69524
71118
  writeFileSync9(phaseFile, import_gray_matter7.default.stringify(body, updated), "utf8");
69525
71119
  }
69526
71120
  function addPhase(planFile, name, afterId) {
69527
- const raw = readFileSync18(planFile, "utf8").replace(/\r\n/g, `
71121
+ const raw = readFileSync19(planFile, "utf8").replace(/\r\n/g, `
69528
71122
  `);
69529
71123
  if (!isCanonicalFormat(raw)) {
69530
71124
  console.error("[!] plan.md is not in canonical format — cannot add phase");
69531
71125
  throw new Error("Non-canonical plan.md — cannot add phase");
69532
71126
  }
69533
71127
  const { data: frontmatter, content: body } = import_gray_matter7.default(raw);
69534
- const planDir = dirname31(planFile);
71128
+ const planDir = dirname32(planFile);
69535
71129
  const existingIds = [];
69536
71130
  for (const match2 of body.matchAll(/^\|\s*(\d+[a-z]?)\s*\|/gim)) {
69537
71131
  existingIds.push(match2[1].toLowerCase());
@@ -69560,7 +71154,7 @@ function addPhase(planFile, name, afterId) {
69560
71154
  insertIdx = i;
69561
71155
  }
69562
71156
  if (insertIdx === -1) {
69563
- throw new Error(`Phase ID "${afterId}" not found in ${basename12(planFile)}`);
71157
+ throw new Error(`Phase ID "${afterId}" not found in ${basename14(planFile)}`);
69564
71158
  }
69565
71159
  lines.splice(insertIdx + 1, 0, newRow);
69566
71160
  updatedBody = lines.join(`
@@ -69594,7 +71188,7 @@ function addPhase(planFile, name, afterId) {
69594
71188
  `);
69595
71189
  }
69596
71190
  writeFileSync9(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
69597
- const phaseFilePath = join106(planDir, filename);
71191
+ const phaseFilePath = join109(planDir, filename);
69598
71192
  writeFileSync9(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
69599
71193
  return { phaseId, phaseFile: phaseFilePath };
69600
71194
  }
@@ -69606,7 +71200,7 @@ function buildPlanSummary(planFile) {
69606
71200
  const inProgress = phases.filter((p2) => p2.status === "in-progress").length;
69607
71201
  const pending = phases.filter((p2) => p2.status === "pending").length;
69608
71202
  return {
69609
- planDir: dirname32(planFile),
71203
+ planDir: dirname33(planFile),
69610
71204
  planFile,
69611
71205
  title: typeof frontmatter.title === "string" ? frontmatter.title : undefined,
69612
71206
  description: typeof frontmatter.description === "string" ? frontmatter.description : undefined,
@@ -69643,7 +71237,7 @@ async function handleParse(target, options2) {
69643
71237
  console.log(JSON.stringify({ file: relative19(process.cwd(), planFile), frontmatter, phases }, null, 2));
69644
71238
  return;
69645
71239
  }
69646
- const title = typeof frontmatter.title === "string" ? frontmatter.title : basename13(dirname33(planFile));
71240
+ const title = typeof frontmatter.title === "string" ? frontmatter.title : basename15(dirname34(planFile));
69647
71241
  console.log();
69648
71242
  console.log(import_picocolors25.default.bold(` Plan: ${title}`));
69649
71243
  console.log(` File: ${planFile}`);
@@ -69697,8 +71291,8 @@ async function handleValidate(target, options2) {
69697
71291
  process.exitCode = 1;
69698
71292
  }
69699
71293
  async function handleStatus(target, options2) {
69700
- const t = target ? resolve25(target) : null;
69701
- const plansDir = t && existsSync51(t) && statSync3(t).isDirectory() && !existsSync51(join107(t, "plan.md")) ? t : null;
71294
+ const t = target ? resolve27(target) : null;
71295
+ const plansDir = t && existsSync54(t) && statSync6(t).isDirectory() && !existsSync54(join110(t, "plan.md")) ? t : null;
69702
71296
  if (plansDir) {
69703
71297
  const planFiles = scanPlanDir(plansDir);
69704
71298
  if (planFiles.length === 0) {
@@ -69723,14 +71317,14 @@ async function handleStatus(target, options2) {
69723
71317
  try {
69724
71318
  const s3 = buildPlanSummary(pf);
69725
71319
  const bar = progressBar(s3.completed, s3.totalPhases);
69726
- const title2 = s3.title ?? basename13(dirname33(pf));
71320
+ const title2 = s3.title ?? basename15(dirname34(pf));
69727
71321
  console.log(` ${import_picocolors25.default.bold(title2)}`);
69728
71322
  console.log(` ${bar}`);
69729
71323
  if (s3.inProgress > 0)
69730
71324
  console.log(` [~] ${s3.inProgress} in progress`);
69731
71325
  console.log();
69732
71326
  } catch {
69733
- console.log(` [X] Failed to read: ${basename13(dirname33(pf))}`);
71327
+ console.log(` [X] Failed to read: ${basename15(dirname34(pf))}`);
69734
71328
  console.log();
69735
71329
  }
69736
71330
  }
@@ -69754,7 +71348,7 @@ async function handleStatus(target, options2) {
69754
71348
  console.log(JSON.stringify(summary, null, 2));
69755
71349
  return;
69756
71350
  }
69757
- const title = summary.title ?? basename13(dirname33(planFile));
71351
+ const title = summary.title ?? basename15(dirname34(planFile));
69758
71352
  console.log();
69759
71353
  console.log(import_picocolors25.default.bold(` ${title}`));
69760
71354
  if (summary.status)
@@ -69780,7 +71374,7 @@ async function handleKanban(target, _options) {
69780
71374
  }
69781
71375
 
69782
71376
  // src/commands/plan/plan-write-handlers.ts
69783
- import { basename as basename14, relative as relative20, resolve as resolve26 } from "node:path";
71377
+ import { basename as basename16, relative as relative20, resolve as resolve28 } from "node:path";
69784
71378
  init_output_manager();
69785
71379
  var import_picocolors26 = __toESM(require_picocolors(), 1);
69786
71380
  async function handleCreate(target, options2) {
@@ -69816,7 +71410,7 @@ async function handleCreate(target, options2) {
69816
71410
  const result = scaffoldPlan({
69817
71411
  title: options2.title,
69818
71412
  phases: phaseNames.map((name) => ({ name })),
69819
- dir: resolve26(dir),
71413
+ dir: resolve28(dir),
69820
71414
  priority,
69821
71415
  issue: options2.issue ? Number(options2.issue) : undefined
69822
71416
  });
@@ -69830,10 +71424,10 @@ async function handleCreate(target, options2) {
69830
71424
  }
69831
71425
  console.log();
69832
71426
  console.log(import_picocolors26.default.bold(` [OK] Plan created: ${options2.title}`));
69833
- console.log(` Directory: ${resolve26(dir)}`);
71427
+ console.log(` Directory: ${resolve28(dir)}`);
69834
71428
  console.log(` Phases: ${result.phaseFiles.length}`);
69835
71429
  for (const f4 of result.phaseFiles) {
69836
- console.log(` [ ] ${basename14(f4)}`);
71430
+ console.log(` [ ] ${basename16(f4)}`);
69837
71431
  }
69838
71432
  console.log();
69839
71433
  }
@@ -69928,23 +71522,23 @@ async function handleAddPhase(target, options2) {
69928
71522
 
69929
71523
  // src/commands/plan/plan-command.ts
69930
71524
  function resolvePlanFile(target) {
69931
- const t = target ? resolve27(target) : process.cwd();
69932
- if (existsSync52(t)) {
69933
- const stat13 = statSync4(t);
71525
+ const t = target ? resolve29(target) : process.cwd();
71526
+ if (existsSync55(t)) {
71527
+ const stat13 = statSync7(t);
69934
71528
  if (stat13.isFile())
69935
71529
  return t;
69936
- const candidate = join108(t, "plan.md");
69937
- if (existsSync52(candidate))
71530
+ const candidate = join111(t, "plan.md");
71531
+ if (existsSync55(candidate))
69938
71532
  return candidate;
69939
71533
  }
69940
71534
  if (!target) {
69941
71535
  let dir = process.cwd();
69942
- const root = parse2(dir).root;
71536
+ const root = parse4(dir).root;
69943
71537
  while (dir !== root) {
69944
- const candidate = join108(dir, "plan.md");
69945
- if (existsSync52(candidate))
71538
+ const candidate = join111(dir, "plan.md");
71539
+ if (existsSync55(candidate))
69946
71540
  return candidate;
69947
- dir = dirname34(dir);
71541
+ dir = dirname35(dir);
69948
71542
  }
69949
71543
  }
69950
71544
  return null;
@@ -69992,7 +71586,7 @@ async function planCommand(action, target, options2) {
69992
71586
  let resolvedTarget = target;
69993
71587
  if (resolvedAction && !knownActions.has(resolvedAction)) {
69994
71588
  const looksLikePath = resolvedAction.includes("/") || resolvedAction.includes("\\") || resolvedAction.endsWith(".md") || resolvedAction === "." || resolvedAction === "..";
69995
- const existsOnDisk = !looksLikePath && existsSync52(resolve27(resolvedAction));
71589
+ const existsOnDisk = !looksLikePath && existsSync55(resolve29(resolvedAction));
69996
71590
  if (looksLikePath || existsOnDisk) {
69997
71591
  resolvedTarget = resolvedAction;
69998
71592
  resolvedAction = undefined;
@@ -70036,24 +71630,24 @@ init_logger();
70036
71630
  init_logger();
70037
71631
 
70038
71632
  // src/commands/telemetry/shared.ts
70039
- import { existsSync as existsSync53, readFileSync as readFileSync19, readdirSync as readdirSync6 } from "node:fs";
70040
- import { homedir as homedir26 } from "node:os";
70041
- import { join as join109 } from "node:path";
71633
+ import { existsSync as existsSync56, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
71634
+ import { homedir as homedir28 } from "node:os";
71635
+ import { join as join112 } from "node:path";
70042
71636
  init_token_store();
70043
71637
  init_manifest_path_resolver();
70044
71638
  init_takumi_constants();
70045
- var USER_CACHE_PATH = join109(homedir26(), ".claude", "sk-user.json");
70046
- var EVENT_BUFFER_DIR = join109(homedir26(), ".claude", "sk-events");
70047
- var RATE_STATE_PATH = join109(homedir26(), ".claude", "sk-rate-state.json");
70048
- var TAKUMI_MANIFEST_PATH = join109(homedir26(), ".claude", MANIFEST_FILENAME);
70049
- var LEGACY_METADATA_PATH = join109(homedir26(), ".claude", LEGACY_MANIFEST_FILENAME);
71639
+ var USER_CACHE_PATH = join112(homedir28(), ".claude", "sk-user.json");
71640
+ var EVENT_BUFFER_DIR = join112(homedir28(), ".claude", "sk-events");
71641
+ var RATE_STATE_PATH = join112(homedir28(), ".claude", "sk-rate-state.json");
71642
+ var TAKUMI_MANIFEST_PATH = join112(homedir28(), ".claude", MANIFEST_FILENAME);
71643
+ var LEGACY_METADATA_PATH = join112(homedir28(), ".claude", LEGACY_MANIFEST_FILENAME);
70050
71644
  var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
70051
71645
  var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
70052
71646
  function readUserCache() {
70053
71647
  try {
70054
- if (!existsSync53(USER_CACHE_PATH))
71648
+ if (!existsSync56(USER_CACHE_PATH))
70055
71649
  return null;
70056
- const parsed = JSON.parse(readFileSync19(USER_CACHE_PATH, "utf8"));
71650
+ const parsed = JSON.parse(readFileSync20(USER_CACHE_PATH, "utf8"));
70057
71651
  if (!parsed || typeof parsed !== "object")
70058
71652
  return null;
70059
71653
  return parsed;
@@ -70063,9 +71657,9 @@ function readUserCache() {
70063
71657
  }
70064
71658
  function countBufferFiles() {
70065
71659
  try {
70066
- if (!existsSync53(EVENT_BUFFER_DIR))
71660
+ if (!existsSync56(EVENT_BUFFER_DIR))
70067
71661
  return 0;
70068
- return readdirSync6(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
71662
+ return readdirSync8(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
70069
71663
  } catch {
70070
71664
  return 0;
70071
71665
  }
@@ -70075,9 +71669,9 @@ function readTelemetryConfig() {
70075
71669
  const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
70076
71670
  let metadata = null;
70077
71671
  try {
70078
- const resolved = findManifestPathSync(join109(homedir26(), ".claude"));
71672
+ const resolved = findManifestPathSync(join112(homedir28(), ".claude"));
70079
71673
  if (resolved) {
70080
- metadata = JSON.parse(readFileSync19(resolved.path, "utf8"));
71674
+ metadata = JSON.parse(readFileSync20(resolved.path, "utf8"));
70081
71675
  }
70082
71676
  } catch {
70083
71677
  metadata = null;
@@ -70093,16 +71687,16 @@ function readTelemetryConfig() {
70093
71687
  return { endpoint, token };
70094
71688
  }
70095
71689
  function collectRuntimeContext() {
70096
- const cache = readUserCache();
71690
+ const cache2 = readUserCache();
70097
71691
  const { endpoint, token } = readTelemetryConfig();
70098
71692
  return {
70099
- githubLogin: typeof cache?.githubLogin === "string" ? cache.githubLogin : null,
70100
- cacheResolvedAt: typeof cache?.resolvedAt === "number" ? cache.resolvedAt : null,
70101
- cacheSource: cache?.source === "gh" || cache?.source === "manual" ? cache.source : null,
71693
+ githubLogin: typeof cache2?.githubLogin === "string" ? cache2.githubLogin : null,
71694
+ cacheResolvedAt: typeof cache2?.resolvedAt === "number" ? cache2.resolvedAt : null,
71695
+ cacheSource: cache2?.source === "gh" || cache2?.source === "manual" ? cache2.source : null,
70102
71696
  bufferFileCount: countBufferFiles(),
70103
71697
  bufferDir: EVENT_BUFFER_DIR,
70104
- rateStateExists: existsSync53(RATE_STATE_PATH),
70105
- userCacheExists: existsSync53(USER_CACHE_PATH),
71698
+ rateStateExists: existsSync56(RATE_STATE_PATH),
71699
+ userCacheExists: existsSync56(USER_CACHE_PATH),
70106
71700
  endpoint,
70107
71701
  tokenConfigured: Boolean(token)
70108
71702
  };
@@ -70252,8 +71846,8 @@ init_logger();
70252
71846
  init_safe_prompts();
70253
71847
  init_safe_spinner();
70254
71848
  var import_fs_extra36 = __toESM(require_lib(), 1);
70255
- import { readdirSync as readdirSync8, rmSync as rmSync8 } from "node:fs";
70256
- import { join as join111, resolve as resolve28, sep as sep8 } from "node:path";
71849
+ import { readdirSync as readdirSync10, rmSync as rmSync8 } from "node:fs";
71850
+ import { join as join114, resolve as resolve30, sep as sep10 } from "node:path";
70257
71851
 
70258
71852
  // src/commands/uninstall/analysis-handler.ts
70259
71853
  init_metadata_migration();
@@ -70263,13 +71857,13 @@ init_logger();
70263
71857
  init_safe_prompts();
70264
71858
  init_takumi_constants();
70265
71859
  var import_picocolors27 = __toESM(require_picocolors(), 1);
70266
- import { existsSync as existsSync54, readdirSync as readdirSync7, rmSync as rmSync7 } from "node:fs";
70267
- import { dirname as dirname35, join as join110 } from "node:path";
71860
+ import { existsSync as existsSync57, readdirSync as readdirSync9, rmSync as rmSync7 } from "node:fs";
71861
+ import { dirname as dirname36, join as join113 } from "node:path";
70268
71862
  function listPresentManifestNames(installPath) {
70269
71863
  const present = [];
70270
- if (existsSync54(getManifestPath(installPath)))
71864
+ if (existsSync57(getManifestPath(installPath)))
70271
71865
  present.push(MANIFEST_FILENAME);
70272
- if (existsSync54(getLegacyManifestPath(installPath)))
71866
+ if (existsSync57(getLegacyManifestPath(installPath)))
70273
71867
  present.push(LEGACY_MANIFEST_FILENAME);
70274
71868
  return present;
70275
71869
  }
@@ -70287,15 +71881,15 @@ function classifyFileByOwnership(ownership, forceOverwrite, deleteReason) {
70287
71881
  }
70288
71882
  async function cleanupEmptyDirectories3(filePath, installationRoot) {
70289
71883
  let cleaned = 0;
70290
- let currentDir = dirname35(filePath);
71884
+ let currentDir = dirname36(filePath);
70291
71885
  while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
70292
71886
  try {
70293
- const entries = readdirSync7(currentDir);
71887
+ const entries = readdirSync9(currentDir);
70294
71888
  if (entries.length === 0) {
70295
71889
  rmSync7(currentDir, { recursive: true });
70296
71890
  cleaned++;
70297
71891
  logger.debug(`Removed empty directory: ${currentDir}`);
70298
- currentDir = dirname35(currentDir);
71892
+ currentDir = dirname36(currentDir);
70299
71893
  } else {
70300
71894
  break;
70301
71895
  }
@@ -70317,7 +71911,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
70317
71911
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
70318
71912
  const kitFiles = metadata.kits[kit].files || [];
70319
71913
  for (const trackedFile of kitFiles) {
70320
- const filePath = join110(installation.path, trackedFile.path);
71914
+ const filePath = join113(installation.path, trackedFile.path);
70321
71915
  if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
70322
71916
  result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
70323
71917
  continue;
@@ -70349,7 +71943,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
70349
71943
  return result;
70350
71944
  }
70351
71945
  for (const trackedFile of allTrackedFiles) {
70352
- const filePath = join110(installation.path, trackedFile.path);
71946
+ const filePath = join113(installation.path, trackedFile.path);
70353
71947
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
70354
71948
  if (!ownershipResult.exists)
70355
71949
  continue;
@@ -70405,17 +71999,17 @@ async function isDirectory(filePath) {
70405
71999
  }
70406
72000
  async function isPathSafeToRemove(filePath, baseDir) {
70407
72001
  try {
70408
- const resolvedPath = resolve28(filePath);
70409
- const resolvedBase = resolve28(baseDir);
70410
- if (!resolvedPath.startsWith(resolvedBase + sep8) && resolvedPath !== resolvedBase) {
72002
+ const resolvedPath = resolve30(filePath);
72003
+ const resolvedBase = resolve30(baseDir);
72004
+ if (!resolvedPath.startsWith(resolvedBase + sep10) && resolvedPath !== resolvedBase) {
70411
72005
  logger.debug(`Path outside installation directory: ${filePath}`);
70412
72006
  return false;
70413
72007
  }
70414
72008
  const stats = await import_fs_extra36.lstat(filePath);
70415
72009
  if (stats.isSymbolicLink()) {
70416
72010
  const realPath = await import_fs_extra36.realpath(filePath);
70417
- const resolvedReal = resolve28(realPath);
70418
- if (!resolvedReal.startsWith(resolvedBase + sep8) && resolvedReal !== resolvedBase) {
72011
+ const resolvedReal = resolve30(realPath);
72012
+ if (!resolvedReal.startsWith(resolvedBase + sep10) && resolvedReal !== resolvedBase) {
70419
72013
  logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
70420
72014
  return false;
70421
72015
  }
@@ -70448,7 +72042,7 @@ async function removeInstallations(installations, options2) {
70448
72042
  let removedCount = 0;
70449
72043
  let cleanedDirs = 0;
70450
72044
  for (const item of analysis.toDelete) {
70451
- const filePath = join111(installation.path, item.path);
72045
+ const filePath = join114(installation.path, item.path);
70452
72046
  if (!await import_fs_extra36.pathExists(filePath))
70453
72047
  continue;
70454
72048
  if (!await isPathSafeToRemove(filePath, installation.path)) {
@@ -70467,7 +72061,7 @@ async function removeInstallations(installations, options2) {
70467
72061
  await ManifestWriter.removeKitFromManifest(installation.path, options2.kit);
70468
72062
  }
70469
72063
  try {
70470
- const remaining = readdirSync8(installation.path);
72064
+ const remaining = readdirSync10(installation.path);
70471
72065
  if (remaining.length === 0) {
70472
72066
  rmSync8(installation.path, { recursive: true });
70473
72067
  logger.debug(`Removed empty installation directory: ${installation.path}`);
@@ -70878,12 +72472,12 @@ async function promptKitUpdate(beta, yes, deps) {
70878
72472
  args.push("--beta");
70879
72473
  const displayCmd = `tkm ${args.join(" ")}`;
70880
72474
  logger.info(`Running: ${displayCmd}`);
70881
- const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((resolve29) => {
72475
+ const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((resolve31) => {
70882
72476
  const child = spawn3("tkm", spawnArgs, { stdio: "inherit", shell: true });
70883
- child.on("close", (code) => resolve29(code ?? 1));
72477
+ child.on("close", (code) => resolve31(code ?? 1));
70884
72478
  child.on("error", (err) => {
70885
72479
  logger.verbose(`Failed to spawn tkm init: ${err.message}`);
70886
- resolve29(1);
72480
+ resolve31(1);
70887
72481
  });
70888
72482
  }));
70889
72483
  const exitCode = await spawnFn(args);
@@ -70921,6 +72515,8 @@ async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps(
70921
72515
  logger.verbose(`Using npm configured registry: ${redactRegistryUrlForLog(registryUrl)}`);
70922
72516
  }
70923
72517
  }
72518
+ if (registryUrl)
72519
+ registryUrl = validateRegistryUrl(registryUrl);
70924
72520
  s3.start("Checking for updates...");
70925
72521
  let targetVersion = null;
70926
72522
  const usePrereleaseChannel = opts.dev || opts.beta;
@@ -70969,6 +72565,9 @@ async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps(
70969
72565
  const isDevChannelSwitch = (opts.dev || opts.beta) && isBetaVersion(targetVersion) && !isBetaVersion(currentVersion);
70970
72566
  if (comparison > 0 && !opts.release && !isDevChannelSwitch) {
70971
72567
  outro(`[+] Current version (${currentVersion}) is newer than latest (${targetVersion})`);
72568
+ if (isBetaVersion(currentVersion)) {
72569
+ note("You are on a prerelease build. `tkm update` tracks the stable channel.\nTo update within the dev/beta channel, run: tkm update --beta");
72570
+ }
70972
72571
  await promptKitUpdateFn(targetIsPrerelease, opts.yes);
70973
72572
  return;
70974
72573
  }
@@ -71215,6 +72814,19 @@ function registerCommands(cli) {
71215
72814
  cli.command("versions", "List available versions of Takumi repositories").option("--kit <kit>", "Filter by specific kit (core)").option("--limit <limit>", "Number of releases to show (default: 30)").option("--all", "Show the beta channel (prereleases only) instead of the stable channel. " + "On --use-gh, returns all release types interleaved.").option("--use-gh", "Use legacy GitHub release source (requires gh CLI)").action(async (options2) => {
71216
72815
  await versionCommand(options2);
71217
72816
  });
72817
+ cli.command("console", "Start local bridge and open session console in browser").option("--port <port>", "Bridge port (default: 8765, auto-bump on conflict)").option("--no-open", "Don't open the browser; print URL only").action(async (options2) => {
72818
+ let port;
72819
+ if (options2.port !== undefined) {
72820
+ const n = Number(options2.port);
72821
+ if (!Number.isInteger(n) || n < 0 || n > 65535) {
72822
+ console.error(`Invalid --port value: ${options2.port}. Expected integer 0-65535.`);
72823
+ process.exitCode = 1;
72824
+ return;
72825
+ }
72826
+ port = n;
72827
+ }
72828
+ await consoleCommand({ port, noOpen: options2.open === false });
72829
+ });
71218
72830
  cli.command("doctor", "Comprehensive health check for Takumi").option("--report", "Generate shareable diagnostic report").option("--fix", "Auto-fix all fixable issues").option("--check-only", "CI mode: no prompts, exit 1 on failures").option("--json", "Output JSON format").option("--full", "Include extended priority checks (slower)").action(async (options2) => {
71219
72831
  await doctorCommand(options2);
71220
72832
  });
@@ -71243,8 +72855,8 @@ function registerCommands(cli) {
71243
72855
  cli.command("plan [action] [target]", "Plan management: parse, validate, status, kanban, create, check, uncheck, add-phase").option("--json", "Output in JSON format").option("--strict", "Strict validation mode").option("--title <title>", "Plan title (for create)").option("--phases <phases>", "Comma-separated phase names (for create)").option("--dir <dir>", "Plan directory (for create)").option("--priority <priority>", "Priority: P1, P2, P3 (for create)").option("--issue <issue>", "GitHub issue number (for create)").option("--after <after>", "Insert after phase ID (for add-phase)").option("--start", "Mark as in-progress instead of completed (for check)").action(async (action, target, options2) => {
71244
72856
  await planCommand(action, target, options2);
71245
72857
  });
71246
- cli.command("api [action] [service] [path]", "Interact with Takumi API and proxy services").option("--method <method>", "HTTP method for proxy requests (default: GET)").option("--body <json>", "Request body as JSON string (proxy only)").option("--query <json>", "Query params as JSON string (proxy only)").option("--key <key>", "API key to use (setup only)").option("--force", "Force re-setup even if key exists (setup only)").option("--json", "Output raw JSON instead of formatted display").option("--locale <locale>", "Locale for vidcap summary/caption (default: en)").option("--max-results <n>", "Max results for vidcap search").option("--second <s>", "Timestamp in seconds for vidcap screenshot").option("--order <order>", "Sort order for vidcap comments (time/relevance)").option("--format <fmt>", "Summary format for reviewweb (bullet/paragraph)").option("--max-length <n>", "Max summary length for reviewweb").option("--instructions <text>", "Extraction instructions for reviewweb extract").option("--template <json>", "JSON template for reviewweb extract").option("--type <type>", "Link type filter for reviewweb links (web/image/file/all)").option("--country <code>", "Country code for reviewweb SEO commands").action(async (action, service, path9, options2) => {
71247
- await apiCommand(action, service, path9, options2);
72858
+ cli.command("api [action] [service] [path]", "Interact with Takumi API and proxy services").option("--method <method>", "HTTP method for proxy requests (default: GET)").option("--body <json>", "Request body as JSON string (proxy only)").option("--query <json>", "Query params as JSON string (proxy only)").option("--key <key>", "API key to use (setup only)").option("--force", "Force re-setup even if key exists (setup only)").option("--json", "Output raw JSON instead of formatted display").option("--locale <locale>", "Locale for vidcap summary/caption (default: en)").option("--max-results <n>", "Max results for vidcap search").option("--second <s>", "Timestamp in seconds for vidcap screenshot").option("--order <order>", "Sort order for vidcap comments (time/relevance)").option("--format <fmt>", "Summary format for reviewweb (bullet/paragraph)").option("--max-length <n>", "Max summary length for reviewweb").option("--instructions <text>", "Extraction instructions for reviewweb extract").option("--template <json>", "JSON template for reviewweb extract").option("--type <type>", "Link type filter for reviewweb links (web/image/file/all)").option("--country <code>", "Country code for reviewweb SEO commands").action(async (action, service, path11, options2) => {
72859
+ await apiCommand(action, service, path11, options2);
71248
72860
  });
71249
72861
  cli.command("auth [action]", "Sign in/out, refresh, and check Takumi session (login|logout|refresh|status)").option("--json", "Machine-readable JSON output (status, refresh)").option("-f, --force", "Force a token refresh even when the current token is still valid (refresh only)").action(async (action, options2 = {}) => {
71250
72862
  switch (action) {
@@ -71279,8 +72891,8 @@ init_version_checker();
71279
72891
  init_manifest_path_resolver();
71280
72892
  init_logger();
71281
72893
  init_types2();
71282
- import { readFileSync as readFileSync20 } from "node:fs";
71283
- import { join as join112 } from "node:path";
72894
+ import { readFileSync as readFileSync21 } from "node:fs";
72895
+ import { join as join115 } from "node:path";
71284
72896
  var PROVIDER_LOCAL_SUBDIRS = {
71285
72897
  "claude-code": ".claude",
71286
72898
  codex: ".codex"
@@ -71335,7 +72947,7 @@ async function displayVersion() {
71335
72947
  const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
71336
72948
  if (!localSubdir)
71337
72949
  continue;
71338
- const localRoot = join112(process.cwd(), localSubdir);
72950
+ const localRoot = join115(process.cwd(), localSubdir);
71339
72951
  if (localRoot === inst.globalRoot())
71340
72952
  continue;
71341
72953
  const resolved = findManifestPathSync(localRoot);
@@ -71345,7 +72957,7 @@ async function displayVersion() {
71345
72957
  }
71346
72958
  for (const { provider, path: metaPath } of localChecks) {
71347
72959
  try {
71348
- const rawMetadata = JSON.parse(readFileSync20(metaPath, "utf-8"));
72960
+ const rawMetadata = JSON.parse(readFileSync21(metaPath, "utf-8"));
71349
72961
  const metadata = MetadataSchema.parse(rawMetadata);
71350
72962
  const kitsDisplay = formatInstalledKits(metadata);
71351
72963
  if (kitsDisplay) {
@@ -71365,7 +72977,7 @@ async function displayVersion() {
71365
72977
  const resolved = findManifestPathSync(installPath);
71366
72978
  if (resolved) {
71367
72979
  try {
71368
- const rawMetadata = JSON.parse(readFileSync20(resolved.path, "utf-8"));
72980
+ const rawMetadata = JSON.parse(readFileSync21(resolved.path, "utf-8"));
71369
72981
  const metadata = MetadataSchema.parse(rawMetadata);
71370
72982
  const kitsDisplay = formatInstalledKits(metadata);
71371
72983
  if (kitsDisplay) {
@@ -71467,18 +73079,18 @@ class Logger2 {
71467
73079
  isVerbose() {
71468
73080
  return this.verboseEnabled;
71469
73081
  }
71470
- setLogFile(path9) {
73082
+ setLogFile(path11) {
71471
73083
  if (this.logFileStream) {
71472
73084
  this.logFileStream.end();
71473
73085
  this.logFileStream = undefined;
71474
73086
  }
71475
- if (path9) {
71476
- this.logFileStream = createWriteStream4(path9, {
73087
+ if (path11) {
73088
+ this.logFileStream = createWriteStream4(path11, {
71477
73089
  flags: "a",
71478
73090
  mode: 384
71479
73091
  });
71480
73092
  this.registerExitHandler();
71481
- this.verbose(`Logging to file: ${path9}`);
73093
+ this.verbose(`Logging to file: ${path11}`);
71482
73094
  }
71483
73095
  }
71484
73096
  close() {