@sunasteriskrnd/takumi 1.0.0-dev.25 → 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 +365 -219
  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.25",
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,11 +50450,11 @@ var exports_monorepo_resolver = {};
50384
50450
  __export(exports_monorepo_resolver, {
50385
50451
  resolveMonorepoRoot: () => resolveMonorepoRoot
50386
50452
  });
50387
- import { existsSync as existsSync48, readFileSync as readFileSync16 } from "node:fs";
50388
- import { dirname as dirname27, join as join98, resolve as resolve22 } 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 (!existsSync48(metadataPath))
50457
+ if (!existsSync49(metadataPath))
50392
50458
  return null;
50393
50459
  try {
50394
50460
  const raw = readFileSync16(metadataPath, "utf-8");
@@ -50402,8 +50468,8 @@ function parseMetadataAt(metadataPath) {
50402
50468
  }
50403
50469
  }
50404
50470
  function readSourceDirFromPackageJson(candidateRoot) {
50405
- const packageJsonPath = join98(candidateRoot, "package.json");
50406
- if (!existsSync48(packageJsonPath))
50471
+ const packageJsonPath = join99(candidateRoot, "package.json");
50472
+ if (!existsSync49(packageJsonPath))
50407
50473
  return null;
50408
50474
  try {
50409
50475
  const parsed = JSON.parse(readFileSync16(packageJsonPath, "utf-8"));
@@ -50425,7 +50491,7 @@ function tryReadAtCandidate(candidateRoot) {
50425
50491
  };
50426
50492
  }
50427
50493
  const sourceDir = readSourceDirFromPackageJson(candidateRoot) ?? "claude";
50428
- const sourceRoot = join98(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 {
@@ -57051,17 +57117,102 @@ async function checkHooksExist(projectDir) {
57051
57117
  autoFixable: false
57052
57118
  };
57053
57119
  }
57054
- // src/domains/health-checks/checkers/settings-checker.ts
57055
- init_paths();
57120
+ // src/domains/health-checks/checkers/codex-hook-health-checker.ts
57056
57121
  init_registry();
57057
- init_logger();
57058
57122
  import { existsSync as existsSync39 } from "node:fs";
57059
57123
  import { readFile as readFile33 } from "node:fs/promises";
57060
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
+ }
57205
+ // src/domains/health-checks/checkers/settings-checker.ts
57206
+ init_paths();
57207
+ init_registry();
57208
+ init_logger();
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";
57061
57212
  async function checkSettingsValid(projectDir) {
57062
- const globalSettings = join78(getInstaller("claude-code")?.globalRoot() ?? "", "settings.json");
57063
- const projectSettings = join78(getLocalClaudeDir(projectDir), "settings.json");
57064
- const settingsPath = existsSync39(globalSettings) ? globalSettings : existsSync39(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;
57065
57216
  if (!settingsPath) {
57066
57217
  return {
57067
57218
  id: "sk-settings-valid",
@@ -57074,7 +57225,7 @@ async function checkSettingsValid(projectDir) {
57074
57225
  };
57075
57226
  }
57076
57227
  try {
57077
- const content = await readFile33(settingsPath, "utf-8");
57228
+ const content = await readFile34(settingsPath, "utf-8");
57078
57229
  JSON.parse(content);
57079
57230
  return {
57080
57231
  id: "sk-settings-valid",
@@ -57131,14 +57282,14 @@ async function checkSettingsValid(projectDir) {
57131
57282
  init_paths();
57132
57283
  init_registry();
57133
57284
  init_logger();
57134
- import { existsSync as existsSync40 } from "node:fs";
57135
- import { readFile as readFile34 } from "node:fs/promises";
57285
+ import { existsSync as existsSync41 } from "node:fs";
57286
+ import { readFile as readFile35 } from "node:fs/promises";
57136
57287
  import { homedir as homedir24 } from "node:os";
57137
- import { dirname as dirname19, join as join79, normalize as normalize6, resolve as resolve17 } from "node:path";
57288
+ import { dirname as dirname19, join as join80, normalize as normalize6, resolve as resolve17 } from "node:path";
57138
57289
  async function checkPathRefsValid(projectDir) {
57139
- const globalClaudeMd = join79(getInstaller("claude-code")?.globalRoot() ?? "", "CLAUDE.md");
57140
- const projectClaudeMd = join79(getLocalClaudeDir(projectDir), "CLAUDE.md");
57141
- const claudeMdPath = existsSync40(globalClaudeMd) ? globalClaudeMd : existsSync40(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;
57142
57293
  if (!claudeMdPath) {
57143
57294
  return {
57144
57295
  id: "sk-path-refs-valid",
@@ -57151,7 +57302,7 @@ async function checkPathRefsValid(projectDir) {
57151
57302
  };
57152
57303
  }
57153
57304
  try {
57154
- const content = await readFile34(claudeMdPath, "utf-8");
57305
+ const content = await readFile35(claudeMdPath, "utf-8");
57155
57306
  const refPattern = /@([^\s\)]+)/g;
57156
57307
  const refs = [...content.matchAll(refPattern)].map((m2) => m2[1]);
57157
57308
  if (refs.length === 0) {
@@ -57191,7 +57342,7 @@ async function checkPathRefsValid(projectDir) {
57191
57342
  logger.verbose("Skipping potentially unsafe path reference", { ref, refPath });
57192
57343
  continue;
57193
57344
  }
57194
- if (!existsSync40(normalizedPath)) {
57345
+ if (!existsSync41(normalizedPath)) {
57195
57346
  broken.push(ref);
57196
57347
  }
57197
57348
  }
@@ -57231,9 +57382,9 @@ async function checkPathRefsValid(projectDir) {
57231
57382
  }
57232
57383
  // src/domains/health-checks/checkers/config-completeness-checker.ts
57233
57384
  init_paths();
57234
- import { existsSync as existsSync41 } from "node:fs";
57385
+ import { existsSync as existsSync42 } from "node:fs";
57235
57386
  import { readdir as readdir24 } from "node:fs/promises";
57236
- import { join as join80 } from "node:path";
57387
+ import { join as join81 } from "node:path";
57237
57388
  async function checkProjectConfigCompleteness(setup, projectDir) {
57238
57389
  if (setup.globals.some((g2) => g2.path === setup.project.path)) {
57239
57390
  return {
@@ -57250,12 +57401,12 @@ async function checkProjectConfigCompleteness(setup, projectDir) {
57250
57401
  const requiredDirs = ["agents", "commands", "skills"];
57251
57402
  const missingDirs = [];
57252
57403
  for (const dir of requiredDirs) {
57253
- const dirPath = join80(projectClaudeDir, dir);
57254
- if (!existsSync41(dirPath)) {
57404
+ const dirPath = join81(projectClaudeDir, dir);
57405
+ if (!existsSync42(dirPath)) {
57255
57406
  missingDirs.push(dir);
57256
57407
  }
57257
57408
  }
57258
- const hasRulesOrWorkflows = existsSync41(join80(projectClaudeDir, "rules")) || existsSync41(join80(projectClaudeDir, "workflows"));
57409
+ const hasRulesOrWorkflows = existsSync42(join81(projectClaudeDir, "rules")) || existsSync42(join81(projectClaudeDir, "workflows"));
57259
57410
  if (!hasRulesOrWorkflows) {
57260
57411
  missingDirs.push("rules");
57261
57412
  }
@@ -57335,6 +57486,8 @@ class TakumiChecker {
57335
57486
  }
57336
57487
  logger.verbose("TakumiChecker: Checking hooks directory");
57337
57488
  results.push(await checkHooksExist(this.projectDir));
57489
+ logger.verbose("TakumiChecker: Checking Codex hook health");
57490
+ results.push(...await checkCodexHooksHealth());
57338
57491
  logger.verbose("TakumiChecker: Checking settings.json validity");
57339
57492
  results.push(await checkSettingsValid(this.projectDir));
57340
57493
  logger.verbose("TakumiChecker: Checking path references");
@@ -57692,9 +57845,9 @@ import { platform as platform7 } from "node:os";
57692
57845
  // src/domains/health-checks/platform/environment-checker.ts
57693
57846
  init_registry();
57694
57847
  init_environment();
57695
- import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile35, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
57848
+ import { constants as constants2, access as access2, mkdir as mkdir19, readFile as readFile36, unlink as unlink8, writeFile as writeFile24 } from "node:fs/promises";
57696
57849
  import { arch as arch2, homedir as homedir25, platform as platform6 } from "node:os";
57697
- import { join as join82, normalize as normalize7 } from "node:path";
57850
+ import { join as join83, normalize as normalize7 } from "node:path";
57698
57851
  function shouldSkipExpensiveOperations4() {
57699
57852
  return shouldSkipExpensiveOperations();
57700
57853
  }
@@ -57787,11 +57940,11 @@ async function checkGlobalDirAccess(provider) {
57787
57940
  autoFixable: false
57788
57941
  };
57789
57942
  }
57790
- const testFile = join82(globalDir, ".sk-doctor-access-test");
57943
+ const testFile = join83(globalDir, ".sk-doctor-access-test");
57791
57944
  try {
57792
57945
  await mkdir19(globalDir, { recursive: true });
57793
57946
  await writeFile24(testFile, "test", "utf-8");
57794
- const content = await readFile35(testFile, "utf-8");
57947
+ const content = await readFile36(testFile, "utf-8");
57795
57948
  await unlink8(testFile);
57796
57949
  if (content !== "test")
57797
57950
  throw new Error("Read mismatch");
@@ -57865,7 +58018,7 @@ async function checkWSLBoundary() {
57865
58018
  // src/domains/health-checks/platform/windows-checker.ts
57866
58019
  init_registry();
57867
58020
  import { mkdir as mkdir20, symlink as symlink2, unlink as unlink9, writeFile as writeFile25 } from "node:fs/promises";
57868
- import { join as join83 } from "node:path";
58021
+ import { join as join84 } from "node:path";
57869
58022
  async function checkLongPathSupport() {
57870
58023
  if (shouldSkipExpensiveOperations4()) {
57871
58024
  return {
@@ -57917,8 +58070,8 @@ async function checkSymlinkSupport() {
57917
58070
  };
57918
58071
  }
57919
58072
  const testDir = getInstaller("claude-code")?.globalRoot() ?? "";
57920
- const target = join83(testDir, ".sk-symlink-test-target");
57921
- const link = join83(testDir, ".sk-symlink-test-link");
58073
+ const target = join84(testDir, ".sk-symlink-test-target");
58074
+ const link = join84(testDir, ".sk-symlink-test-link");
57922
58075
  try {
57923
58076
  await mkdir20(testDir, { recursive: true });
57924
58077
  await writeFile25(target, "test", "utf-8");
@@ -58214,7 +58367,7 @@ class AutoHealer {
58214
58367
  import { execSync as execSync4, spawnSync as spawnSync4 } from "node:child_process";
58215
58368
  import { readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "node:fs";
58216
58369
  import { tmpdir as tmpdir2 } from "node:os";
58217
- import { dirname as dirname20, join as join84 } from "node:path";
58370
+ import { dirname as dirname20, join as join85 } from "node:path";
58218
58371
  import { fileURLToPath as fileURLToPath2 } from "node:url";
58219
58372
  init_environment();
58220
58373
  init_logger();
@@ -58222,7 +58375,7 @@ init_dist2();
58222
58375
  function getCliVersion3() {
58223
58376
  try {
58224
58377
  const __dirname3 = dirname20(fileURLToPath2(import.meta.url));
58225
- const pkgPath = join84(__dirname3, "../../../package.json");
58378
+ const pkgPath = join85(__dirname3, "../../../package.json");
58226
58379
  const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
58227
58380
  return pkg.version || "unknown";
58228
58381
  } catch (err) {
@@ -58361,7 +58514,7 @@ class ReportGenerator {
58361
58514
  return null;
58362
58515
  }
58363
58516
  }
58364
- const tmpFile = join84(tmpdir2(), `sk-report-${Date.now()}.txt`);
58517
+ const tmpFile = join85(tmpdir2(), `sk-report-${Date.now()}.txt`);
58365
58518
  writeFileSync6(tmpFile, report);
58366
58519
  try {
58367
58520
  const result = spawnSync4("gh", ["gist", "create", tmpFile, "--desc", "Takumi Diagnostic Report"], {
@@ -58674,7 +58827,7 @@ async function authedFetch(url, init) {
58674
58827
  // src/commands/hooks/lib/detached-put.ts
58675
58828
  import { spawn as spawn2 } from "node:child_process";
58676
58829
  import { openSync as openSync4 } from "node:fs";
58677
- import { dirname as dirname21, join as join85 } from "node:path";
58830
+ import { dirname as dirname21, join as join86 } from "node:path";
58678
58831
 
58679
58832
  // src/commands/hooks/lib/hook-logger.ts
58680
58833
  import { appendFileSync } from "node:fs";
@@ -58721,7 +58874,7 @@ function effectiveDetachMode(flags) {
58721
58874
  return flags.noDetach ? "inline" : "detached";
58722
58875
  }
58723
58876
  function sessionDebugLogPath(sessionDir) {
58724
- return join85(sessionDir, DETACH_DEBUG_LOG_NAME);
58877
+ return join86(sessionDir, DETACH_DEBUG_LOG_NAME);
58725
58878
  }
58726
58879
  var BUNFS_PREFIX = "/$bunfs/";
58727
58880
  function resolveInvocationPrefix() {
@@ -58751,7 +58904,7 @@ function resolvePreloadScript(entryPath) {
58751
58904
  try {
58752
58905
  const srcDir = dirname21(entryPath);
58753
58906
  const repoRoot = dirname21(srcDir);
58754
- return join85(repoRoot, "scripts", "preload-config-override.ts");
58907
+ return join86(repoRoot, "scripts", "preload-config-override.ts");
58755
58908
  } catch {
58756
58909
  return null;
58757
58910
  }
@@ -58823,13 +58976,13 @@ import { promises as fs13 } from "node:fs";
58823
58976
 
58824
58977
  // src/commands/hooks/lib/session-paths.ts
58825
58978
  init_paths2();
58826
- import { join as join87 } from "node:path";
58979
+ import { join as join88 } from "node:path";
58827
58980
 
58828
58981
  // src/commands/hooks/lib/project-paths.ts
58829
58982
  init_paths2();
58830
58983
  import { createHash as createHash8 } from "node:crypto";
58831
58984
  import { realpathSync as realpathSync2 } from "node:fs";
58832
- import { basename as basename12, join as join86 } from "node:path";
58985
+ import { basename as basename12, join as join87 } from "node:path";
58833
58986
  function encodeCwd(cwd2) {
58834
58987
  const stripped = cwd2.replace(/^\/+/, "");
58835
58988
  const sanitized = stripped.replace(/[^a-zA-Z0-9-]/g, "-");
@@ -58848,10 +59001,10 @@ function getProjectLabel(cwd2) {
58848
59001
  return basename12(cwd2) || "";
58849
59002
  }
58850
59003
  function getProjectsRoot() {
58851
- return join86(getConfigDir(), "projects");
59004
+ return join87(getConfigDir(), "projects");
58852
59005
  }
58853
59006
  function getProjectDir(args) {
58854
- return join86(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
59007
+ return join87(getProjectsRoot(), encodeCwd(args.cwd), args.agent);
58855
59008
  }
58856
59009
 
58857
59010
  // src/commands/hooks/lib/session-paths.ts
@@ -58863,25 +59016,25 @@ function safeSessionSegment(sessionId) {
58863
59016
  return cleaned.length > 0 ? cleaned.slice(0, MAX_SESSION_ID_LEN) : null;
58864
59017
  }
58865
59018
  function getSessionsRoot() {
58866
- return join87(getConfigDir(), "sessions");
59019
+ return join88(getConfigDir(), "sessions");
58867
59020
  }
58868
59021
  function getSessionDirV2(args) {
58869
59022
  const segment = safeSessionSegment(args.sessionId);
58870
59023
  if (!segment)
58871
59024
  return null;
58872
- return join87(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
59025
+ return join88(getProjectDir({ agent: args.agent, cwd: args.cwd }), "sessions", segment);
58873
59026
  }
58874
59027
  function getEventsFile(sessionDir) {
58875
- return join87(sessionDir, "events.jsonl");
59028
+ return join88(sessionDir, "events.jsonl");
58876
59029
  }
58877
59030
  function getSummaryFile(sessionDir) {
58878
- return join87(sessionDir, "summary.json");
59031
+ return join88(sessionDir, "summary.json");
58879
59032
  }
58880
59033
  function getLastPushFile(sessionDir) {
58881
- return join87(sessionDir, "last_push.txt");
59034
+ return join88(sessionDir, "last_push.txt");
58882
59035
  }
58883
59036
  function getMetaFile(sessionDir) {
58884
- return join87(sessionDir, "meta.json");
59037
+ return join88(sessionDir, "meta.json");
58885
59038
  }
58886
59039
 
58887
59040
  // src/commands/hooks/lib/throttle.ts
@@ -59499,9 +59652,9 @@ function resolveEndpoint() {
59499
59652
 
59500
59653
  // src/commands/hooks/lib/manifest-versions.ts
59501
59654
  init_manifest_path_resolver();
59502
- import { existsSync as existsSync43, readFileSync as readFileSync12 } from "node:fs";
59655
+ import { existsSync as existsSync44, readFileSync as readFileSync12 } from "node:fs";
59503
59656
  import { homedir as homedir26 } from "node:os";
59504
- import { dirname as dirname22, join as join88, resolve as resolve18 } from "node:path";
59657
+ import { dirname as dirname22, join as join89, resolve as resolve18 } from "node:path";
59505
59658
  var PROVIDER_DIRS = [".claude", ".codex"];
59506
59659
  var MAX_WALK = 6;
59507
59660
  function readManifestRaw(path10) {
@@ -59520,8 +59673,8 @@ function findManifest(cwd2) {
59520
59673
  let dir = resolve18(cwd2);
59521
59674
  for (let i = 0;i < MAX_WALK; i++) {
59522
59675
  for (const provider of PROVIDER_DIRS) {
59523
- const providerRoot = join88(dir, provider);
59524
- if (existsSync43(providerRoot)) {
59676
+ const providerRoot = join89(dir, provider);
59677
+ if (existsSync44(providerRoot)) {
59525
59678
  const path10 = findManifestInProviderDir(providerRoot);
59526
59679
  if (path10)
59527
59680
  return path10;
@@ -59534,11 +59687,11 @@ function findManifest(cwd2) {
59534
59687
  }
59535
59688
  const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
59536
59689
  if (pluginRoot) {
59537
- const pluginPath = findManifestInProviderDir(join88(pluginRoot, ".claude"));
59690
+ const pluginPath = findManifestInProviderDir(join89(pluginRoot, ".claude"));
59538
59691
  if (pluginPath)
59539
59692
  return pluginPath;
59540
59693
  }
59541
- const globalPath = findManifestInProviderDir(join88(homedir26(), ".claude"));
59694
+ const globalPath = findManifestInProviderDir(join89(homedir26(), ".claude"));
59542
59695
  if (globalPath)
59543
59696
  return globalPath;
59544
59697
  return null;
@@ -59653,8 +59806,8 @@ async function handleSessionEnd(agent, flags = {}) {
59653
59806
  session_end_raw: data
59654
59807
  };
59655
59808
  const { promises: fs18 } = await import("node:fs");
59656
- const { join: join89 } = await import("node:path");
59657
- const target = join89(sessionDir, "meta.json");
59809
+ const { join: join90 } = await import("node:path");
59810
+ const target = join90(sessionDir, "meta.json");
59658
59811
  const tmp = `${target}.tmp`;
59659
59812
  await fs18.writeFile(tmp, JSON.stringify(updated), "utf8");
59660
59813
  await fs18.rename(tmp, target);
@@ -59725,7 +59878,7 @@ init_auth_client();
59725
59878
 
59726
59879
  // src/commands/hooks/lib/retention.ts
59727
59880
  import { promises as fs18 } from "node:fs";
59728
- import { join as join89 } from "node:path";
59881
+ import { join as join90 } from "node:path";
59729
59882
  async function hasLastPush(dir) {
59730
59883
  try {
59731
59884
  await fs18.access(getLastPushFile(dir));
@@ -59755,7 +59908,7 @@ async function decideDelete(dir, args) {
59755
59908
  async function listChildren(dir) {
59756
59909
  try {
59757
59910
  const names = await fs18.readdir(dir);
59758
- return names.map((n) => join89(dir, n));
59911
+ return names.map((n) => join90(dir, n));
59759
59912
  } catch {
59760
59913
  return [];
59761
59914
  }
@@ -59766,7 +59919,7 @@ async function collectV2Sessions() {
59766
59919
  const sessions = [];
59767
59920
  for (const projectDir of projects) {
59768
59921
  for (const agentDir of await listChildren(projectDir)) {
59769
- for (const sessionDir of await listChildren(join89(agentDir, "sessions"))) {
59922
+ for (const sessionDir of await listChildren(join90(agentDir, "sessions"))) {
59770
59923
  sessions.push(sessionDir);
59771
59924
  }
59772
59925
  }
@@ -60166,7 +60319,7 @@ init_hooks_settings_merger();
60166
60319
 
60167
60320
  // src/commands/portable/settings-write-with-confirm.ts
60168
60321
  init_safe_prompts();
60169
- import { existsSync as existsSync44, mkdirSync as mkdirSync4, readFileSync as readFileSync13, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "node:fs";
60322
+ import { existsSync as existsSync45, mkdirSync as mkdirSync4, readFileSync as readFileSync13, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "node:fs";
60170
60323
  import { dirname as dirname23 } from "node:path";
60171
60324
 
60172
60325
  // node_modules/diff/libesm/diff/base.js
@@ -61339,7 +61492,7 @@ var EMPTY_RESULT = (status2) => ({
61339
61492
  backupPath: null
61340
61493
  });
61341
61494
  function readCurrent(path10) {
61342
- if (!existsSync44(path10))
61495
+ if (!existsSync45(path10))
61343
61496
  return { kind: "missing" };
61344
61497
  let raw = "";
61345
61498
  try {
@@ -61456,18 +61609,18 @@ init_dist2();
61456
61609
  // src/commands/hooks/lib/agent-target-picker.ts
61457
61610
  init_safe_prompts();
61458
61611
  init_dist2();
61459
- import { existsSync as existsSync45 } from "node:fs";
61612
+ import { existsSync as existsSync46 } from "node:fs";
61460
61613
 
61461
61614
  // src/commands/hooks/lib/settings-path-resolver.ts
61462
61615
  import { lstatSync as lstatSync3, realpathSync as realpathSync3 } from "node:fs";
61463
61616
  import { homedir as homedir27 } from "node:os";
61464
- import { join as join90 } from "node:path";
61617
+ import { join as join91 } from "node:path";
61465
61618
  function rawPath(agent, global3) {
61466
61619
  const root = global3 ? homedir27() : process.cwd();
61467
61620
  if (agent === "claude") {
61468
- return join90(root, ".claude", "settings.json");
61621
+ return join91(root, ".claude", "settings.json");
61469
61622
  }
61470
- return join90(root, ".codex", "hooks.json");
61623
+ return join91(root, ".codex", "hooks.json");
61471
61624
  }
61472
61625
  function resolveSettingsPath(agent, options2 = {}) {
61473
61626
  const originalPath = rawPath(agent, Boolean(options2.global));
@@ -61495,7 +61648,7 @@ function probe(global3) {
61495
61648
  return {
61496
61649
  agent,
61497
61650
  path: location2.realPath,
61498
- exists: existsSync45(location2.realPath)
61651
+ exists: existsSync46(location2.realPath)
61499
61652
  };
61500
61653
  });
61501
61654
  }
@@ -61540,7 +61693,7 @@ async function promptHookAgentTargets(options2) {
61540
61693
 
61541
61694
  // src/commands/hooks/lib/entry-builder.ts
61542
61695
  init_capabilities();
61543
- var TIMEOUT_SECONDS = 2;
61696
+ var TIMEOUT_SECONDS = 10;
61544
61697
  var DEFAULT_HOOK_BIN = "tkm";
61545
61698
  var CLAUDE_SESSION_START_MATCHER = "startup|resume|clear|compact";
61546
61699
  var HOOK_EVENT_TO_CLAUDE_EVENT = {
@@ -61610,7 +61763,7 @@ function buildHookSection(agent, bin, flags = {}) {
61610
61763
 
61611
61764
  // src/commands/hooks/uninstall-handler.ts
61612
61765
  init_logger();
61613
- import { existsSync as existsSync46, mkdirSync as mkdirSync5, readFileSync as readFileSync14, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
61766
+ import { existsSync as existsSync47, mkdirSync as mkdirSync5, readFileSync as readFileSync14, renameSync as renameSync3, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
61614
61767
  import { dirname as dirname24 } from "node:path";
61615
61768
  var AGENT_DISPLAY2 = {
61616
61769
  claude: "Claude Code",
@@ -61665,7 +61818,7 @@ async function uninstallForAgent(agent, options2) {
61665
61818
  removed: 0,
61666
61819
  dryRun: Boolean(options2.dryRun)
61667
61820
  };
61668
- if (!existsSync46(location2.realPath)) {
61821
+ if (!existsSync47(location2.realPath)) {
61669
61822
  return result;
61670
61823
  }
61671
61824
  let parsed;
@@ -63219,7 +63372,7 @@ init_logger();
63219
63372
  init_safe_spinner();
63220
63373
  import { mkdir as mkdir25, stat as stat10 } from "node:fs/promises";
63221
63374
  import { tmpdir as tmpdir3 } from "node:os";
63222
- import { join as join96 } from "node:path";
63375
+ import { join as join97 } from "node:path";
63223
63376
 
63224
63377
  // src/shared/temp-cleanup.ts
63225
63378
  init_logger();
@@ -63238,7 +63391,7 @@ init_logger();
63238
63391
  init_output_manager();
63239
63392
  import { createWriteStream as createWriteStream2, rmSync as rmSync5 } from "node:fs";
63240
63393
  import { mkdir as mkdir21 } from "node:fs/promises";
63241
- import { join as join91 } from "node:path";
63394
+ import { join as join92 } from "node:path";
63242
63395
 
63243
63396
  // src/shared/progress-bar.ts
63244
63397
  init_output_manager();
@@ -63448,7 +63601,7 @@ var MAX_DOWNLOAD_SIZE = 500 * 1024 * 1024;
63448
63601
  class FileDownloader {
63449
63602
  async downloadAsset(asset, destDir) {
63450
63603
  try {
63451
- const destPath = join91(destDir, asset.name);
63604
+ const destPath = join92(destDir, asset.name);
63452
63605
  await mkdir21(destDir, { recursive: true });
63453
63606
  output.info(`Downloading ${asset.name} (${formatBytes(asset.size)})...`);
63454
63607
  logger.verbose("Download details", {
@@ -63533,7 +63686,7 @@ class FileDownloader {
63533
63686
  }
63534
63687
  async downloadFile(params) {
63535
63688
  const { url, name, size, destDir, token } = params;
63536
- const destPath = join91(destDir, name);
63689
+ const destPath = join92(destDir, name);
63537
63690
  await mkdir21(destDir, { recursive: true });
63538
63691
  output.info(`Downloading ${name}${size ? ` (${formatBytes(size)})` : ""}...`);
63539
63692
  const headers = {};
@@ -63636,7 +63789,7 @@ init_logger();
63636
63789
  init_types2();
63637
63790
  import { constants as constants3 } from "node:fs";
63638
63791
  import { access as access3, readdir as readdir25 } from "node:fs/promises";
63639
- import { join as join92 } from "node:path";
63792
+ import { join as join93 } from "node:path";
63640
63793
  async function validateExtraction(extractDir) {
63641
63794
  try {
63642
63795
  const entries = await readdir25(extractDir, { encoding: "utf8" });
@@ -63648,7 +63801,7 @@ async function validateExtraction(extractDir) {
63648
63801
  const missingPaths = [];
63649
63802
  for (const path10 of criticalPaths) {
63650
63803
  try {
63651
- await access3(join92(extractDir, path10), constants3.F_OK);
63804
+ await access3(join93(extractDir, path10), constants3.F_OK);
63652
63805
  logger.debug(`Found: ${path10}`);
63653
63806
  } catch {
63654
63807
  logger.warning(`Expected path not found: ${path10}`);
@@ -63670,7 +63823,7 @@ async function validateExtraction(extractDir) {
63670
63823
  // src/domains/installation/extraction/tar-extractor.ts
63671
63824
  init_logger();
63672
63825
  import { copyFile as copyFile5, mkdir as mkdir23, readdir as readdir27, rm as rm7, stat as stat8 } from "node:fs/promises";
63673
- import { join as join94 } from "node:path";
63826
+ import { join as join95 } from "node:path";
63674
63827
 
63675
63828
  // node_modules/tar/dist/esm/index.min.js
63676
63829
  import Kr from "events";
@@ -66883,7 +67036,7 @@ function decodeFilePath(path10) {
66883
67036
  init_logger();
66884
67037
  init_types2();
66885
67038
  import { copyFile as copyFile4, lstat as lstat6, mkdir as mkdir22, readdir as readdir26 } from "node:fs/promises";
66886
- import { join as join93, relative as relative15 } from "node:path";
67039
+ import { join as join94, relative as relative15 } from "node:path";
66887
67040
  async function withRetry2(fn2, retries = 3) {
66888
67041
  for (let i = 0;i < retries; i++) {
66889
67042
  try {
@@ -66905,8 +67058,8 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
66905
67058
  await mkdir22(destDir, { recursive: true });
66906
67059
  const entries = await readdir26(sourceDir, { encoding: "utf8" });
66907
67060
  for (const entry of entries) {
66908
- const sourcePath = join93(sourceDir, entry);
66909
- const destPath = join93(destDir, entry);
67061
+ const sourcePath = join94(sourceDir, entry);
67062
+ const destPath = join94(destDir, entry);
66910
67063
  const relativePath = relative15(sourceDir, sourcePath);
66911
67064
  if (!isPathSafe(destDir, destPath)) {
66912
67065
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -66933,8 +67086,8 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
66933
67086
  await mkdir22(destDir, { recursive: true });
66934
67087
  const entries = await readdir26(sourceDir, { encoding: "utf8" });
66935
67088
  for (const entry of entries) {
66936
- const sourcePath = join93(sourceDir, entry);
66937
- const destPath = join93(destDir, entry);
67089
+ const sourcePath = join94(sourceDir, entry);
67090
+ const destPath = join94(destDir, entry);
66938
67091
  const relativePath = relative15(sourceDir, sourcePath);
66939
67092
  if (!isPathSafe(destDir, destPath)) {
66940
67093
  logger.warning(`Skipping unsafe path: ${relativePath}`);
@@ -66989,7 +67142,7 @@ class TarExtractor {
66989
67142
  logger.debug(`Root entries: ${entries.join(", ")}`);
66990
67143
  if (entries.length === 1) {
66991
67144
  const rootEntry = entries[0];
66992
- const rootPath = join94(tempExtractDir, rootEntry);
67145
+ const rootPath = join95(tempExtractDir, rootEntry);
66993
67146
  const rootStat = await stat8(rootPath);
66994
67147
  if (rootStat.isDirectory()) {
66995
67148
  const rootContents = await readdir27(rootPath, { encoding: "utf8" });
@@ -67005,7 +67158,7 @@ class TarExtractor {
67005
67158
  }
67006
67159
  } else {
67007
67160
  await mkdir23(destDir, { recursive: true });
67008
- await copyFile5(rootPath, join94(destDir, rootEntry));
67161
+ await copyFile5(rootPath, join95(destDir, rootEntry));
67009
67162
  }
67010
67163
  } else {
67011
67164
  logger.debug("Multiple root entries - moving all");
@@ -67026,7 +67179,7 @@ class TarExtractor {
67026
67179
  init_logger();
67027
67180
  import { createWriteStream as createWriteStream3 } from "node:fs";
67028
67181
  import { chmod as chmod3, copyFile as copyFile6, mkdir as mkdir24, readdir as readdir28, rm as rm8, stat as stat9 } from "node:fs/promises";
67029
- import { dirname as dirname25, join as join95, resolve as resolve20 } from "node:path";
67182
+ import { dirname as dirname25, join as join96, resolve as resolve20 } from "node:path";
67030
67183
  import { pipeline } from "node:stream/promises";
67031
67184
  import yauzl from "yauzl-promise";
67032
67185
  class ZipExtractor {
@@ -67040,7 +67193,7 @@ class ZipExtractor {
67040
67193
  logger.debug(`Root entries: ${entries.join(", ")}`);
67041
67194
  if (entries.length === 1) {
67042
67195
  const rootEntry = entries[0];
67043
- const rootPath = join95(tempExtractDir, rootEntry);
67196
+ const rootPath = join96(tempExtractDir, rootEntry);
67044
67197
  const rootStat = await stat9(rootPath);
67045
67198
  if (rootStat.isDirectory()) {
67046
67199
  const rootContents = await readdir28(rootPath, { encoding: "utf8" });
@@ -67056,7 +67209,7 @@ class ZipExtractor {
67056
67209
  }
67057
67210
  } else {
67058
67211
  await mkdir24(destDir, { recursive: true });
67059
- await copyFile6(rootPath, join95(destDir, rootEntry));
67212
+ await copyFile6(rootPath, join96(destDir, rootEntry));
67060
67213
  }
67061
67214
  } else {
67062
67215
  logger.debug("Multiple root entries - moving all");
@@ -67185,7 +67338,7 @@ class DownloadManager {
67185
67338
  async createTempDir() {
67186
67339
  const timestamp = Date.now();
67187
67340
  const counter = DownloadManager.tempDirCounter++;
67188
- const primaryTempDir = join96(tmpdir3(), `takumi-${timestamp}-${counter}`);
67341
+ const primaryTempDir = join97(tmpdir3(), `takumi-${timestamp}-${counter}`);
67189
67342
  try {
67190
67343
  await mkdir25(primaryTempDir, { recursive: true });
67191
67344
  logger.debug(`Created temp directory: ${primaryTempDir}`);
@@ -67202,7 +67355,7 @@ Solutions:
67202
67355
  2. Set HOME environment variable
67203
67356
  3. Try running from a different directory`);
67204
67357
  }
67205
- const fallbackTempDir = join96(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
67358
+ const fallbackTempDir = join97(homeDir, ".sunagentkit", "tmp", `takumi-${timestamp}-${counter}`);
67206
67359
  try {
67207
67360
  await mkdir25(fallbackTempDir, { recursive: true });
67208
67361
  logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
@@ -67908,7 +68061,7 @@ Re-run with explicit base kit, e.g. --kit ${BASE_KIT} --kit ${parsed2.join(" --k
67908
68061
  }
67909
68062
  // src/commands/init/phases/selection-handler.ts
67910
68063
  import { mkdir as mkdir26 } from "node:fs/promises";
67911
- import { join as join100, resolve as resolve24 } from "node:path";
68064
+ import { join as join101, resolve as resolve24 } from "node:path";
67912
68065
 
67913
68066
  // src/commands/shared/agent-selector.ts
67914
68067
  init_registry();
@@ -68061,8 +68214,8 @@ init_logger();
68061
68214
  init_safe_spinner();
68062
68215
  init_takumi_constants();
68063
68216
  var import_fs_extra31 = __toESM(require_lib(), 1);
68064
- import { existsSync as existsSync49, readdirSync as readdirSync6, rmSync as rmSync6, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
68065
- import { dirname as dirname28, join as join99, resolve as resolve23 } 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";
68066
68219
  var TAKUMI_SUBDIRECTORIES = ["commands", "agents", "skills", "rules", "hooks"];
68067
68220
  async function analyzeFreshInstallation(claudeDir) {
68068
68221
  const metadata = await readManifest(claudeDir);
@@ -68132,9 +68285,9 @@ async function removeFilesByOwnership(claudeDir, analysis, includeModified) {
68132
68285
  const filesToRemove = includeModified ? [...analysis.ckFiles, ...analysis.ckModifiedFiles] : analysis.ckFiles;
68133
68286
  const filesToPreserve = includeModified ? analysis.userFiles : [...analysis.ckModifiedFiles, ...analysis.userFiles];
68134
68287
  for (const file of filesToRemove) {
68135
- const fullPath = join99(claudeDir, file.path);
68288
+ const fullPath = join100(claudeDir, file.path);
68136
68289
  try {
68137
- if (existsSync49(fullPath)) {
68290
+ if (existsSync50(fullPath)) {
68138
68291
  unlinkSync5(fullPath);
68139
68292
  removedFiles.push(file.path);
68140
68293
  logger.debug(`Removed: ${file.path}`);
@@ -68206,7 +68359,7 @@ async function removeSubdirectoriesFallback(claudeDir) {
68206
68359
  const removedFiles = [];
68207
68360
  let removedDirCount = 0;
68208
68361
  for (const subdir of TAKUMI_SUBDIRECTORIES) {
68209
- const subdirPath = join99(claudeDir, subdir);
68362
+ const subdirPath = join100(claudeDir, subdir);
68210
68363
  if (await import_fs_extra31.pathExists(subdirPath)) {
68211
68364
  rmSync6(subdirPath, { recursive: true, force: true });
68212
68365
  removedDirCount++;
@@ -68431,7 +68584,7 @@ async function handleSelection(ctx) {
68431
68584
  }
68432
68585
  if (!ctx.options.fresh) {
68433
68586
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
68434
- const claudeDir = prefix ? join100(resolvedDir, prefix) : resolvedDir;
68587
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
68435
68588
  try {
68436
68589
  const existingMetadata = await readManifest(claudeDir);
68437
68590
  if (existingMetadata?.kits) {
@@ -68464,7 +68617,7 @@ async function handleSelection(ctx) {
68464
68617
  }
68465
68618
  if (ctx.options.fresh) {
68466
68619
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
68467
- const claudeDir = prefix ? join100(resolvedDir, prefix) : resolvedDir;
68620
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
68468
68621
  const canProceed = await handleFreshInstallation(claudeDir, ctx.prompts);
68469
68622
  if (!canProceed) {
68470
68623
  return { ...ctx, cancelled: true };
@@ -68484,7 +68637,7 @@ async function handleSelection(ctx) {
68484
68637
  let currentVersion = null;
68485
68638
  try {
68486
68639
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
68487
- const claudeDir = prefix ? join100(resolvedDir, prefix) : resolvedDir;
68640
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
68488
68641
  const existingMetadata = await readManifest(claudeDir);
68489
68642
  currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
68490
68643
  if (currentVersion) {
@@ -68572,7 +68725,7 @@ async function handleSelection(ctx) {
68572
68725
  if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && releaseTag && !isOfflineMode) {
68573
68726
  try {
68574
68727
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
68575
- const claudeDir = prefix ? join100(resolvedDir, prefix) : resolvedDir;
68728
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
68576
68729
  const existingMetadata = await readManifest(claudeDir);
68577
68730
  const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
68578
68731
  if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
@@ -68595,7 +68748,7 @@ async function handleSelection(ctx) {
68595
68748
  let currentSecondaryVersion = null;
68596
68749
  try {
68597
68750
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
68598
- const claudeDir = prefix ? join100(resolvedDir, prefix) : resolvedDir;
68751
+ const claudeDir = prefix ? join101(resolvedDir, prefix) : resolvedDir;
68599
68752
  const existingMetadata = await readManifest(claudeDir);
68600
68753
  currentSecondaryVersion = existingMetadata?.kits?.[secondaryKit]?.version || null;
68601
68754
  } catch {}
@@ -68678,13 +68831,13 @@ function resolveGlobalTargetDir(targetAgents2) {
68678
68831
  }
68679
68832
  // src/commands/init/phases/sync-handler.ts
68680
68833
  init_paths();
68681
- 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";
68682
- import { dirname as dirname29, join as join103, resolve as resolve25 } 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";
68683
68836
 
68684
68837
  // src/domains/sync/config-version-checker.ts
68685
68838
  init_auth_client();
68686
- import { mkdir as mkdir27, readFile as readFile37, unlink as unlink10, writeFile as writeFile27 } from "node:fs/promises";
68687
- import { join as join101 } 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";
68688
68841
  init_version_utils();
68689
68842
  init_logger();
68690
68843
  init_path_resolver();
@@ -68720,12 +68873,12 @@ var CACHE_FILENAME = "config-update-cache.json";
68720
68873
  class ConfigVersionChecker {
68721
68874
  static getCacheFilePath(kitType, global3) {
68722
68875
  const cacheDir = PathResolver.getCacheDir(global3);
68723
- return join101(cacheDir, `${kitType}-${CACHE_FILENAME}`);
68876
+ return join102(cacheDir, `${kitType}-${CACHE_FILENAME}`);
68724
68877
  }
68725
68878
  static async loadCache(kitType, global3) {
68726
68879
  try {
68727
68880
  const cachePath = ConfigVersionChecker.getCacheFilePath(kitType, global3);
68728
- const data = await readFile37(cachePath, "utf8");
68881
+ const data = await readFile38(cachePath, "utf8");
68729
68882
  const parsed = JSON.parse(data);
68730
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) {
68731
68884
  logger.debug("Invalid cache structure, ignoring");
@@ -68839,8 +68992,8 @@ class ConfigVersionChecker {
68839
68992
  // src/domains/sync/sync-engine.ts
68840
68993
  init_ownership_checker();
68841
68994
  init_logger();
68842
- import { lstat as lstat7, readFile as readFile38, readlink, realpath as realpath3, stat as stat11 } from "node:fs/promises";
68843
- import { isAbsolute as isAbsolute3, join as join102, 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";
68844
68997
  var MAX_SYNC_FILE_SIZE = 10 * 1024 * 1024;
68845
68998
  var MAX_SYMLINK_DEPTH = 20;
68846
68999
  async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEPTH) {
@@ -68852,7 +69005,7 @@ async function validateSymlinkChain(path11, basePath, maxDepth = MAX_SYMLINK_DEP
68852
69005
  if (!stats.isSymbolicLink())
68853
69006
  break;
68854
69007
  const target = await readlink(current);
68855
- const resolvedTarget = isAbsolute3(target) ? target : join102(current, "..", target);
69008
+ const resolvedTarget = isAbsolute3(target) ? target : join103(current, "..", target);
68856
69009
  const normalizedTarget = normalize8(resolvedTarget);
68857
69010
  const rel = relative16(basePath, normalizedTarget);
68858
69011
  if (rel.startsWith("..") || isAbsolute3(rel)) {
@@ -68888,7 +69041,7 @@ async function validateSyncPath(basePath, filePath) {
68888
69041
  if (normalized.startsWith("..") || normalized.includes("/../")) {
68889
69042
  throw new Error(`Path traversal not allowed: ${filePath}`);
68890
69043
  }
68891
- const fullPath = join102(basePath, normalized);
69044
+ const fullPath = join103(basePath, normalized);
68892
69045
  const rel = relative16(basePath, fullPath);
68893
69046
  if (rel.startsWith("..") || isAbsolute3(rel)) {
68894
69047
  throw new Error(`Path escapes base directory: ${filePath}`);
@@ -68903,7 +69056,7 @@ async function validateSyncPath(basePath, filePath) {
68903
69056
  }
68904
69057
  } catch (error) {
68905
69058
  if (error.code === "ENOENT") {
68906
- const parentPath = join102(fullPath, "..");
69059
+ const parentPath = join103(fullPath, "..");
68907
69060
  try {
68908
69061
  const resolvedBase = await realpath3(basePath);
68909
69062
  const resolvedParent = await realpath3(parentPath);
@@ -69074,7 +69227,7 @@ class SyncEngine {
69074
69227
  if (lstats.size > MAX_SYNC_FILE_SIZE) {
69075
69228
  throw new Error(`File too large for sync (${Math.round(lstats.size / 1024 / 1024)}MB > ${MAX_SYNC_FILE_SIZE / 1024 / 1024}MB limit)`);
69076
69229
  }
69077
- const buffer = await readFile38(filePath);
69230
+ const buffer = await readFile39(filePath);
69078
69231
  if (buffer.includes(0)) {
69079
69232
  return { content: "", isBinary: true };
69080
69233
  }
@@ -69394,7 +69547,7 @@ function getLockTimeout() {
69394
69547
  var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
69395
69548
  async function acquireSyncLock(global3) {
69396
69549
  const cacheDir = PathResolver.getCacheDir(global3);
69397
- const lockPath = join103(cacheDir, ".sync-lock");
69550
+ const lockPath = join104(cacheDir, ".sync-lock");
69398
69551
  const startTime = Date.now();
69399
69552
  const lockTimeout = getLockTimeout();
69400
69553
  await mkdir28(dirname29(lockPath), { recursive: true });
@@ -69445,7 +69598,7 @@ async function executeSyncMerge(ctx) {
69445
69598
  try {
69446
69599
  const sourceManifest = await findManifestPath(upstreamDir);
69447
69600
  if (sourceManifest) {
69448
- const content = await readFile39(sourceManifest.path, "utf-8");
69601
+ const content = await readFile40(sourceManifest.path, "utf-8");
69449
69602
  const sourceMetadata = JSON.parse(content);
69450
69603
  deletions = sourceMetadata.deletions || [];
69451
69604
  }
@@ -69475,7 +69628,7 @@ async function executeSyncMerge(ctx) {
69475
69628
  try {
69476
69629
  const sourcePath = await validateSyncPath(upstreamDir, file.path);
69477
69630
  const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
69478
- const targetDir = join103(targetPath, "..");
69631
+ const targetDir = join104(targetPath, "..");
69479
69632
  try {
69480
69633
  await mkdir28(targetDir, { recursive: true });
69481
69634
  } catch (mkdirError) {
@@ -69646,7 +69799,7 @@ async function createBackup(claudeDir, files, backupDir) {
69646
69799
  const sourcePath = await validateSyncPath(claudeDir, file.path);
69647
69800
  if (await import_fs_extra33.pathExists(sourcePath)) {
69648
69801
  const targetPath = await validateSyncPath(backupDir, file.path);
69649
- const targetDir = join103(targetPath, "..");
69802
+ const targetDir = join104(targetPath, "..");
69650
69803
  await mkdir28(targetDir, { recursive: true });
69651
69804
  await copyFile7(sourcePath, targetPath);
69652
69805
  }
@@ -69672,38 +69825,38 @@ init_logger();
69672
69825
  init_types2();
69673
69826
  var import_fs_extra34 = __toESM(require_lib(), 1);
69674
69827
  import { rename as rename8, rm as rm9 } from "node:fs/promises";
69675
- import { join as join104, relative as relative17 } from "node:path";
69828
+ import { join as join105, relative as relative17 } from "node:path";
69676
69829
  async function collectDirsToRename(extractDir, folders) {
69677
69830
  const dirsToRename = [];
69678
69831
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
69679
- const docsPath = join104(extractDir, DEFAULT_FOLDERS.docs);
69832
+ const docsPath = join105(extractDir, DEFAULT_FOLDERS.docs);
69680
69833
  if (await import_fs_extra34.pathExists(docsPath)) {
69681
69834
  dirsToRename.push({
69682
69835
  from: docsPath,
69683
- to: join104(extractDir, folders.docs)
69836
+ to: join105(extractDir, folders.docs)
69684
69837
  });
69685
69838
  }
69686
- const claudeDocsPath = join104(extractDir, ".claude", DEFAULT_FOLDERS.docs);
69839
+ const claudeDocsPath = join105(extractDir, ".claude", DEFAULT_FOLDERS.docs);
69687
69840
  if (await import_fs_extra34.pathExists(claudeDocsPath)) {
69688
69841
  dirsToRename.push({
69689
69842
  from: claudeDocsPath,
69690
- to: join104(extractDir, ".claude", folders.docs)
69843
+ to: join105(extractDir, ".claude", folders.docs)
69691
69844
  });
69692
69845
  }
69693
69846
  }
69694
69847
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
69695
- const plansPath = join104(extractDir, DEFAULT_FOLDERS.plans);
69848
+ const plansPath = join105(extractDir, DEFAULT_FOLDERS.plans);
69696
69849
  if (await import_fs_extra34.pathExists(plansPath)) {
69697
69850
  dirsToRename.push({
69698
69851
  from: plansPath,
69699
- to: join104(extractDir, folders.plans)
69852
+ to: join105(extractDir, folders.plans)
69700
69853
  });
69701
69854
  }
69702
- const claudePlansPath = join104(extractDir, ".claude", DEFAULT_FOLDERS.plans);
69855
+ const claudePlansPath = join105(extractDir, ".claude", DEFAULT_FOLDERS.plans);
69703
69856
  if (await import_fs_extra34.pathExists(claudePlansPath)) {
69704
69857
  dirsToRename.push({
69705
69858
  from: claudePlansPath,
69706
- to: join104(extractDir, ".claude", folders.plans)
69859
+ to: join105(extractDir, ".claude", folders.plans)
69707
69860
  });
69708
69861
  }
69709
69862
  }
@@ -69743,8 +69896,8 @@ async function renameFolders(dirsToRename, extractDir, options2) {
69743
69896
  // src/services/transformers/folder-transform/path-replacer.ts
69744
69897
  init_logger();
69745
69898
  init_types2();
69746
- import { readFile as readFile40, readdir as readdir29, writeFile as writeFile29 } from "node:fs/promises";
69747
- import { join as join105, 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";
69748
69901
  var TRANSFORMABLE_FILE_PATTERNS = [
69749
69902
  ".md",
69750
69903
  ".txt",
@@ -69797,7 +69950,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
69797
69950
  let replacementsCount = 0;
69798
69951
  const entries = await readdir29(dir, { withFileTypes: true });
69799
69952
  for (const entry of entries) {
69800
- const fullPath = join105(dir, entry.name);
69953
+ const fullPath = join106(dir, entry.name);
69801
69954
  if (entry.isDirectory()) {
69802
69955
  if (entry.name === "node_modules" || entry.name === ".git") {
69803
69956
  continue;
@@ -69810,7 +69963,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
69810
69963
  if (!shouldTransform)
69811
69964
  continue;
69812
69965
  try {
69813
- const content = await readFile40(fullPath, "utf-8");
69966
+ const content = await readFile41(fullPath, "utf-8");
69814
69967
  let newContent = content;
69815
69968
  let changeCount = 0;
69816
69969
  for (const { regex: regex2, replacement } of compiledReplacements) {
@@ -69932,11 +70085,11 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
69932
70085
 
69933
70086
  // src/services/transformers/global-path-transformer.ts
69934
70087
  init_logger();
69935
- 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";
69936
70089
  import { platform as platform9 } from "node:os";
69937
- import { extname as extname6, join as join106 } from "node:path";
70090
+ import { extname as extname6, join as join107 } from "node:path";
69938
70091
  var IS_WINDOWS3 = platform9() === "win32";
69939
- var HOME_PREFIX = IS_WINDOWS3 ? "%USERPROFILE%" : "$HOME";
70092
+ var HOME_PREFIX = "$HOME";
69940
70093
  function getHomeDirPrefix() {
69941
70094
  return HOME_PREFIX;
69942
70095
  }
@@ -69959,24 +70112,14 @@ function transformContent(content) {
69959
70112
  let transformed = content;
69960
70113
  const homePrefix = getHomeDirPrefix();
69961
70114
  const claudePath = `${homePrefix}/.claude/`;
69962
- if (IS_WINDOWS3) {
69963
- transformed = transformed.replace(/\$HOME\/\.claude\//g, () => {
69964
- changes++;
69965
- return claudePath;
69966
- });
69967
- transformed = transformed.replace(/\$\{HOME\}\/\.claude\//g, () => {
69968
- changes++;
69969
- return claudePath;
69970
- });
69971
- transformed = transformed.replace(/\$HOME(?=\/|\\)/g, () => {
69972
- changes++;
69973
- return homePrefix;
69974
- });
69975
- transformed = transformed.replace(/\$\{HOME\}(?=\/|\\)/g, () => {
69976
- changes++;
69977
- return homePrefix;
69978
- });
69979
- }
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
+ });
69980
70123
  transformed = transformed.replace(/\$CLAUDE_PROJECT_DIR\/\.claude\//g, () => {
69981
70124
  changes++;
69982
70125
  return claudePath;
@@ -69989,12 +70132,10 @@ function transformContent(content) {
69989
70132
  changes++;
69990
70133
  return claudePath;
69991
70134
  });
69992
- if (IS_WINDOWS3) {
69993
- transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%\/\.claude\//g, () => {
69994
- changes++;
69995
- return claudePath;
69996
- });
69997
- }
70135
+ transformed = transformed.replace(/%CLAUDE_PROJECT_DIR%\/\.claude\//g, () => {
70136
+ changes++;
70137
+ return claudePath;
70138
+ });
69998
70139
  transformed = transformed.replace(/\.\/\.claude\//g, () => {
69999
70140
  changes++;
70000
70141
  return claudePath;
@@ -70046,7 +70187,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
70046
70187
  async function processDirectory2(dir) {
70047
70188
  const entries = await readdir30(dir, { withFileTypes: true });
70048
70189
  for (const entry of entries) {
70049
- const fullPath = join106(dir, entry.name);
70190
+ const fullPath = join107(dir, entry.name);
70050
70191
  if (entry.isDirectory()) {
70051
70192
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
70052
70193
  continue;
@@ -70054,7 +70195,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
70054
70195
  await processDirectory2(fullPath);
70055
70196
  } else if (entry.isFile() && shouldTransformFile3(entry.name)) {
70056
70197
  try {
70057
- const content = await readFile41(fullPath, "utf-8");
70198
+ const content = await readFile42(fullPath, "utf-8");
70058
70199
  const { transformed, changes } = transformContent(content);
70059
70200
  if (changes > 0) {
70060
70201
  await writeFile30(fullPath, transformed, "utf-8");
@@ -70313,12 +70454,12 @@ async function initCommand(options2) {
70313
70454
  }
70314
70455
  // src/commands/plan/plan-command.ts
70315
70456
  init_output_manager();
70316
- import { existsSync as existsSync54, statSync as statSync7 } from "node:fs";
70317
- import { dirname as dirname35, join as join110, parse as parse4, resolve as resolve29 } 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";
70318
70459
 
70319
70460
  // src/commands/plan/plan-read-handlers.ts
70320
- import { existsSync as existsSync53, statSync as statSync6 } from "node:fs";
70321
- import { basename as basename15, dirname as dirname34, join as join109, relative as relative19, resolve as resolve27 } 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";
70322
70463
 
70323
70464
  // src/domains/plan-parser/index.ts
70324
70465
  import { dirname as dirname33 } from "node:path";
@@ -70698,20 +70839,20 @@ function parsePlanFile(planFilePath, options2) {
70698
70839
  return { frontmatter, phases };
70699
70840
  }
70700
70841
  // src/domains/plan-parser/plan-scanner.ts
70701
- import { existsSync as existsSync50, readdirSync as readdirSync7 } from "node:fs";
70702
- import { join as join107 } from "node:path";
70842
+ import { existsSync as existsSync51, readdirSync as readdirSync7 } from "node:fs";
70843
+ import { join as join108 } from "node:path";
70703
70844
  function scanPlanDir(dir) {
70704
- if (!existsSync50(dir))
70845
+ if (!existsSync51(dir))
70705
70846
  return [];
70706
70847
  try {
70707
- return readdirSync7(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join107(dir, entry.name, "plan.md")).filter(existsSync50);
70848
+ return readdirSync7(dir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => join108(dir, entry.name, "plan.md")).filter(existsSync51);
70708
70849
  } catch {
70709
70850
  return [];
70710
70851
  }
70711
70852
  }
70712
70853
  // src/domains/plan-parser/plan-validator.ts
70713
70854
  var import_gray_matter6 = __toESM(require_gray_matter(), 1);
70714
- import { existsSync as existsSync51, readFileSync as readFileSync18 } from "node:fs";
70855
+ import { existsSync as existsSync52, readFileSync as readFileSync18 } from "node:fs";
70715
70856
  import { basename as basename13, dirname as dirname31 } from "node:path";
70716
70857
  function validatePlanFile(filePath, strict = false) {
70717
70858
  const content = readFileSync18(filePath, "utf8");
@@ -70751,7 +70892,7 @@ function validatePlanFile(filePath, strict = false) {
70751
70892
  });
70752
70893
  }
70753
70894
  for (const phase of phases) {
70754
- if (phase.file && !existsSync51(phase.file)) {
70895
+ if (phase.file && !existsSync52(phase.file)) {
70755
70896
  const fileBasename = basename13(phase.file);
70756
70897
  const refLine = lines.findIndex((l2) => l2.includes(fileBasename));
70757
70898
  issues.push({
@@ -70772,8 +70913,8 @@ function validatePlanFile(filePath, strict = false) {
70772
70913
  // src/domains/plan-parser/plan-writer.ts
70773
70914
  var import_gray_matter7 = __toESM(require_gray_matter(), 1);
70774
70915
  import { mkdirSync as mkdirSync6, readFileSync as readFileSync19, writeFileSync as writeFileSync9 } from "node:fs";
70775
- import { existsSync as existsSync52 } from "node:fs";
70776
- import { basename as basename14, dirname as dirname32, join as join108 } from "node:path";
70916
+ import { existsSync as existsSync53 } from "node:fs";
70917
+ import { basename as basename14, dirname as dirname32, join as join109 } from "node:path";
70777
70918
  function phaseNameToFilename(id, name) {
70778
70919
  const numMatch = /^(\d+)([a-z]*)$/i.exec(id);
70779
70920
  const num3 = numMatch ? numMatch[1] : id;
@@ -70881,12 +71022,12 @@ function scaffoldPlan(options2) {
70881
71022
  mkdirSync6(dir, { recursive: true });
70882
71023
  const resolvedPhases = resolvePhaseIds(options2.phases);
70883
71024
  const optionsWithResolved = { ...options2, phases: resolvedPhases };
70884
- const planFile = join108(dir, "plan.md");
71025
+ const planFile = join109(dir, "plan.md");
70885
71026
  writeFileSync9(planFile, generatePlanMd(optionsWithResolved), "utf8");
70886
71027
  const phaseFiles = [];
70887
71028
  for (const phase of resolvedPhases) {
70888
71029
  const filename = phaseNameToFilename(phase.id, phase.name);
70889
- const phaseFile = join108(dir, filename);
71030
+ const phaseFile = join109(dir, filename);
70890
71031
  writeFileSync9(phaseFile, generatePhaseTemplate(phase), "utf8");
70891
71032
  phaseFiles.push(phaseFile);
70892
71033
  }
@@ -70954,7 +71095,7 @@ function updatePhaseStatus(planFile, phaseId, newStatus) {
70954
71095
  writeFileSync9(planFile, updatedContent, "utf8");
70955
71096
  const planDir = dirname32(planFile);
70956
71097
  const phaseFilename = phaseNameFilenameFromTableRow(updatedBody, phaseId, planDir);
70957
- if (phaseFilename && existsSync52(phaseFilename)) {
71098
+ if (phaseFilename && existsSync53(phaseFilename)) {
70958
71099
  updatePhaseFileFrontmatter(phaseFilename, newStatus);
70959
71100
  }
70960
71101
  }
@@ -70966,7 +71107,7 @@ function phaseNameFilenameFromTableRow(body, phaseId, planDir) {
70966
71107
  continue;
70967
71108
  const linkMatch = /\[([^\]]+)\]\(\.\/([^)]+)\)/.exec(row);
70968
71109
  if (linkMatch)
70969
- return join108(planDir, linkMatch[2]);
71110
+ return join109(planDir, linkMatch[2]);
70970
71111
  }
70971
71112
  return null;
70972
71113
  }
@@ -71047,7 +71188,7 @@ function addPhase(planFile, name, afterId) {
71047
71188
  `);
71048
71189
  }
71049
71190
  writeFileSync9(planFile, import_gray_matter7.default.stringify(updatedBody, frontmatter), "utf8");
71050
- const phaseFilePath = join108(planDir, filename);
71191
+ const phaseFilePath = join109(planDir, filename);
71051
71192
  writeFileSync9(phaseFilePath, generatePhaseTemplate({ id: phaseId, name }), "utf8");
71052
71193
  return { phaseId, phaseFile: phaseFilePath };
71053
71194
  }
@@ -71151,7 +71292,7 @@ async function handleValidate(target, options2) {
71151
71292
  }
71152
71293
  async function handleStatus(target, options2) {
71153
71294
  const t = target ? resolve27(target) : null;
71154
- const plansDir = t && existsSync53(t) && statSync6(t).isDirectory() && !existsSync53(join109(t, "plan.md")) ? t : null;
71295
+ const plansDir = t && existsSync54(t) && statSync6(t).isDirectory() && !existsSync54(join110(t, "plan.md")) ? t : null;
71155
71296
  if (plansDir) {
71156
71297
  const planFiles = scanPlanDir(plansDir);
71157
71298
  if (planFiles.length === 0) {
@@ -71382,20 +71523,20 @@ async function handleAddPhase(target, options2) {
71382
71523
  // src/commands/plan/plan-command.ts
71383
71524
  function resolvePlanFile(target) {
71384
71525
  const t = target ? resolve29(target) : process.cwd();
71385
- if (existsSync54(t)) {
71526
+ if (existsSync55(t)) {
71386
71527
  const stat13 = statSync7(t);
71387
71528
  if (stat13.isFile())
71388
71529
  return t;
71389
- const candidate = join110(t, "plan.md");
71390
- if (existsSync54(candidate))
71530
+ const candidate = join111(t, "plan.md");
71531
+ if (existsSync55(candidate))
71391
71532
  return candidate;
71392
71533
  }
71393
71534
  if (!target) {
71394
71535
  let dir = process.cwd();
71395
71536
  const root = parse4(dir).root;
71396
71537
  while (dir !== root) {
71397
- const candidate = join110(dir, "plan.md");
71398
- if (existsSync54(candidate))
71538
+ const candidate = join111(dir, "plan.md");
71539
+ if (existsSync55(candidate))
71399
71540
  return candidate;
71400
71541
  dir = dirname35(dir);
71401
71542
  }
@@ -71445,7 +71586,7 @@ async function planCommand(action, target, options2) {
71445
71586
  let resolvedTarget = target;
71446
71587
  if (resolvedAction && !knownActions.has(resolvedAction)) {
71447
71588
  const looksLikePath = resolvedAction.includes("/") || resolvedAction.includes("\\") || resolvedAction.endsWith(".md") || resolvedAction === "." || resolvedAction === "..";
71448
- const existsOnDisk = !looksLikePath && existsSync54(resolve29(resolvedAction));
71589
+ const existsOnDisk = !looksLikePath && existsSync55(resolve29(resolvedAction));
71449
71590
  if (looksLikePath || existsOnDisk) {
71450
71591
  resolvedTarget = resolvedAction;
71451
71592
  resolvedAction = undefined;
@@ -71489,22 +71630,22 @@ init_logger();
71489
71630
  init_logger();
71490
71631
 
71491
71632
  // src/commands/telemetry/shared.ts
71492
- import { existsSync as existsSync55, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
71633
+ import { existsSync as existsSync56, readFileSync as readFileSync20, readdirSync as readdirSync8 } from "node:fs";
71493
71634
  import { homedir as homedir28 } from "node:os";
71494
- import { join as join111 } from "node:path";
71635
+ import { join as join112 } from "node:path";
71495
71636
  init_token_store();
71496
71637
  init_manifest_path_resolver();
71497
71638
  init_takumi_constants();
71498
- var USER_CACHE_PATH = join111(homedir28(), ".claude", "sk-user.json");
71499
- var EVENT_BUFFER_DIR = join111(homedir28(), ".claude", "sk-events");
71500
- var RATE_STATE_PATH = join111(homedir28(), ".claude", "sk-rate-state.json");
71501
- var TAKUMI_MANIFEST_PATH = join111(homedir28(), ".claude", MANIFEST_FILENAME);
71502
- var LEGACY_METADATA_PATH = join111(homedir28(), ".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);
71503
71644
  var TELEMETRY_HOOK_FIELD = "hooks.telemetry";
71504
71645
  var TOKEN_PLACEHOLDER = "__INJECT_AT_RELEASE__";
71505
71646
  function readUserCache() {
71506
71647
  try {
71507
- if (!existsSync55(USER_CACHE_PATH))
71648
+ if (!existsSync56(USER_CACHE_PATH))
71508
71649
  return null;
71509
71650
  const parsed = JSON.parse(readFileSync20(USER_CACHE_PATH, "utf8"));
71510
71651
  if (!parsed || typeof parsed !== "object")
@@ -71516,7 +71657,7 @@ function readUserCache() {
71516
71657
  }
71517
71658
  function countBufferFiles() {
71518
71659
  try {
71519
- if (!existsSync55(EVENT_BUFFER_DIR))
71660
+ if (!existsSync56(EVENT_BUFFER_DIR))
71520
71661
  return 0;
71521
71662
  return readdirSync8(EVENT_BUFFER_DIR).filter((f4) => f4.endsWith(".jsonl")).length;
71522
71663
  } catch {
@@ -71528,7 +71669,7 @@ function readTelemetryConfig() {
71528
71669
  const envToken = process.env.TAKUMI_TELEMETRY_TOKEN;
71529
71670
  let metadata = null;
71530
71671
  try {
71531
- const resolved = findManifestPathSync(join111(homedir28(), ".claude"));
71672
+ const resolved = findManifestPathSync(join112(homedir28(), ".claude"));
71532
71673
  if (resolved) {
71533
71674
  metadata = JSON.parse(readFileSync20(resolved.path, "utf8"));
71534
71675
  }
@@ -71554,8 +71695,8 @@ function collectRuntimeContext() {
71554
71695
  cacheSource: cache2?.source === "gh" || cache2?.source === "manual" ? cache2.source : null,
71555
71696
  bufferFileCount: countBufferFiles(),
71556
71697
  bufferDir: EVENT_BUFFER_DIR,
71557
- rateStateExists: existsSync55(RATE_STATE_PATH),
71558
- userCacheExists: existsSync55(USER_CACHE_PATH),
71698
+ rateStateExists: existsSync56(RATE_STATE_PATH),
71699
+ userCacheExists: existsSync56(USER_CACHE_PATH),
71559
71700
  endpoint,
71560
71701
  tokenConfigured: Boolean(token)
71561
71702
  };
@@ -71706,7 +71847,7 @@ init_safe_prompts();
71706
71847
  init_safe_spinner();
71707
71848
  var import_fs_extra36 = __toESM(require_lib(), 1);
71708
71849
  import { readdirSync as readdirSync10, rmSync as rmSync8 } from "node:fs";
71709
- import { join as join113, resolve as resolve30, sep as sep10 } from "node:path";
71850
+ import { join as join114, resolve as resolve30, sep as sep10 } from "node:path";
71710
71851
 
71711
71852
  // src/commands/uninstall/analysis-handler.ts
71712
71853
  init_metadata_migration();
@@ -71716,13 +71857,13 @@ init_logger();
71716
71857
  init_safe_prompts();
71717
71858
  init_takumi_constants();
71718
71859
  var import_picocolors27 = __toESM(require_picocolors(), 1);
71719
- import { existsSync as existsSync56, readdirSync as readdirSync9, rmSync as rmSync7 } from "node:fs";
71720
- import { dirname as dirname36, join as join112 } 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";
71721
71862
  function listPresentManifestNames(installPath) {
71722
71863
  const present = [];
71723
- if (existsSync56(getManifestPath(installPath)))
71864
+ if (existsSync57(getManifestPath(installPath)))
71724
71865
  present.push(MANIFEST_FILENAME);
71725
- if (existsSync56(getLegacyManifestPath(installPath)))
71866
+ if (existsSync57(getLegacyManifestPath(installPath)))
71726
71867
  present.push(LEGACY_MANIFEST_FILENAME);
71727
71868
  return present;
71728
71869
  }
@@ -71770,7 +71911,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
71770
71911
  if (uninstallManifest.isMultiKit && kit && metadata?.kits?.[kit]) {
71771
71912
  const kitFiles = metadata.kits[kit].files || [];
71772
71913
  for (const trackedFile of kitFiles) {
71773
- const filePath = join112(installation.path, trackedFile.path);
71914
+ const filePath = join113(installation.path, trackedFile.path);
71774
71915
  if (uninstallManifest.filesToPreserve.includes(trackedFile.path)) {
71775
71916
  result.toPreserve.push({ path: trackedFile.path, reason: "shared with other kit" });
71776
71917
  continue;
@@ -71802,7 +71943,7 @@ async function analyzeInstallation(installation, forceOverwrite, kit) {
71802
71943
  return result;
71803
71944
  }
71804
71945
  for (const trackedFile of allTrackedFiles) {
71805
- const filePath = join112(installation.path, trackedFile.path);
71946
+ const filePath = join113(installation.path, trackedFile.path);
71806
71947
  const ownershipResult = await OwnershipChecker.checkOwnership(filePath, metadata, installation.path);
71807
71948
  if (!ownershipResult.exists)
71808
71949
  continue;
@@ -71901,7 +72042,7 @@ async function removeInstallations(installations, options2) {
71901
72042
  let removedCount = 0;
71902
72043
  let cleanedDirs = 0;
71903
72044
  for (const item of analysis.toDelete) {
71904
- const filePath = join113(installation.path, item.path);
72045
+ const filePath = join114(installation.path, item.path);
71905
72046
  if (!await import_fs_extra36.pathExists(filePath))
71906
72047
  continue;
71907
72048
  if (!await isPathSafeToRemove(filePath, installation.path)) {
@@ -72374,6 +72515,8 @@ async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps(
72374
72515
  logger.verbose(`Using npm configured registry: ${redactRegistryUrlForLog(registryUrl)}`);
72375
72516
  }
72376
72517
  }
72518
+ if (registryUrl)
72519
+ registryUrl = validateRegistryUrl(registryUrl);
72377
72520
  s3.start("Checking for updates...");
72378
72521
  let targetVersion = null;
72379
72522
  const usePrereleaseChannel = opts.dev || opts.beta;
@@ -72422,6 +72565,9 @@ async function updateCliCommand(options2, deps = getDefaultUpdateCliCommandDeps(
72422
72565
  const isDevChannelSwitch = (opts.dev || opts.beta) && isBetaVersion(targetVersion) && !isBetaVersion(currentVersion);
72423
72566
  if (comparison > 0 && !opts.release && !isDevChannelSwitch) {
72424
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
+ }
72425
72571
  await promptKitUpdateFn(targetIsPrerelease, opts.yes);
72426
72572
  return;
72427
72573
  }
@@ -72746,7 +72892,7 @@ init_manifest_path_resolver();
72746
72892
  init_logger();
72747
72893
  init_types2();
72748
72894
  import { readFileSync as readFileSync21 } from "node:fs";
72749
- import { join as join114 } from "node:path";
72895
+ import { join as join115 } from "node:path";
72750
72896
  var PROVIDER_LOCAL_SUBDIRS = {
72751
72897
  "claude-code": ".claude",
72752
72898
  codex: ".codex"
@@ -72801,7 +72947,7 @@ async function displayVersion() {
72801
72947
  const localSubdir = PROVIDER_LOCAL_SUBDIRS[provider];
72802
72948
  if (!localSubdir)
72803
72949
  continue;
72804
- const localRoot = join114(process.cwd(), localSubdir);
72950
+ const localRoot = join115(process.cwd(), localSubdir);
72805
72951
  if (localRoot === inst.globalRoot())
72806
72952
  continue;
72807
72953
  const resolved = findManifestPathSync(localRoot);