claudekit-cli 4.5.0-dev.7 → 4.5.0-dev.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15561,8 +15561,9 @@ var init_types2 = __esm(() => {
15561
15561
  });
15562
15562
 
15563
15563
  // src/domains/installation/plugin/install-mode-detector.ts
15564
+ import { createHash as createHash4 } from "node:crypto";
15564
15565
  import { existsSync as existsSync6, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
15565
- import { join as join6 } from "node:path";
15566
+ import { join as join6, relative as relative3, resolve as resolve5 } from "node:path";
15566
15567
  function readJsonSafe(filePath) {
15567
15568
  try {
15568
15569
  return JSON.parse(readFileSync3(filePath, "utf-8"));
@@ -15665,14 +15666,12 @@ function hasTrackedPluginSuppliedLegacyFiles(claudeDir = PathResolver.getGlobalK
15665
15666
  if (!isRecord(metadata))
15666
15667
  return false;
15667
15668
  for (const file of collectTrackedFiles(metadata)) {
15668
- if (file.ownership === "user")
15669
+ const resolvedPath = resolveSafePluginSuppliedLegacyPath(claudeDir, file.path);
15670
+ if (!resolvedPath || !existsSync6(resolvedPath))
15669
15671
  continue;
15670
- const normalized = file.path.replace(/\\/g, "/").replace(/^\.claude\//, "");
15671
- if (!PLUGIN_SUPPLIED_LEGACY_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {
15672
+ if (file.ownership === "user" && !checksumMatches(resolvedPath, file.checksum))
15672
15673
  continue;
15673
- }
15674
- if (existsSync6(join6(claudeDir, normalized)))
15675
- return true;
15674
+ return true;
15676
15675
  }
15677
15676
  return false;
15678
15677
  }
@@ -15685,7 +15684,11 @@ function collectTrackedFiles(metadata) {
15685
15684
  if (!isRecord(file) || typeof file.path !== "string")
15686
15685
  continue;
15687
15686
  const ownership = file.ownership === "user" || file.ownership === "ck-modified" ? file.ownership : "ck";
15688
- tracked.push({ path: file.path, ownership });
15687
+ tracked.push({
15688
+ path: file.path,
15689
+ ownership,
15690
+ checksum: typeof file.checksum === "string" ? file.checksum : undefined
15691
+ });
15689
15692
  }
15690
15693
  };
15691
15694
  if (isRecord(metadata.kits)) {
@@ -15697,6 +15700,54 @@ function collectTrackedFiles(metadata) {
15697
15700
  }
15698
15701
  return tracked;
15699
15702
  }
15703
+ function resolveSafePluginSuppliedLegacyPath(claudeDir, pathValue) {
15704
+ const normalized = normalizeLegacyPath(pathValue).replace(/^\.\/+/, "");
15705
+ if (!isPluginSuppliedLegacyPath(normalized))
15706
+ return null;
15707
+ const safe = resolveSafeChildPath(claudeDir, normalized);
15708
+ if (!safe)
15709
+ return null;
15710
+ const relativePath = normalizeLegacyPath(relative3(resolve5(claudeDir), safe));
15711
+ if (!isPluginSuppliedLegacyPath(relativePath))
15712
+ return null;
15713
+ return safe;
15714
+ }
15715
+ function resolveSafeChildPath(baseDir, pathValue) {
15716
+ const normalized = normalizeLegacyPath(pathValue);
15717
+ if (!normalized || hasPathTraversal(normalized) || isAbsoluteLike(normalized))
15718
+ return null;
15719
+ const resolvedBase = resolve5(baseDir);
15720
+ const resolvedTarget = resolve5(resolvedBase, normalized);
15721
+ const relativePath = normalizeLegacyPath(relative3(resolvedBase, resolvedTarget));
15722
+ if (!relativePath || relativePath === ".." || relativePath.startsWith("../"))
15723
+ return null;
15724
+ if (isAbsoluteLike(relativePath))
15725
+ return null;
15726
+ return resolvedTarget;
15727
+ }
15728
+ function isPluginSuppliedLegacyPath(pathValue) {
15729
+ const normalized = normalizeLegacyPath(pathValue).replace(/^\.claude\//, "");
15730
+ return PLUGIN_SUPPLIED_LEGACY_PREFIXES.some((prefix) => normalized.startsWith(prefix));
15731
+ }
15732
+ function checksumMatches(filePath, expected) {
15733
+ if (!expected || !/^[a-f0-9]{64}$/i.test(expected))
15734
+ return false;
15735
+ try {
15736
+ const actual = createHash4("sha256").update(readFileSync3(filePath)).digest("hex");
15737
+ return actual.toLowerCase() === expected.toLowerCase();
15738
+ } catch {
15739
+ return false;
15740
+ }
15741
+ }
15742
+ function hasPathTraversal(pathValue) {
15743
+ return pathValue.split("/").some((segment) => segment === "..");
15744
+ }
15745
+ function isAbsoluteLike(pathValue) {
15746
+ return pathValue.startsWith("/") || pathValue.startsWith("//") || /^[A-Za-z]:/.test(pathValue);
15747
+ }
15748
+ function normalizeLegacyPath(pathValue) {
15749
+ return pathValue.replace(/\\/g, "/");
15750
+ }
15700
15751
  function safeReaddir(dir) {
15701
15752
  try {
15702
15753
  return readdirSync2(dir);
@@ -15865,7 +15916,8 @@ var init_commands = __esm(() => {
15865
15916
  sync: exports_external.boolean().default(false),
15866
15917
  useGit: exports_external.boolean().default(false),
15867
15918
  archive: exports_external.string().optional(),
15868
- kitPath: exports_external.string().optional()
15919
+ kitPath: exports_external.string().optional(),
15920
+ installMode: exports_external.enum(["auto", "plugin", "legacy"]).default("auto")
15869
15921
  }).merge(GlobalOutputOptionsSchema);
15870
15922
  VersionCommandOptionsSchema = exports_external.object({
15871
15923
  kit: KitType.optional(),
@@ -19941,8 +19993,8 @@ var require_universalify = __commonJS((exports) => {
19941
19993
  if (typeof args[args.length - 1] === "function")
19942
19994
  fn.apply(this, args);
19943
19995
  else {
19944
- return new Promise((resolve5, reject) => {
19945
- args.push((err, res) => err != null ? reject(err) : resolve5(res));
19996
+ return new Promise((resolve6, reject) => {
19997
+ args.push((err, res) => err != null ? reject(err) : resolve6(res));
19946
19998
  fn.apply(this, args);
19947
19999
  });
19948
20000
  }
@@ -20015,19 +20067,19 @@ var require_fs = __commonJS((exports) => {
20015
20067
  if (typeof callback === "function") {
20016
20068
  return fs.exists(filename, callback);
20017
20069
  }
20018
- return new Promise((resolve5) => {
20019
- return fs.exists(filename, resolve5);
20070
+ return new Promise((resolve6) => {
20071
+ return fs.exists(filename, resolve6);
20020
20072
  });
20021
20073
  };
20022
20074
  exports.read = function(fd, buffer, offset, length, position, callback) {
20023
20075
  if (typeof callback === "function") {
20024
20076
  return fs.read(fd, buffer, offset, length, position, callback);
20025
20077
  }
20026
- return new Promise((resolve5, reject) => {
20078
+ return new Promise((resolve6, reject) => {
20027
20079
  fs.read(fd, buffer, offset, length, position, (err, bytesRead, buffer2) => {
20028
20080
  if (err)
20029
20081
  return reject(err);
20030
- resolve5({ bytesRead, buffer: buffer2 });
20082
+ resolve6({ bytesRead, buffer: buffer2 });
20031
20083
  });
20032
20084
  });
20033
20085
  };
@@ -20035,11 +20087,11 @@ var require_fs = __commonJS((exports) => {
20035
20087
  if (typeof args[args.length - 1] === "function") {
20036
20088
  return fs.write(fd, buffer, ...args);
20037
20089
  }
20038
- return new Promise((resolve5, reject) => {
20090
+ return new Promise((resolve6, reject) => {
20039
20091
  fs.write(fd, buffer, ...args, (err, bytesWritten, buffer2) => {
20040
20092
  if (err)
20041
20093
  return reject(err);
20042
- resolve5({ bytesWritten, buffer: buffer2 });
20094
+ resolve6({ bytesWritten, buffer: buffer2 });
20043
20095
  });
20044
20096
  });
20045
20097
  };
@@ -20047,11 +20099,11 @@ var require_fs = __commonJS((exports) => {
20047
20099
  if (typeof args[args.length - 1] === "function") {
20048
20100
  return fs.readv(fd, buffers, ...args);
20049
20101
  }
20050
- return new Promise((resolve5, reject) => {
20102
+ return new Promise((resolve6, reject) => {
20051
20103
  fs.readv(fd, buffers, ...args, (err, bytesRead, buffers2) => {
20052
20104
  if (err)
20053
20105
  return reject(err);
20054
- resolve5({ bytesRead, buffers: buffers2 });
20106
+ resolve6({ bytesRead, buffers: buffers2 });
20055
20107
  });
20056
20108
  });
20057
20109
  };
@@ -20059,11 +20111,11 @@ var require_fs = __commonJS((exports) => {
20059
20111
  if (typeof args[args.length - 1] === "function") {
20060
20112
  return fs.writev(fd, buffers, ...args);
20061
20113
  }
20062
- return new Promise((resolve5, reject) => {
20114
+ return new Promise((resolve6, reject) => {
20063
20115
  fs.writev(fd, buffers, ...args, (err, bytesWritten, buffers2) => {
20064
20116
  if (err)
20065
20117
  return reject(err);
20066
- resolve5({ bytesWritten, buffers: buffers2 });
20118
+ resolve6({ bytesWritten, buffers: buffers2 });
20067
20119
  });
20068
20120
  });
20069
20121
  };
@@ -20896,9 +20948,9 @@ var require_symlink = __commonJS((exports, module) => {
20896
20948
  if (areIdentical(srcStat, dstStat))
20897
20949
  return;
20898
20950
  }
20899
- const relative3 = await symlinkPaths(srcpath, dstpath);
20900
- srcpath = relative3.toDst;
20901
- const toType = await symlinkType(relative3.toCwd, type);
20951
+ const relative4 = await symlinkPaths(srcpath, dstpath);
20952
+ srcpath = relative4.toDst;
20953
+ const toType = await symlinkType(relative4.toCwd, type);
20902
20954
  const dir = path3.dirname(dstpath);
20903
20955
  if (!await pathExists(dir)) {
20904
20956
  await mkdirs(dir);
@@ -20916,9 +20968,9 @@ var require_symlink = __commonJS((exports, module) => {
20916
20968
  if (areIdentical(srcStat, dstStat))
20917
20969
  return;
20918
20970
  }
20919
- const relative3 = symlinkPathsSync(srcpath, dstpath);
20920
- srcpath = relative3.toDst;
20921
- type = symlinkTypeSync(relative3.toCwd, type);
20971
+ const relative4 = symlinkPathsSync(srcpath, dstpath);
20972
+ srcpath = relative4.toDst;
20973
+ type = symlinkTypeSync(relative4.toCwd, type);
20922
20974
  const dir = path3.dirname(dstpath);
20923
20975
  const exists = fs.existsSync(dir);
20924
20976
  if (exists)
@@ -21323,7 +21375,7 @@ var init_safe_prompts = __esm(() => {
21323
21375
  // src/commands/commands/commands-discovery.ts
21324
21376
  import { readdir as readdir4 } from "node:fs/promises";
21325
21377
  import { homedir as homedir9 } from "node:os";
21326
- import { join as join17, relative as relative3 } from "node:path";
21378
+ import { join as join17, relative as relative4 } from "node:path";
21327
21379
  function getCommandSourcePath(globalOnly = false) {
21328
21380
  const globalPath = join17(homedir9(), ".claude/commands");
21329
21381
  if (globalOnly) {
@@ -21348,7 +21400,7 @@ async function scanCommandDir(dir, rootDir) {
21348
21400
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
21349
21401
  try {
21350
21402
  const { frontmatter, body } = await parseFrontmatterFile(fullPath);
21351
- const relPath = relative3(rootDir, fullPath);
21403
+ const relPath = relative4(rootDir, fullPath);
21352
21404
  const segments = relPath.replace(/\.md$/, "").split(/[/\\]/);
21353
21405
  const name = segments.join("/");
21354
21406
  const displayName = segments.join(":");
@@ -22130,7 +22182,7 @@ var require_depd = __commonJS((exports, module) => {
22130
22182
  * Copyright(c) 2014-2018 Douglas Christopher Wilson
22131
22183
  * MIT Licensed
22132
22184
  */
22133
- var relative5 = __require("path").relative;
22185
+ var relative6 = __require("path").relative;
22134
22186
  module.exports = depd;
22135
22187
  var basePath = process.cwd();
22136
22188
  function containsNamespace(str2, namespace) {
@@ -22326,7 +22378,7 @@ var require_depd = __commonJS((exports, module) => {
22326
22378
  return formatted;
22327
22379
  }
22328
22380
  function formatLocation(callSite) {
22329
- return relative5(basePath, callSite[0]) + ":" + callSite[1] + ":" + callSite[2];
22381
+ return relative6(basePath, callSite[0]) + ":" + callSite[1] + ":" + callSite[2];
22330
22382
  }
22331
22383
  function getStack() {
22332
22384
  var limit = Error.stackTraceLimit;
@@ -26663,11 +26715,11 @@ var require_raw_body = __commonJS((exports, module) => {
26663
26715
  if (done) {
26664
26716
  return readStream(stream, encoding, length, limit, wrap2(done));
26665
26717
  }
26666
- return new Promise(function executor(resolve9, reject) {
26718
+ return new Promise(function executor(resolve10, reject) {
26667
26719
  readStream(stream, encoding, length, limit, function onRead(err, buf) {
26668
26720
  if (err)
26669
26721
  return reject(err);
26670
- resolve9(buf);
26722
+ resolve10(buf);
26671
26723
  });
26672
26724
  });
26673
26725
  }
@@ -39773,7 +39825,7 @@ var require_view = __commonJS((exports, module) => {
39773
39825
  var basename6 = path3.basename;
39774
39826
  var extname2 = path3.extname;
39775
39827
  var join19 = path3.join;
39776
- var resolve9 = path3.resolve;
39828
+ var resolve10 = path3.resolve;
39777
39829
  module.exports = View;
39778
39830
  function View(name, options2) {
39779
39831
  var opts = options2 || {};
@@ -39807,7 +39859,7 @@ var require_view = __commonJS((exports, module) => {
39807
39859
  debug('lookup "%s"', name);
39808
39860
  for (var i = 0;i < roots.length && !path4; i++) {
39809
39861
  var root = roots[i];
39810
- var loc = resolve9(root, name);
39862
+ var loc = resolve10(root, name);
39811
39863
  var dir = dirname7(loc);
39812
39864
  var file = basename6(loc);
39813
39865
  path4 = this.resolve(dir, file);
@@ -41991,7 +42043,7 @@ var require_application = __commonJS((exports, module) => {
41991
42043
  var compileETag = require_utils6().compileETag;
41992
42044
  var compileQueryParser = require_utils6().compileQueryParser;
41993
42045
  var compileTrust = require_utils6().compileTrust;
41994
- var resolve9 = __require("node:path").resolve;
42046
+ var resolve10 = __require("node:path").resolve;
41995
42047
  var once = require_once();
41996
42048
  var Router = require_router();
41997
42049
  var slice = Array.prototype.slice;
@@ -42045,7 +42097,7 @@ var require_application = __commonJS((exports, module) => {
42045
42097
  this.mountpath = "/";
42046
42098
  this.locals.settings = this.settings;
42047
42099
  this.set("view", View);
42048
- this.set("views", resolve9("views"));
42100
+ this.set("views", resolve10("views"));
42049
42101
  this.set("jsonp callback name", "callback");
42050
42102
  if (env2 === "production") {
42051
42103
  this.enable("view cache");
@@ -43536,7 +43588,7 @@ var require_send = __commonJS((exports, module) => {
43536
43588
  var extname2 = path3.extname;
43537
43589
  var join19 = path3.join;
43538
43590
  var normalize3 = path3.normalize;
43539
- var resolve9 = path3.resolve;
43591
+ var resolve10 = path3.resolve;
43540
43592
  var sep5 = path3.sep;
43541
43593
  var BYTES_RANGE_REGEXP = /^ *bytes=/;
43542
43594
  var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1000;
@@ -43565,7 +43617,7 @@ var require_send = __commonJS((exports, module) => {
43565
43617
  this._maxage = opts.maxAge || opts.maxage;
43566
43618
  this._maxage = typeof this._maxage === "string" ? ms(this._maxage) : Number(this._maxage);
43567
43619
  this._maxage = !isNaN(this._maxage) ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) : 0;
43568
- this._root = opts.root ? resolve9(opts.root) : null;
43620
+ this._root = opts.root ? resolve10(opts.root) : null;
43569
43621
  }
43570
43622
  util3.inherits(SendStream, Stream);
43571
43623
  SendStream.prototype.error = function error(status, err) {
@@ -43714,7 +43766,7 @@ var require_send = __commonJS((exports, module) => {
43714
43766
  return res;
43715
43767
  }
43716
43768
  parts = normalize3(path4).split(sep5);
43717
- path4 = resolve9(path4);
43769
+ path4 = resolve10(path4);
43718
43770
  }
43719
43771
  if (containsDotFile(parts)) {
43720
43772
  debug('%s dotfile "%s"', this._dotfiles, path4);
@@ -44117,7 +44169,7 @@ var require_response = __commonJS((exports, module) => {
44117
44169
  var cookie = require_cookie();
44118
44170
  var send = require_send();
44119
44171
  var extname2 = path3.extname;
44120
- var resolve9 = path3.resolve;
44172
+ var resolve10 = path3.resolve;
44121
44173
  var vary = require_vary();
44122
44174
  var { Buffer: Buffer2 } = __require("node:buffer");
44123
44175
  var res = Object.create(http.ServerResponse.prototype);
@@ -44326,7 +44378,7 @@ var require_response = __commonJS((exports, module) => {
44326
44378
  }
44327
44379
  opts = Object.create(opts);
44328
44380
  opts.headers = headers;
44329
- var fullPath = !opts.root ? resolve9(path4) : path4;
44381
+ var fullPath = !opts.root ? resolve10(path4) : path4;
44330
44382
  return this.sendFile(fullPath, opts, done);
44331
44383
  };
44332
44384
  res.contentType = res.type = function contentType(type) {
@@ -44587,7 +44639,7 @@ var require_serve_static = __commonJS((exports, module) => {
44587
44639
  var encodeUrl = require_encodeurl();
44588
44640
  var escapeHtml = require_escape_html();
44589
44641
  var parseUrl = require_parseurl();
44590
- var resolve9 = __require("path").resolve;
44642
+ var resolve10 = __require("path").resolve;
44591
44643
  var send = require_send();
44592
44644
  var url = __require("url");
44593
44645
  module.exports = serveStatic;
@@ -44606,7 +44658,7 @@ var require_serve_static = __commonJS((exports, module) => {
44606
44658
  throw new TypeError("option setHeaders must be function");
44607
44659
  }
44608
44660
  opts.maxage = opts.maxage || opts.maxAge || 0;
44609
- opts.root = resolve9(root);
44661
+ opts.root = resolve10(root);
44610
44662
  var onDirectory = redirect ? createRedirectDirectoryListener() : createNotFoundDirectoryListener();
44611
44663
  return function serveStatic(req, res, next) {
44612
44664
  if (req.method !== "GET" && req.method !== "HEAD") {
@@ -44817,14 +44869,14 @@ var Locked, lockedPorts, releaseOldLockedPortsIntervalMs, timeout, getLocalHosts
44817
44869
  }
44818
44870
  }
44819
44871
  return results;
44820
- }, checkAvailablePort = (options2) => new Promise((resolve9, reject) => {
44872
+ }, checkAvailablePort = (options2) => new Promise((resolve10, reject) => {
44821
44873
  const server = net.createServer();
44822
44874
  server.unref();
44823
44875
  server.on("error", reject);
44824
44876
  server.listen(options2, () => {
44825
44877
  const { port } = server.address();
44826
44878
  server.close(() => {
44827
- resolve9(port);
44879
+ resolve10(port);
44828
44880
  });
44829
44881
  });
44830
44882
  }), getAvailablePort = async (options2, hosts) => {
@@ -45397,19 +45449,19 @@ var fallbackAttemptSymbol, __dirname2, localXdgOpenPath, platform3, arch, tryEac
45397
45449
  }
45398
45450
  const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
45399
45451
  if (options2.wait) {
45400
- return new Promise((resolve9, reject) => {
45452
+ return new Promise((resolve10, reject) => {
45401
45453
  subprocess.once("error", reject);
45402
45454
  subprocess.once("close", (exitCode) => {
45403
45455
  if (!options2.allowNonzeroExitCode && exitCode !== 0) {
45404
45456
  reject(new Error(`Exited with code ${exitCode}`));
45405
45457
  return;
45406
45458
  }
45407
- resolve9(subprocess);
45459
+ resolve10(subprocess);
45408
45460
  });
45409
45461
  });
45410
45462
  }
45411
45463
  if (isFallbackAttempt) {
45412
- return new Promise((resolve9, reject) => {
45464
+ return new Promise((resolve10, reject) => {
45413
45465
  subprocess.once("error", reject);
45414
45466
  subprocess.once("spawn", () => {
45415
45467
  subprocess.once("close", (exitCode) => {
@@ -45419,17 +45471,17 @@ var fallbackAttemptSymbol, __dirname2, localXdgOpenPath, platform3, arch, tryEac
45419
45471
  return;
45420
45472
  }
45421
45473
  subprocess.unref();
45422
- resolve9(subprocess);
45474
+ resolve10(subprocess);
45423
45475
  });
45424
45476
  });
45425
45477
  });
45426
45478
  }
45427
45479
  subprocess.unref();
45428
- return new Promise((resolve9, reject) => {
45480
+ return new Promise((resolve10, reject) => {
45429
45481
  subprocess.once("error", reject);
45430
45482
  subprocess.once("spawn", () => {
45431
45483
  subprocess.off("error", reject);
45432
- resolve9(subprocess);
45484
+ resolve10(subprocess);
45433
45485
  });
45434
45486
  });
45435
45487
  }, open = (target, options2) => {
@@ -46782,8 +46834,11 @@ var init_config_generator = __esm(() => {
46782
46834
  });
46783
46835
 
46784
46836
  // src/domains/config/config-validator.ts
46837
+ function normalizeApiKeyInput(value) {
46838
+ return value.replace(/\u200B|\u200C|\u200D|\uFEFF/g, "").trim();
46839
+ }
46785
46840
  function validateApiKey2(value, pattern) {
46786
- return pattern.test(value);
46841
+ return pattern.test(normalizeApiKeyInput(value));
46787
46842
  }
46788
46843
  var VALIDATION_PATTERNS;
46789
46844
  var init_config_validator = __esm(() => {
@@ -47225,7 +47280,7 @@ class NodeFsHandler {
47225
47280
  this._addToNodeFs(path4, initialAdd, wh, depth + 1);
47226
47281
  }
47227
47282
  }).on(EV.ERROR, this._boundHandleError);
47228
- return new Promise((resolve10, reject) => {
47283
+ return new Promise((resolve11, reject) => {
47229
47284
  if (!stream)
47230
47285
  return reject();
47231
47286
  stream.once(STR_END, () => {
@@ -47234,7 +47289,7 @@ class NodeFsHandler {
47234
47289
  return;
47235
47290
  }
47236
47291
  const wasThrottled = throttler ? throttler.clear() : false;
47237
- resolve10(undefined);
47292
+ resolve11(undefined);
47238
47293
  previous.getChildren().filter((item) => {
47239
47294
  return item !== directory && !current.has(item);
47240
47295
  }).forEach((item) => {
@@ -47763,11 +47818,11 @@ function createPattern(matcher) {
47763
47818
  if (matcher.path === string)
47764
47819
  return true;
47765
47820
  if (matcher.recursive) {
47766
- const relative7 = sp2.relative(matcher.path, string);
47767
- if (!relative7) {
47821
+ const relative8 = sp2.relative(matcher.path, string);
47822
+ if (!relative8) {
47768
47823
  return false;
47769
47824
  }
47770
- return !relative7.startsWith("..") && !sp2.isAbsolute(relative7);
47825
+ return !relative8.startsWith("..") && !sp2.isAbsolute(relative8);
47771
47826
  }
47772
47827
  return false;
47773
47828
  };
@@ -48601,7 +48656,7 @@ __export(exports_projects_registry, {
48601
48656
  import { randomUUID as randomUUID2 } from "node:crypto";
48602
48657
  import { existsSync as existsSync13, statSync as statSync3 } from "node:fs";
48603
48658
  import { copyFile, mkdir as mkdir8, open as open3, readFile as readFile10, unlink as unlink5, writeFile as writeFile9 } from "node:fs/promises";
48604
- import { basename as basename8, dirname as dirname10, resolve as resolve11 } from "node:path";
48659
+ import { basename as basename8, dirname as dirname10, resolve as resolve12 } from "node:path";
48605
48660
 
48606
48661
  class ProjectsRegistryManager {
48607
48662
  static registry = null;
@@ -48719,7 +48774,7 @@ class ProjectsRegistryManager {
48719
48774
  if (projectPath.includes("..") || projectPath.startsWith("~")) {
48720
48775
  throw new Error("Invalid path: path traversal patterns not allowed");
48721
48776
  }
48722
- const absolutePath = resolve11(projectPath);
48777
+ const absolutePath = resolve12(projectPath);
48723
48778
  if (!existsSync13(absolutePath)) {
48724
48779
  throw new Error(`Path does not exist: ${absolutePath}`);
48725
48780
  }
@@ -48850,7 +48905,7 @@ class ProjectsRegistryManager {
48850
48905
  return projects;
48851
48906
  }
48852
48907
  static async isRegistered(projectPath) {
48853
- const absolutePath = resolve11(projectPath);
48908
+ const absolutePath = resolve12(projectPath);
48854
48909
  const registry = await ProjectsRegistryManager.load();
48855
48910
  return registry.projects.some((p) => p.path === absolutePath);
48856
48911
  }
@@ -48966,7 +49021,7 @@ var init_claudekit_data2 = __esm(() => {
48966
49021
  import { spawn, spawnSync } from "node:child_process";
48967
49022
  import { existsSync as existsSync15 } from "node:fs";
48968
49023
  import { homedir as homedir13 } from "node:os";
48969
- import { join as join28, resolve as resolve12, sep as sep5 } from "node:path";
49024
+ import { join as join28, resolve as resolve13, sep as sep5 } from "node:path";
48970
49025
  function getWindowsPaths(...relativePaths) {
48971
49026
  const roots = [
48972
49027
  WINDOWS_PATHS.localAppData,
@@ -49225,8 +49280,8 @@ function buildOsaScriptCommand(scriptLines, argv = []) {
49225
49280
  return { command: "osascript", args };
49226
49281
  }
49227
49282
  function isPathInsideBase(path4, base) {
49228
- const normalizedPath = resolve12(path4);
49229
- const normalizedBase = resolve12(base);
49283
+ const normalizedPath = resolve13(path4);
49284
+ const normalizedBase = resolve13(base);
49230
49285
  if (normalizedPath === normalizedBase)
49231
49286
  return true;
49232
49287
  return normalizedPath.startsWith(`${normalizedBase}${sep5}`);
@@ -49236,19 +49291,19 @@ async function isActionPathAllowed(dirPath, projectId) {
49236
49291
  const project = await ProjectsRegistryManager.getProject(projectId);
49237
49292
  if (!project)
49238
49293
  return false;
49239
- return resolve12(project.path) === dirPath;
49294
+ return resolve13(project.path) === dirPath;
49240
49295
  }
49241
49296
  if (projectId?.startsWith("discovered-")) {
49242
49297
  try {
49243
49298
  const encodedPath = projectId.slice("discovered-".length);
49244
- const discoveredPath = resolve12(Buffer.from(encodedPath, "base64url").toString("utf-8"));
49299
+ const discoveredPath = resolve13(Buffer.from(encodedPath, "base64url").toString("utf-8"));
49245
49300
  if (discoveredPath === dirPath && (isPathInsideBase(discoveredPath, process.cwd()) || isPathInsideBase(discoveredPath, homedir13()))) {
49246
49301
  return true;
49247
49302
  }
49248
49303
  } catch {}
49249
49304
  }
49250
49305
  const registeredProjects = await ProjectsRegistryManager.listProjects();
49251
- if (registeredProjects.some((project) => resolve12(project.path) === dirPath)) {
49306
+ if (registeredProjects.some((project) => resolve13(project.path) === dirPath)) {
49252
49307
  return true;
49253
49308
  }
49254
49309
  if (isPathInsideBase(dirPath, process.cwd())) {
@@ -49498,7 +49553,7 @@ function registerActionRoutes(app) {
49498
49553
  return;
49499
49554
  }
49500
49555
  const { action, path: rawPath, appId, projectId } = validation.data;
49501
- const dirPath = resolve12(rawPath);
49556
+ const dirPath = resolve13(rawPath);
49502
49557
  if (!existsSync15(dirPath)) {
49503
49558
  res.status(400).json({ error: "Path does not exist" });
49504
49559
  return;
@@ -49540,7 +49595,7 @@ function registerActionRoutes(app) {
49540
49595
  } else {
49541
49596
  commandToRun = buildLaunchCommand(dirPath);
49542
49597
  }
49543
- const spawnCwd = resolve12(commandToRun.cwd || dirPath);
49598
+ const spawnCwd = resolve13(commandToRun.cwd || dirPath);
49544
49599
  if (spawnCwd !== dirPath) {
49545
49600
  const spawnCwdAllowed = await isActionPathAllowed(spawnCwd, typeof projectId === "string" ? projectId : undefined);
49546
49601
  if (!spawnCwdAllowed) {
@@ -49884,13 +49939,13 @@ var init_action_routes = __esm(() => {
49884
49939
  // src/domains/web-server/routes/agents-routes.ts
49885
49940
  import { readdir as readdir7 } from "node:fs/promises";
49886
49941
  import { homedir as homedir14 } from "node:os";
49887
- import { isAbsolute as isAbsolute4, join as join29, relative as relative7 } from "node:path";
49942
+ import { isAbsolute as isAbsolute4, join as join29, relative as relative8 } from "node:path";
49888
49943
  function resolveAgentDirs() {
49889
49944
  const dirs = [];
49890
49945
  const projectCandidates = getProjectLayoutCandidates(process.cwd(), "agents");
49891
49946
  for (const candidate of projectCandidates) {
49892
49947
  if (candidate) {
49893
- const rel = relative7(process.cwd(), candidate);
49948
+ const rel = relative8(process.cwd(), candidate);
49894
49949
  dirs.push({ path: candidate, label: rel });
49895
49950
  }
49896
49951
  }
@@ -49928,7 +49983,7 @@ async function scanAgentDir(dirPath, dirLabel) {
49928
49983
  color: frontmatter.color || null,
49929
49984
  skillCount: countSkills(frontmatter.tools),
49930
49985
  dirLabel,
49931
- relativePath: relative7(homedir14(), filePath)
49986
+ relativePath: relative8(homedir14(), filePath)
49932
49987
  });
49933
49988
  } catch {}
49934
49989
  }
@@ -49958,7 +50013,7 @@ function registerAgentsBrowserRoutes(app) {
49958
50013
  const dirs = resolveAgentDirs();
49959
50014
  for (const dir of dirs) {
49960
50015
  const filePath = join29(dir.path, `${slug}.md`);
49961
- const rel = relative7(dir.path, filePath);
50016
+ const rel = relative8(dir.path, filePath);
49962
50017
  if (rel.startsWith("..") || isAbsolute4(rel)) {
49963
50018
  continue;
49964
50019
  }
@@ -49972,7 +50027,7 @@ function registerAgentsBrowserRoutes(app) {
49972
50027
  color: frontmatter.color || null,
49973
50028
  skillCount: countSkills(frontmatter.tools),
49974
50029
  dirLabel: dir.label,
49975
- relativePath: relative7(homedir14(), filePath),
50030
+ relativePath: relative8(homedir14(), filePath),
49976
50031
  frontmatter,
49977
50032
  body
49978
50033
  };
@@ -50837,7 +50892,7 @@ var init_ck_config_routes = __esm(() => {
50837
50892
  import { existsSync as existsSync17 } from "node:fs";
50838
50893
  import { readFile as readFile12, readdir as readdir8 } from "node:fs/promises";
50839
50894
  import { homedir as homedir15 } from "node:os";
50840
- import { basename as basename9, isAbsolute as isAbsolute5, join as join31, relative as relative8, resolve as resolve13 } from "node:path";
50895
+ import { basename as basename9, isAbsolute as isAbsolute5, join as join31, relative as relative9, resolve as resolve14 } from "node:path";
50841
50896
  async function buildCommandTree(dir, baseDir) {
50842
50897
  let dirents;
50843
50898
  try {
@@ -50857,7 +50912,7 @@ async function buildCommandTree(dir, baseDir) {
50857
50912
  const name = entry.name;
50858
50913
  const isDir2 = entry.isDirectory();
50859
50914
  const fullPath = join31(dir, name);
50860
- const relPath = relative8(baseDir, fullPath);
50915
+ const relPath = relative9(baseDir, fullPath);
50861
50916
  if (isDir2) {
50862
50917
  const children = await buildCommandTree(fullPath, baseDir);
50863
50918
  if (children.length > 0) {
@@ -50902,8 +50957,8 @@ function registerCommandRoutes(app) {
50902
50957
  return;
50903
50958
  }
50904
50959
  const commandsDir = join31(homedir15(), ".claude", "commands");
50905
- const safePath = resolve13(commandsDir, rawPath);
50906
- const rel = relative8(commandsDir, safePath);
50960
+ const safePath = resolve14(commandsDir, rawPath);
50961
+ const rel = relative9(commandsDir, safePath);
50907
50962
  if (rel.startsWith("..") || isAbsolute5(rel)) {
50908
50963
  res.status(403).json({ error: "Access denied" });
50909
50964
  return;
@@ -52023,7 +52078,7 @@ var init_hook_log_routes = __esm(() => {
52023
52078
  import { existsSync as existsSync22 } from "node:fs";
52024
52079
  import { readFile as readFile18 } from "node:fs/promises";
52025
52080
  import { homedir as homedir22 } from "node:os";
52026
- import { basename as basename12, join as join40, resolve as resolve14 } from "node:path";
52081
+ import { basename as basename12, join as join40, resolve as resolve15 } from "node:path";
52027
52082
  function parseMcpServers(raw, source, sourceLabel) {
52028
52083
  const entries = [];
52029
52084
  for (const [name, value] of Object.entries(raw)) {
@@ -52073,7 +52128,7 @@ function isSafeProjectPath(projectPath) {
52073
52128
  return false;
52074
52129
  const home3 = homedir22();
52075
52130
  try {
52076
- const resolved = resolve14(projectPath);
52131
+ const resolved = resolve15(projectPath);
52077
52132
  if (!resolved.startsWith(home3))
52078
52133
  return false;
52079
52134
  return existsSync22(resolved);
@@ -52213,23 +52268,23 @@ var init_migrate_provider_scopes = __esm(() => {
52213
52268
  // src/commands/migrate/skill-directory-installer.ts
52214
52269
  import { existsSync as existsSync23 } from "node:fs";
52215
52270
  import { cp, mkdir as mkdir10, readFile as readFile19, realpath as realpath6, rename as rename6, rm as rm5, writeFile as writeFile11 } from "node:fs/promises";
52216
- import { dirname as dirname11, join as join41, resolve as resolve15 } from "node:path";
52271
+ import { dirname as dirname11, join as join41, resolve as resolve16 } from "node:path";
52217
52272
  async function canonicalize(path4) {
52218
52273
  try {
52219
52274
  return await realpath6(path4);
52220
52275
  } catch {
52221
52276
  const parent = dirname11(path4);
52222
52277
  if (parent === path4) {
52223
- return resolve15(path4);
52278
+ return resolve16(path4);
52224
52279
  }
52225
52280
  try {
52226
52281
  const canonicalParent = await realpath6(parent);
52227
- const absPath = resolve15(path4);
52228
- const absParent = resolve15(parent);
52282
+ const absPath = resolve16(path4);
52283
+ const absParent = resolve16(parent);
52229
52284
  const basename13 = absPath.slice(absParent.length + 1) || "";
52230
52285
  return join41(canonicalParent, basename13);
52231
52286
  } catch {
52232
- return resolve15(path4);
52287
+ return resolve16(path4);
52233
52288
  }
52234
52289
  }
52235
52290
  }
@@ -52274,7 +52329,7 @@ async function installSkillDirectories(skills, targetProviders, options2) {
52274
52329
  const sourceRoot = skills.length > 0 ? dirname11(skills[0].path) : null;
52275
52330
  const canonicalBase = existsSync23(basePath) ? await canonicalize(basePath) : null;
52276
52331
  const canonicalSourceRoot = sourceRoot ? await canonicalize(sourceRoot) : null;
52277
- const basePathIsSymlinkedToSource = canonicalBase !== null && canonicalSourceRoot !== null && canonicalBase === canonicalSourceRoot && resolve15(basePath) !== resolve15(sourceRoot ?? "");
52332
+ const basePathIsSymlinkedToSource = canonicalBase !== null && canonicalSourceRoot !== null && canonicalBase === canonicalSourceRoot && resolve16(basePath) !== resolve16(sourceRoot ?? "");
52278
52333
  if (basePathIsSymlinkedToSource) {
52279
52334
  for (const skill of skills) {
52280
52335
  results.push({
@@ -52370,14 +52425,14 @@ var init_skill_directory_installer = __esm(() => {
52370
52425
  import { existsSync as existsSync24, readFileSync as readFileSync7 } from "node:fs";
52371
52426
  import { cp as cp2, mkdir as mkdir11, readFile as readFile20, readdir as readdir12, stat as stat8 } from "node:fs/promises";
52372
52427
  import { homedir as homedir23 } from "node:os";
52373
- import { basename as basename13, dirname as dirname12, extname as extname3, join as join42, relative as relative9, resolve as resolve16, sep as sep6 } from "node:path";
52428
+ import { basename as basename13, dirname as dirname12, extname as extname3, join as join42, relative as relative10, resolve as resolve17, sep as sep6 } from "node:path";
52374
52429
  async function copyHooksCompanionDirs(sourceDir, targetDir) {
52375
52430
  const result = {
52376
52431
  copiedDirs: [],
52377
52432
  copiedDotfiles: [],
52378
52433
  errors: []
52379
52434
  };
52380
- if (resolve16(sourceDir) === resolve16(targetDir)) {
52435
+ if (resolve17(sourceDir) === resolve17(targetDir)) {
52381
52436
  return result;
52382
52437
  }
52383
52438
  if (!existsSync24(sourceDir)) {
@@ -52398,8 +52453,8 @@ async function copyHooksCompanionDirs(sourceDir, targetDir) {
52398
52453
  });
52399
52454
  return result;
52400
52455
  }
52401
- const sourceParent = resolve16(sourceDir, "..");
52402
- const targetParent = resolve16(targetDir, "..");
52456
+ const sourceParent = resolve17(sourceDir, "..");
52457
+ const targetParent = resolve17(targetDir, "..");
52403
52458
  if (sourceParent !== targetParent) {
52404
52459
  for (const dotfile of HOOKS_COMPANION_DOTFILES) {
52405
52460
  const srcPath = join42(sourceParent, dotfile);
@@ -52428,7 +52483,7 @@ async function copyHooksCompanionDirs(sourceDir, targetDir) {
52428
52483
  continue;
52429
52484
  const srcDir = join42(sourceDir, entry.name);
52430
52485
  const dstDir = join42(targetDir, entry.name);
52431
- if (resolve16(srcDir) === resolve16(dstDir))
52486
+ if (resolve17(srcDir) === resolve17(dstDir))
52432
52487
  continue;
52433
52488
  try {
52434
52489
  const s = await stat8(srcDir);
@@ -52658,7 +52713,7 @@ async function collectHookFiles(dir, baseDir = dir) {
52658
52713
  }
52659
52714
  for (const entry of entries) {
52660
52715
  const fullPath = join42(dir, entry.name);
52661
- const relPath = relative9(baseDir, fullPath).split(/[/\\]/).join("/");
52716
+ const relPath = relative10(baseDir, fullPath).split(/[/\\]/).join("/");
52662
52717
  if (entry.isSymbolicLink())
52663
52718
  continue;
52664
52719
  if (entry.isDirectory()) {
@@ -52751,7 +52806,7 @@ async function discoverPortableFiles(dir, baseDir, options2) {
52751
52806
  const extension = extname3(entry.name).toLowerCase();
52752
52807
  if (!options2.includeExtensions.has(extension))
52753
52808
  continue;
52754
- const relPath = relative9(baseDir, fullPath);
52809
+ const relPath = relative10(baseDir, fullPath);
52755
52810
  const normalizedPath = relPath.split(/[/\\]/).join("/");
52756
52811
  const name = options2.stripExtension ? normalizedPath.replace(/\.[^.]+$/, "") : normalizedPath;
52757
52812
  try {
@@ -54712,17 +54767,17 @@ var init_codex_capabilities = __esm(() => {
54712
54767
  import { existsSync as existsSync25 } from "node:fs";
54713
54768
  import { mkdir as mkdir12, realpath as realpath7 } from "node:fs/promises";
54714
54769
  import { homedir as homedir24 } from "node:os";
54715
- import { dirname as dirname13, join as join43, resolve as resolve17, sep as sep7 } from "node:path";
54770
+ import { dirname as dirname13, join as join43, resolve as resolve18, sep as sep7 } from "node:path";
54716
54771
  function isPathWithinBoundary3(targetPath, boundaryPath) {
54717
- const resolvedTarget = resolve17(targetPath);
54718
- const resolvedBoundary = resolve17(boundaryPath);
54772
+ const resolvedTarget = resolve18(targetPath);
54773
+ const resolvedBoundary = resolve18(boundaryPath);
54719
54774
  return resolvedTarget === resolvedBoundary || resolvedTarget.startsWith(`${resolvedBoundary}${sep7}`);
54720
54775
  }
54721
54776
  async function resolveRealPathSafe2(path4) {
54722
54777
  try {
54723
54778
  return await realpath7(path4);
54724
54779
  } catch {
54725
- return resolve17(path4);
54780
+ return resolve18(path4);
54726
54781
  }
54727
54782
  }
54728
54783
  async function isCanonicalPathWithinBoundary2(targetPath, boundaryPath) {
@@ -54731,10 +54786,10 @@ async function isCanonicalPathWithinBoundary2(targetPath, boundaryPath) {
54731
54786
  return isPathWithinBoundary3(canonicalTarget, canonicalBoundary);
54732
54787
  }
54733
54788
  function getCodexLockPath2(targetFilePath) {
54734
- return join43(dirname13(resolve17(targetFilePath)), ".config.toml.ck-codex.lock");
54789
+ return join43(dirname13(resolve18(targetFilePath)), ".config.toml.ck-codex.lock");
54735
54790
  }
54736
54791
  async function withCodexTargetLock2(targetFilePath, operation) {
54737
- const resolvedTargetPath = resolve17(targetFilePath);
54792
+ const resolvedTargetPath = resolve18(targetFilePath);
54738
54793
  const dir = dirname13(resolvedTargetPath);
54739
54794
  if (!existsSync25(dir)) {
54740
54795
  await mkdir12(dir, { recursive: true });
@@ -54768,10 +54823,10 @@ var init_codex_path_safety = __esm(() => {
54768
54823
  // src/commands/portable/codex-features-flag.ts
54769
54824
  import { existsSync as existsSync26 } from "node:fs";
54770
54825
  import { readFile as readFile21, rename as rename7, unlink as unlink6, writeFile as writeFile12 } from "node:fs/promises";
54771
- import { dirname as dirname14, resolve as resolve18 } from "node:path";
54826
+ import { dirname as dirname14, resolve as resolve19 } from "node:path";
54772
54827
  async function ensureCodexHooksFeatureFlag(configTomlPath, isGlobal = false) {
54773
- const boundary = isGlobal ? getCodexGlobalBoundary() : dirname14(resolve18(configTomlPath));
54774
- if (!await isCanonicalPathWithinBoundary2(dirname14(resolve18(configTomlPath)), boundary)) {
54828
+ const boundary = isGlobal ? getCodexGlobalBoundary() : dirname14(resolve19(configTomlPath));
54829
+ if (!await isCanonicalPathWithinBoundary2(dirname14(resolve19(configTomlPath)), boundary)) {
54775
54830
  return {
54776
54831
  status: "failed",
54777
54832
  configPath: configTomlPath,
@@ -54935,18 +54990,18 @@ ${SENTINEL_END2}`;
54935
54990
  });
54936
54991
 
54937
54992
  // src/commands/portable/codex-hook-wrapper.ts
54938
- import { createHash as createHash5 } from "node:crypto";
54993
+ import { createHash as createHash6 } from "node:crypto";
54939
54994
  import { mkdirSync, writeFileSync as writeFileSync2 } from "node:fs";
54940
- import { dirname as dirname15, join as join44, resolve as resolve19 } from "node:path";
54995
+ import { dirname as dirname15, join as join44, resolve as resolve20 } from "node:path";
54941
54996
  function wrapperFilename(originalPath) {
54942
- const abs = resolve19(originalPath);
54943
- const hash = createHash5("sha256").update(abs).digest("hex").slice(0, 8);
54997
+ const abs = resolve20(originalPath);
54998
+ const hash = createHash6("sha256").update(abs).digest("hex").slice(0, 8);
54944
54999
  const base = abs.split(/[\\/]/).pop() ?? "hook.cjs";
54945
55000
  return `${hash}-${base}`;
54946
55001
  }
54947
55002
  function generateCodexHookWrappers(originalPaths, wrapperDir, capabilities, timeoutsByPath) {
54948
55003
  const results = [];
54949
- const resolvedWrapperDir = resolve19(wrapperDir);
55004
+ const resolvedWrapperDir = resolve20(wrapperDir);
54950
55005
  for (const originalPath of originalPaths) {
54951
55006
  const filename = wrapperFilename(originalPath);
54952
55007
  const wrapperPath = join44(resolvedWrapperDir, filename);
@@ -54961,7 +55016,7 @@ function generateCodexHookWrappers(originalPaths, wrapperDir, capabilities, time
54961
55016
  }
54962
55017
  try {
54963
55018
  mkdirSync(dirname15(wrapperPath), { recursive: true });
54964
- const resolvedPath = resolve19(originalPath);
55019
+ const resolvedPath = resolve20(originalPath);
54965
55020
  const hookTimeoutMs = timeoutsByPath?.[resolvedPath] ?? timeoutsByPath?.[originalPath];
54966
55021
  const content = buildWrapperScript(originalPath, capabilities, hookTimeoutMs);
54967
55022
  writeFileSync2(wrapperPath, content, { mode: 493 });
@@ -55366,7 +55421,7 @@ var init_gemini_hook_event_map = __esm(() => {
55366
55421
  import { existsSync as existsSync27, readFileSync as readFileSync8 } from "node:fs";
55367
55422
  import { mkdir as mkdir13, readFile as readFile22, rename as rename8, rm as rm6, writeFile as writeFile13 } from "node:fs/promises";
55368
55423
  import { homedir as homedir26 } from "node:os";
55369
- import { basename as basename14, dirname as dirname16, extname as extname4, isAbsolute as isAbsolute6, join as join45, resolve as resolve20 } from "node:path";
55424
+ import { basename as basename14, dirname as dirname16, extname as extname4, isAbsolute as isAbsolute6, join as join45, resolve as resolve21 } from "node:path";
55370
55425
  function resolveSettingsPath(pathValue, isGlobal) {
55371
55426
  if (isGlobal || isAbsolute6(pathValue))
55372
55427
  return pathValue;
@@ -55988,7 +56043,7 @@ async function migrateHooksSettingsForCodex(options2) {
55988
56043
  addKey(`./${join45(targetHooksDir, base)}`);
55989
56044
  }
55990
56045
  for (const commandSourceHooksDir of sourceHookCommandDirs) {
55991
- const sourceAbs = join45(resolve20(commandSourceHooksDir), base);
56046
+ const sourceAbs = join45(resolve21(commandSourceHooksDir), base);
55992
56047
  addKey(sourceAbs);
55993
56048
  addKey(join45(commandSourceHooksDir, base));
55994
56049
  addKey(`./${join45(commandSourceHooksDir, base)}`);
@@ -56152,7 +56207,7 @@ var init_generated_context_hooks = __esm(() => {
56152
56207
  // src/commands/portable/migrated-hook-settings-cleanup.ts
56153
56208
  import { existsSync as existsSync28, realpathSync } from "node:fs";
56154
56209
  import { readFile as readFile23, rename as rename9, rm as rm7, unlink as unlink7, writeFile as writeFile14 } from "node:fs/promises";
56155
- import { basename as basename16, isAbsolute as isAbsolute7, relative as relative10, resolve as resolve21 } from "node:path";
56210
+ import { basename as basename16, isAbsolute as isAbsolute7, relative as relative11, resolve as resolve22 } from "node:path";
56156
56211
  async function pruneSettingsHooks(settingsPath, hooksDir) {
56157
56212
  const filesToRemove = new Set;
56158
56213
  const warnings = [];
@@ -56236,9 +56291,9 @@ function hookFilesFromCommand(command, hooksDir) {
56236
56291
  if (!name || !isGeneratedContextHookName(name))
56237
56292
  continue;
56238
56293
  if (isAbsolute7(cleaned) && isPathWithin(cleaned, hooksDir))
56239
- files.add(resolve21(cleaned));
56294
+ files.add(resolve22(cleaned));
56240
56295
  else if (referencesHooksDir(cleaned, hooksDir) || cleaned.includes(".claude/hooks/")) {
56241
- files.add(resolve21(hooksDir, name));
56296
+ files.add(resolve22(hooksDir, name));
56242
56297
  }
56243
56298
  }
56244
56299
  return Array.from(files);
@@ -56249,14 +56304,14 @@ function referencesHooksDir(command, hooksDir) {
56249
56304
  return normalized.includes(normalizedDir) || normalized.includes(".claude/hooks/") || normalized.includes(".codex/hooks/") || normalized.includes(".gemini/hooks/") || normalized.includes(".factory/hooks/");
56250
56305
  }
56251
56306
  function isPathWithin(filePath, parentDir) {
56252
- const rel = relative10(resolvePathForContainment(parentDir), resolvePathForContainment(filePath));
56307
+ const rel = relative11(resolvePathForContainment(parentDir), resolvePathForContainment(filePath));
56253
56308
  return rel === "" || !!rel && !rel.startsWith("..") && !isAbsolute7(rel);
56254
56309
  }
56255
56310
  function resolvePathForContainment(pathValue) {
56256
56311
  try {
56257
56312
  return realpathSync.native(pathValue);
56258
56313
  } catch {
56259
- return resolve21(pathValue);
56314
+ return resolve22(pathValue);
56260
56315
  }
56261
56316
  }
56262
56317
  async function atomicWrite2(filePath, content) {
@@ -56283,7 +56338,7 @@ __export(exports_migrated_hooks_cleanup, {
56283
56338
  isGeneratedContextHookName: () => isGeneratedContextHookName,
56284
56339
  cleanupMigratedHooksForProviders: () => cleanupMigratedHooksForProviders
56285
56340
  });
56286
- import { isAbsolute as isAbsolute8, resolve as resolve22 } from "node:path";
56341
+ import { isAbsolute as isAbsolute8, resolve as resolve23 } from "node:path";
56287
56342
  async function cleanupMigratedHooksForProviders(providerIds, options2) {
56288
56343
  const uniqueProviders = Array.from(new Set(providerIds));
56289
56344
  const results = [];
@@ -56337,7 +56392,7 @@ async function cleanupMigratedHooksForProvider(provider, options2) {
56337
56392
  function resolveProviderPath(pathValue) {
56338
56393
  if (!pathValue)
56339
56394
  return null;
56340
- return isAbsolute8(pathValue) ? pathValue : resolve22(process.cwd(), pathValue);
56395
+ return isAbsolute8(pathValue) ? pathValue : resolve23(process.cwd(), pathValue);
56341
56396
  }
56342
56397
  var init_migrated_hooks_cleanup = __esm(() => {
56343
56398
  init_generated_context_hooks();
@@ -56702,7 +56757,7 @@ function normalizePortablePath(value) {
56702
56757
  return "";
56703
56758
  return normalized.replace(/^\.\/+/, "");
56704
56759
  }
56705
- function isAbsoluteLike(value) {
56760
+ function isAbsoluteLike2(value) {
56706
56761
  return path5.isAbsolute(value) || /^[a-zA-Z]:[\\/]/.test(value) || /^\\\\/.test(value);
56707
56762
  }
56708
56763
  function hasDotDotSegment(value) {
@@ -57259,7 +57314,7 @@ function detectRenames(input) {
57259
57314
  const actions = [];
57260
57315
  const activeProviderConfigs = dedupeProviderConfigs(input.providerConfigs);
57261
57316
  for (const rename10 of applicable) {
57262
- if (hasDotDotSegment(rename10.from) || hasDotDotSegment(rename10.to) || isAbsoluteLike(rename10.from) || isAbsoluteLike(rename10.to)) {
57317
+ if (hasDotDotSegment(rename10.from) || hasDotDotSegment(rename10.to) || isAbsoluteLike2(rename10.from) || isAbsoluteLike2(rename10.to)) {
57263
57318
  console.warn(`[!] Skipping suspicious manifest rename: ${rename10.from} -> ${rename10.to}`);
57264
57319
  continue;
57265
57320
  }
@@ -57777,7 +57832,7 @@ var init_migration_result_utils = __esm(() => {
57777
57832
  import { existsSync as existsSync31 } from "node:fs";
57778
57833
  import { readFile as readFile27, rm as rm8 } from "node:fs/promises";
57779
57834
  import { homedir as homedir28 } from "node:os";
57780
- import { basename as basename17, join as join47, resolve as resolve23 } from "node:path";
57835
+ import { basename as basename17, join as join47, resolve as resolve24 } from "node:path";
57781
57836
  function resolveRegistryDeps(deps) {
57782
57837
  return {
57783
57838
  ...defaultRegistryDeps,
@@ -57933,8 +57988,8 @@ function parseConfigSource(input) {
57933
57988
  if (!trimmed) {
57934
57989
  return { ok: true, value: undefined };
57935
57990
  }
57936
- const projectSourcePath = resolve23(process.cwd(), "CLAUDE.md");
57937
- const globalSourcePath = resolve23(getGlobalConfigSourcePath());
57991
+ const projectSourcePath = resolve24(process.cwd(), "CLAUDE.md");
57992
+ const globalSourcePath = resolve24(getGlobalConfigSourcePath());
57938
57993
  const sourceMap = {
57939
57994
  default: undefined,
57940
57995
  global: globalSourcePath,
@@ -57945,7 +58000,7 @@ function parseConfigSource(input) {
57945
58000
  if (normalizedKey in sourceMap) {
57946
58001
  return { ok: true, value: sourceMap[normalizedKey] };
57947
58002
  }
57948
- const resolved = resolve23(trimmed);
58003
+ const resolved = resolve24(trimmed);
57949
58004
  if (resolved === globalSourcePath || resolved === projectSourcePath) {
57950
58005
  return { ok: true, value: resolved };
57951
58006
  }
@@ -58013,7 +58068,7 @@ function shouldExecuteAction(action) {
58013
58068
  }
58014
58069
  async function executePlanDeleteAction(action, options2) {
58015
58070
  const preservePaths = options2?.preservePaths ?? new Set;
58016
- const shouldPreserveTarget = action.targetPath.length > 0 && preservePaths.has(resolve23(action.targetPath));
58071
+ const shouldPreserveTarget = action.targetPath.length > 0 && preservePaths.has(resolve24(action.targetPath));
58017
58072
  try {
58018
58073
  if (!shouldPreserveTarget && action.targetPath && existsSync31(action.targetPath)) {
58019
58074
  await rm8(action.targetPath, { recursive: true, force: true });
@@ -58038,7 +58093,7 @@ async function executePlanDeleteAction(action, options2) {
58038
58093
  }
58039
58094
  }
58040
58095
  function hasSuccessfulReplacementWriteForDelete(action, results) {
58041
- return results.some((result) => result.success && !result.skipped && result.provider === action.provider && replacementTypeMatchesForDelete(action.type, result.portableType) && replacementItemMatchesForDelete(action, result) && result.path.length > 0 && resolve23(result.path) !== resolve23(action.targetPath));
58096
+ return results.some((result) => result.success && !result.skipped && result.provider === action.provider && replacementTypeMatchesForDelete(action.type, result.portableType) && replacementItemMatchesForDelete(action, result) && result.path.length > 0 && resolve24(result.path) !== resolve24(action.targetPath));
58042
58097
  }
58043
58098
  function replacementTypeMatchesForDelete(actionType, resultType) {
58044
58099
  return resultType === actionType || actionType === "command" && resultType === "skill";
@@ -58986,7 +59041,7 @@ function registerMigrationRoutes(app, deps) {
58986
59041
  successfulHookFiles2.set(provider, entry);
58987
59042
  if (result.path.length > 0) {
58988
59043
  const absEntry = successfulHookAbsPaths2.get(provider) ?? [];
58989
- absEntry.push(resolve23(result.path));
59044
+ absEntry.push(resolve24(result.path));
58990
59045
  successfulHookAbsPaths2.set(provider, absEntry);
58991
59046
  }
58992
59047
  }
@@ -59035,7 +59090,7 @@ function registerMigrationRoutes(app, deps) {
59035
59090
  }
59036
59091
  }
59037
59092
  }
59038
- const writtenPaths = new Set(allResults.filter((r2) => r2.success && !r2.skipped && r2.path.length > 0).map((r2) => resolve23(r2.path)));
59093
+ const writtenPaths = new Set(allResults.filter((r2) => r2.success && !r2.skipped && r2.path.length > 0).map((r2) => resolve24(r2.path)));
59039
59094
  for (const deleteAction of deleteActions) {
59040
59095
  if (!shouldRunPlanDeleteAction(deleteAction, allResults)) {
59041
59096
  const skippedDelete = createSkippedPathMigrationCleanupResult({
@@ -59084,7 +59139,7 @@ function registerMigrationRoutes(app, deps) {
59084
59139
  const agentSrc = getAgentSourcePath();
59085
59140
  const cmdSrc = getCommandSourcePath();
59086
59141
  const skillSrc = getSkillSourcePath();
59087
- const kitRoot = (agentSrc ? resolve23(agentSrc, "..") : null) ?? (cmdSrc ? resolve23(cmdSrc, "..") : null) ?? (skillSrc ? resolve23(skillSrc, "..") : null) ?? null;
59142
+ const kitRoot = (agentSrc ? resolve24(agentSrc, "..") : null) ?? (cmdSrc ? resolve24(cmdSrc, "..") : null) ?? (skillSrc ? resolve24(skillSrc, "..") : null) ?? null;
59088
59143
  const manifest = kitRoot ? await loadPortableManifest(kitRoot) : null;
59089
59144
  if (manifest?.cliVersion) {
59090
59145
  await registryDeps.updateAppliedManifestVersion(manifest.cliVersion);
@@ -59241,7 +59296,7 @@ function registerMigrationRoutes(app, deps) {
59241
59296
  successfulHookFiles.set(result.provider, existing);
59242
59297
  if (result.path.length > 0) {
59243
59298
  const absExisting = successfulHookAbsPaths.get(result.provider) ?? [];
59244
- absExisting.push(resolve23(result.path));
59299
+ absExisting.push(resolve24(result.path));
59245
59300
  successfulHookAbsPaths.set(result.provider, absExisting);
59246
59301
  }
59247
59302
  }
@@ -59504,7 +59559,7 @@ var init_plan_metadata = __esm(() => {
59504
59559
 
59505
59560
  // src/domains/plan-parser/plan-table-parser.ts
59506
59561
  import { readFileSync as readFileSync10 } from "node:fs";
59507
- import { dirname as dirname18, resolve as resolve24 } from "node:path";
59562
+ import { dirname as dirname18, resolve as resolve25 } from "node:path";
59508
59563
  function normalizeStatus(raw) {
59509
59564
  const s = raw.toLowerCase().trim();
59510
59565
  if (s.includes("complete") || s.includes("done") || s.includes("✓") || s.includes("✅")) {
@@ -59587,7 +59642,7 @@ function parseHeaderAwareTable(content, dir, options2) {
59587
59642
  hasLinks = true;
59588
59643
  linkText = linkMatch[1].trim();
59589
59644
  name = filenameToTitle(linkText);
59590
- file = resolve24(dir, linkMatch[2]);
59645
+ file = resolve25(dir, linkMatch[2]);
59591
59646
  } else {
59592
59647
  name = nameRaw.replace(/\[.*?\]\(.*?\)/g, "").trim() || `Phase ${phaseId}`;
59593
59648
  linkText = name;
@@ -59627,7 +59682,7 @@ function parseFormat1(content, dir, options2) {
59627
59682
  phaseId,
59628
59683
  name: name.trim(),
59629
59684
  status: normalizeStatus(status),
59630
- file: resolve24(dir, linkPath),
59685
+ file: resolve25(dir, linkPath),
59631
59686
  linkText: linkText.trim(),
59632
59687
  anchor
59633
59688
  });
@@ -59647,7 +59702,7 @@ function parseFormat2(content, dir, options2) {
59647
59702
  phaseId,
59648
59703
  name: name.trim(),
59649
59704
  status: normalizeStatus(status),
59650
- file: resolve24(dir, linkPath),
59705
+ file: resolve25(dir, linkPath),
59651
59706
  linkText,
59652
59707
  anchor
59653
59708
  });
@@ -59666,7 +59721,7 @@ function parseFormat2b(content, dir, options2) {
59666
59721
  phaseId,
59667
59722
  name: name.trim(),
59668
59723
  status: normalizeStatus(status),
59669
- file: resolve24(dir, linkPath),
59724
+ file: resolve25(dir, linkPath),
59670
59725
  linkText: name.trim(),
59671
59726
  anchor
59672
59727
  });
@@ -59765,7 +59820,7 @@ function parseFormat4(content, planFilePath, options2) {
59765
59820
  current = { name, status: hasCheck ? "completed" : "pending" };
59766
59821
  } else if (fileMatch && current) {
59767
59822
  const planDir = dirname18(planFilePath);
59768
- current.file = resolve24(planDir, fileMatch[1].trim());
59823
+ current.file = resolve25(planDir, fileMatch[1].trim());
59769
59824
  } else if (statusMatch && current) {
59770
59825
  current.status = normalizeStatus(statusMatch[2]);
59771
59826
  }
@@ -59831,7 +59886,7 @@ function parseFormat6(content, dir, options2) {
59831
59886
  phaseId,
59832
59887
  name: phaseName,
59833
59888
  status: checked.toLowerCase() === "x" ? "completed" : "pending",
59834
- file: resolve24(dir, linkPath),
59889
+ file: resolve25(dir, linkPath),
59835
59890
  linkText: phaseName,
59836
59891
  anchor
59837
59892
  });
@@ -59885,7 +59940,7 @@ var init_plan_table_parser = __esm(() => {
59885
59940
  // src/domains/plan-parser/activity-tracker.ts
59886
59941
  import { spawnSync as spawnSync2 } from "node:child_process";
59887
59942
  import { readdirSync as readdirSync5, statSync as statSync8 } from "node:fs";
59888
- import { join as join48, relative as relative11 } from "node:path";
59943
+ import { join as join48, relative as relative12 } from "node:path";
59889
59944
  function startOfDay(date) {
59890
59945
  const copy2 = new Date(date);
59891
59946
  copy2.setHours(0, 0, 0, 0);
@@ -59943,7 +59998,7 @@ function getMtimeSamples(dir, samples) {
59943
59998
  if (!sample)
59944
59999
  continue;
59945
60000
  sample.fileModCount += 1;
59946
- sample.files.add(relative11(process.cwd(), file));
60001
+ sample.files.add(relative12(process.cwd(), file));
59947
60002
  }
59948
60003
  }
59949
60004
  function computeLevel(value, max) {
@@ -60016,13 +60071,13 @@ var init_plan_scanner = () => {};
60016
60071
 
60017
60072
  // src/domains/plan-parser/plan-scope.ts
60018
60073
  import { homedir as homedir29 } from "node:os";
60019
- import { isAbsolute as isAbsolute9, join as join50, relative as relative12, resolve as resolve25 } from "node:path";
60074
+ import { isAbsolute as isAbsolute9, join as join50, relative as relative13, resolve as resolve26 } from "node:path";
60020
60075
  function resolveConfiguredDir(configuredPath, baseDir) {
60021
60076
  const trimmed = configuredPath?.trim();
60022
60077
  if (!trimmed) {
60023
60078
  return join50(baseDir, DEFAULT_PLANS_DIRNAME);
60024
60079
  }
60025
- return isAbsolute9(trimmed) ? resolve25(trimmed) : resolve25(baseDir, trimmed);
60080
+ return isAbsolute9(trimmed) ? resolve26(trimmed) : resolve26(baseDir, trimmed);
60026
60081
  }
60027
60082
  function resolveProjectPlansDir(projectRoot, config) {
60028
60083
  return resolveConfiguredDir(config?.paths?.plans, projectRoot);
@@ -60034,9 +60089,9 @@ function resolvePlanDirForScope(scope, projectRoot, config) {
60034
60089
  return scope === "global" ? resolveGlobalPlansDir(config) : resolveProjectPlansDir(projectRoot, config);
60035
60090
  }
60036
60091
  function isWithinDir(targetPath, baseDir) {
60037
- const resolvedTarget = resolve25(targetPath);
60038
- const resolvedBase = resolve25(baseDir);
60039
- const relativePath = relative12(resolvedBase, resolvedTarget);
60092
+ const resolvedTarget = resolve26(targetPath);
60093
+ const resolvedBase = resolve26(baseDir);
60094
+ const relativePath = relative13(resolvedBase, resolvedTarget);
60040
60095
  return relativePath === "" || !relativePath.startsWith("..") && relativePath !== ".." && !isAbsolute9(relativePath);
60041
60096
  }
60042
60097
  function inferPlanScopeForDir(planDir, config) {
@@ -60827,7 +60882,7 @@ import {
60827
60882
  unlinkSync,
60828
60883
  writeFileSync as writeFileSync4
60829
60884
  } from "node:fs";
60830
- import { dirname as dirname22, isAbsolute as isAbsolute10, join as join53, parse as parse2, relative as relative13, resolve as resolve26 } from "node:path";
60885
+ import { dirname as dirname22, isAbsolute as isAbsolute10, join as join53, parse as parse2, relative as relative14, resolve as resolve27 } from "node:path";
60831
60886
  function createEmptyRegistry() {
60832
60887
  return {
60833
60888
  version: 1,
@@ -60882,8 +60937,8 @@ function migrateFromProjectLocal(cwd2, globalPath) {
60882
60937
  }
60883
60938
  }
60884
60939
  function normalizeRegistryDir(cwd2, dir) {
60885
- const absoluteDir = isAbsolute10(dir) ? dir : resolve26(cwd2, dir);
60886
- const relativeDir = relative13(cwd2, absoluteDir) || dir;
60940
+ const absoluteDir = isAbsolute10(dir) ? dir : resolve27(cwd2, dir);
60941
+ const relativeDir = relative14(cwd2, absoluteDir) || dir;
60887
60942
  return relativeDir.replace(/\\/g, "/");
60888
60943
  }
60889
60944
  function findProjectRoot(startDir) {
@@ -61237,24 +61292,24 @@ function pLimit(concurrency) {
61237
61292
  activeCount--;
61238
61293
  resumeNext();
61239
61294
  };
61240
- const run = async (function_, resolve27, arguments_) => {
61295
+ const run = async (function_, resolve28, arguments_) => {
61241
61296
  const result = (async () => function_(...arguments_))();
61242
- resolve27(result);
61297
+ resolve28(result);
61243
61298
  try {
61244
61299
  await result;
61245
61300
  } catch {}
61246
61301
  next();
61247
61302
  };
61248
- const enqueue = (function_, resolve27, arguments_) => {
61303
+ const enqueue = (function_, resolve28, arguments_) => {
61249
61304
  new Promise((internalResolve) => {
61250
61305
  queue.enqueue(internalResolve);
61251
- }).then(run.bind(undefined, function_, resolve27, arguments_));
61306
+ }).then(run.bind(undefined, function_, resolve28, arguments_));
61252
61307
  if (activeCount < concurrency) {
61253
61308
  resumeNext();
61254
61309
  }
61255
61310
  };
61256
- const generator = (function_, ...arguments_) => new Promise((resolve27) => {
61257
- enqueue(function_, resolve27, arguments_);
61311
+ const generator = (function_, ...arguments_) => new Promise((resolve28) => {
61312
+ enqueue(function_, resolve28, arguments_);
61258
61313
  });
61259
61314
  Object.defineProperties(generator, {
61260
61315
  activeCount: {
@@ -61301,7 +61356,7 @@ var init_p_limit = __esm(() => {
61301
61356
  // src/domains/web-server/routes/plan-routes.ts
61302
61357
  import { existsSync as existsSync37, readFileSync as readFileSync14, realpathSync as realpathSync2 } from "node:fs";
61303
61358
  import { homedir as homedir30 } from "node:os";
61304
- import { basename as basename20, dirname as dirname24, join as join55, relative as relative14, resolve as resolve27, sep as sep8 } from "node:path";
61359
+ import { basename as basename20, dirname as dirname24, join as join55, relative as relative15, resolve as resolve28, sep as sep8 } from "node:path";
61305
61360
  function sanitizeError(err) {
61306
61361
  if (err instanceof Error) {
61307
61362
  if (/^(ENOENT|EACCES|EPERM|EISDIR)/.test(err.message))
@@ -61316,8 +61371,8 @@ function hasBasePrefix(targetPath, baseDir) {
61316
61371
  return targetPath === baseDir || targetPath.startsWith(basePrefix);
61317
61372
  }
61318
61373
  function isWithinBase(targetPath, baseDir) {
61319
- const resolvedTarget = resolve27(targetPath);
61320
- const resolvedBase = resolve27(baseDir);
61374
+ const resolvedTarget = resolve28(targetPath);
61375
+ const resolvedBase = resolve28(baseDir);
61321
61376
  const logicalMatch = hasBasePrefix(resolvedTarget, resolvedBase);
61322
61377
  if (existsSync37(resolvedTarget)) {
61323
61378
  try {
@@ -61401,7 +61456,7 @@ async function getAllowedRoots(projectId) {
61401
61456
  roots.push(projectPlansDir);
61402
61457
  roots.push(getGlobalPlanRoot());
61403
61458
  } catch {}
61404
- return Array.from(new Set(roots.map((root) => resolve27(root))));
61459
+ return Array.from(new Set(roots.map((root) => resolve28(root))));
61405
61460
  }
61406
61461
  async function isWithinAllowedRoots(targetPath, projectId) {
61407
61462
  const allowedRoots = await getAllowedRoots(projectId);
@@ -61423,7 +61478,7 @@ async function getSafePath(value, kind, res, projectId) {
61423
61478
  return null;
61424
61479
  }
61425
61480
  try {
61426
- return realpathSync2(resolve27(value));
61481
+ return realpathSync2(resolve28(value));
61427
61482
  } catch {
61428
61483
  res.status(403).json({ error: "Cannot resolve path" });
61429
61484
  return null;
@@ -61436,7 +61491,7 @@ function getPlanFilePath(value, res, projectId) {
61436
61491
  return getSafePath(value, "file", res, projectId);
61437
61492
  }
61438
61493
  function toProjectPathKey(projectPath) {
61439
- const resolvedPath = resolve27(projectPath);
61494
+ const resolvedPath = resolve28(projectPath);
61440
61495
  if (!existsSync37(resolvedPath)) {
61441
61496
  return resolvedPath;
61442
61497
  }
@@ -61451,13 +61506,13 @@ function createDiscoveredProjectId(projectPath) {
61451
61506
  }
61452
61507
  function toProjectPlanListItem(summary, plansDir) {
61453
61508
  return {
61454
- file: relative14(plansDir, summary.planFile),
61509
+ file: relative15(plansDir, summary.planFile),
61455
61510
  name: basename20(dirname24(summary.planFile)),
61456
61511
  slug: basename20(dirname24(summary.planFile)),
61457
61512
  summary: {
61458
61513
  ...summary,
61459
- planDir: relative14(plansDir, summary.planDir),
61460
- planFile: relative14(plansDir, summary.planFile)
61514
+ planDir: relative15(plansDir, summary.planDir),
61515
+ planFile: relative15(plansDir, summary.planFile)
61461
61516
  }
61462
61517
  };
61463
61518
  }
@@ -61507,7 +61562,7 @@ function registerPlanRoutes(app) {
61507
61562
  return;
61508
61563
  try {
61509
61564
  const { frontmatter, phases } = parsePlanFile(file);
61510
- res.json({ file: relative14(process.cwd(), file), frontmatter, phases });
61565
+ res.json({ file: relative15(process.cwd(), file), frontmatter, phases });
61511
61566
  } catch (err) {
61512
61567
  res.status(500).json({ error: sanitizeError(err) });
61513
61568
  }
@@ -61534,17 +61589,17 @@ function registerPlanRoutes(app) {
61534
61589
  const entries = (await Promise.all(scanPlanDir(dir).map(async (planFile) => await isWithinAllowedRoots(planFile, projectId) ? planFile : null))).filter((planFile) => planFile !== null);
61535
61590
  const summaries = buildPlanSummaries(entries.slice(offset, offset + limit));
61536
61591
  const plans = summaries.map((summary) => ({
61537
- file: relative14(process.cwd(), summary.planFile),
61592
+ file: relative15(process.cwd(), summary.planFile),
61538
61593
  name: basename20(dirname24(summary.planFile)),
61539
61594
  slug: basename20(dirname24(summary.planFile)),
61540
61595
  summary: {
61541
61596
  ...summary,
61542
- planDir: relative14(process.cwd(), summary.planDir),
61543
- planFile: relative14(process.cwd(), summary.planFile)
61597
+ planDir: relative15(process.cwd(), summary.planDir),
61598
+ planFile: relative15(process.cwd(), summary.planFile)
61544
61599
  }
61545
61600
  }));
61546
61601
  res.json({
61547
- dir: relative14(process.cwd(), dir),
61602
+ dir: relative15(process.cwd(), dir),
61548
61603
  total: entries.length,
61549
61604
  limit,
61550
61605
  offset,
@@ -61560,7 +61615,7 @@ function registerPlanRoutes(app) {
61560
61615
  const seenProjectKeys = new Set;
61561
61616
  const scanTargets = [];
61562
61617
  for (const project of await ProjectsRegistryManager.listProjects()) {
61563
- if (!existsSync37(resolve27(project.path)))
61618
+ if (!existsSync37(resolve28(project.path)))
61564
61619
  continue;
61565
61620
  const projectKey = toProjectPathKey(project.path);
61566
61621
  if (projectKey === globalProjectKey || seenProjectKeys.has(projectKey))
@@ -61583,7 +61638,7 @@ function registerPlanRoutes(app) {
61583
61638
  path: project.path
61584
61639
  });
61585
61640
  }
61586
- const currentPath = resolve27(process.cwd());
61641
+ const currentPath = resolve28(process.cwd());
61587
61642
  const currentProjectKey = toProjectPathKey(currentPath);
61588
61643
  if (isCurrentProjectFallbackCandidate(currentPath, globalProjectKey) && !seenProjectKeys.has(currentProjectKey)) {
61589
61644
  scanTargets.push({
@@ -61672,7 +61727,7 @@ function registerPlanRoutes(app) {
61672
61727
  const file = await getPlanFilePath(String(req.query.file ?? ""), res, projectId);
61673
61728
  if (!file)
61674
61729
  return;
61675
- const dir = req.query.dir ? resolve27(String(req.query.dir)) : null;
61730
+ const dir = req.query.dir ? resolve28(String(req.query.dir)) : null;
61676
61731
  if (dir && (!await isWithinAllowedRoots(dir, projectId) || !isWithinBase(file, dir))) {
61677
61732
  res.status(403).json({ error: "File must stay within the selected plan directory" });
61678
61733
  return;
@@ -61681,7 +61736,7 @@ function registerPlanRoutes(app) {
61681
61736
  const raw = readFileSync14(file, "utf8");
61682
61737
  const parsed = import_gray_matter10.default(raw);
61683
61738
  res.json({
61684
- file: relative14(process.cwd(), file),
61739
+ file: relative15(process.cwd(), file),
61685
61740
  frontmatter: parsed.data,
61686
61741
  content: parsed.content,
61687
61742
  raw
@@ -61804,7 +61859,7 @@ var init_project_plan_data = __esm(() => {
61804
61859
  import { existsSync as existsSync38 } from "node:fs";
61805
61860
  import { readFile as readFile28 } from "node:fs/promises";
61806
61861
  import { homedir as homedir31 } from "node:os";
61807
- import { basename as basename21, join as join56, resolve as resolve28 } from "node:path";
61862
+ import { basename as basename21, join as join56, resolve as resolve29 } from "node:path";
61808
61863
  function registerProjectRoutes(app) {
61809
61864
  app.get("/api/projects", async (req, res) => {
61810
61865
  try {
@@ -61916,7 +61971,7 @@ function registerProjectRoutes(app) {
61916
61971
  } else if (projectPath.startsWith("~\\")) {
61917
61972
  projectPath = join56(homedir31(), projectPath.slice(1));
61918
61973
  }
61919
- projectPath = resolve28(projectPath);
61974
+ projectPath = resolve29(projectPath);
61920
61975
  const homeDir = homedir31();
61921
61976
  if (projectPath.includes("..") || !projectPath.startsWith(homeDir)) {
61922
61977
  res.status(400).json({ error: "Invalid path after expansion" });
@@ -62622,7 +62677,7 @@ var init_settings_routes = __esm(() => {
62622
62677
  // src/domains/skills/skill-catalog-generator.ts
62623
62678
  import { mkdir as mkdir14, readFile as readFile30, readdir as readdir15, rename as rename10, stat as stat11, writeFile as writeFile15 } from "node:fs/promises";
62624
62679
  import { homedir as homedir34 } from "node:os";
62625
- import { dirname as dirname25, join as join58, relative as relative15 } from "node:path";
62680
+ import { dirname as dirname25, join as join58, relative as relative16 } from "node:path";
62626
62681
  async function hasScripts(skillPath) {
62627
62682
  try {
62628
62683
  const entries = await readdir15(skillPath, { withFileTypes: true });
@@ -62658,7 +62713,7 @@ async function hasReferences(skillPath) {
62658
62713
  class SkillCatalogGenerator {
62659
62714
  async generate(enrichedSkills, basePath) {
62660
62715
  const entries = await Promise.all(enrichedSkills.map(async (skill) => {
62661
- const relPath = relative15(basePath, join58(skill.path, "SKILL.md"));
62716
+ const relPath = relative16(basePath, join58(skill.path, "SKILL.md"));
62662
62717
  const [scripts, refs] = await Promise.all([
62663
62718
  hasScripts(skill.path),
62664
62719
  hasReferences(skill.path)
@@ -63421,10 +63476,10 @@ var init_skills_registry = __esm(() => {
63421
63476
  import { existsSync as existsSync42 } from "node:fs";
63422
63477
  import { cp as cp3, mkdir as mkdir16, readFile as readFile33, rm as rm9, stat as stat12, writeFile as writeFile17 } from "node:fs/promises";
63423
63478
  import { homedir as homedir38 } from "node:os";
63424
- import { dirname as dirname27, join as join62, resolve as resolve30 } from "node:path";
63479
+ import { dirname as dirname27, join as join62, resolve as resolve31 } from "node:path";
63425
63480
  function isSamePath2(path1, path22) {
63426
63481
  try {
63427
- return resolve30(path1) === resolve30(path22);
63482
+ return resolve31(path1) === resolve31(path22);
63428
63483
  } catch {
63429
63484
  return false;
63430
63485
  }
@@ -63577,10 +63632,10 @@ var init_skills_installer = __esm(() => {
63577
63632
  // src/commands/skills/skills-uninstaller.ts
63578
63633
  import { existsSync as existsSync43 } from "node:fs";
63579
63634
  import { rm as rm10 } from "node:fs/promises";
63580
- import { join as join63, resolve as resolve31 } from "node:path";
63635
+ import { join as join63, resolve as resolve32 } from "node:path";
63581
63636
  function isSamePath3(path1, path22) {
63582
63637
  try {
63583
- return resolve31(path1) === resolve31(path22);
63638
+ return resolve32(path1) === resolve32(path22);
63584
63639
  } catch {
63585
63640
  return false;
63586
63641
  }
@@ -64518,7 +64573,7 @@ var package_default;
64518
64573
  var init_package = __esm(() => {
64519
64574
  package_default = {
64520
64575
  name: "claudekit-cli",
64521
- version: "4.5.0-dev.7",
64576
+ version: "4.5.0-dev.8",
64522
64577
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
64523
64578
  type: "module",
64524
64579
  repository: {
@@ -65020,7 +65075,7 @@ var init_package_manager_runner = __esm(() => {
65020
65075
  // src/domains/installation/merger/zombie-wirings-pruner.ts
65021
65076
  import { existsSync as existsSync45, readdirSync as readdirSync8 } from "node:fs";
65022
65077
  import { homedir as homedir39 } from "node:os";
65023
- import { basename as basename23, dirname as dirname28, isAbsolute as isAbsolute11, resolve as resolve32, sep as sep10 } from "node:path";
65078
+ import { basename as basename23, dirname as dirname28, isAbsolute as isAbsolute11, resolve as resolve33, sep as sep10 } from "node:path";
65024
65079
  function pruneZombieEngineerWirings(settings, hookDir, preserveCommands = new Set) {
65025
65080
  const pruned = [];
65026
65081
  const normalizedPreserveCommands = new Set(Array.from(preserveCommands).map((command) => normalizeCommand(command)));
@@ -65118,7 +65173,7 @@ function extractHookFilePath(command, hookDir) {
65118
65173
  const bashMatch = command.match(/^bash\s+["']([^"']+\.sh)["']/);
65119
65174
  if (bashMatch) {
65120
65175
  const rawPath = bashMatch[1].replace(/\\/g, "/");
65121
- const resolved = isAbsolute11(rawPath) || /^[A-Za-z]:[\\/]/.test(rawPath) ? rawPath : resolve32(hookDir, rawPath);
65176
+ const resolved = isAbsolute11(rawPath) || /^[A-Za-z]:[\\/]/.test(rawPath) ? rawPath : resolve33(hookDir, rawPath);
65122
65177
  return process.platform === "win32" ? resolved.replace(/\//g, sep10) : resolved;
65123
65178
  }
65124
65179
  return null;
@@ -65143,7 +65198,7 @@ function extractHookFilePath(command, hookDir) {
65143
65198
  if (isAbsolute11(tildeResolved) || /^[A-Za-z]:[\\/]/.test(tildeResolved)) {
65144
65199
  return process.platform === "win32" ? tildeResolved.replace(/\//g, sep10) : tildeResolved;
65145
65200
  }
65146
- return resolve32(hookDir, tildeResolved);
65201
+ return resolve33(hookDir, tildeResolved);
65147
65202
  }
65148
65203
  const unquotedMatch = command.match(/(?:^|\s)node\s+(\S+\.(?:cjs|sh|mjs|js))/);
65149
65204
  if (unquotedMatch) {
@@ -65157,7 +65212,7 @@ function extractHookFilePath(command, hookDir) {
65157
65212
  if (isAbsolute11(tildeResolved) || /^[A-Za-z]:[\\/]/.test(tildeResolved)) {
65158
65213
  return process.platform === "win32" ? tildeResolved.replace(/\//g, sep10) : tildeResolved;
65159
65214
  }
65160
- return resolve32(hookDir, tildeResolved);
65215
+ return resolve33(hookDir, tildeResolved);
65161
65216
  }
65162
65217
  return null;
65163
65218
  }
@@ -65180,7 +65235,7 @@ import { spawnSync as spawnSync3 } from "node:child_process";
65180
65235
  import { existsSync as existsSync46, readFileSync as readFileSync15, readdirSync as readdirSync9, statSync as statSync10, writeFileSync as writeFileSync5 } from "node:fs";
65181
65236
  import { readdir as readdir17 } from "node:fs/promises";
65182
65237
  import { homedir as homedir40, tmpdir } from "node:os";
65183
- import { dirname as dirname29, join as join65, resolve as resolve33, sep as sep11 } from "node:path";
65238
+ import { dirname as dirname29, join as join65, resolve as resolve34, sep as sep11 } from "node:path";
65184
65239
  function resolveDoctorCkExecutable(platformName = process.platform) {
65185
65240
  return platformName === "win32" ? "ck.cmd" : "ck";
65186
65241
  }
@@ -65196,8 +65251,8 @@ function parseDoctorCliVersionOutput(output2) {
65196
65251
  return bareMatch?.[1] ?? null;
65197
65252
  }
65198
65253
  function getHooksDir(projectDir) {
65199
- const projectHooksDir = resolve33(projectDir, ".claude", "hooks");
65200
- const globalHooksDir = resolve33(PathResolver.getGlobalKitDir(), "hooks");
65254
+ const projectHooksDir = resolve34(projectDir, ".claude", "hooks");
65255
+ const globalHooksDir = resolve34(PathResolver.getGlobalKitDir(), "hooks");
65201
65256
  if (existsSync46(projectHooksDir))
65202
65257
  return projectHooksDir;
65203
65258
  if (existsSync46(globalHooksDir))
@@ -65205,7 +65260,7 @@ function getHooksDir(projectDir) {
65205
65260
  return null;
65206
65261
  }
65207
65262
  function isPathWithin2(filePath, parentDir) {
65208
- return resolve33(filePath).startsWith(resolve33(parentDir));
65263
+ return resolve34(filePath).startsWith(resolve34(parentDir));
65209
65264
  }
65210
65265
  function getCanonicalGlobalCommandRoot() {
65211
65266
  const configuredGlobalDir = PathResolver.getGlobalKitDir().replace(/\\/g, "/").replace(/\/+$/, "");
@@ -65231,23 +65286,23 @@ function getClaudeSettingsFiles(projectDir) {
65231
65286
  const ccsSettingsDir = join65(process.env.CK_TEST_HOME ?? homedir40(), ".ccs");
65232
65287
  const candidates = [
65233
65288
  {
65234
- path: resolve33(projectDir, ".claude", "settings.json"),
65289
+ path: resolve34(projectDir, ".claude", "settings.json"),
65235
65290
  label: "project settings.json",
65236
65291
  root: "$CLAUDE_PROJECT_DIR"
65237
65292
  },
65238
65293
  {
65239
- path: resolve33(projectDir, ".claude", "settings.local.json"),
65294
+ path: resolve34(projectDir, ".claude", "settings.local.json"),
65240
65295
  label: "project settings.local.json",
65241
65296
  root: "$CLAUDE_PROJECT_DIR"
65242
65297
  },
65243
65298
  {
65244
- path: resolve33(globalClaudeDir, "settings.json"),
65299
+ path: resolve34(globalClaudeDir, "settings.json"),
65245
65300
  label: "global settings.json",
65246
65301
  root: getCanonicalGlobalCommandRoot(),
65247
65302
  managedHookNames: globalManagedHookNames
65248
65303
  },
65249
65304
  {
65250
- path: resolve33(globalClaudeDir, "settings.local.json"),
65305
+ path: resolve34(globalClaudeDir, "settings.local.json"),
65251
65306
  label: "global settings.local.json",
65252
65307
  root: getCanonicalGlobalCommandRoot(),
65253
65308
  managedHookNames: globalManagedHookNames
@@ -65258,7 +65313,7 @@ function getClaudeSettingsFiles(projectDir) {
65258
65313
  if (!dirent.isFile() || !dirent.name.endsWith(".settings.json"))
65259
65314
  continue;
65260
65315
  candidates.push({
65261
- path: resolve33(ccsSettingsDir, dirent.name),
65316
+ path: resolve34(ccsSettingsDir, dirent.name),
65262
65317
  label: `.ccs/${dirent.name}`,
65263
65318
  root: "$HOME"
65264
65319
  });
@@ -65988,7 +66043,7 @@ function resolveHookScriptPath(scriptPath, projectDir) {
65988
66043
  if (resolved.startsWith(".claude/") || resolved === ".claude") {
65989
66044
  resolved = join65(projectDir, resolved);
65990
66045
  }
65991
- return resolve33(resolved);
66046
+ return resolve34(resolved);
65992
66047
  }
65993
66048
  function collectMissingHookReferences(settings, settingsFile, projectDir) {
65994
66049
  const findings = [];
@@ -66183,10 +66238,10 @@ async function countMissingHookFileReferences(projectDir = process.cwd()) {
66183
66238
  return count;
66184
66239
  }
66185
66240
  async function countMissingHookFileReferencesForClaudeDir(claudeDir3, projectRoot = dirname29(claudeDir3)) {
66186
- const hooksDirPrefix = `${resolve33(claudeDir3, "hooks")}${sep11}`;
66241
+ const hooksDirPrefix = `${resolve34(claudeDir3, "hooks")}${sep11}`;
66187
66242
  let count = 0;
66188
66243
  for (const fileName of ["settings.json", "settings.local.json"]) {
66189
- const filePath = resolve33(claudeDir3, fileName);
66244
+ const filePath = resolve34(claudeDir3, fileName);
66190
66245
  if (!existsSync46(filePath))
66191
66246
  continue;
66192
66247
  const settings = await SettingsMerger.readSettingsFile(filePath);
@@ -66704,11 +66759,24 @@ This is a bug. Please open an issue at https://github.com/mrgoonie/claudekit-cli
66704
66759
  // src/domains/installation/plugin/codex-plugin-installer.ts
66705
66760
  import { execFile as execFile8 } from "node:child_process";
66706
66761
  import { promisify as promisify9 } from "node:util";
66707
- function resolveCodexExecutable(platformName = process.platform) {
66708
- return platformName === "win32" ? "codex.cmd" : "codex";
66762
+ function resolveCodexExecutable(_platformName = process.platform) {
66763
+ return "codex";
66709
66764
  }
66710
- function shouldRunCodexInShell(platformName = process.platform) {
66711
- return platformName === "win32";
66765
+ function shouldRunCodexInShell(_platformName = process.platform) {
66766
+ return false;
66767
+ }
66768
+ function resolveCodexExecutableCandidates(platformName = process.platform) {
66769
+ if (platformName === "win32") {
66770
+ return [
66771
+ { command: "codex", argsPrefix: [] },
66772
+ { command: "cmd.exe", argsPrefix: ["/d", "/s", "/c", "codex.cmd"] }
66773
+ ];
66774
+ }
66775
+ return [{ command: resolveCodexExecutable(platformName), argsPrefix: [] }];
66776
+ }
66777
+ function isSpawnResolutionError(err) {
66778
+ const code = err?.code;
66779
+ return code === "ENOENT" || code === "EACCES" || code === "EINVAL";
66712
66780
  }
66713
66781
 
66714
66782
  class CodexPluginInstaller {
@@ -66731,24 +66799,41 @@ class CodexPluginInstaller {
66731
66799
  async marketplaceAdd(source) {
66732
66800
  return this.run(["plugin", "marketplace", "add", source], this.opts());
66733
66801
  }
66802
+ async marketplaceRemove(name = CK_MARKETPLACE_NAME) {
66803
+ return this.run(["plugin", "marketplace", "remove", name], this.opts());
66804
+ }
66734
66805
  async add() {
66735
66806
  return this.run(["plugin", "add", `${CK_PLUGIN_NAME}@${CK_MARKETPLACE_NAME}`], this.opts());
66736
66807
  }
66808
+ async remove() {
66809
+ return this.run(["plugin", "remove", `${CK_PLUGIN_NAME}@${CK_MARKETPLACE_NAME}`], this.opts());
66810
+ }
66737
66811
  async listJson() {
66738
66812
  return this.run(["plugin", "list", "--json"], this.opts(15000));
66739
66813
  }
66814
+ async listText() {
66815
+ return this.run(["plugin", "list"], this.opts(15000));
66816
+ }
66740
66817
  async verifyInstalled() {
66741
66818
  const r2 = await this.listJson();
66742
- if (!r2.ok)
66743
- return false;
66819
+ if (!r2.ok) {
66820
+ const text = await this.listText();
66821
+ return text.ok && parseTextPluginList(text.stdout + text.stderr);
66822
+ }
66744
66823
  try {
66745
66824
  const parsed = JSON.parse(r2.stdout);
66746
66825
  return (parsed.installed ?? []).some((plugin) => plugin.pluginId === `${CK_PLUGIN_NAME}@${CK_MARKETPLACE_NAME}` && plugin.installed === true && plugin.enabled === true);
66747
66826
  } catch {
66748
- return false;
66827
+ const text = await this.listText();
66828
+ return text.ok && parseTextPluginList(text.stdout + text.stderr);
66749
66829
  }
66750
66830
  }
66751
66831
  }
66832
+ function parseTextPluginList(output2) {
66833
+ const pluginId = `${CK_PLUGIN_NAME}@${CK_MARKETPLACE_NAME}`.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
66834
+ const row = new RegExp(`^\\s*${pluginId}\\s+.*\\binstalled\\b.*\\benabled\\b`, "im");
66835
+ return row.test(output2);
66836
+ }
66752
66837
  async function installCodexPlugin(opts) {
66753
66838
  const installer = opts.installer ?? new CodexPluginInstaller(undefined, opts.codexHome);
66754
66839
  if (!await installer.isCodexAvailable() || !await installer.isPluginSupported()) {
@@ -66780,6 +66865,18 @@ async function installCodexPlugin(opts) {
66780
66865
  }
66781
66866
  return { action: "installed", pluginVerified: true };
66782
66867
  }
66868
+ async function removeCodexPlugin(opts = {}) {
66869
+ const installer = opts.installer ?? new CodexPluginInstaller(undefined, opts.codexHome);
66870
+ if (!await installer.isCodexAvailable() || !await installer.isPluginSupported()) {
66871
+ return { removed: false, marketplaceRemoved: false };
66872
+ }
66873
+ const removed = await installer.remove();
66874
+ const marketplaceRemoved = await installer.marketplaceRemove();
66875
+ return {
66876
+ removed: removed.ok,
66877
+ marketplaceRemoved: marketplaceRemoved.ok
66878
+ };
66879
+ }
66783
66880
  async function shouldRefreshCodexPlugin(installer = new CodexPluginInstaller) {
66784
66881
  if (!await installer.isCodexAvailable() || !await installer.isPluginSupported()) {
66785
66882
  return false;
@@ -66790,23 +66887,32 @@ var execFileAsync6, DEFAULT_TIMEOUT_MS2 = 120000, defaultCodexRunner = async (ar
66790
66887
  const env2 = { ...process.env };
66791
66888
  if (opts?.codexHome)
66792
66889
  env2.CODEX_HOME = opts.codexHome;
66793
- try {
66794
- const { stdout, stderr } = await execFileAsync6(resolveCodexExecutable(), args, {
66795
- env: env2,
66796
- shell: shouldRunCodexInShell(),
66797
- timeout: opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
66798
- maxBuffer: 10 * 1024 * 1024
66799
- });
66800
- return { ok: true, stdout: String(stdout), stderr: String(stderr), code: 0 };
66801
- } catch (err) {
66802
- const e2 = err;
66803
- return {
66804
- ok: false,
66805
- stdout: e2.stdout ? String(e2.stdout) : "",
66806
- stderr: e2.stderr ? String(e2.stderr) : e2.message ?? "",
66807
- code: typeof e2.code === "number" ? e2.code : null
66808
- };
66890
+ let lastError = null;
66891
+ const candidates = resolveCodexExecutableCandidates();
66892
+ for (const [index, candidate] of candidates.entries()) {
66893
+ try {
66894
+ const { stdout, stderr } = await execFileAsync6(candidate.command, [...candidate.argsPrefix, ...args], {
66895
+ env: env2,
66896
+ shell: shouldRunCodexInShell(),
66897
+ timeout: opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
66898
+ maxBuffer: 10 * 1024 * 1024
66899
+ });
66900
+ return { ok: true, stdout: String(stdout), stderr: String(stderr), code: 0 };
66901
+ } catch (err) {
66902
+ lastError = err;
66903
+ if (index < candidates.length - 1 && isSpawnResolutionError(err)) {
66904
+ continue;
66905
+ }
66906
+ break;
66907
+ }
66809
66908
  }
66909
+ const e2 = lastError;
66910
+ return {
66911
+ ok: false,
66912
+ stdout: e2?.stdout ? String(e2.stdout) : "",
66913
+ stderr: e2?.stderr ? String(e2.stderr) : e2?.message ?? "",
66914
+ code: typeof e2?.code === "number" ? e2.code : null
66915
+ };
66810
66916
  };
66811
66917
  var init_codex_plugin_installer = __esm(() => {
66812
66918
  init_install_mode_detector();
@@ -67083,7 +67189,7 @@ var init_claudekit_scanner = __esm(() => {
67083
67189
 
67084
67190
  // src/ui/ck-cli-design/tokens.ts
67085
67191
  import { homedir as homedir41, platform as platform7 } from "node:os";
67086
- import { resolve as resolve34, win32 } from "node:path";
67192
+ import { resolve as resolve35, win32 } from "node:path";
67087
67193
  function createCliDesignContext(options2 = {}) {
67088
67194
  const env2 = options2.env ?? process.env;
67089
67195
  const isTTY2 = options2.isTTY ?? process.stdout.isTTY === true;
@@ -67232,7 +67338,7 @@ function formatCdHint(value, currentPlatform = platform7()) {
67232
67338
  const absolutePath2 = win32.resolve(value);
67233
67339
  return `cd /d "${absolutePath2}"`;
67234
67340
  }
67235
- const absolutePath = resolve34(value);
67341
+ const absolutePath = resolve35(value);
67236
67342
  const displayPath = formatDisplayPath(absolutePath);
67237
67343
  if (displayPath.includes(" ")) {
67238
67344
  return `cd "${displayPath}"`;
@@ -68985,13 +69091,13 @@ async function promptKitUpdate(beta, yes, deps) {
68985
69091
  args.push("--beta");
68986
69092
  const displayCmd = `ck ${args.join(" ")}`;
68987
69093
  logger.info(`Running: ${displayCmd}`);
68988
- const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((resolve35) => {
69094
+ const spawnFn = deps?.spawnInitFn ?? ((spawnArgs) => new Promise((resolve36) => {
68989
69095
  const initCommand = resolveCkInitSpawnCommand(spawnArgs);
68990
69096
  const child = spawn2(initCommand.command, initCommand.args, { stdio: "inherit" });
68991
- child.on("close", (code) => resolve35(code ?? 1));
69097
+ child.on("close", (code) => resolve36(code ?? 1));
68992
69098
  child.on("error", (err) => {
68993
69099
  logger.verbose(`Failed to spawn ck init: ${err.message}`);
68994
- resolve35(1);
69100
+ resolve36(1);
68995
69101
  });
68996
69102
  }));
68997
69103
  const exitCode = await spawnFn(args);
@@ -69465,7 +69571,7 @@ class ConfigVersionChecker {
69465
69571
  return null;
69466
69572
  }
69467
69573
  const delay = baseBackoff * 2 ** attempt;
69468
- await new Promise((resolve35) => setTimeout(resolve35, delay));
69574
+ await new Promise((resolve36) => setTimeout(resolve36, delay));
69469
69575
  }
69470
69576
  }
69471
69577
  return null;
@@ -69571,12 +69677,12 @@ import { readFile as readFile40 } from "node:fs/promises";
69571
69677
  import { cpus, homedir as homedir42, totalmem } from "node:os";
69572
69678
  import { join as join71 } from "node:path";
69573
69679
  function runCommand(cmd, args, fallback2) {
69574
- return new Promise((resolve35) => {
69680
+ return new Promise((resolve36) => {
69575
69681
  execFile9(cmd, args, { timeout: 5000 }, (err, stdout) => {
69576
69682
  if (err) {
69577
- resolve35(fallback2);
69683
+ resolve36(fallback2);
69578
69684
  } else {
69579
- resolve35(stdout.trim() || fallback2);
69685
+ resolve36(stdout.trim() || fallback2);
69580
69686
  }
69581
69687
  });
69582
69688
  });
@@ -70013,7 +70119,7 @@ var init_routes = __esm(() => {
70013
70119
 
70014
70120
  // src/domains/web-server/static-server.ts
70015
70121
  import { existsSync as existsSync50 } from "node:fs";
70016
- import { basename as basename24, dirname as dirname31, join as join72, resolve as resolve35 } from "node:path";
70122
+ import { basename as basename24, dirname as dirname31, join as join72, resolve as resolve36 } from "node:path";
70017
70123
  import { fileURLToPath as fileURLToPath2 } from "node:url";
70018
70124
  function addRuntimeUiCandidate(candidates, runtimePath) {
70019
70125
  if (!runtimePath) {
@@ -70023,7 +70129,7 @@ function addRuntimeUiCandidate(candidates, runtimePath) {
70023
70129
  if (!looksLikePath) {
70024
70130
  return;
70025
70131
  }
70026
- const entryDir = dirname31(resolve35(runtimePath));
70132
+ const entryDir = dirname31(resolve36(runtimePath));
70027
70133
  if (basename24(entryDir) === "dist") {
70028
70134
  candidates.add(join72(entryDir, "ui"));
70029
70135
  }
@@ -71726,7 +71832,7 @@ var require_websocket = __commonJS((exports, module) => {
71726
71832
  var http = __require("http");
71727
71833
  var net2 = __require("net");
71728
71834
  var tls = __require("tls");
71729
- var { randomBytes, createHash: createHash6 } = __require("crypto");
71835
+ var { randomBytes, createHash: createHash7 } = __require("crypto");
71730
71836
  var { Duplex, Readable: Readable2 } = __require("stream");
71731
71837
  var { URL: URL2 } = __require("url");
71732
71838
  var PerMessageDeflate = require_permessage_deflate();
@@ -72261,7 +72367,7 @@ var require_websocket = __commonJS((exports, module) => {
72261
72367
  abortHandshake(websocket, socket, "Invalid Upgrade header");
72262
72368
  return;
72263
72369
  }
72264
- const digest = createHash6("sha1").update(key + GUID).digest("base64");
72370
+ const digest = createHash7("sha1").update(key + GUID).digest("base64");
72265
72371
  if (res.headers["sec-websocket-accept"] !== digest) {
72266
72372
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
72267
72373
  return;
@@ -72634,7 +72740,7 @@ var require_websocket_server = __commonJS((exports, module) => {
72634
72740
  var EventEmitter3 = __require("events");
72635
72741
  var http = __require("http");
72636
72742
  var { Duplex } = __require("stream");
72637
- var { createHash: createHash6 } = __require("crypto");
72743
+ var { createHash: createHash7 } = __require("crypto");
72638
72744
  var extension = require_extension();
72639
72745
  var PerMessageDeflate = require_permessage_deflate();
72640
72746
  var subprotocol = require_subprotocol();
@@ -72843,7 +72949,7 @@ var require_websocket_server = __commonJS((exports, module) => {
72843
72949
  }
72844
72950
  if (this._state > RUNNING)
72845
72951
  return abortHandshake(socket, 503);
72846
- const digest = createHash6("sha1").update(key + GUID).digest("base64");
72952
+ const digest = createHash7("sha1").update(key + GUID).digest("base64");
72847
72953
  const headers = [
72848
72954
  "HTTP/1.1 101 Switching Protocols",
72849
72955
  "Upgrade: websocket",
@@ -73055,10 +73161,10 @@ async function createAppServer(options2 = {}) {
73055
73161
  wsManager = new WebSocketManager(server);
73056
73162
  fileWatcher = new FileWatcher({ wsManager });
73057
73163
  fileWatcher.start();
73058
- await new Promise((resolve36, reject) => {
73164
+ await new Promise((resolve37, reject) => {
73059
73165
  const onListening = () => {
73060
73166
  server.off("error", onError);
73061
- resolve36();
73167
+ resolve37();
73062
73168
  };
73063
73169
  const onError = (error) => {
73064
73170
  server.off("listening", onListening);
@@ -73095,16 +73201,16 @@ async function createAppServer(options2 = {}) {
73095
73201
  };
73096
73202
  }
73097
73203
  async function closeHttpServer(server) {
73098
- await new Promise((resolve36) => {
73204
+ await new Promise((resolve37) => {
73099
73205
  if (!server.listening) {
73100
- resolve36();
73206
+ resolve37();
73101
73207
  return;
73102
73208
  }
73103
73209
  server.close((err) => {
73104
73210
  if (err) {
73105
73211
  logger.debug(`Server close error: ${err.message}`);
73106
73212
  }
73107
- resolve36();
73213
+ resolve37();
73108
73214
  });
73109
73215
  });
73110
73216
  }
@@ -74840,7 +74946,7 @@ var require_picomatch2 = __commonJS((exports, module) => {
74840
74946
  import { exec as exec7, execFile as execFile10, spawn as spawn4 } from "node:child_process";
74841
74947
  import { promisify as promisify15 } from "node:util";
74842
74948
  function executeInteractiveScript(command, args, options2) {
74843
- return new Promise((resolve38, reject) => {
74949
+ return new Promise((resolve39, reject) => {
74844
74950
  const child = spawn4(command, args, {
74845
74951
  stdio: ["ignore", "inherit", "inherit"],
74846
74952
  cwd: options2?.cwd,
@@ -74861,7 +74967,7 @@ function executeInteractiveScript(command, args, options2) {
74861
74967
  } else if (code !== 0) {
74862
74968
  reject(new Error(`Command exited with code ${code}`));
74863
74969
  } else {
74864
- resolve38();
74970
+ resolve39();
74865
74971
  }
74866
74972
  });
74867
74973
  child.on("error", (error) => {
@@ -75040,7 +75146,7 @@ var init_opencode_installer = __esm(() => {
75040
75146
  var PARTIAL_INSTALL_VERSION = "partial", EXIT_CODE_CRITICAL_FAILURE = 1, EXIT_CODE_PARTIAL_SUCCESS = 2;
75041
75147
 
75042
75148
  // src/services/package-installer/validators.ts
75043
- import { resolve as resolve38 } from "node:path";
75149
+ import { resolve as resolve39 } from "node:path";
75044
75150
  function validatePackageName(packageName) {
75045
75151
  if (!packageName || typeof packageName !== "string") {
75046
75152
  throw new Error("Package name must be a non-empty string");
@@ -75053,8 +75159,8 @@ function validatePackageName(packageName) {
75053
75159
  }
75054
75160
  }
75055
75161
  function validateScriptPath(skillsDir2, scriptPath) {
75056
- const skillsDirResolved = resolve38(skillsDir2);
75057
- const scriptPathResolved = resolve38(scriptPath);
75162
+ const skillsDirResolved = resolve39(skillsDir2);
75163
+ const scriptPathResolved = resolve39(scriptPath);
75058
75164
  const skillsDirNormalized = isWindows() ? skillsDirResolved.toLowerCase() : skillsDirResolved;
75059
75165
  const scriptPathNormalized = isWindows() ? scriptPathResolved.toLowerCase() : scriptPathResolved;
75060
75166
  if (!scriptPathNormalized.startsWith(skillsDirNormalized)) {
@@ -75872,10 +75978,10 @@ __export(exports_agy_mcp_linker, {
75872
75978
  checkExistingAgyConfig: () => checkExistingAgyConfig,
75873
75979
  addAgyToGitignore: () => addAgyToGitignore
75874
75980
  });
75875
- import { resolve as resolve39 } from "node:path";
75981
+ import { resolve as resolve40 } from "node:path";
75876
75982
  async function linkAgyMcpConfig(projectDir, options2 = {}) {
75877
75983
  const { skipGitignore = false, isGlobal = false } = options2;
75878
- const resolvedProjectDir = resolve39(projectDir);
75984
+ const resolvedProjectDir = resolve40(projectDir);
75879
75985
  const agyConfigPath = getAgyMcpConfigPath(resolvedProjectDir, isGlobal);
75880
75986
  const mcpConfigPath = findMcpConfigPath(resolvedProjectDir);
75881
75987
  if (!mcpConfigPath) {
@@ -76524,7 +76630,7 @@ var require_get_stream = __commonJS((exports, module) => {
76524
76630
  };
76525
76631
  const { maxBuffer } = options2;
76526
76632
  let stream;
76527
- await new Promise((resolve41, reject) => {
76633
+ await new Promise((resolve42, reject) => {
76528
76634
  const rejectPromise = (error) => {
76529
76635
  if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
76530
76636
  error.bufferedData = stream.getBufferedValue();
@@ -76536,7 +76642,7 @@ var require_get_stream = __commonJS((exports, module) => {
76536
76642
  rejectPromise(error);
76537
76643
  return;
76538
76644
  }
76539
- resolve41();
76645
+ resolve42();
76540
76646
  });
76541
76647
  stream.on("data", () => {
76542
76648
  if (stream.getBufferedLength() > maxBuffer) {
@@ -77897,7 +78003,7 @@ var require_extract_zip = __commonJS((exports, module) => {
77897
78003
  debug("opening", this.zipPath, "with opts", this.opts);
77898
78004
  this.zipfile = await openZip(this.zipPath, { lazyEntries: true });
77899
78005
  this.canceled = false;
77900
- return new Promise((resolve41, reject) => {
78006
+ return new Promise((resolve42, reject) => {
77901
78007
  this.zipfile.on("error", (err) => {
77902
78008
  this.canceled = true;
77903
78009
  reject(err);
@@ -77906,7 +78012,7 @@ var require_extract_zip = __commonJS((exports, module) => {
77906
78012
  this.zipfile.on("close", () => {
77907
78013
  if (!this.canceled) {
77908
78014
  debug("zip extraction complete");
77909
- resolve41();
78015
+ resolve42();
77910
78016
  }
77911
78017
  });
77912
78018
  this.zipfile.on("entry", async (entry) => {
@@ -78225,7 +78331,7 @@ async function restoreOriginalBranch(branchName, cwd2, issueNumber) {
78225
78331
  }
78226
78332
  }
78227
78333
  function spawnAndCollect(command, args, cwd2) {
78228
- return new Promise((resolve57, reject) => {
78334
+ return new Promise((resolve59, reject) => {
78229
78335
  const child = spawn5(command, args, { ...cwd2 && { cwd: cwd2 }, stdio: ["ignore", "pipe", "pipe"] });
78230
78336
  const chunks = [];
78231
78337
  const stderrChunks = [];
@@ -78238,7 +78344,7 @@ function spawnAndCollect(command, args, cwd2) {
78238
78344
  reject(new Error(`${command} ${args[0] ?? ""} exited with code ${code2}: ${stderr}`));
78239
78345
  return;
78240
78346
  }
78241
- resolve57(Buffer.concat(chunks).toString("utf-8"));
78347
+ resolve59(Buffer.concat(chunks).toString("utf-8"));
78242
78348
  });
78243
78349
  });
78244
78350
  }
@@ -78422,8 +78528,8 @@ var init_content_validator = __esm(() => {
78422
78528
  });
78423
78529
 
78424
78530
  // src/commands/content/phases/context-cache-manager.ts
78425
- import { createHash as createHash9 } from "node:crypto";
78426
- import { existsSync as existsSync83, mkdirSync as mkdirSync7, readFileSync as readFileSync23, readdirSync as readdirSync14, statSync as statSync15 } from "node:fs";
78531
+ import { createHash as createHash11 } from "node:crypto";
78532
+ import { existsSync as existsSync83, mkdirSync as mkdirSync7, readFileSync as readFileSync23, readdirSync as readdirSync15, statSync as statSync15 } from "node:fs";
78427
78533
  import { rename as rename16, writeFile as writeFile43 } from "node:fs/promises";
78428
78534
  import { homedir as homedir54 } from "node:os";
78429
78535
  import { basename as basename34, join as join167 } from "node:path";
@@ -78455,7 +78561,7 @@ async function saveCachedContext(repoPath, cache5) {
78455
78561
  await rename16(tmpPath, cachePath);
78456
78562
  }
78457
78563
  function computeSourceHash(repoPath) {
78458
- const hash = createHash9("sha256");
78564
+ const hash = createHash11("sha256");
78459
78565
  const paths = getDocSourcePaths(repoPath);
78460
78566
  for (const filePath of paths) {
78461
78567
  try {
@@ -78472,7 +78578,7 @@ function getDocSourcePaths(repoPath) {
78472
78578
  const docsDir = join167(repoPath, "docs");
78473
78579
  if (existsSync83(docsDir)) {
78474
78580
  try {
78475
- const files = readdirSync14(docsDir);
78581
+ const files = readdirSync15(docsDir);
78476
78582
  for (const f3 of files) {
78477
78583
  if (f3.endsWith(".md"))
78478
78584
  paths.push(join167(docsDir, f3));
@@ -78485,7 +78591,7 @@ function getDocSourcePaths(repoPath) {
78485
78591
  const stylesDir = join167(repoPath, "assets", "writing-styles");
78486
78592
  if (existsSync83(stylesDir)) {
78487
78593
  try {
78488
- const files = readdirSync14(stylesDir);
78594
+ const files = readdirSync15(stylesDir);
78489
78595
  for (const f3 of files) {
78490
78596
  paths.push(join167(stylesDir, f3));
78491
78597
  }
@@ -78495,7 +78601,7 @@ function getDocSourcePaths(repoPath) {
78495
78601
  }
78496
78602
  function getCacheFilePath(repoPath) {
78497
78603
  const repoName = basename34(repoPath).replace(/[^a-zA-Z0-9_-]/g, "_");
78498
- const pathHash = createHash9("sha256").update(repoPath).digest("hex").slice(0, 8);
78604
+ const pathHash = createHash11("sha256").update(repoPath).digest("hex").slice(0, 8);
78499
78605
  return join167(CACHE_DIR, `${repoName}-${pathHash}-context-cache.json`);
78500
78606
  }
78501
78607
  var CACHE_DIR, CACHE_TTL_MS5;
@@ -78680,7 +78786,7 @@ function extractContentFromResponse(response) {
78680
78786
 
78681
78787
  // src/commands/content/phases/docs-summarizer.ts
78682
78788
  import { execSync as execSync7 } from "node:child_process";
78683
- import { existsSync as existsSync84, readFileSync as readFileSync24, readdirSync as readdirSync15 } from "node:fs";
78789
+ import { existsSync as existsSync84, readFileSync as readFileSync24, readdirSync as readdirSync16 } from "node:fs";
78684
78790
  import { join as join168 } from "node:path";
78685
78791
  async function summarizeProjectDocs(repoPath, contentLogger) {
78686
78792
  const rawContent = collectRawDocs(repoPath);
@@ -78738,7 +78844,7 @@ function collectRawDocs(repoPath) {
78738
78844
  const docsDir = join168(repoPath, "docs");
78739
78845
  if (existsSync84(docsDir)) {
78740
78846
  try {
78741
- const files = readdirSync15(docsDir).filter((f3) => f3.endsWith(".md")).sort();
78847
+ const files = readdirSync16(docsDir).filter((f3) => f3.endsWith(".md")).sort();
78742
78848
  for (const f3 of files) {
78743
78849
  const content = readCapped(join168(docsDir, f3), 5000);
78744
78850
  if (content) {
@@ -78762,7 +78868,7 @@ ${content}`);
78762
78868
  const stylesDir = join168(repoPath, "assets", "writing-styles");
78763
78869
  if (existsSync84(stylesDir)) {
78764
78870
  try {
78765
- const files = readdirSync15(stylesDir).slice(0, 3);
78871
+ const files = readdirSync16(stylesDir).slice(0, 3);
78766
78872
  styles3 = files.map((f3) => readCapped(join168(stylesDir, f3), 1000)).filter(Boolean).join(`
78767
78873
 
78768
78874
  `);
@@ -78953,7 +79059,7 @@ IMPORTANT: Generate the image and output the path as JSON: {"imagePath": "/path/
78953
79059
 
78954
79060
  // src/commands/content/phases/photo-generator.ts
78955
79061
  import { execSync as execSync8 } from "node:child_process";
78956
- import { existsSync as existsSync85, mkdirSync as mkdirSync8, readdirSync as readdirSync16 } from "node:fs";
79062
+ import { existsSync as existsSync85, mkdirSync as mkdirSync8, readdirSync as readdirSync17 } from "node:fs";
78957
79063
  import { homedir as homedir55 } from "node:os";
78958
79064
  import { join as join169 } from "node:path";
78959
79065
  async function generatePhoto(_content, context, config, platform18, contentId, contentLogger) {
@@ -78978,7 +79084,7 @@ async function generatePhoto(_content, context, config, platform18, contentId, c
78978
79084
  return { path: imagePath, ...dimensions, format: "png" };
78979
79085
  }
78980
79086
  }
78981
- const files = readdirSync16(mediaDir);
79087
+ const files = readdirSync17(mediaDir);
78982
79088
  const imageFile = files.find((f3) => /\.(png|jpg|jpeg|webp)$/i.test(f3));
78983
79089
  if (imageFile) {
78984
79090
  const ext2 = imageFile.split(".").pop() ?? "png";
@@ -79410,7 +79516,7 @@ function isNoiseCommit(title, author) {
79410
79516
 
79411
79517
  // src/commands/content/phases/change-detector.ts
79412
79518
  import { execSync as execSync10, spawnSync as spawnSync9 } from "node:child_process";
79413
- import { existsSync as existsSync88, readFileSync as readFileSync25, readdirSync as readdirSync17, statSync as statSync17 } from "node:fs";
79519
+ import { existsSync as existsSync88, readFileSync as readFileSync25, readdirSync as readdirSync18, statSync as statSync17 } from "node:fs";
79414
79520
  import { join as join171 } from "node:path";
79415
79521
  function detectCommits(repo, since) {
79416
79522
  try {
@@ -79526,7 +79632,7 @@ function detectCompletedPlans(repo, since) {
79526
79632
  const sinceMs = new Date(since).getTime();
79527
79633
  const events = [];
79528
79634
  try {
79529
- const entries = readdirSync17(plansDir, { withFileTypes: true });
79635
+ const entries = readdirSync18(plansDir, { withFileTypes: true });
79530
79636
  for (const entry of entries) {
79531
79637
  if (!entry.isDirectory())
79532
79638
  continue;
@@ -79607,7 +79713,7 @@ function classifyCommit(event) {
79607
79713
 
79608
79714
  // src/commands/content/phases/repo-discoverer.ts
79609
79715
  import { execSync as execSync11 } from "node:child_process";
79610
- import { readdirSync as readdirSync18 } from "node:fs";
79716
+ import { readdirSync as readdirSync19 } from "node:fs";
79611
79717
  import { join as join172 } from "node:path";
79612
79718
  function discoverRepos2(cwd2) {
79613
79719
  const repos = [];
@@ -79617,7 +79723,7 @@ function discoverRepos2(cwd2) {
79617
79723
  repos.push(info);
79618
79724
  }
79619
79725
  try {
79620
- const entries = readdirSync18(cwd2, { withFileTypes: true });
79726
+ const entries = readdirSync19(cwd2, { withFileTypes: true });
79621
79727
  for (const entry of entries) {
79622
79728
  if (!entry.isDirectory() || entry.name.startsWith("."))
79623
79729
  continue;
@@ -81085,8 +81191,8 @@ function shouldRunCleanup(lastAt) {
81085
81191
  return Date.now() - new Date(lastAt).getTime() >= 86400000;
81086
81192
  }
81087
81193
  function sleep2(ms) {
81088
- return new Promise((resolve57) => {
81089
- setTimeout(resolve57, ms);
81194
+ return new Promise((resolve59) => {
81195
+ setTimeout(resolve59, ms);
81090
81196
  });
81091
81197
  }
81092
81198
  var LOCK_DIR2, LOCK_FILE, MAX_CREATION_RETRIES = 3, MAX_PUBLISH_RETRIES_PER_CYCLE = 3, PUBLISH_RETRY_WINDOW_HOURS = 24;
@@ -82174,6 +82280,10 @@ var init_init_command_help = __esm(() => {
82174
82280
  flags: "--sync",
82175
82281
  description: "Sync config files from upstream with interactive hunk-by-hunk merge"
82176
82282
  },
82283
+ {
82284
+ flags: "--install-mode <mode>",
82285
+ description: "Engineer global install mode: auto, plugin, or legacy (default: auto)"
82286
+ },
82177
82287
  {
82178
82288
  flags: "--archive <path>",
82179
82289
  description: "Use local archive file instead of downloading (zip/tar.gz)"
@@ -83340,7 +83450,7 @@ function getPagerArgs(pagerCmd) {
83340
83450
  return [];
83341
83451
  }
83342
83452
  async function trySystemPager(content) {
83343
- return new Promise((resolve57) => {
83453
+ return new Promise((resolve59) => {
83344
83454
  const pagerCmd = process.env.PAGER || "less";
83345
83455
  const pagerArgs = getPagerArgs(pagerCmd);
83346
83456
  try {
@@ -83350,20 +83460,20 @@ async function trySystemPager(content) {
83350
83460
  });
83351
83461
  const timeout2 = setTimeout(() => {
83352
83462
  pager.kill();
83353
- resolve57(false);
83463
+ resolve59(false);
83354
83464
  }, 30000);
83355
83465
  pager.stdin.write(content);
83356
83466
  pager.stdin.end();
83357
83467
  pager.on("close", (code2) => {
83358
83468
  clearTimeout(timeout2);
83359
- resolve57(code2 === 0);
83469
+ resolve59(code2 === 0);
83360
83470
  });
83361
83471
  pager.on("error", () => {
83362
83472
  clearTimeout(timeout2);
83363
- resolve57(false);
83473
+ resolve59(false);
83364
83474
  });
83365
83475
  } catch {
83366
- resolve57(false);
83476
+ resolve59(false);
83367
83477
  }
83368
83478
  });
83369
83479
  }
@@ -83390,16 +83500,16 @@ async function basicPager(content) {
83390
83500
  break;
83391
83501
  }
83392
83502
  const remaining = lines.length - currentLine;
83393
- await new Promise((resolve57) => {
83503
+ await new Promise((resolve59) => {
83394
83504
  rl.question(`-- More (${remaining} lines) [Enter/q] --`, (answer) => {
83395
83505
  if (answer.toLowerCase() === "q") {
83396
83506
  rl.close();
83397
83507
  process.exitCode = 0;
83398
- resolve57();
83508
+ resolve59();
83399
83509
  return;
83400
83510
  }
83401
83511
  process.stdout.write("\x1B[1A\x1B[2K");
83402
- resolve57();
83512
+ resolve59();
83403
83513
  });
83404
83514
  });
83405
83515
  }
@@ -85314,7 +85424,7 @@ class ClaudekitHttpClient {
85314
85424
  } catch (error) {
85315
85425
  if (error instanceof CkApiError && error.code === "RATE_LIMIT_EXCEEDED" && error.retryAfter) {
85316
85426
  const delayMs = error.retryAfter * 1000;
85317
- await new Promise((resolve5) => setTimeout(resolve5, delayMs));
85427
+ await new Promise((resolve6) => setTimeout(resolve6, delayMs));
85318
85428
  return fn();
85319
85429
  }
85320
85430
  throw error;
@@ -86228,7 +86338,7 @@ function showApiHelp() {
86228
86338
  }
86229
86339
  // src/services/file-operations/destructive-operation-backup-manager.ts
86230
86340
  import { readdir as readdir3, stat } from "node:fs/promises";
86231
- import { basename as basename4, join as join14, resolve as resolve6, sep as sep3 } from "node:path";
86341
+ import { basename as basename4, join as join14, resolve as resolve7, sep as sep3 } from "node:path";
86232
86342
 
86233
86343
  // src/services/file-operations/destructive-operation-backup.ts
86234
86344
  init_logger();
@@ -86236,7 +86346,7 @@ init_path_resolver();
86236
86346
  init_zod();
86237
86347
  var import_fs_extra = __toESM(require_lib(), 1);
86238
86348
  import { mkdir as mkdir4, readdir as readdir2, readlink, rename as rename2, symlink } from "node:fs/promises";
86239
- import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute2, join as join13, normalize as normalize2, resolve as resolve5, sep as sep2 } from "node:path";
86349
+ import { basename as basename3, dirname as dirname5, isAbsolute as isAbsolute2, join as join13, normalize as normalize2, resolve as resolve6, sep as sep2 } from "node:path";
86240
86350
  var SNAPSHOT_DIR = "snapshot";
86241
86351
  var MANIFEST_FILE = "manifest.json";
86242
86352
  function normalizeRelativePath(rootDir, inputPath) {
@@ -86244,21 +86354,21 @@ function normalizeRelativePath(rootDir, inputPath) {
86244
86354
  throw new Error(`Unsafe backup path: ${inputPath}`);
86245
86355
  }
86246
86356
  const normalized = normalize2(inputPath).replaceAll("\\", "/");
86247
- const resolvedRoot = resolve5(rootDir);
86248
- const resolvedPath = resolve5(rootDir, normalized);
86357
+ const resolvedRoot = resolve6(rootDir);
86358
+ const resolvedPath = resolve6(rootDir, normalized);
86249
86359
  if (normalized === ".." || normalized.startsWith("../") || !resolvedPath.startsWith(`${resolvedRoot}${sep2}`) && resolvedPath !== resolvedRoot) {
86250
86360
  throw new Error(`Path escapes installation root: ${inputPath}`);
86251
86361
  }
86252
86362
  return normalized;
86253
86363
  }
86254
86364
  function getManagedBackupRoot() {
86255
- return resolve5(PathResolver.getConfigDir(false), "backups");
86365
+ return resolve6(PathResolver.getConfigDir(false), "backups");
86256
86366
  }
86257
86367
  async function getExistingRealpath(pathToResolve) {
86258
86368
  if (await import_fs_extra.pathExists(pathToResolve)) {
86259
- return resolve5(await import_fs_extra.realpath(pathToResolve));
86369
+ return resolve6(await import_fs_extra.realpath(pathToResolve));
86260
86370
  }
86261
- return resolve5(pathToResolve);
86371
+ return resolve6(pathToResolve);
86262
86372
  }
86263
86373
  async function assertManagedBackupDir(backupDir) {
86264
86374
  const resolvedBackupDir = await getExistingRealpath(backupDir);
@@ -86303,13 +86413,13 @@ function buildTargets(sourceRoot, deletePaths, mutatePaths) {
86303
86413
  });
86304
86414
  }
86305
86415
  async function snapshotItem(sourceRoot, backupDir, target) {
86306
- const sourcePath = resolve5(sourceRoot, target.path);
86416
+ const sourcePath = resolve6(sourceRoot, target.path);
86307
86417
  if (!await import_fs_extra.pathExists(sourcePath)) {
86308
86418
  return null;
86309
86419
  }
86310
86420
  const stats = await import_fs_extra.lstat(sourcePath);
86311
86421
  if (stats.isSymbolicLink()) {
86312
- const realTargetPath = resolve5(await import_fs_extra.realpath(sourcePath));
86422
+ const realTargetPath = resolve6(await import_fs_extra.realpath(sourcePath));
86313
86423
  const resolvedSourceRoot = await getExistingRealpath(sourceRoot);
86314
86424
  if (!realTargetPath.startsWith(`${resolvedSourceRoot}${sep2}`) && realTargetPath !== resolvedSourceRoot) {
86315
86425
  throw new Error(`Symlink target escapes installation root: ${target.path}`);
@@ -86349,7 +86459,7 @@ async function copyDirectorySnapshot(sourceDir, destDir, rootDir) {
86349
86459
  const sourceEntry = join13(sourceDir, entry.name);
86350
86460
  const destEntry = join13(destDir, entry.name);
86351
86461
  if (entry.isSymbolicLink()) {
86352
- const realTargetPath = resolve5(await import_fs_extra.realpath(sourceEntry));
86462
+ const realTargetPath = resolve6(await import_fs_extra.realpath(sourceEntry));
86353
86463
  const resolvedRoot = await getExistingRealpath(rootDir);
86354
86464
  if (!realTargetPath.startsWith(`${resolvedRoot}${sep2}`) && realTargetPath !== resolvedRoot) {
86355
86465
  throw new Error(`Nested symlink target escapes installation root: ${sourceEntry}`);
@@ -86372,10 +86482,10 @@ function buildRestoreTempPath(sourcePath, suffix) {
86372
86482
  }
86373
86483
  async function assertSafeRestoreDestination(targetPath, rootDir) {
86374
86484
  const resolvedRoot = await getExistingRealpath(rootDir);
86375
- const lexicalRoot = resolve5(rootDir);
86485
+ const lexicalRoot = resolve6(rootDir);
86376
86486
  let currentPath = dirname5(targetPath);
86377
86487
  while (true) {
86378
- const resolvedCurrent = resolve5(currentPath);
86488
+ const resolvedCurrent = resolve6(currentPath);
86379
86489
  if (!resolvedCurrent.startsWith(`${lexicalRoot}${sep2}`) && resolvedCurrent !== lexicalRoot) {
86380
86490
  throw new Error(`Restore target escapes installation root: ${targetPath}`);
86381
86491
  }
@@ -86403,8 +86513,8 @@ async function copySnapshotDirectoryForRestore(snapshotDir, destDir, rootDir) {
86403
86513
  const destEntry = join13(destDir, entry.name);
86404
86514
  if (entry.isSymbolicLink()) {
86405
86515
  const linkTarget = await readlink(sourceEntry);
86406
- const resolvedTarget = resolve5(dirname5(destEntry), linkTarget);
86407
- const lexicalRoot = resolve5(rootDir);
86516
+ const resolvedTarget = resolve6(dirname5(destEntry), linkTarget);
86517
+ const lexicalRoot = resolve6(rootDir);
86408
86518
  if (!resolvedTarget.startsWith(`${lexicalRoot}${sep2}`) && resolvedTarget !== lexicalRoot) {
86409
86519
  throw new Error(`Nested restore symlink escapes installation root: ${destEntry}`);
86410
86520
  }
@@ -86479,7 +86589,7 @@ async function createDestructiveOperationBackup(request) {
86479
86589
  version: 1,
86480
86590
  operation: request.operation,
86481
86591
  createdAt: new Date().toISOString(),
86482
- sourceRoot: resolve5(request.sourceRoot),
86592
+ sourceRoot: resolve6(request.sourceRoot),
86483
86593
  scope: request.scope,
86484
86594
  kit: request.kit,
86485
86595
  items,
@@ -86503,7 +86613,7 @@ async function loadDestructiveOperationBackup(backupDir) {
86503
86613
  if (!isAbsolute2(manifest.sourceRoot)) {
86504
86614
  throw new Error(`Backup manifest source root must be absolute: ${manifest.sourceRoot}`);
86505
86615
  }
86506
- const resolvedSourceRoot = resolve5(manifest.sourceRoot);
86616
+ const resolvedSourceRoot = resolve6(manifest.sourceRoot);
86507
86617
  for (const item of manifest.items) {
86508
86618
  normalizeRelativePath(resolvedSourceRoot, item.path);
86509
86619
  const normalizedSnapshotPath = normalizeRelativePath(resolvedBackupDir, item.snapshotPath);
@@ -86523,8 +86633,8 @@ async function loadDestructiveOperationBackup(backupDir) {
86523
86633
  async function restoreDestructiveOperationBackup(backup) {
86524
86634
  const restorePlans = [];
86525
86635
  for (const item of backup.manifest.items) {
86526
- const sourcePath = resolve5(backup.manifest.sourceRoot, normalizeRelativePath(backup.manifest.sourceRoot, item.path));
86527
- const snapshotPath = resolve5(backup.backupDir, normalizeRelativePath(backup.backupDir, item.snapshotPath));
86636
+ const sourcePath = resolve6(backup.manifest.sourceRoot, normalizeRelativePath(backup.manifest.sourceRoot, item.path));
86637
+ const snapshotPath = resolve6(backup.backupDir, normalizeRelativePath(backup.backupDir, item.snapshotPath));
86528
86638
  try {
86529
86639
  await import_fs_extra.lstat(snapshotPath);
86530
86640
  } catch {
@@ -86566,7 +86676,7 @@ init_path_resolver();
86566
86676
  var import_fs_extra2 = __toESM(require_lib(), 1);
86567
86677
  var DEFAULT_DESTRUCTIVE_BACKUP_KEEP_COUNT = 10;
86568
86678
  function getBackupsRoot() {
86569
- return resolve6(PathResolver.getConfigDir(false), "backups");
86679
+ return resolve7(PathResolver.getConfigDir(false), "backups");
86570
86680
  }
86571
86681
  function validateBackupId(backupId) {
86572
86682
  if (!backupId || !/^[A-Za-z0-9._:-]+$/.test(backupId) || backupId.includes("..")) {
@@ -86576,7 +86686,7 @@ function validateBackupId(backupId) {
86576
86686
  function resolveBackupDir(backupId) {
86577
86687
  validateBackupId(backupId);
86578
86688
  const backupsRoot = getBackupsRoot();
86579
- const backupDir = resolve6(backupsRoot, backupId);
86689
+ const backupDir = resolve7(backupsRoot, backupId);
86580
86690
  if (!backupDir.startsWith(`${backupsRoot}${sep3}`) && backupDir !== backupsRoot) {
86581
86691
  throw new Error(`Backup id escapes backup root: ${backupId}`);
86582
86692
  }
@@ -86949,8 +87059,8 @@ init_logger();
86949
87059
  init_path_resolver();
86950
87060
  var import_fs_extra3 = __toESM(require_lib(), 1);
86951
87061
  var import_proper_lockfile5 = __toESM(require_proper_lockfile(), 1);
86952
- import { createHash as createHash4 } from "node:crypto";
86953
- import { join as join16, resolve as resolve7 } from "node:path";
87062
+ import { createHash as createHash5 } from "node:crypto";
87063
+ import { join as join16, resolve as resolve8 } from "node:path";
86954
87064
  var LOCK_OPTIONS = {
86955
87065
  realpath: false,
86956
87066
  retries: { retries: 5, minTimeout: 100, maxTimeout: 1000 },
@@ -86958,13 +87068,13 @@ var LOCK_OPTIONS = {
86958
87068
  };
86959
87069
  async function getCanonicalInstallationRoot(installationRoot) {
86960
87070
  if (await import_fs_extra3.pathExists(installationRoot)) {
86961
- return resolve7(await import_fs_extra3.realpath(installationRoot));
87071
+ return resolve8(await import_fs_extra3.realpath(installationRoot));
86962
87072
  }
86963
- return resolve7(installationRoot);
87073
+ return resolve8(installationRoot);
86964
87074
  }
86965
87075
  async function getInstallationStateLockPath(installationRoot) {
86966
87076
  const normalizedRoot = await getCanonicalInstallationRoot(installationRoot);
86967
- const hash = createHash4("sha256").update(normalizedRoot).digest("hex").slice(0, 16);
87077
+ const hash = createHash5("sha256").update(normalizedRoot).digest("hex").slice(0, 16);
86968
87078
  return join16(PathResolver.getConfigDir(false), "locks", `installation-${hash}.lock`);
86969
87079
  }
86970
87080
  async function acquireInstallationStateLock(installationRoot) {
@@ -87082,7 +87192,7 @@ init_portable_registry();
87082
87192
  init_provider_registry();
87083
87193
  import { existsSync as existsSync10 } from "node:fs";
87084
87194
  import { lstat as lstat3, rm as rm2 } from "node:fs/promises";
87085
- import { basename as basename5, dirname as dirname6, join as join18, relative as relative4, resolve as resolve8, sep as sep4 } from "node:path";
87195
+ import { basename as basename5, dirname as dirname6, join as join18, relative as relative5, resolve as resolve9, sep as sep4 } from "node:path";
87086
87196
  var defaultCommandRegistryDeps = {
87087
87197
  readPortableRegistry,
87088
87198
  removePortableInstallation
@@ -87094,8 +87204,8 @@ function resolveCommandRegistryDeps(deps) {
87094
87204
  };
87095
87205
  }
87096
87206
  function isPathWithinBase(targetPath, basePath) {
87097
- const resolvedTarget = resolve8(targetPath);
87098
- const resolvedBase = resolve8(basePath);
87207
+ const resolvedTarget = resolve9(targetPath);
87208
+ const resolvedBase = resolve9(basePath);
87099
87209
  return resolvedTarget === resolvedBase || resolvedTarget.startsWith(`${resolvedBase}${sep4}`);
87100
87210
  }
87101
87211
  function isWindowsAbsolutePath2(path3) {
@@ -87131,8 +87241,8 @@ function getSafeCommandNameSegments(commandName) {
87131
87241
  }
87132
87242
  function isCodexCommandSkillPath(targetPath, basePath) {
87133
87243
  const targetDir = dirname6(targetPath);
87134
- const resolvedTargetDir = resolve8(targetDir);
87135
- const resolvedBase = resolve8(basePath);
87244
+ const resolvedTargetDir = resolve9(targetDir);
87245
+ const resolvedBase = resolve9(basePath);
87136
87246
  return basename5(targetPath) === CODEX_COMMAND_SKILL_FILENAME && basename5(targetDir).startsWith("source-command-") && resolvedTargetDir !== resolvedBase && isPathWithinBase(targetDir, basePath);
87137
87247
  }
87138
87248
  function getCodexLegacyPromptBasePath(basePath) {
@@ -87171,8 +87281,8 @@ function validateCommandTargetPath(targetPath, basePath) {
87171
87281
  if (!basePath) {
87172
87282
  return "Provider command base path is unavailable";
87173
87283
  }
87174
- const resolvedTarget = resolve8(targetPath);
87175
- const resolvedBase = resolve8(basePath);
87284
+ const resolvedTarget = resolve9(targetPath);
87285
+ const resolvedBase = resolve9(basePath);
87176
87286
  if (resolvedTarget === resolvedBase) {
87177
87287
  return "Unsafe path: refusing to remove provider command base directory";
87178
87288
  }
@@ -87182,12 +87292,12 @@ function validateCommandTargetPath(targetPath, basePath) {
87182
87292
  return null;
87183
87293
  }
87184
87294
  async function validateNoSymlinkComponents2(targetPath, boundaryPath) {
87185
- const resolvedTarget = resolve8(targetPath);
87186
- const resolvedBoundary = resolve8(boundaryPath);
87295
+ const resolvedTarget = resolve9(targetPath);
87296
+ const resolvedBoundary = resolve9(boundaryPath);
87187
87297
  if (!isPathWithinBase(resolvedTarget, resolvedBoundary)) {
87188
87298
  return `Unsafe path: target escapes ${resolvedBoundary}`;
87189
87299
  }
87190
- const segments = relative4(resolvedBoundary, resolvedTarget).split(/[\\/]+/).filter(Boolean);
87300
+ const segments = relative5(resolvedBoundary, resolvedTarget).split(/[\\/]+/).filter(Boolean);
87191
87301
  let cursor = resolvedBoundary;
87192
87302
  for (const segment of segments) {
87193
87303
  cursor = join18(cursor, segment);
@@ -87852,12 +87962,12 @@ async function configUICommand(options2 = {}) {
87852
87962
  console.log();
87853
87963
  console.log(import_picocolors15.default.dim(" Press Ctrl+C to stop"));
87854
87964
  console.log();
87855
- await new Promise((resolve36) => {
87965
+ await new Promise((resolve37) => {
87856
87966
  const shutdown = async () => {
87857
87967
  console.log();
87858
87968
  logger.info("Shutting down...");
87859
87969
  await server.close();
87860
- resolve36();
87970
+ resolve37();
87861
87971
  };
87862
87972
  process.on("SIGINT", shutdown);
87863
87973
  process.on("SIGTERM", shutdown);
@@ -87878,12 +87988,12 @@ async function configUICommand(options2 = {}) {
87878
87988
  }
87879
87989
  async function checkPort(port, host) {
87880
87990
  const { createServer: createServer2 } = await import("node:net");
87881
- return new Promise((resolve36) => {
87991
+ return new Promise((resolve37) => {
87882
87992
  const server = createServer2();
87883
- server.once("error", () => resolve36(false));
87993
+ server.once("error", () => resolve37(false));
87884
87994
  server.once("listening", () => {
87885
87995
  server.close();
87886
- resolve36(true);
87996
+ resolve37(true);
87887
87997
  });
87888
87998
  server.listen(port, host);
87889
87999
  });
@@ -89237,13 +89347,13 @@ function checkComponentCounts(setup) {
89237
89347
  }
89238
89348
  // src/domains/health-checks/checkers/skill-budget-checker.ts
89239
89349
  init_path_resolver();
89240
- import { join as join77, resolve as resolve36 } from "node:path";
89350
+ import { join as join77, resolve as resolve37 } from "node:path";
89241
89351
 
89242
89352
  // src/domains/health-checks/checkers/skill-budget-scanner.ts
89243
89353
  var import_gray_matter11 = __toESM(require_gray_matter(), 1);
89244
89354
  import { existsSync as existsSync55 } from "node:fs";
89245
89355
  import { readFile as readFile41, readdir as readdir20 } from "node:fs/promises";
89246
- import { basename as basename25, join as join76, relative as relative16 } from "node:path";
89356
+ import { basename as basename25, join as join76, relative as relative17 } from "node:path";
89247
89357
  var SKIP_DIRS5 = new Set([".git", ".venv", "__pycache__", "node_modules", "scripts", "common"]);
89248
89358
  async function scanSkills2(skillsDir2) {
89249
89359
  if (!existsSync55(skillsDir2))
@@ -89256,7 +89366,7 @@ async function scanSkills2(skillsDir2) {
89256
89366
  const content = await readFile41(file, "utf8");
89257
89367
  const { data } = import_gray_matter11.default(content, { engines: { javascript: { parse: () => ({}) } } });
89258
89368
  const rawName = typeof data.name === "string" ? data.name : "";
89259
- const fallbackId = relative16(skillsDir2, dir).replace(/\\/g, "/") || basename25(dir);
89369
+ const fallbackId = relative17(skillsDir2, dir).replace(/\\/g, "/") || basename25(dir);
89260
89370
  skills.push({
89261
89371
  id: normalizeSkillId(rawName, fallbackId),
89262
89372
  description: typeof data.description === "string" ? data.description : "",
@@ -89356,8 +89466,8 @@ async function applyBudgetDefaults(settingsPath, projectClaudeDir, requiredFract
89356
89466
  // src/domains/health-checks/checkers/skill-budget-checker.ts
89357
89467
  var ENGINEER_SKILL_COUNT_THRESHOLD = 20;
89358
89468
  async function checkSkillBudget(setup, projectDir) {
89359
- const projectClaudeDir = resolve36(projectDir, ".claude");
89360
- const globalClaudeDir = resolve36(PathResolver.getGlobalKitDir());
89469
+ const projectClaudeDir = resolve37(projectDir, ".claude");
89470
+ const globalClaudeDir = resolve37(PathResolver.getGlobalKitDir());
89361
89471
  const projectScopeAliasesGlobal = projectClaudeDir === globalClaudeDir;
89362
89472
  const [projectSkills, globalSkills] = await Promise.all([
89363
89473
  projectScopeAliasesGlobal ? Promise.resolve([]) : scanSkills2(join77(projectClaudeDir, "skills")),
@@ -89757,7 +89867,7 @@ init_path_resolver();
89757
89867
  import { existsSync as existsSync59 } from "node:fs";
89758
89868
  import { readFile as readFile44 } from "node:fs/promises";
89759
89869
  import { homedir as homedir43 } from "node:os";
89760
- import { dirname as dirname32, join as join81, normalize as normalize6, resolve as resolve37 } from "node:path";
89870
+ import { dirname as dirname32, join as join81, normalize as normalize6, resolve as resolve38 } from "node:path";
89761
89871
  async function checkPathRefsValid(projectDir) {
89762
89872
  const globalClaudeMd = join81(PathResolver.getGlobalKitDir(), "CLAUDE.md");
89763
89873
  const projectClaudeMd = join81(projectDir, ".claude", "CLAUDE.md");
@@ -89804,7 +89914,7 @@ async function checkPathRefsValid(projectDir) {
89804
89914
  } else if (/^[A-Za-z]:/.test(ref)) {
89805
89915
  refPath = normalize6(ref);
89806
89916
  } else {
89807
- refPath = resolve37(baseDir, ref);
89917
+ refPath = resolve38(baseDir, ref);
89808
89918
  }
89809
89919
  const normalizedPath = normalize6(refPath);
89810
89920
  const isWithinHome = normalizedPath.startsWith(home5);
@@ -90094,7 +90204,8 @@ async function parseEnvFile(path7) {
90094
90204
  if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
90095
90205
  value = value.slice(1, -1);
90096
90206
  }
90097
- env2[key.trim()] = value.trim();
90207
+ const normalizedKey = key.trim();
90208
+ env2[normalizedKey] = normalizeParsedEnvValue(normalizedKey, value);
90098
90209
  }
90099
90210
  }
90100
90211
  return env2;
@@ -90103,6 +90214,13 @@ async function parseEnvFile(path7) {
90103
90214
  return {};
90104
90215
  }
90105
90216
  }
90217
+ function normalizeParsedEnvValue(key, value) {
90218
+ const trimmed = value.trim();
90219
+ if (key === "GEMINI_API_KEY" || key.startsWith("GEMINI_API_KEY_") || key === "OPENROUTER_API_KEY" || key === "MINIMAX_API_KEY") {
90220
+ return normalizeApiKeyInput(trimmed);
90221
+ }
90222
+ return trimmed;
90223
+ }
90106
90224
  async function checkGlobalConfig() {
90107
90225
  const globalEnvPath = join83(PathResolver.getGlobalKitDir(), ".env");
90108
90226
  if (!await import_fs_extra9.pathExists(globalEnvPath))
@@ -90166,8 +90284,10 @@ async function runSetupWizard(options2) {
90166
90284
  f2.warning("Setup cancelled");
90167
90285
  return false;
90168
90286
  }
90169
- if (typeof result === "string" && result) {
90170
- values[config.key] = result;
90287
+ if (typeof result === "string") {
90288
+ const normalized = normalizeApiKeyInput(result);
90289
+ if (normalized)
90290
+ values[config.key] = normalized;
90171
90291
  }
90172
90292
  }
90173
90293
  const configuredProviders = getConfiguredImageProviders(values);
@@ -90240,7 +90360,7 @@ async function promptForAdditionalGeminiKeys(primaryKey) {
90240
90360
  validate: (value) => {
90241
90361
  if (!value)
90242
90362
  return;
90243
- const trimmed = value.trim();
90363
+ const trimmed = normalizeApiKeyInput(value);
90244
90364
  if (!trimmed)
90245
90365
  return;
90246
90366
  if (!validateApiKey2(trimmed, VALIDATION_PATTERNS.GEMINI_API_KEY)) {
@@ -90255,12 +90375,12 @@ async function promptForAdditionalGeminiKeys(primaryKey) {
90255
90375
  if (lD(result)) {
90256
90376
  break;
90257
90377
  }
90258
- if (!result || result.trim() === "") {
90378
+ const normalized = typeof result === "string" ? normalizeApiKeyInput(result) : "";
90379
+ if (!normalized) {
90259
90380
  break;
90260
90381
  }
90261
- const trimmedKey = result.trim();
90262
- additionalKeys.push(trimmedKey);
90263
- allKeys.add(trimmedKey);
90382
+ additionalKeys.push(normalized);
90383
+ allKeys.add(normalized);
90264
90384
  keyNumber++;
90265
90385
  }
90266
90386
  return additionalKeys;
@@ -91314,17 +91434,17 @@ function createDefaultDns() {
91314
91434
  }
91315
91435
  function createDefaultTcp() {
91316
91436
  return {
91317
- connect: ({ host, port, timeoutMs }) => new Promise((resolve38) => {
91437
+ connect: ({ host, port, timeoutMs }) => new Promise((resolve39) => {
91318
91438
  const start = Date.now();
91319
91439
  const socket = net2.createConnection({ host, port });
91320
91440
  const timer = setTimeout(() => {
91321
91441
  socket.destroy();
91322
- resolve38({ ok: false, layer: "tcp", detail: "timeout", latencyMs: Date.now() - start });
91442
+ resolve39({ ok: false, layer: "tcp", detail: "timeout", latencyMs: Date.now() - start });
91323
91443
  }, timeoutMs);
91324
91444
  socket.on("connect", () => {
91325
91445
  clearTimeout(timer);
91326
91446
  socket.destroy();
91327
- resolve38({
91447
+ resolve39({
91328
91448
  ok: true,
91329
91449
  layer: "tcp",
91330
91450
  detail: "connected",
@@ -91333,7 +91453,7 @@ function createDefaultTcp() {
91333
91453
  });
91334
91454
  socket.on("error", (err) => {
91335
91455
  clearTimeout(timer);
91336
- resolve38({
91456
+ resolve39({
91337
91457
  ok: false,
91338
91458
  layer: "tcp",
91339
91459
  detail: err.message,
@@ -91345,11 +91465,11 @@ function createDefaultTcp() {
91345
91465
  }
91346
91466
  function createDefaultTls() {
91347
91467
  return {
91348
- get: (url, timeoutMs) => new Promise((resolve38) => {
91468
+ get: (url, timeoutMs) => new Promise((resolve39) => {
91349
91469
  const start = Date.now();
91350
91470
  const timer = setTimeout(() => {
91351
91471
  req.destroy();
91352
- resolve38({ ok: false, layer: "tls", detail: "timeout", latencyMs: Date.now() - start });
91472
+ resolve39({ ok: false, layer: "tls", detail: "timeout", latencyMs: Date.now() - start });
91353
91473
  }, timeoutMs);
91354
91474
  const req = https.get(url, {
91355
91475
  headers: {
@@ -91361,14 +91481,14 @@ function createDefaultTls() {
91361
91481
  const status = res.statusCode ?? 0;
91362
91482
  const latencyMs = Date.now() - start;
91363
91483
  if (status === 200) {
91364
- resolve38({ ok: true, layer: "tls", detail: `HTTP ${status}`, latencyMs });
91484
+ resolve39({ ok: true, layer: "tls", detail: `HTTP ${status}`, latencyMs });
91365
91485
  } else {
91366
- resolve38({ ok: false, layer: "tls", detail: `HTTP ${status}`, latencyMs });
91486
+ resolve39({ ok: false, layer: "tls", detail: `HTTP ${status}`, latencyMs });
91367
91487
  }
91368
91488
  });
91369
91489
  req.on("error", (err) => {
91370
91490
  clearTimeout(timer);
91371
- resolve38({
91491
+ resolve39({
91372
91492
  ok: false,
91373
91493
  layer: "tls",
91374
91494
  detail: err.message,
@@ -91489,7 +91609,7 @@ async function checkGitHubReachability(deps) {
91489
91609
  };
91490
91610
  }
91491
91611
  function raceTimeout(promise, ms) {
91492
- return new Promise((resolve38, reject) => {
91612
+ return new Promise((resolve39, reject) => {
91493
91613
  let settled = false;
91494
91614
  const timer = setTimeout(() => {
91495
91615
  setImmediate(() => {
@@ -91504,7 +91624,7 @@ function raceTimeout(promise, ms) {
91504
91624
  return;
91505
91625
  settled = true;
91506
91626
  clearTimeout(timer);
91507
- resolve38(v2);
91627
+ resolve39(v2);
91508
91628
  }, (e2) => {
91509
91629
  if (settled)
91510
91630
  return;
@@ -92172,13 +92292,13 @@ init_config_version_checker();
92172
92292
 
92173
92293
  // src/domains/sync/sync-engine.ts
92174
92294
  import { lstat as lstat6, readFile as readFile48, readlink as readlink2, realpath as realpath8, stat as stat14 } from "node:fs/promises";
92175
- import { isAbsolute as isAbsolute12, join as join89, normalize as normalize8, relative as relative18 } from "node:path";
92295
+ import { isAbsolute as isAbsolute12, join as join89, normalize as normalize8, relative as relative19 } from "node:path";
92176
92296
 
92177
92297
  // src/services/file-operations/ownership-checker.ts
92178
92298
  init_metadata_migration();
92179
- import { createHash as createHash6 } from "node:crypto";
92299
+ import { createHash as createHash7 } from "node:crypto";
92180
92300
  import { readFile as readFile47, stat as stat13 } from "node:fs/promises";
92181
- import { relative as relative17 } from "node:path";
92301
+ import { relative as relative18 } from "node:path";
92182
92302
 
92183
92303
  // src/shared/concurrent-file-ops.ts
92184
92304
  init_p_limit();
@@ -92192,7 +92312,7 @@ async function mapWithLimit(items, fn, concurrency = DEFAULT_CONCURRENCY) {
92192
92312
  class OwnershipChecker {
92193
92313
  static async calculateChecksum(filePath) {
92194
92314
  try {
92195
- return createHash6("sha256").update(await readFile47(filePath)).digest("hex");
92315
+ return createHash7("sha256").update(await readFile47(filePath)).digest("hex");
92196
92316
  } catch (err) {
92197
92317
  const message = err instanceof Error ? err.message : String(err);
92198
92318
  throw new Error(operationError("Checksum calculation", filePath, message));
@@ -92208,7 +92328,7 @@ class OwnershipChecker {
92208
92328
  if (!metadata || allTrackedFiles.length === 0) {
92209
92329
  return { path: filePath, ownership: "user", exists: true };
92210
92330
  }
92211
- const relativePath = relative17(claudeDir3, filePath).replace(/\\/g, "/");
92331
+ const relativePath = relative18(claudeDir3, filePath).replace(/\\/g, "/");
92212
92332
  const tracked = allTrackedFiles.find((f3) => f3.path.replace(/\\/g, "/") === relativePath);
92213
92333
  if (!tracked) {
92214
92334
  return { path: filePath, ownership: "user", exists: true };
@@ -93389,7 +93509,7 @@ async function validateSymlinkChain(path8, basePath, maxDepth = MAX_SYMLINK_DEPT
93389
93509
  const target = await readlink2(current);
93390
93510
  const resolvedTarget = isAbsolute12(target) ? target : join89(current, "..", target);
93391
93511
  const normalizedTarget = normalize8(resolvedTarget);
93392
- const rel = relative18(basePath, normalizedTarget);
93512
+ const rel = relative19(basePath, normalizedTarget);
93393
93513
  if (rel.startsWith("..") || isAbsolute12(rel)) {
93394
93514
  throw new Error(`Symlink chain escapes base directory at depth ${depth}: ${path8}`);
93395
93515
  }
@@ -93424,7 +93544,7 @@ async function validateSyncPath(basePath, filePath) {
93424
93544
  throw new Error(`Path traversal not allowed: ${filePath}`);
93425
93545
  }
93426
93546
  const fullPath = join89(basePath, normalized);
93427
- const rel = relative18(basePath, fullPath);
93547
+ const rel = relative19(basePath, fullPath);
93428
93548
  if (rel.startsWith("..") || isAbsolute12(rel)) {
93429
93549
  throw new Error(`Path escapes base directory: ${filePath}`);
93430
93550
  }
@@ -93432,7 +93552,7 @@ async function validateSyncPath(basePath, filePath) {
93432
93552
  try {
93433
93553
  const resolvedBase = await realpath8(basePath);
93434
93554
  const resolvedFull = await realpath8(fullPath);
93435
- const resolvedRel = relative18(resolvedBase, resolvedFull);
93555
+ const resolvedRel = relative19(resolvedBase, resolvedFull);
93436
93556
  if (resolvedRel.startsWith("..") || isAbsolute12(resolvedRel)) {
93437
93557
  throw new Error(`Symlink escapes base directory: ${filePath}`);
93438
93558
  }
@@ -93442,7 +93562,7 @@ async function validateSyncPath(basePath, filePath) {
93442
93562
  try {
93443
93563
  const resolvedBase = await realpath8(basePath);
93444
93564
  const resolvedParent = await realpath8(parentPath);
93445
- const resolvedRel = relative18(resolvedBase, resolvedParent);
93565
+ const resolvedRel = relative19(resolvedBase, resolvedParent);
93446
93566
  if (resolvedRel.startsWith("..") || isAbsolute12(resolvedRel)) {
93447
93567
  throw new Error(`Parent symlink escapes base directory: ${filePath}`);
93448
93568
  }
@@ -94971,10 +95091,10 @@ init_types3();
94971
95091
  // src/domains/installation/utils/path-security.ts
94972
95092
  init_types3();
94973
95093
  import { lstatSync as lstatSync2, realpathSync as realpathSync4 } from "node:fs";
94974
- import { relative as relative19, resolve as resolve40 } from "node:path";
95094
+ import { relative as relative20, resolve as resolve41 } from "node:path";
94975
95095
  var MAX_EXTRACTION_SIZE = 500 * 1024 * 1024;
94976
95096
  function isPathSafe(basePath, targetPath) {
94977
- const resolvedBase = resolve40(basePath);
95097
+ const resolvedBase = resolve41(basePath);
94978
95098
  try {
94979
95099
  const stat15 = lstatSync2(targetPath);
94980
95100
  if (stat15.isSymbolicLink()) {
@@ -94984,8 +95104,8 @@ function isPathSafe(basePath, targetPath) {
94984
95104
  }
94985
95105
  }
94986
95106
  } catch {}
94987
- const resolvedTarget = resolve40(targetPath);
94988
- const relativePath = relative19(resolvedBase, resolvedTarget);
95107
+ const resolvedTarget = resolve41(targetPath);
95108
+ const relativePath = relative20(resolvedBase, resolvedTarget);
94989
95109
  return !relativePath.startsWith("..") && !relativePath.startsWith("/") && resolvedTarget.startsWith(resolvedBase);
94990
95110
  }
94991
95111
 
@@ -95072,7 +95192,7 @@ class FileDownloader {
95072
95192
  }
95073
95193
  if (downloadedSize !== totalSize) {
95074
95194
  fileStream.end();
95075
- await new Promise((resolve41) => fileStream.once("close", resolve41));
95195
+ await new Promise((resolve42) => fileStream.once("close", resolve42));
95076
95196
  try {
95077
95197
  rmSync(destPath, { force: true });
95078
95198
  } catch (cleanupError) {
@@ -95086,7 +95206,7 @@ class FileDownloader {
95086
95206
  return destPath;
95087
95207
  } catch (error) {
95088
95208
  fileStream.end();
95089
- await new Promise((resolve41) => fileStream.once("close", resolve41));
95209
+ await new Promise((resolve42) => fileStream.once("close", resolve42));
95090
95210
  try {
95091
95211
  rmSync(destPath, { force: true });
95092
95212
  } catch (cleanupError) {
@@ -95152,7 +95272,7 @@ class FileDownloader {
95152
95272
  const expectedSize = Number(response.headers.get("content-length"));
95153
95273
  if (expectedSize > 0 && downloadedSize !== expectedSize) {
95154
95274
  fileStream.end();
95155
- await new Promise((resolve41) => fileStream.once("close", resolve41));
95275
+ await new Promise((resolve42) => fileStream.once("close", resolve42));
95156
95276
  try {
95157
95277
  rmSync(destPath, { force: true });
95158
95278
  } catch (cleanupError) {
@@ -95170,7 +95290,7 @@ class FileDownloader {
95170
95290
  return destPath;
95171
95291
  } catch (error) {
95172
95292
  fileStream.end();
95173
- await new Promise((resolve41) => fileStream.once("close", resolve41));
95293
+ await new Promise((resolve42) => fileStream.once("close", resolve42));
95174
95294
  try {
95175
95295
  rmSync(destPath, { force: true });
95176
95296
  } catch (cleanupError) {
@@ -95789,10 +95909,10 @@ class Minipass extends EventEmitter3 {
95789
95909
  return this[ENCODING] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
95790
95910
  }
95791
95911
  async promise() {
95792
- return new Promise((resolve41, reject) => {
95912
+ return new Promise((resolve42, reject) => {
95793
95913
  this.on(DESTROYED, () => reject(new Error("stream destroyed")));
95794
95914
  this.on("error", (er) => reject(er));
95795
- this.on("end", () => resolve41());
95915
+ this.on("end", () => resolve42());
95796
95916
  });
95797
95917
  }
95798
95918
  [Symbol.asyncIterator]() {
@@ -95811,7 +95931,7 @@ class Minipass extends EventEmitter3 {
95811
95931
  return Promise.resolve({ done: false, value: res });
95812
95932
  if (this[EOF])
95813
95933
  return stop();
95814
- let resolve41;
95934
+ let resolve42;
95815
95935
  let reject;
95816
95936
  const onerr = (er) => {
95817
95937
  this.off("data", ondata);
@@ -95825,19 +95945,19 @@ class Minipass extends EventEmitter3 {
95825
95945
  this.off("end", onend);
95826
95946
  this.off(DESTROYED, ondestroy);
95827
95947
  this.pause();
95828
- resolve41({ value, done: !!this[EOF] });
95948
+ resolve42({ value, done: !!this[EOF] });
95829
95949
  };
95830
95950
  const onend = () => {
95831
95951
  this.off("error", onerr);
95832
95952
  this.off("data", ondata);
95833
95953
  this.off(DESTROYED, ondestroy);
95834
95954
  stop();
95835
- resolve41({ done: true, value: undefined });
95955
+ resolve42({ done: true, value: undefined });
95836
95956
  };
95837
95957
  const ondestroy = () => onerr(new Error("stream destroyed"));
95838
95958
  return new Promise((res2, rej) => {
95839
95959
  reject = rej;
95840
- resolve41 = res2;
95960
+ resolve42 = res2;
95841
95961
  this.once(DESTROYED, ondestroy);
95842
95962
  this.once("error", onerr);
95843
95963
  this.once("end", onend);
@@ -96943,10 +97063,10 @@ class Minipass2 extends EventEmitter4 {
96943
97063
  return this[ENCODING2] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
96944
97064
  }
96945
97065
  async promise() {
96946
- return new Promise((resolve41, reject) => {
97066
+ return new Promise((resolve42, reject) => {
96947
97067
  this.on(DESTROYED2, () => reject(new Error("stream destroyed")));
96948
97068
  this.on("error", (er) => reject(er));
96949
- this.on("end", () => resolve41());
97069
+ this.on("end", () => resolve42());
96950
97070
  });
96951
97071
  }
96952
97072
  [Symbol.asyncIterator]() {
@@ -96965,7 +97085,7 @@ class Minipass2 extends EventEmitter4 {
96965
97085
  return Promise.resolve({ done: false, value: res });
96966
97086
  if (this[EOF2])
96967
97087
  return stop();
96968
- let resolve41;
97088
+ let resolve42;
96969
97089
  let reject;
96970
97090
  const onerr = (er) => {
96971
97091
  this.off("data", ondata);
@@ -96979,19 +97099,19 @@ class Minipass2 extends EventEmitter4 {
96979
97099
  this.off("end", onend);
96980
97100
  this.off(DESTROYED2, ondestroy);
96981
97101
  this.pause();
96982
- resolve41({ value, done: !!this[EOF2] });
97102
+ resolve42({ value, done: !!this[EOF2] });
96983
97103
  };
96984
97104
  const onend = () => {
96985
97105
  this.off("error", onerr);
96986
97106
  this.off("data", ondata);
96987
97107
  this.off(DESTROYED2, ondestroy);
96988
97108
  stop();
96989
- resolve41({ done: true, value: undefined });
97109
+ resolve42({ done: true, value: undefined });
96990
97110
  };
96991
97111
  const ondestroy = () => onerr(new Error("stream destroyed"));
96992
97112
  return new Promise((res2, rej) => {
96993
97113
  reject = rej;
96994
- resolve41 = res2;
97114
+ resolve42 = res2;
96995
97115
  this.once(DESTROYED2, ondestroy);
96996
97116
  this.once("error", onerr);
96997
97117
  this.once("end", onend);
@@ -98419,10 +98539,10 @@ class Minipass3 extends EventEmitter5 {
98419
98539
  return this[ENCODING3] ? buf.join("") : Buffer.concat(buf, buf.dataLength);
98420
98540
  }
98421
98541
  async promise() {
98422
- return new Promise((resolve41, reject) => {
98542
+ return new Promise((resolve42, reject) => {
98423
98543
  this.on(DESTROYED3, () => reject(new Error("stream destroyed")));
98424
98544
  this.on("error", (er) => reject(er));
98425
- this.on("end", () => resolve41());
98545
+ this.on("end", () => resolve42());
98426
98546
  });
98427
98547
  }
98428
98548
  [Symbol.asyncIterator]() {
@@ -98441,7 +98561,7 @@ class Minipass3 extends EventEmitter5 {
98441
98561
  return Promise.resolve({ done: false, value: res });
98442
98562
  if (this[EOF3])
98443
98563
  return stop();
98444
- let resolve41;
98564
+ let resolve42;
98445
98565
  let reject;
98446
98566
  const onerr = (er) => {
98447
98567
  this.off("data", ondata);
@@ -98455,19 +98575,19 @@ class Minipass3 extends EventEmitter5 {
98455
98575
  this.off("end", onend);
98456
98576
  this.off(DESTROYED3, ondestroy);
98457
98577
  this.pause();
98458
- resolve41({ value, done: !!this[EOF3] });
98578
+ resolve42({ value, done: !!this[EOF3] });
98459
98579
  };
98460
98580
  const onend = () => {
98461
98581
  this.off("error", onerr);
98462
98582
  this.off("data", ondata);
98463
98583
  this.off(DESTROYED3, ondestroy);
98464
98584
  stop();
98465
- resolve41({ done: true, value: undefined });
98585
+ resolve42({ done: true, value: undefined });
98466
98586
  };
98467
98587
  const ondestroy = () => onerr(new Error("stream destroyed"));
98468
98588
  return new Promise((res2, rej) => {
98469
98589
  reject = rej;
98470
- resolve41 = res2;
98590
+ resolve42 = res2;
98471
98591
  this.once(DESTROYED3, ondestroy);
98472
98592
  this.once("error", onerr);
98473
98593
  this.once("end", onend);
@@ -99238,9 +99358,9 @@ var listFile = (opt, _files) => {
99238
99358
  const parse5 = new Parser(opt);
99239
99359
  const readSize = opt.maxReadSize || 16 * 1024 * 1024;
99240
99360
  const file = opt.file;
99241
- const p = new Promise((resolve41, reject) => {
99361
+ const p = new Promise((resolve42, reject) => {
99242
99362
  parse5.on("error", reject);
99243
- parse5.on("end", resolve41);
99363
+ parse5.on("end", resolve42);
99244
99364
  fs10.stat(file, (er, stat15) => {
99245
99365
  if (er) {
99246
99366
  reject(er);
@@ -101820,9 +101940,9 @@ var extractFile = (opt, _3) => {
101820
101940
  const u = new Unpack(opt);
101821
101941
  const readSize = opt.maxReadSize || 16 * 1024 * 1024;
101822
101942
  const file = opt.file;
101823
- const p = new Promise((resolve41, reject) => {
101943
+ const p = new Promise((resolve42, reject) => {
101824
101944
  u.on("error", reject);
101825
- u.on("close", resolve41);
101945
+ u.on("close", resolve42);
101826
101946
  fs17.stat(file, (er, stat15) => {
101827
101947
  if (er) {
101828
101948
  reject(er);
@@ -101955,7 +102075,7 @@ var replaceAsync = (opt, files) => {
101955
102075
  };
101956
102076
  fs18.read(fd, headBuf, 0, 512, position, onread);
101957
102077
  };
101958
- const promise = new Promise((resolve41, reject) => {
102078
+ const promise = new Promise((resolve42, reject) => {
101959
102079
  p.on("error", reject);
101960
102080
  let flag = "r+";
101961
102081
  const onopen = (er, fd) => {
@@ -101980,7 +102100,7 @@ var replaceAsync = (opt, files) => {
101980
102100
  });
101981
102101
  p.pipe(stream);
101982
102102
  stream.on("error", reject);
101983
- stream.on("close", resolve41);
102103
+ stream.on("close", resolve42);
101984
102104
  addFilesAsync2(p, files);
101985
102105
  });
101986
102106
  });
@@ -102110,7 +102230,7 @@ function decodeFilePath(path15) {
102110
102230
  init_logger();
102111
102231
  init_types3();
102112
102232
  import { copyFile as copyFile3, lstat as lstat7, mkdir as mkdir27, readdir as readdir24 } from "node:fs/promises";
102113
- import { join as join102, relative as relative20 } from "node:path";
102233
+ import { join as join102, relative as relative21 } from "node:path";
102114
102234
  async function withRetry(fn, retries = 3) {
102115
102235
  for (let i = 0;i < retries; i++) {
102116
102236
  try {
@@ -102134,7 +102254,7 @@ async function moveDirectoryContents(sourceDir, destDir, shouldExclude, sizeTrac
102134
102254
  for (const entry of entries) {
102135
102255
  const sourcePath = join102(sourceDir, entry);
102136
102256
  const destPath = join102(destDir, entry);
102137
- const relativePath = relative20(sourceDir, sourcePath);
102257
+ const relativePath = relative21(sourceDir, sourcePath);
102138
102258
  if (!isPathSafe(destDir, destPath)) {
102139
102259
  logger.warning(`Skipping unsafe path: ${relativePath}`);
102140
102260
  throw new ExtractionError(`Path traversal attempt detected: ${relativePath}`);
@@ -102162,7 +102282,7 @@ async function copyDirectory(sourceDir, destDir, shouldExclude, sizeTracker) {
102162
102282
  for (const entry of entries) {
102163
102283
  const sourcePath = join102(sourceDir, entry);
102164
102284
  const destPath = join102(destDir, entry);
102165
- const relativePath = relative20(sourceDir, sourcePath);
102285
+ const relativePath = relative21(sourceDir, sourcePath);
102166
102286
  if (!isPathSafe(destDir, destPath)) {
102167
102287
  logger.warning(`Skipping unsafe path: ${relativePath}`);
102168
102288
  throw new ExtractionError(`Path traversal attempt detected: ${relativePath}`);
@@ -102937,7 +103057,7 @@ import { join as join123 } from "node:path";
102937
103057
 
102938
103058
  // src/domains/installation/deletion-handler.ts
102939
103059
  import { existsSync as existsSync66, lstatSync as lstatSync3, readdirSync as readdirSync10, rmSync as rmSync2, rmdirSync, unlinkSync as unlinkSync4 } from "node:fs";
102940
- import { dirname as dirname38, join as join108, relative as relative21, resolve as resolve42, sep as sep12 } from "node:path";
103060
+ import { dirname as dirname38, join as join108, relative as relative22, resolve as resolve43, sep as sep12 } from "node:path";
102941
103061
 
102942
103062
  // src/services/file-operations/manifest/manifest-reader.ts
102943
103063
  init_metadata_migration();
@@ -103133,7 +103253,7 @@ function collectFilesRecursively(dir, baseDir) {
103133
103253
  const entries = readdirSync10(dir, { withFileTypes: true });
103134
103254
  for (const entry of entries) {
103135
103255
  const fullPath = join108(dir, entry.name);
103136
- const relativePath = relative21(baseDir, fullPath);
103256
+ const relativePath = relative22(baseDir, fullPath);
103137
103257
  if (entry.isDirectory()) {
103138
103258
  results.push(...collectFilesRecursively(fullPath, baseDir));
103139
103259
  } else {
@@ -103162,8 +103282,8 @@ function expandGlobPatterns(patterns, claudeDir3) {
103162
103282
  }
103163
103283
  var MAX_CLEANUP_ITERATIONS = 50;
103164
103284
  function cleanupEmptyDirectories(filePath, claudeDir3) {
103165
- const normalizedClaudeDir = resolve42(claudeDir3);
103166
- let currentDir = resolve42(dirname38(filePath));
103285
+ const normalizedClaudeDir = resolve43(claudeDir3);
103286
+ let currentDir = resolve43(dirname38(filePath));
103167
103287
  let iterations = 0;
103168
103288
  while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir) && iterations < MAX_CLEANUP_ITERATIONS) {
103169
103289
  iterations++;
@@ -103172,7 +103292,7 @@ function cleanupEmptyDirectories(filePath, claudeDir3) {
103172
103292
  if (entries.length === 0) {
103173
103293
  rmdirSync(currentDir);
103174
103294
  logger.debug(`Removed empty directory: ${currentDir}`);
103175
- currentDir = resolve42(dirname38(currentDir));
103295
+ currentDir = resolve43(dirname38(currentDir));
103176
103296
  } else {
103177
103297
  break;
103178
103298
  }
@@ -103182,8 +103302,8 @@ function cleanupEmptyDirectories(filePath, claudeDir3) {
103182
103302
  }
103183
103303
  }
103184
103304
  function deletePath(fullPath, claudeDir3) {
103185
- const normalizedPath = resolve42(fullPath);
103186
- const normalizedClaudeDir = resolve42(claudeDir3);
103305
+ const normalizedPath = resolve43(fullPath);
103306
+ const normalizedClaudeDir = resolve43(claudeDir3);
103187
103307
  if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep12}`) && normalizedPath !== normalizedClaudeDir) {
103188
103308
  throw new Error(`Path traversal detected: ${fullPath}`);
103189
103309
  }
@@ -103256,8 +103376,8 @@ async function handleDeletions(sourceMetadata, claudeDir3, kitType) {
103256
103376
  const result = { deletedPaths: [], preservedPaths: [], errors: [] };
103257
103377
  for (const path16 of deletions) {
103258
103378
  const fullPath = join108(claudeDir3, path16);
103259
- const normalizedPath = resolve42(fullPath);
103260
- const normalizedClaudeDir = resolve42(claudeDir3);
103379
+ const normalizedPath = resolve43(fullPath);
103380
+ const normalizedClaudeDir = resolve43(claudeDir3);
103261
103381
  if (!normalizedPath.startsWith(`${normalizedClaudeDir}${sep12}`)) {
103262
103382
  logger.warning(`Skipping invalid path: ${path16}`);
103263
103383
  result.errors.push(path16);
@@ -103295,7 +103415,7 @@ init_logger();
103295
103415
  init_types3();
103296
103416
  var import_fs_extra16 = __toESM(require_lib(), 1);
103297
103417
  var import_ignore3 = __toESM(require_ignore(), 1);
103298
- import { dirname as dirname42, join as join113, relative as relative24 } from "node:path";
103418
+ import { dirname as dirname42, join as join113, relative as relative25 } from "node:path";
103299
103419
 
103300
103420
  // src/domains/installation/selective-merger.ts
103301
103421
  import { stat as stat18 } from "node:fs/promises";
@@ -103471,7 +103591,7 @@ class SelectiveMerger {
103471
103591
 
103472
103592
  // src/domains/installation/merger/deleted-skill-preservation.ts
103473
103593
  init_metadata_migration();
103474
- import { dirname as dirname39, join as join109, relative as relative22 } from "node:path";
103594
+ import { dirname as dirname39, join as join109, relative as relative23 } from "node:path";
103475
103595
  var import_fs_extra13 = __toESM(require_lib(), 1);
103476
103596
  async function findIgnoredSkillDirectories({
103477
103597
  files,
@@ -103516,7 +103636,7 @@ function shouldSkipIgnoredSkill(normalizedRelativePath, ignoredSkillDirectories)
103516
103636
  function findSourceSkillRoots(files, sourceDir) {
103517
103637
  const sourceSkillRoots = new Map;
103518
103638
  for (const file of files) {
103519
- const normalizedPath = relative22(sourceDir, file).replace(/\\/g, "/");
103639
+ const normalizedPath = relative23(sourceDir, file).replace(/\\/g, "/");
103520
103640
  const metadataPath = toMetadataPath(normalizedPath);
103521
103641
  if (!metadataPath?.endsWith("/SKILL.md"))
103522
103642
  continue;
@@ -103548,7 +103668,7 @@ function findSkillRoot(path16, skillRoots) {
103548
103668
  init_logger();
103549
103669
  var import_fs_extra14 = __toESM(require_lib(), 1);
103550
103670
  var import_ignore2 = __toESM(require_ignore(), 1);
103551
- import { relative as relative23 } from "node:path";
103671
+ import { relative as relative24 } from "node:path";
103552
103672
  import { join as join110 } from "node:path";
103553
103673
 
103554
103674
  // node_modules/@isaacs/balanced-match/dist/esm/index.js
@@ -105006,7 +105126,7 @@ class FileScanner {
105006
105126
  const entries = await import_fs_extra14.readdir(dir, { encoding: "utf8" });
105007
105127
  for (const entry of entries) {
105008
105128
  const fullPath = join110(dir, entry);
105009
- const relativePath = relative23(baseDir, fullPath);
105129
+ const relativePath = relative24(baseDir, fullPath);
105010
105130
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
105011
105131
  const stats = await import_fs_extra14.lstat(fullPath);
105012
105132
  if (stats.isSymbolicLink()) {
@@ -105977,7 +106097,7 @@ class CopyExecutor {
105977
106097
  const conflicts = [];
105978
106098
  const files = await this.fileScanner.getFiles(sourceDir, sourceDir);
105979
106099
  for (const file of files) {
105980
- const relativePath = relative24(sourceDir, file);
106100
+ const relativePath = relative25(sourceDir, file);
105981
106101
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
105982
106102
  const destPath = join113(destDir, relativePath);
105983
106103
  if (await import_fs_extra16.pathExists(destPath)) {
@@ -106001,7 +106121,7 @@ class CopyExecutor {
106001
106121
  let skippedCount = 0;
106002
106122
  let ignoredSkillSkipped = 0;
106003
106123
  for (const file of files) {
106004
- const relativePath = relative24(sourceDir, file);
106124
+ const relativePath = relative25(sourceDir, file);
106005
106125
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
106006
106126
  const destPath = join113(destDir, relativePath);
106007
106127
  if (this.fileScanner.shouldNeverCopy(normalizedRelativePath)) {
@@ -106215,7 +106335,7 @@ class FileMerger {
106215
106335
 
106216
106336
  // src/domains/migration/legacy-migration.ts
106217
106337
  import { readdir as readdir28, stat as stat19 } from "node:fs/promises";
106218
- import { join as join117, relative as relative25 } from "node:path";
106338
+ import { join as join117, relative as relative26 } from "node:path";
106219
106339
  // src/services/file-operations/manifest/manifest-tracker.ts
106220
106340
  import { join as join116 } from "node:path";
106221
106341
 
@@ -106688,7 +106808,7 @@ class LegacyMigration {
106688
106808
  static async classifyFiles(claudeDir3, manifest) {
106689
106809
  const files = await LegacyMigration.scanFiles(claudeDir3);
106690
106810
  const relevantFiles = files.filter((file) => {
106691
- const relativePath = relative25(claudeDir3, file);
106811
+ const relativePath = relative26(claudeDir3, file);
106692
106812
  return !hasSkippedDirectorySegment(relativePath);
106693
106813
  });
106694
106814
  const skippedRuntimeArtifacts = files.length - relevantFiles.length;
@@ -106703,7 +106823,7 @@ class LegacyMigration {
106703
106823
  };
106704
106824
  const filesInManifest = [];
106705
106825
  for (const file of relevantFiles) {
106706
- const relativePath = relative25(claudeDir3, file).replace(/\\/g, "/");
106826
+ const relativePath = relative26(claudeDir3, file).replace(/\\/g, "/");
106707
106827
  const manifestEntry = ReleaseManifestLoader.findFile(manifest, relativePath);
106708
106828
  if (!manifestEntry) {
106709
106829
  preview.userCreated.push(relativePath);
@@ -106899,7 +107019,7 @@ function buildConflictSummary(fileConflicts, hookConflicts, mcpConflicts) {
106899
107019
  init_logger();
106900
107020
  init_skip_directories();
106901
107021
  var import_fs_extra20 = __toESM(require_lib(), 1);
106902
- import { join as join118, relative as relative26, resolve as resolve43 } from "node:path";
107022
+ import { join as join118, relative as relative27, resolve as resolve44 } from "node:path";
106903
107023
 
106904
107024
  class FileScanner2 {
106905
107025
  static async getFiles(dirPath, relativeTo) {
@@ -106938,7 +107058,7 @@ class FileScanner2 {
106938
107058
  const subFiles = await FileScanner2.getFiles(fullPath, basePath);
106939
107059
  files.push(...subFiles);
106940
107060
  } else if (stats.isFile()) {
106941
- const relativePath = relative26(basePath, fullPath);
107061
+ const relativePath = relative27(basePath, fullPath);
106942
107062
  files.push(FileScanner2.toPosixPath(relativePath));
106943
107063
  }
106944
107064
  }
@@ -106979,8 +107099,8 @@ class FileScanner2 {
106979
107099
  return customFiles;
106980
107100
  }
106981
107101
  static isSafePath(basePath, targetPath) {
106982
- const resolvedBase = resolve43(basePath);
106983
- const resolvedTarget = resolve43(targetPath);
107102
+ const resolvedBase = resolve44(basePath);
107103
+ const resolvedTarget = resolve44(targetPath);
106984
107104
  return resolvedTarget.startsWith(resolvedBase);
106985
107105
  }
106986
107106
  static toPosixPath(path17) {
@@ -107605,9 +107725,9 @@ init_logger();
107605
107725
  init_skip_directories();
107606
107726
  init_types3();
107607
107727
  var import_fs_extra25 = __toESM(require_lib(), 1);
107608
- import { createHash as createHash7 } from "node:crypto";
107728
+ import { createHash as createHash8 } from "node:crypto";
107609
107729
  import { readFile as readFile58, readdir as readdir34, writeFile as writeFile32 } from "node:fs/promises";
107610
- import { join as join124, relative as relative27 } from "node:path";
107730
+ import { join as join124, relative as relative28 } from "node:path";
107611
107731
 
107612
107732
  class SkillsManifestManager {
107613
107733
  static MANIFEST_FILENAME = ".skills-manifest.json";
@@ -107707,11 +107827,11 @@ class SkillsManifestManager {
107707
107827
  return skills.sort((a3, b3) => a3.name.localeCompare(b3.name));
107708
107828
  }
107709
107829
  static async hashDirectory(dirPath) {
107710
- const hash = createHash7("sha256");
107830
+ const hash = createHash8("sha256");
107711
107831
  const files = await SkillsManifestManager.getAllFiles(dirPath);
107712
107832
  files.sort();
107713
107833
  for (const file of files) {
107714
- const relativePath = relative27(dirPath, file);
107834
+ const relativePath = relative28(dirPath, file);
107715
107835
  const content = await readFile58(file);
107716
107836
  hash.update(relativePath);
107717
107837
  hash.update(content);
@@ -108446,14 +108566,14 @@ init_logger();
108446
108566
 
108447
108567
  // src/domains/skills/customization/comparison-engine.ts
108448
108568
  var import_fs_extra30 = __toESM(require_lib(), 1);
108449
- import { relative as relative29 } from "node:path";
108569
+ import { relative as relative30 } from "node:path";
108450
108570
 
108451
108571
  // src/domains/skills/customization/hash-calculator.ts
108452
108572
  init_skip_directories();
108453
- import { createHash as createHash8 } from "node:crypto";
108573
+ import { createHash as createHash9 } from "node:crypto";
108454
108574
  import { createReadStream as createReadStream2 } from "node:fs";
108455
108575
  import { readFile as readFile59, readdir as readdir38 } from "node:fs/promises";
108456
- import { join as join128, relative as relative28 } from "node:path";
108576
+ import { join as join128, relative as relative29 } from "node:path";
108457
108577
  async function getAllFiles(dirPath) {
108458
108578
  const files = [];
108459
108579
  const entries = await readdir38(dirPath, { withFileTypes: true });
@@ -108472,12 +108592,12 @@ async function getAllFiles(dirPath) {
108472
108592
  return files;
108473
108593
  }
108474
108594
  async function hashFile(filePath) {
108475
- return new Promise((resolve44, reject) => {
108476
- const hash = createHash8("sha256");
108595
+ return new Promise((resolve45, reject) => {
108596
+ const hash = createHash9("sha256");
108477
108597
  const stream = createReadStream2(filePath);
108478
108598
  stream.on("data", (chunk) => hash.update(chunk));
108479
108599
  stream.on("end", () => {
108480
- resolve44(hash.digest("hex"));
108600
+ resolve45(hash.digest("hex"));
108481
108601
  });
108482
108602
  stream.on("error", (error) => {
108483
108603
  stream.destroy();
@@ -108486,11 +108606,11 @@ async function hashFile(filePath) {
108486
108606
  });
108487
108607
  }
108488
108608
  async function hashDirectory(dirPath) {
108489
- const hash = createHash8("sha256");
108609
+ const hash = createHash9("sha256");
108490
108610
  const files = await getAllFiles(dirPath);
108491
108611
  files.sort();
108492
108612
  for (const file of files) {
108493
- const relativePath = relative28(dirPath, file);
108613
+ const relativePath = relative29(dirPath, file);
108494
108614
  const content = await readFile59(file);
108495
108615
  hash.update(relativePath);
108496
108616
  hash.update(content);
@@ -108524,8 +108644,8 @@ async function compareDirectories(dir1, dir2) {
108524
108644
  if (files1.length !== files2.length) {
108525
108645
  return true;
108526
108646
  }
108527
- const relFiles1 = files1.map((f3) => relative29(dir1, f3)).sort();
108528
- const relFiles2 = files2.map((f3) => relative29(dir2, f3)).sort();
108647
+ const relFiles1 = files1.map((f3) => relative30(dir1, f3)).sort();
108648
+ const relFiles2 = files2.map((f3) => relative30(dir2, f3)).sort();
108529
108649
  if (JSON.stringify(relFiles1) !== JSON.stringify(relFiles2)) {
108530
108650
  return true;
108531
108651
  }
@@ -108543,12 +108663,12 @@ async function detectFileChanges(currentSkillPath, baselineSkillPath) {
108543
108663
  const currentFiles = await getAllFiles(currentSkillPath);
108544
108664
  const baselineFiles = await import_fs_extra30.pathExists(baselineSkillPath) ? await getAllFiles(baselineSkillPath) : [];
108545
108665
  const currentFileMap = new Map(await Promise.all(currentFiles.map(async (f3) => {
108546
- const relPath = relative29(currentSkillPath, f3);
108666
+ const relPath = relative30(currentSkillPath, f3);
108547
108667
  const hash = await hashFile(f3);
108548
108668
  return [relPath, hash];
108549
108669
  })));
108550
108670
  const baselineFileMap = new Map(await Promise.all(baselineFiles.map(async (f3) => {
108551
- const relPath = relative29(baselineSkillPath, f3);
108671
+ const relPath = relative30(baselineSkillPath, f3);
108552
108672
  const hash = await hashFile(f3);
108553
108673
  return [relPath, hash];
108554
108674
  })));
@@ -108995,7 +109115,8 @@ async function resolveOptions(ctx) {
108995
109115
  sync: parsed.sync ?? false,
108996
109116
  useGit: parsed.useGit ?? false,
108997
109117
  archive: parsed.archive,
108998
- kitPath: parsed.kitPath
109118
+ kitPath: parsed.kitPath,
109119
+ installMode: parsed.installMode ?? "auto"
108999
109120
  };
109000
109121
  ConfigManager.setGlobalFlag(validOptions.global);
109001
109122
  if (validOptions.global) {
@@ -109125,13 +109246,22 @@ async function handlePostInstall(ctx) {
109125
109246
  }
109126
109247
  // src/commands/init/phases/plugin-install-handler.ts
109127
109248
  init_codex_plugin_installer();
109128
- import { cpSync as cpSync2, existsSync as existsSync69, mkdirSync as mkdirSync6, readFileSync as readFileSync22, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
109129
- import { join as join136 } from "node:path";
109249
+ import { cpSync as cpSync2, existsSync as existsSync70, mkdirSync as mkdirSync6, readFileSync as readFileSync22, rmSync as rmSync5, writeFileSync as writeFileSync8 } from "node:fs";
109250
+ import { join as join137 } from "node:path";
109130
109251
 
109131
109252
  // src/domains/installation/plugin/migrate-legacy-to-plugin.ts
109132
109253
  init_install_mode_detector();
109133
- import { cpSync, existsSync as existsSync68, mkdirSync as mkdirSync5, readFileSync as readFileSync21, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "node:fs";
109134
- import { dirname as dirname43, join as join135 } from "node:path";
109254
+ import { createHash as createHash10 } from "node:crypto";
109255
+ import {
109256
+ cpSync,
109257
+ existsSync as existsSync68,
109258
+ mkdirSync as mkdirSync5,
109259
+ readFileSync as readFileSync21,
109260
+ readdirSync as readdirSync11,
109261
+ rmSync as rmSync3,
109262
+ writeFileSync as writeFileSync7
109263
+ } from "node:fs";
109264
+ import { dirname as dirname43, join as join135, relative as relative31, resolve as resolve45 } from "node:path";
109135
109265
 
109136
109266
  // src/domains/installation/plugin/plugin-installer.ts
109137
109267
  init_install_mode_detector();
@@ -109239,18 +109369,11 @@ async function migrateLegacyToPlugin(opts) {
109239
109369
  if (!await installer.isClaudeAvailable() || !await installer.isPluginSupported()) {
109240
109370
  return base("skipped-cc-unsupported", before.mode, false);
109241
109371
  }
109242
- const added = await installer.marketplaceAdd(opts.pluginSourceDir);
109243
- if (!added.ok) {
109372
+ const prepared = before.plugin.installed ? await refreshExistingPlugin(installer, opts.pluginSourceDir, before.plugin.enabled) : await installPlugin(installer, opts.pluginSourceDir);
109373
+ if (!prepared.ok) {
109244
109374
  return {
109245
109375
  ...base("install-failed", before.mode, false),
109246
- error: `marketplace add failed: ${added.stderr.trim()}`
109247
- };
109248
- }
109249
- const installed = await installer.install("user");
109250
- if (!installed.ok) {
109251
- return {
109252
- ...base("install-failed", before.mode, false),
109253
- error: `plugin install failed: ${installed.stderr.trim()}`
109376
+ error: prepared.error
109254
109377
  };
109255
109378
  }
109256
109379
  const verified = await installer.verifyInstalled();
@@ -109296,30 +109419,172 @@ function base(action, modeBefore, pluginVerified) {
109296
109419
  };
109297
109420
  }
109298
109421
  var PLUGIN_SUPPLIED_LEGACY_PREFIXES2 = ["agents/", "skills/"];
109422
+ var LEGACY_SENTINEL_FILENAMES = new Set([".gitignore"]);
109299
109423
  function defaultLegacyRemover(claudeDir3, backupDir) {
109300
109424
  const meta = readJsonSafe3(join135(claudeDir3, "metadata.json"));
109301
109425
  const files = collectTrackedFiles2(meta);
109302
109426
  const removed = [];
109303
109427
  for (const file of files) {
109304
- if (file.ownership === "user")
109428
+ const legacyPath = resolveSafePluginSuppliedLegacyPath2(claudeDir3, file.path);
109429
+ if (!legacyPath)
109305
109430
  continue;
109306
- if (!isPluginSuppliedLegacyPath(file.path))
109431
+ if (!existsSync68(legacyPath.absolutePath))
109307
109432
  continue;
109308
- const abs = join135(claudeDir3, file.path);
109309
- if (!existsSync68(abs))
109433
+ if (!isSafeToRemovePluginSuppliedLegacyFile(file, legacyPath.absolutePath))
109310
109434
  continue;
109311
- const backupTarget = join135(backupDir, file.path);
109312
- mkdirSync5(dirname43(backupTarget), { recursive: true });
109313
- cpSync(abs, backupTarget, { recursive: true });
109314
- rmSync3(abs, { recursive: true, force: true });
109315
- removed.push(file.path);
109435
+ if (!backupAndRemove(backupDir, legacyPath.relativePath, legacyPath.absolutePath))
109436
+ continue;
109437
+ removed.push(legacyPath.relativePath);
109316
109438
  }
109439
+ removed.push(...removeOrphanLegacySentinels(claudeDir3, backupDir, removed));
109317
109440
  return removed;
109318
109441
  }
109319
- function isPluginSuppliedLegacyPath(pathValue) {
109320
- const normalized = pathValue.replace(/\\/g, "/").replace(/^\.claude\//, "");
109442
+ function backupAndRemove(backupDir, relativePath, abs) {
109443
+ const backupTarget = resolveSafeChildPath2(backupDir, relativePath);
109444
+ if (!backupTarget)
109445
+ return false;
109446
+ mkdirSync5(dirname43(backupTarget), { recursive: true });
109447
+ cpSync(abs, backupTarget, { recursive: true });
109448
+ rmSync3(abs, { recursive: true, force: true });
109449
+ return true;
109450
+ }
109451
+ function removeOrphanLegacySentinels(claudeDir3, backupDir, removedTrackedPaths) {
109452
+ const normalizedRemoved = removedTrackedPaths.map(normalizeLegacyPath2);
109453
+ const rootsToSweep = new Set;
109454
+ for (const pathValue of normalizedRemoved) {
109455
+ const [root] = pathValue.split("/");
109456
+ if (root && PLUGIN_SUPPLIED_LEGACY_PREFIXES2.includes(`${root}/`)) {
109457
+ rootsToSweep.add(root);
109458
+ }
109459
+ }
109460
+ const removed = [];
109461
+ for (const root of [...rootsToSweep].sort(compareLegacyPaths)) {
109462
+ const rootAbs = join135(claudeDir3, root);
109463
+ if (!existsSync68(rootAbs))
109464
+ continue;
109465
+ const sentinels = findLegacySentinels(rootAbs).sort((a3, b3) => compareLegacyPaths(relative31(claudeDir3, a3), relative31(claudeDir3, b3)));
109466
+ for (const sentinelAbs of sentinels) {
109467
+ const sentinelPath = normalizeLegacyPath2(relative31(claudeDir3, sentinelAbs));
109468
+ if (!isSafeToRemoveLegacySentinel(sentinelPath, sentinelAbs, normalizedRemoved))
109469
+ continue;
109470
+ if (!backupAndRemove(backupDir, sentinelPath, sentinelAbs))
109471
+ continue;
109472
+ removed.push(sentinelPath);
109473
+ }
109474
+ }
109475
+ return removed;
109476
+ }
109477
+ function findLegacySentinels(dir) {
109478
+ const out = [];
109479
+ let entries;
109480
+ try {
109481
+ entries = readdirSync11(dir, { withFileTypes: true });
109482
+ } catch {
109483
+ return out;
109484
+ }
109485
+ for (const entry of entries.sort((a3, b3) => compareLegacyPaths(a3.name, b3.name))) {
109486
+ const abs = join135(dir, entry.name);
109487
+ if (entry.isDirectory()) {
109488
+ out.push(...findLegacySentinels(abs));
109489
+ } else if (entry.isFile() && LEGACY_SENTINEL_FILENAMES.has(entry.name)) {
109490
+ out.push(abs);
109491
+ }
109492
+ }
109493
+ return out;
109494
+ }
109495
+ function isSafeToRemoveLegacySentinel(sentinelPath, sentinelAbs, removedTrackedPaths) {
109496
+ if (!isPluginSuppliedLegacyPath2(sentinelPath))
109497
+ return false;
109498
+ if (!LEGACY_SENTINEL_FILENAMES.has(sentinelPath.split("/").pop() ?? ""))
109499
+ return false;
109500
+ const sentinelDir = dirname43(sentinelPath).replace(/\\/g, "/");
109501
+ if (!removedTrackedPaths.some((removedPath) => removedPath.startsWith(`${sentinelDir}/`))) {
109502
+ return false;
109503
+ }
109504
+ return directoryContainsOnlySentinels(dirname43(sentinelAbs));
109505
+ }
109506
+ function directoryContainsOnlySentinels(dir) {
109507
+ let entries;
109508
+ try {
109509
+ entries = readdirSync11(dir, { withFileTypes: true });
109510
+ } catch {
109511
+ return false;
109512
+ }
109513
+ for (const entry of entries) {
109514
+ const abs = join135(dir, entry.name);
109515
+ if (entry.isDirectory()) {
109516
+ if (!directoryContainsOnlySentinels(abs))
109517
+ return false;
109518
+ } else if (!entry.isFile() || !LEGACY_SENTINEL_FILENAMES.has(entry.name)) {
109519
+ return false;
109520
+ }
109521
+ }
109522
+ return true;
109523
+ }
109524
+ function isSafeToRemovePluginSuppliedLegacyFile(file, abs) {
109525
+ if (file.ownership !== "user") {
109526
+ return true;
109527
+ }
109528
+ return checksumMatches2(abs, file.checksum);
109529
+ }
109530
+ function checksumMatches2(filePath, expected) {
109531
+ if (!expected || !/^[a-f0-9]{64}$/i.test(expected)) {
109532
+ return false;
109533
+ }
109534
+ try {
109535
+ const actual = createHash10("sha256").update(readFileSync21(filePath)).digest("hex");
109536
+ return actual.toLowerCase() === expected.toLowerCase();
109537
+ } catch {
109538
+ return false;
109539
+ }
109540
+ }
109541
+ function isPluginSuppliedLegacyPath2(pathValue) {
109542
+ const normalized = normalizeLegacyPath2(pathValue).replace(/^\.claude\//, "");
109321
109543
  return PLUGIN_SUPPLIED_LEGACY_PREFIXES2.some((prefix) => normalized.startsWith(prefix));
109322
109544
  }
109545
+ function resolveSafePluginSuppliedLegacyPath2(claudeDir3, pathValue) {
109546
+ const normalized = normalizeLegacyPath2(pathValue).replace(/^\.\/+/, "");
109547
+ if (!isPluginSuppliedLegacyPath2(normalized))
109548
+ return null;
109549
+ const safe = resolveSafeChildPath2(claudeDir3, normalized);
109550
+ if (!safe)
109551
+ return null;
109552
+ const relativePath = normalizeLegacyPath2(relative31(resolve45(claudeDir3), safe));
109553
+ if (!isPluginSuppliedLegacyPath2(relativePath))
109554
+ return null;
109555
+ return { absolutePath: safe, relativePath };
109556
+ }
109557
+ function resolveSafeChildPath2(baseDir, pathValue) {
109558
+ const normalized = normalizeLegacyPath2(pathValue);
109559
+ if (!normalized || hasPathTraversal2(normalized) || isAbsoluteLike3(normalized))
109560
+ return null;
109561
+ const resolvedBase = resolve45(baseDir);
109562
+ const resolvedTarget = resolve45(resolvedBase, normalized);
109563
+ const relativePath = normalizeLegacyPath2(relative31(resolvedBase, resolvedTarget));
109564
+ if (!relativePath || relativePath === ".." || relativePath.startsWith("../"))
109565
+ return null;
109566
+ if (isAbsoluteLike3(relativePath))
109567
+ return null;
109568
+ return resolvedTarget;
109569
+ }
109570
+ function hasPathTraversal2(pathValue) {
109571
+ return pathValue.split("/").some((segment) => segment === "..");
109572
+ }
109573
+ function isAbsoluteLike3(pathValue) {
109574
+ return pathValue.startsWith("/") || pathValue.startsWith("//") || /^[A-Za-z]:/.test(pathValue);
109575
+ }
109576
+ function normalizeLegacyPath2(pathValue) {
109577
+ return pathValue.replace(/\\/g, "/");
109578
+ }
109579
+ function compareLegacyPaths(a3, b3) {
109580
+ const normalizedA = normalizeLegacyPath2(a3);
109581
+ const normalizedB = normalizeLegacyPath2(b3);
109582
+ if (normalizedA < normalizedB)
109583
+ return -1;
109584
+ if (normalizedA > normalizedB)
109585
+ return 1;
109586
+ return 0;
109587
+ }
109323
109588
  function collectTrackedFiles2(meta) {
109324
109589
  if (!isRecord3(meta))
109325
109590
  return [];
@@ -109330,7 +109595,11 @@ function collectTrackedFiles2(meta) {
109330
109595
  for (const f3 of arr) {
109331
109596
  if (isRecord3(f3) && typeof f3.path === "string") {
109332
109597
  const ownership = f3.ownership === "user" || f3.ownership === "ck-modified" ? f3.ownership : "ck";
109333
- out.push({ path: f3.path, ownership });
109598
+ out.push({
109599
+ path: f3.path,
109600
+ ownership,
109601
+ checksum: typeof f3.checksum === "string" ? f3.checksum : undefined
109602
+ });
109334
109603
  }
109335
109604
  }
109336
109605
  };
@@ -109359,10 +109628,86 @@ function readJsonSafe3(filePath) {
109359
109628
  return null;
109360
109629
  }
109361
109630
  }
109631
+ async function installPlugin(installer, pluginSourceDir) {
109632
+ const added = await installer.marketplaceAdd(pluginSourceDir);
109633
+ if (!added.ok) {
109634
+ return { ok: false, error: `marketplace add failed: ${added.stderr.trim()}` };
109635
+ }
109636
+ const installed = await installer.install("user");
109637
+ if (!installed.ok) {
109638
+ return { ok: false, error: `plugin install failed: ${installed.stderr.trim()}` };
109639
+ }
109640
+ return { ok: true };
109641
+ }
109642
+ async function refreshExistingPlugin(installer, pluginSourceDir, enabled) {
109643
+ const added = await installer.marketplaceAdd(pluginSourceDir);
109644
+ if (!added.ok) {
109645
+ const updatedMarketplace = await installer.marketplaceUpdate();
109646
+ if (!updatedMarketplace.ok) {
109647
+ return {
109648
+ ok: false,
109649
+ error: `marketplace refresh failed: ${updatedMarketplace.stderr.trim() || added.stderr.trim()}`
109650
+ };
109651
+ }
109652
+ }
109653
+ if (!enabled) {
109654
+ const enabledResult = await installer.enable();
109655
+ if (!enabledResult.ok) {
109656
+ return { ok: false, error: `plugin enable failed: ${enabledResult.stderr.trim()}` };
109657
+ }
109658
+ }
109659
+ const updated = await installer.update();
109660
+ if (!updated.ok) {
109661
+ return { ok: false, error: `plugin update failed: ${updated.stderr.trim()}` };
109662
+ }
109663
+ return { ok: true };
109664
+ }
109362
109665
  function isRecord3(value) {
109363
109666
  return typeof value === "object" && value !== null && !Array.isArray(value);
109364
109667
  }
109365
109668
 
109669
+ // src/domains/installation/plugin/uninstall-plugin.ts
109670
+ init_install_mode_detector();
109671
+ import { existsSync as existsSync69, rmSync as rmSync4 } from "node:fs";
109672
+ import { join as join136 } from "node:path";
109673
+ init_path_resolver();
109674
+ async function uninstallEnginePlugin(opts = {}) {
109675
+ const claudeDir3 = opts.claudeDir ?? PathResolver.getGlobalKitDir();
109676
+ const installer = opts.installer ?? new PluginInstaller(undefined, claudeDir3);
109677
+ const state = detectPluginState(claudeDir3);
109678
+ let uninstalled = false;
109679
+ const errors2 = [];
109680
+ if (state.installed) {
109681
+ const removed = await installer.uninstall();
109682
+ if (removed.ok) {
109683
+ uninstalled = true;
109684
+ } else {
109685
+ errors2.push(`plugin uninstall failed: ${removed.stderr.trim() || "unknown error"}`);
109686
+ }
109687
+ const marketplaceRemoved = await installer.marketplaceRemove(state.marketplace ?? CK_MARKETPLACE_NAME);
109688
+ if (!marketplaceRemoved.ok) {
109689
+ errors2.push(`marketplace remove failed: ${marketplaceRemoved.stderr.trim() || "unknown error"}`);
109690
+ }
109691
+ }
109692
+ let staleCacheRemoved = false;
109693
+ const marketplace = state.marketplace ?? CK_MARKETPLACE_NAME;
109694
+ const cacheDir = join136(claudeDir3, "plugins", "cache", marketplace, CK_PLUGIN_NAME);
109695
+ if (existsSync69(cacheDir)) {
109696
+ rmSync4(cacheDir, { recursive: true, force: true });
109697
+ staleCacheRemoved = true;
109698
+ }
109699
+ const pluginStillInstalled = state.installed ? detectPluginState(claudeDir3).installed : false;
109700
+ if (pluginStillInstalled) {
109701
+ errors2.push("plugin remains registered after cleanup");
109702
+ }
109703
+ return {
109704
+ uninstalled,
109705
+ staleCacheRemoved,
109706
+ pluginStillInstalled,
109707
+ error: errors2.length > 0 ? errors2.join("; ") : undefined
109708
+ };
109709
+ }
109710
+
109366
109711
  // src/commands/init/phases/plugin-install-handler.ts
109367
109712
  init_logger();
109368
109713
  init_path_resolver();
@@ -109373,12 +109718,43 @@ async function handlePluginInstall(ctx, deps = {}) {
109373
109718
  }
109374
109719
  const migrate = deps.migrate ?? migrateLegacyToPlugin;
109375
109720
  const installCodex = deps.installCodex ?? installCodexPlugin;
109721
+ const uninstallClaude = deps.uninstallClaudePlugin ?? uninstallEnginePlugin;
109722
+ const removeCodex = deps.removeCodexPlugin ?? removeCodexPlugin;
109723
+ if (ctx.options.installMode === "legacy") {
109724
+ let cleanupError = null;
109725
+ try {
109726
+ const result = await uninstallClaude({ claudeDir: ctx.claudeDir });
109727
+ logLegacyPluginCleanup(result);
109728
+ if (result.pluginStillInstalled) {
109729
+ cleanupError = new Error(`Claude plugin cleanup failed for legacy install mode: ${result.error ?? "plugin remains registered"}`);
109730
+ }
109731
+ } catch (err) {
109732
+ logger.verbose(`Claude plugin cleanup skipped: ${err.message}`);
109733
+ cleanupError = err;
109734
+ }
109735
+ try {
109736
+ const result = await removeCodex();
109737
+ logCodexPluginCleanup(result);
109738
+ } catch (err) {
109739
+ logger.verbose(`Codex plugin cleanup skipped: ${err.message}`);
109740
+ }
109741
+ if (cleanupError) {
109742
+ throw cleanupError;
109743
+ }
109744
+ return ctx;
109745
+ }
109376
109746
  try {
109377
109747
  const pluginSourceDir = stagePluginSource(ctx.extractDir, deps.stageBaseDir);
109378
109748
  try {
109379
109749
  const result = await migrate({ pluginSourceDir, claudeDir: ctx.claudeDir });
109380
109750
  logPluginResult(result);
109751
+ if (ctx.options.installMode === "plugin" && !result.pluginVerified) {
109752
+ throw new Error(`Claude plugin install failed: ${result.error ?? result.action}`);
109753
+ }
109381
109754
  } catch (err) {
109755
+ if (ctx.options.installMode === "plugin") {
109756
+ throw err;
109757
+ }
109382
109758
  logger.verbose(`Claude plugin install skipped (legacy copy retained): ${err.message}`);
109383
109759
  }
109384
109760
  try {
@@ -109388,19 +109764,29 @@ async function handlePluginInstall(ctx, deps = {}) {
109388
109764
  logger.verbose(`Codex plugin install skipped: ${err.message}`);
109389
109765
  }
109390
109766
  } catch (err) {
109767
+ if (ctx.options.installMode === "plugin") {
109768
+ throw err;
109769
+ }
109391
109770
  logger.verbose(`Plugin staging skipped (legacy copy retained): ${err.message}`);
109392
109771
  }
109393
109772
  return ctx;
109394
109773
  }
109774
+ function logLegacyPluginCleanup(result) {
109775
+ if (result.uninstalled || result.staleCacheRemoved) {
109776
+ logger.info("Removed ClaudeKit Engineer plugin state for legacy install mode.");
109777
+ } else {
109778
+ logger.verbose("No ClaudeKit Engineer Claude plugin state found for legacy install mode.");
109779
+ }
109780
+ }
109395
109781
  function stagePluginSource(extractDir, stageBaseDir) {
109396
- const base2 = stageBaseDir ?? join136(PathResolver.getCacheDir(true), "ck-plugin-source");
109397
- const payloadSrc = join136(extractDir, ".claude");
109398
- if (!existsSync69(payloadSrc)) {
109782
+ const base2 = stageBaseDir ?? join137(PathResolver.getCacheDir(true), "ck-plugin-source");
109783
+ const payloadSrc = join137(extractDir, ".claude");
109784
+ if (!existsSync70(payloadSrc)) {
109399
109785
  throw new Error(`plugin payload not found in archive: ${payloadSrc}`);
109400
109786
  }
109401
- rmSync4(base2, { recursive: true, force: true });
109787
+ rmSync5(base2, { recursive: true, force: true });
109402
109788
  mkdirSync6(base2, { recursive: true });
109403
- const stagedPayload = join136(base2, ".claude");
109789
+ const stagedPayload = join137(base2, ".claude");
109404
109790
  cpSync2(payloadSrc, stagedPayload, { recursive: true });
109405
109791
  ensureCodexPluginManifest(stagedPayload);
109406
109792
  const claudeMarketplace = {
@@ -109408,8 +109794,8 @@ function stagePluginSource(extractDir, stageBaseDir) {
109408
109794
  owner: { name: "ClaudeKit" },
109409
109795
  plugins: [{ name: "ck", source: "./.claude", description: "ClaudeKit Engineer" }]
109410
109796
  };
109411
- mkdirSync6(join136(base2, ".claude-plugin"), { recursive: true });
109412
- writeFileSync8(join136(base2, ".claude-plugin", "marketplace.json"), `${JSON.stringify(claudeMarketplace, null, 2)}
109797
+ mkdirSync6(join137(base2, ".claude-plugin"), { recursive: true });
109798
+ writeFileSync8(join137(base2, ".claude-plugin", "marketplace.json"), `${JSON.stringify(claudeMarketplace, null, 2)}
109413
109799
  `, "utf-8");
109414
109800
  const codexMarketplace = {
109415
109801
  name: "claudekit",
@@ -109423,16 +109809,16 @@ function stagePluginSource(extractDir, stageBaseDir) {
109423
109809
  }
109424
109810
  ]
109425
109811
  };
109426
- mkdirSync6(join136(base2, ".agents", "plugins"), { recursive: true });
109427
- writeFileSync8(join136(base2, ".agents", "plugins", "marketplace.json"), `${JSON.stringify(codexMarketplace, null, 2)}
109812
+ mkdirSync6(join137(base2, ".agents", "plugins"), { recursive: true });
109813
+ writeFileSync8(join137(base2, ".agents", "plugins", "marketplace.json"), `${JSON.stringify(codexMarketplace, null, 2)}
109428
109814
  `, "utf-8");
109429
109815
  return base2;
109430
109816
  }
109431
109817
  function ensureCodexPluginManifest(pluginRoot) {
109432
- const manifestPath = join136(pluginRoot, ".codex-plugin", "plugin.json");
109433
- if (existsSync69(manifestPath))
109818
+ const manifestPath = join137(pluginRoot, ".codex-plugin", "plugin.json");
109819
+ if (existsSync70(manifestPath))
109434
109820
  return;
109435
- const claudeManifest = readJsonSafe4(join136(pluginRoot, ".claude-plugin", "plugin.json"));
109821
+ const claudeManifest = readJsonSafe4(join137(pluginRoot, ".claude-plugin", "plugin.json"));
109436
109822
  const manifest = pruneUndefined({
109437
109823
  name: stringField(claudeManifest, "name") ?? "ck",
109438
109824
  version: stringField(claudeManifest, "version") ?? "0.0.0",
@@ -109453,7 +109839,7 @@ function ensureCodexPluginManifest(pluginRoot) {
109453
109839
  websiteURL: "https://github.com/claudekit/claudekit-engineer"
109454
109840
  }
109455
109841
  });
109456
- mkdirSync6(join136(pluginRoot, ".codex-plugin"), { recursive: true });
109842
+ mkdirSync6(join137(pluginRoot, ".codex-plugin"), { recursive: true });
109457
109843
  writeFileSync8(manifestPath, `${JSON.stringify(manifest, null, 2)}
109458
109844
  `, "utf-8");
109459
109845
  }
@@ -109514,11 +109900,18 @@ function logCodexPluginResult(result) {
109514
109900
  break;
109515
109901
  }
109516
109902
  }
109903
+ function logCodexPluginCleanup(result) {
109904
+ if (result.removed || result.marketplaceRemoved) {
109905
+ logger.info("Removed ClaudeKit Engineer Codex plugin state for legacy install mode.");
109906
+ } else {
109907
+ logger.verbose("No ClaudeKit Engineer Codex plugin state found for legacy install mode.");
109908
+ }
109909
+ }
109517
109910
  // src/commands/init/phases/selection-handler.ts
109518
109911
  init_config_manager();
109519
109912
  init_github_client();
109520
109913
  import { mkdir as mkdir36 } from "node:fs/promises";
109521
- import { join as join139, resolve as resolve46 } from "node:path";
109914
+ import { join as join140, resolve as resolve48 } from "node:path";
109522
109915
 
109523
109916
  // src/domains/github/kit-access-checker.ts
109524
109917
  init_error2();
@@ -109690,8 +110083,8 @@ init_hook_health_checker();
109690
110083
 
109691
110084
  // src/domains/installation/fresh-installer.ts
109692
110085
  init_metadata_migration();
109693
- import { existsSync as existsSync70, readdirSync as readdirSync11, rmSync as rmSync5, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
109694
- import { basename as basename28, dirname as dirname44, join as join137, resolve as resolve44 } from "node:path";
110086
+ import { existsSync as existsSync71, readdirSync as readdirSync12, rmSync as rmSync6, rmdirSync as rmdirSync2, unlinkSync as unlinkSync5 } from "node:fs";
110087
+ import { basename as basename28, dirname as dirname44, join as join138, resolve as resolve46 } from "node:path";
109695
110088
  init_logger();
109696
110089
  init_safe_spinner();
109697
110090
  var import_fs_extra35 = __toESM(require_lib(), 1);
@@ -109743,15 +110136,15 @@ async function analyzeFreshInstallation(claudeDir3) {
109743
110136
  };
109744
110137
  }
109745
110138
  function cleanupEmptyDirectories2(filePath, claudeDir3) {
109746
- const normalizedClaudeDir = resolve44(claudeDir3);
109747
- let currentDir = resolve44(dirname44(filePath));
110139
+ const normalizedClaudeDir = resolve46(claudeDir3);
110140
+ let currentDir = resolve46(dirname44(filePath));
109748
110141
  while (currentDir !== normalizedClaudeDir && currentDir.startsWith(normalizedClaudeDir)) {
109749
110142
  try {
109750
- const entries = readdirSync11(currentDir);
110143
+ const entries = readdirSync12(currentDir);
109751
110144
  if (entries.length === 0) {
109752
110145
  rmdirSync2(currentDir);
109753
110146
  logger.debug(`Removed empty directory: ${currentDir}`);
109754
- currentDir = resolve44(dirname44(currentDir));
110147
+ currentDir = resolve46(dirname44(currentDir));
109755
110148
  } else {
109756
110149
  break;
109757
110150
  }
@@ -109773,8 +110166,8 @@ async function removeFilesByOwnership(claudeDir3, analysis, includeModified) {
109773
110166
  logger.debug(`${KIT_MANIFEST_FILE} was self-tracked; skipping from delete loop — will be rewritten by updateMetadataAfterFresh`);
109774
110167
  }
109775
110168
  for (const file of filesToRemove) {
109776
- const fullPath = join137(claudeDir3, file.path);
109777
- if (!existsSync70(fullPath)) {
110169
+ const fullPath = join138(claudeDir3, file.path);
110170
+ if (!existsSync71(fullPath)) {
109778
110171
  continue;
109779
110172
  }
109780
110173
  try {
@@ -109801,7 +110194,7 @@ async function removeFilesByOwnership(claudeDir3, analysis, includeModified) {
109801
110194
  };
109802
110195
  }
109803
110196
  async function updateMetadataAfterFresh(claudeDir3, removedFiles, metadata) {
109804
- const metadataPath = join137(claudeDir3, KIT_MANIFEST_FILE);
110197
+ const metadataPath = join138(claudeDir3, KIT_MANIFEST_FILE);
109805
110198
  const removedSet = new Set(removedFiles);
109806
110199
  if (metadata.kits) {
109807
110200
  for (const kitName of Object.keys(metadata.kits)) {
@@ -109832,8 +110225,8 @@ function getFreshBackupTargets(claudeDir3, analysis, includeModified) {
109832
110225
  mutatePaths: filesToRemove.length > 0 ? ["metadata.json"] : []
109833
110226
  };
109834
110227
  }
109835
- const deletePaths = CLAUDEKIT_SUBDIRECTORIES.filter((subdir) => existsSync70(join137(claudeDir3, subdir)));
109836
- if (existsSync70(join137(claudeDir3, "metadata.json"))) {
110228
+ const deletePaths = CLAUDEKIT_SUBDIRECTORIES.filter((subdir) => existsSync71(join138(claudeDir3, subdir)));
110229
+ if (existsSync71(join138(claudeDir3, "metadata.json"))) {
109837
110230
  deletePaths.push("metadata.json");
109838
110231
  }
109839
110232
  return {
@@ -109855,15 +110248,15 @@ async function removeSubdirectoriesFallback(claudeDir3) {
109855
110248
  const removedFiles = [];
109856
110249
  let removedDirCount = 0;
109857
110250
  for (const subdir of CLAUDEKIT_SUBDIRECTORIES) {
109858
- const subdirPath = join137(claudeDir3, subdir);
110251
+ const subdirPath = join138(claudeDir3, subdir);
109859
110252
  if (await import_fs_extra35.pathExists(subdirPath)) {
109860
- rmSync5(subdirPath, { recursive: true, force: true });
110253
+ rmSync6(subdirPath, { recursive: true, force: true });
109861
110254
  removedDirCount++;
109862
110255
  removedFiles.push(`${subdir}/ (entire directory)`);
109863
110256
  logger.debug(`Removed subdirectory: ${subdir}/`);
109864
110257
  }
109865
110258
  }
109866
- const metadataPath = join137(claudeDir3, "metadata.json");
110259
+ const metadataPath = join138(claudeDir3, "metadata.json");
109867
110260
  if (await import_fs_extra35.pathExists(metadataPath)) {
109868
110261
  unlinkSync5(metadataPath);
109869
110262
  removedFiles.push("metadata.json");
@@ -109941,7 +110334,7 @@ async function handleFreshInstallation(claudeDir3, prompts) {
109941
110334
  var import_fs_extra36 = __toESM(require_lib(), 1);
109942
110335
  import { cp as cp5, mkdir as mkdir35, readdir as readdir42, rename as rename11, rm as rm16, stat as stat22 } from "node:fs/promises";
109943
110336
  import { homedir as homedir47 } from "node:os";
109944
- import { dirname as dirname45, join as join138, normalize as normalize11, resolve as resolve45 } from "node:path";
110337
+ import { dirname as dirname45, join as join139, normalize as normalize11, resolve as resolve47 } from "node:path";
109945
110338
  var LEGACY_KIT_MARKERS = [
109946
110339
  "metadata.json",
109947
110340
  ".ck.json",
@@ -109967,7 +110360,7 @@ function uniqueNormalizedPaths(paths) {
109967
110360
  const seen = new Set;
109968
110361
  const result = [];
109969
110362
  for (const path17 of paths) {
109970
- const normalized = normalize11(resolve45(path17));
110363
+ const normalized = normalize11(resolve47(path17));
109971
110364
  if (seen.has(normalized))
109972
110365
  continue;
109973
110366
  seen.add(normalized);
@@ -109980,10 +110373,10 @@ function getLegacyWindowsGlobalKitDirCandidates(env2 = process.env, homeDir = ho
109980
110373
  const localAppData = safeEnvPath(env2.LOCALAPPDATA);
109981
110374
  const appData = safeEnvPath(env2.APPDATA);
109982
110375
  if (localAppData) {
109983
- candidates.push(join138(localAppData, ".claude"));
110376
+ candidates.push(join139(localAppData, ".claude"));
109984
110377
  }
109985
110378
  if (appData) {
109986
- candidates.push(join138(appData, ".claude"));
110379
+ candidates.push(join139(appData, ".claude"));
109987
110380
  }
109988
110381
  if (homeDir) {
109989
110382
  candidates.push(`${withoutTrailingSeparators(homeDir)}.claude`);
@@ -110001,7 +110394,7 @@ async function hasKitMarkers(dir) {
110001
110394
  if (!await isDirectory(dir))
110002
110395
  return false;
110003
110396
  for (const marker of LEGACY_KIT_MARKERS) {
110004
- if (await import_fs_extra36.pathExists(join138(dir, marker))) {
110397
+ if (await import_fs_extra36.pathExists(join139(dir, marker))) {
110005
110398
  return true;
110006
110399
  }
110007
110400
  }
@@ -110032,8 +110425,8 @@ async function repairLegacyWindowsGlobalKitDir(options2) {
110032
110425
  if (safeEnvPath(env2.CLAUDE_CONFIG_DIR)) {
110033
110426
  return { status: "skipped", reason: "custom-global-dir", candidateDirs: [] };
110034
110427
  }
110035
- const targetDir = normalize11(resolve45(options2.targetDir));
110036
- const candidateDirs = getLegacyWindowsGlobalKitDirCandidates(env2, options2.homeDir).filter((candidate) => normalize11(resolve45(candidate)) !== targetDir);
110428
+ const targetDir = normalize11(resolve47(options2.targetDir));
110429
+ const candidateDirs = getLegacyWindowsGlobalKitDirCandidates(env2, options2.homeDir).filter((candidate) => normalize11(resolve47(candidate)) !== targetDir);
110037
110430
  const legacyDirs = [];
110038
110431
  for (const candidate of candidateDirs) {
110039
110432
  if (await hasKitMarkers(candidate)) {
@@ -110256,7 +110649,7 @@ async function handleSelection(ctx) {
110256
110649
  }
110257
110650
  }
110258
110651
  }
110259
- const resolvedDir = resolve46(targetDir);
110652
+ const resolvedDir = resolve48(targetDir);
110260
110653
  if (ctx.options.global) {
110261
110654
  try {
110262
110655
  const repairResult = await repairLegacyWindowsGlobalKitDir({ targetDir: resolvedDir });
@@ -110303,7 +110696,7 @@ async function handleSelection(ctx) {
110303
110696
  }
110304
110697
  if (!ctx.options.fresh) {
110305
110698
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
110306
- const claudeDir3 = prefix ? join139(resolvedDir, prefix) : resolvedDir;
110699
+ const claudeDir3 = prefix ? join140(resolvedDir, prefix) : resolvedDir;
110307
110700
  try {
110308
110701
  const existingMetadata = await readManifest(claudeDir3);
110309
110702
  if (existingMetadata?.kits) {
@@ -110340,7 +110733,7 @@ async function handleSelection(ctx) {
110340
110733
  }
110341
110734
  if (ctx.options.fresh) {
110342
110735
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
110343
- const claudeDir3 = prefix ? join139(resolvedDir, prefix) : resolvedDir;
110736
+ const claudeDir3 = prefix ? join140(resolvedDir, prefix) : resolvedDir;
110344
110737
  const canProceed = await handleFreshInstallation(claudeDir3, ctx.prompts);
110345
110738
  if (!canProceed) {
110346
110739
  return { ...ctx, cancelled: true };
@@ -110360,7 +110753,7 @@ async function handleSelection(ctx) {
110360
110753
  let currentVersion = null;
110361
110754
  try {
110362
110755
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
110363
- const claudeDir3 = prefix ? join139(resolvedDir, prefix) : resolvedDir;
110756
+ const claudeDir3 = prefix ? join140(resolvedDir, prefix) : resolvedDir;
110364
110757
  const existingMetadata = await readManifest(claudeDir3);
110365
110758
  currentVersion = existingMetadata?.kits?.[kitType]?.version || null;
110366
110759
  if (currentVersion) {
@@ -110429,7 +110822,7 @@ async function handleSelection(ctx) {
110429
110822
  if (ctx.options.yes && !ctx.options.fresh && !ctx.options.force && !ctx.options.restoreCkHooks && releaseTag && !isOfflineMode && !pendingKits?.length) {
110430
110823
  try {
110431
110824
  const prefix = PathResolver.getPathPrefix(ctx.options.global);
110432
- const claudeDir3 = prefix ? join139(resolvedDir, prefix) : resolvedDir;
110825
+ const claudeDir3 = prefix ? join140(resolvedDir, prefix) : resolvedDir;
110433
110826
  const existingMetadata = await readManifest(claudeDir3);
110434
110827
  const installedKitVersion = existingMetadata?.kits?.[kitType]?.version;
110435
110828
  if (installedKitVersion && versionsMatch(installedKitVersion, releaseTag)) {
@@ -110458,7 +110851,7 @@ async function handleSelection(ctx) {
110458
110851
  }
110459
110852
  // src/commands/init/phases/sync-handler.ts
110460
110853
  import { copyFile as copyFile8, mkdir as mkdir37, open as open5, readFile as readFile61, rename as rename12, stat as stat23, unlink as unlink13, writeFile as writeFile35 } from "node:fs/promises";
110461
- import { dirname as dirname46, join as join140, resolve as resolve47 } from "node:path";
110854
+ import { dirname as dirname46, join as join141, resolve as resolve49 } from "node:path";
110462
110855
  init_logger();
110463
110856
  init_path_resolver();
110464
110857
  var import_fs_extra38 = __toESM(require_lib(), 1);
@@ -110467,14 +110860,14 @@ async function handleSync(ctx) {
110467
110860
  if (!ctx.options.sync) {
110468
110861
  return ctx;
110469
110862
  }
110470
- const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve47(ctx.options.dir || ".");
110471
- const claudeDir3 = ctx.options.global ? resolvedDir : join140(resolvedDir, ".claude");
110863
+ const resolvedDir = ctx.options.global ? PathResolver.getGlobalKitDir() : resolve49(ctx.options.dir || ".");
110864
+ const claudeDir3 = ctx.options.global ? resolvedDir : join141(resolvedDir, ".claude");
110472
110865
  if (!await import_fs_extra38.pathExists(claudeDir3)) {
110473
110866
  logger.error("Cannot sync: no .claude directory found");
110474
110867
  ctx.prompts.note("Run 'ck init' without --sync to install first.", "No Installation Found");
110475
110868
  return { ...ctx, cancelled: true };
110476
110869
  }
110477
- const metadataPath = join140(claudeDir3, "metadata.json");
110870
+ const metadataPath = join141(claudeDir3, "metadata.json");
110478
110871
  if (!await import_fs_extra38.pathExists(metadataPath)) {
110479
110872
  logger.error("Cannot sync: no metadata.json found");
110480
110873
  ctx.prompts.note(`Your installation may be from an older version.
@@ -110574,7 +110967,7 @@ function getLockTimeout() {
110574
110967
  var STALE_LOCK_THRESHOLD_MS = 5 * 60 * 1000;
110575
110968
  async function acquireSyncLock(global3) {
110576
110969
  const cacheDir = PathResolver.getCacheDir(global3);
110577
- const lockPath = join140(cacheDir, ".sync-lock");
110970
+ const lockPath = join141(cacheDir, ".sync-lock");
110578
110971
  const startTime = Date.now();
110579
110972
  const lockTimeout = getLockTimeout();
110580
110973
  await mkdir37(dirname46(lockPath), { recursive: true });
@@ -110601,7 +110994,7 @@ async function acquireSyncLock(global3) {
110601
110994
  }
110602
110995
  logger.debug(`Lock stat failed: ${statError}`);
110603
110996
  }
110604
- await new Promise((resolve48) => setTimeout(resolve48, 100));
110997
+ await new Promise((resolve50) => setTimeout(resolve50, 100));
110605
110998
  continue;
110606
110999
  }
110607
111000
  throw err;
@@ -110620,11 +111013,11 @@ async function executeSyncMerge(ctx) {
110620
111013
  const releaseLock = await acquireSyncLock(ctx.options.global);
110621
111014
  try {
110622
111015
  const trackedFiles = ctx.syncTrackedFiles;
110623
- const upstreamDir = ctx.options.global ? join140(ctx.extractDir, ".claude") : ctx.extractDir;
111016
+ const upstreamDir = ctx.options.global ? join141(ctx.extractDir, ".claude") : ctx.extractDir;
110624
111017
  let sourceMetadata = null;
110625
111018
  let deletions = [];
110626
111019
  try {
110627
- const sourceMetadataPath = join140(upstreamDir, "metadata.json");
111020
+ const sourceMetadataPath = join141(upstreamDir, "metadata.json");
110628
111021
  if (await import_fs_extra38.pathExists(sourceMetadataPath)) {
110629
111022
  const content = await readFile61(sourceMetadataPath, "utf-8");
110630
111023
  sourceMetadata = JSON.parse(content);
@@ -110686,7 +111079,7 @@ async function executeSyncMerge(ctx) {
110686
111079
  try {
110687
111080
  const sourcePath = await validateSyncPath(upstreamDir, file.path);
110688
111081
  const targetPath = await validateSyncPath(ctx.claudeDir, file.path);
110689
- const targetDir = join140(targetPath, "..");
111082
+ const targetDir = join141(targetPath, "..");
110690
111083
  try {
110691
111084
  await mkdir37(targetDir, { recursive: true });
110692
111085
  } catch (mkdirError) {
@@ -110857,7 +111250,7 @@ async function createBackup(claudeDir3, files, backupDir) {
110857
111250
  const sourcePath = await validateSyncPath(claudeDir3, file.path);
110858
111251
  if (await import_fs_extra38.pathExists(sourcePath)) {
110859
111252
  const targetPath = await validateSyncPath(backupDir, file.path);
110860
- const targetDir = join140(targetPath, "..");
111253
+ const targetDir = join141(targetPath, "..");
110861
111254
  await mkdir37(targetDir, { recursive: true });
110862
111255
  await copyFile8(sourcePath, targetPath);
110863
111256
  }
@@ -110872,7 +111265,7 @@ async function createBackup(claudeDir3, files, backupDir) {
110872
111265
  }
110873
111266
  // src/commands/init/phases/transform-handler.ts
110874
111267
  init_config_manager();
110875
- import { join as join144 } from "node:path";
111268
+ import { join as join145 } from "node:path";
110876
111269
 
110877
111270
  // src/services/transformers/folder-path-transformer.ts
110878
111271
  init_logger();
@@ -110883,38 +111276,38 @@ init_logger();
110883
111276
  init_types3();
110884
111277
  var import_fs_extra39 = __toESM(require_lib(), 1);
110885
111278
  import { rename as rename13, rm as rm17 } from "node:fs/promises";
110886
- import { join as join141, relative as relative30 } from "node:path";
111279
+ import { join as join142, relative as relative32 } from "node:path";
110887
111280
  async function collectDirsToRename(extractDir, folders) {
110888
111281
  const dirsToRename = [];
110889
111282
  if (folders.docs !== DEFAULT_FOLDERS.docs) {
110890
- const docsPath = join141(extractDir, DEFAULT_FOLDERS.docs);
111283
+ const docsPath = join142(extractDir, DEFAULT_FOLDERS.docs);
110891
111284
  if (await import_fs_extra39.pathExists(docsPath)) {
110892
111285
  dirsToRename.push({
110893
111286
  from: docsPath,
110894
- to: join141(extractDir, folders.docs)
111287
+ to: join142(extractDir, folders.docs)
110895
111288
  });
110896
111289
  }
110897
- const claudeDocsPath = join141(extractDir, ".claude", DEFAULT_FOLDERS.docs);
111290
+ const claudeDocsPath = join142(extractDir, ".claude", DEFAULT_FOLDERS.docs);
110898
111291
  if (await import_fs_extra39.pathExists(claudeDocsPath)) {
110899
111292
  dirsToRename.push({
110900
111293
  from: claudeDocsPath,
110901
- to: join141(extractDir, ".claude", folders.docs)
111294
+ to: join142(extractDir, ".claude", folders.docs)
110902
111295
  });
110903
111296
  }
110904
111297
  }
110905
111298
  if (folders.plans !== DEFAULT_FOLDERS.plans) {
110906
- const plansPath = join141(extractDir, DEFAULT_FOLDERS.plans);
111299
+ const plansPath = join142(extractDir, DEFAULT_FOLDERS.plans);
110907
111300
  if (await import_fs_extra39.pathExists(plansPath)) {
110908
111301
  dirsToRename.push({
110909
111302
  from: plansPath,
110910
- to: join141(extractDir, folders.plans)
111303
+ to: join142(extractDir, folders.plans)
110911
111304
  });
110912
111305
  }
110913
- const claudePlansPath = join141(extractDir, ".claude", DEFAULT_FOLDERS.plans);
111306
+ const claudePlansPath = join142(extractDir, ".claude", DEFAULT_FOLDERS.plans);
110914
111307
  if (await import_fs_extra39.pathExists(claudePlansPath)) {
110915
111308
  dirsToRename.push({
110916
111309
  from: claudePlansPath,
110917
- to: join141(extractDir, ".claude", folders.plans)
111310
+ to: join142(extractDir, ".claude", folders.plans)
110918
111311
  });
110919
111312
  }
110920
111313
  }
@@ -110937,11 +111330,11 @@ async function renameFolders(dirsToRename, extractDir, options2) {
110937
111330
  let foldersRenamed = 0;
110938
111331
  for (const { from, to } of dirsToRename) {
110939
111332
  if (options2.dryRun) {
110940
- logger.info(`[dry-run] Would rename: ${relative30(extractDir, from)} -> ${relative30(extractDir, to)}`);
111333
+ logger.info(`[dry-run] Would rename: ${relative32(extractDir, from)} -> ${relative32(extractDir, to)}`);
110941
111334
  } else {
110942
111335
  try {
110943
111336
  await moveAcrossDevices(from, to);
110944
- logger.debug(`Renamed: ${relative30(extractDir, from)} -> ${relative30(extractDir, to)}`);
111337
+ logger.debug(`Renamed: ${relative32(extractDir, from)} -> ${relative32(extractDir, to)}`);
110945
111338
  foldersRenamed++;
110946
111339
  } catch (error) {
110947
111340
  logger.warning(`Failed to rename ${from}: ${error instanceof Error ? error.message : "Unknown error"}`);
@@ -110955,7 +111348,7 @@ async function renameFolders(dirsToRename, extractDir, options2) {
110955
111348
  init_logger();
110956
111349
  init_types3();
110957
111350
  import { readFile as readFile62, readdir as readdir43, writeFile as writeFile36 } from "node:fs/promises";
110958
- import { join as join142, relative as relative31 } from "node:path";
111351
+ import { join as join143, relative as relative33 } from "node:path";
110959
111352
  var TRANSFORMABLE_FILE_PATTERNS = [
110960
111353
  ".md",
110961
111354
  ".txt",
@@ -111008,7 +111401,7 @@ async function transformFileContents(dir, compiledReplacements, options2) {
111008
111401
  let replacementsCount = 0;
111009
111402
  const entries = await readdir43(dir, { withFileTypes: true });
111010
111403
  for (const entry of entries) {
111011
- const fullPath = join142(dir, entry.name);
111404
+ const fullPath = join143(dir, entry.name);
111012
111405
  if (entry.isDirectory()) {
111013
111406
  if (entry.name === "node_modules" || entry.name === ".git") {
111014
111407
  continue;
@@ -111035,10 +111428,10 @@ async function transformFileContents(dir, compiledReplacements, options2) {
111035
111428
  }
111036
111429
  if (changeCount > 0) {
111037
111430
  if (options2.dryRun) {
111038
- logger.debug(`[dry-run] Would update ${relative31(dir, fullPath)}: ${changeCount} replacement(s)`);
111431
+ logger.debug(`[dry-run] Would update ${relative33(dir, fullPath)}: ${changeCount} replacement(s)`);
111039
111432
  } else {
111040
111433
  await writeFile36(fullPath, newContent, "utf-8");
111041
- logger.debug(`Updated ${relative31(dir, fullPath)}: ${changeCount} replacement(s)`);
111434
+ logger.debug(`Updated ${relative33(dir, fullPath)}: ${changeCount} replacement(s)`);
111042
111435
  }
111043
111436
  filesChanged++;
111044
111437
  replacementsCount += changeCount;
@@ -111145,7 +111538,7 @@ async function transformFolderPaths(extractDir, folders, options2 = {}) {
111145
111538
  init_logger();
111146
111539
  import { readFile as readFile63, readdir as readdir44, writeFile as writeFile37 } from "node:fs/promises";
111147
111540
  import { homedir as homedir48, platform as platform16 } from "node:os";
111148
- import { extname as extname7, join as join143 } from "node:path";
111541
+ import { extname as extname7, join as join144 } from "node:path";
111149
111542
  var IS_WINDOWS3 = platform16() === "win32";
111150
111543
  var HOME_PREFIX = "$HOME";
111151
111544
  function getHomeDirPrefix() {
@@ -111155,7 +111548,7 @@ function normalizeInstallPath(path17) {
111155
111548
  return path17.replace(/\\/g, "/").replace(/\/+$/, "");
111156
111549
  }
111157
111550
  function getDefaultGlobalClaudeDir() {
111158
- return normalizeInstallPath(join143(homedir48(), ".claude"));
111551
+ return normalizeInstallPath(join144(homedir48(), ".claude"));
111159
111552
  }
111160
111553
  function getCustomGlobalClaudeDir(targetClaudeDir) {
111161
111554
  if (!targetClaudeDir)
@@ -111286,7 +111679,7 @@ async function transformPathsForGlobalInstall(directory, options2 = {}) {
111286
111679
  async function processDirectory2(dir) {
111287
111680
  const entries = await readdir44(dir, { withFileTypes: true });
111288
111681
  for (const entry of entries) {
111289
- const fullPath = join143(dir, entry.name);
111682
+ const fullPath = join144(dir, entry.name);
111290
111683
  if (entry.isDirectory()) {
111291
111684
  if (entry.name === "node_modules" || entry.name.startsWith(".") && entry.name !== ".claude") {
111292
111685
  continue;
@@ -111365,7 +111758,7 @@ async function handleTransforms(ctx) {
111365
111758
  logger.debug(ctx.options.global ? "Saved folder configuration to ~/.claude/.ck.json" : "Saved folder configuration to .claude/.ck.json");
111366
111759
  }
111367
111760
  }
111368
- const claudeDir3 = ctx.options.global ? ctx.resolvedDir : join144(ctx.resolvedDir, ".claude");
111761
+ const claudeDir3 = ctx.options.global ? ctx.resolvedDir : join145(ctx.resolvedDir, ".claude");
111369
111762
  return {
111370
111763
  ...ctx,
111371
111764
  foldersConfig,
@@ -111441,7 +111834,8 @@ function createInitContext(rawOptions, prompts) {
111441
111834
  dryRun: false,
111442
111835
  prefix: false,
111443
111836
  sync: false,
111444
- useGit: false
111837
+ useGit: false,
111838
+ installMode: "auto"
111445
111839
  };
111446
111840
  return {
111447
111841
  rawOptions,
@@ -111589,10 +111983,10 @@ async function initCommand(options2) {
111589
111983
  // src/commands/migrate/migrate-command.ts
111590
111984
  init_dist2();
111591
111985
  var import_picocolors30 = __toESM(require_picocolors(), 1);
111592
- import { existsSync as existsSync71 } from "node:fs";
111986
+ import { existsSync as existsSync72 } from "node:fs";
111593
111987
  import { readFile as readFile67, rm as rm18, unlink as unlink14 } from "node:fs/promises";
111594
111988
  import { homedir as homedir52 } from "node:os";
111595
- import { basename as basename30, dirname as dirname49, join as join148, resolve as resolve48 } from "node:path";
111989
+ import { basename as basename30, dirname as dirname49, join as join149, resolve as resolve50 } from "node:path";
111596
111990
  init_logger();
111597
111991
 
111598
111992
  // src/ui/ck-cli-design/next-steps-footer.ts
@@ -111807,13 +112201,13 @@ init_dist2();
111807
112201
  init_model_taxonomy();
111808
112202
  import { mkdir as mkdir39, readFile as readFile66, writeFile as writeFile39 } from "node:fs/promises";
111809
112203
  import { homedir as homedir51 } from "node:os";
111810
- import { dirname as dirname47, join as join147 } from "node:path";
112204
+ import { dirname as dirname47, join as join148 } from "node:path";
111811
112205
 
111812
112206
  // src/commands/portable/models-dev-cache.ts
111813
112207
  init_logger();
111814
112208
  import { mkdir as mkdir38, readFile as readFile64, rename as rename14, writeFile as writeFile38 } from "node:fs/promises";
111815
112209
  import { homedir as homedir49 } from "node:os";
111816
- import { join as join145 } from "node:path";
112210
+ import { join as join146 } from "node:path";
111817
112211
 
111818
112212
  class ModelsDevUnavailableError extends Error {
111819
112213
  constructor(message, cause) {
@@ -111825,13 +112219,13 @@ var MODELS_DEV_URL = "https://models.dev/api.json";
111825
112219
  var CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
111826
112220
  var FETCH_TIMEOUT_MS = 1e4;
111827
112221
  function defaultCacheDir() {
111828
- return join145(homedir49(), ".config", "claudekit", "cache");
112222
+ return join146(homedir49(), ".config", "claudekit", "cache");
111829
112223
  }
111830
112224
  function cacheFilePath(cacheDir) {
111831
- return join145(cacheDir, "models-dev.json");
112225
+ return join146(cacheDir, "models-dev.json");
111832
112226
  }
111833
112227
  function tmpFilePath(cacheDir) {
111834
- return join145(cacheDir, "models-dev.json.tmp");
112228
+ return join146(cacheDir, "models-dev.json.tmp");
111835
112229
  }
111836
112230
  async function readCacheEntry(cacheDir) {
111837
112231
  const filePath = cacheFilePath(cacheDir);
@@ -111906,14 +112300,14 @@ async function getModelsDevCatalog(opts = {}) {
111906
112300
  init_logger();
111907
112301
  import { readFile as readFile65 } from "node:fs/promises";
111908
112302
  import { homedir as homedir50, platform as platform17 } from "node:os";
111909
- import { join as join146 } from "node:path";
112303
+ import { join as join147 } from "node:path";
111910
112304
  function resolveOpenCodeAuthPath(homeDir) {
111911
112305
  if (platform17() === "win32") {
111912
- const dataRoot2 = process.env.LOCALAPPDATA ?? join146(homeDir, "AppData", "Local");
111913
- return join146(dataRoot2, "opencode", "auth.json");
112306
+ const dataRoot2 = process.env.LOCALAPPDATA ?? join147(homeDir, "AppData", "Local");
112307
+ return join147(dataRoot2, "opencode", "auth.json");
111914
112308
  }
111915
- const dataRoot = process.env.XDG_DATA_HOME ?? join146(homeDir, ".local", "share");
111916
- return join146(dataRoot, "opencode", "auth.json");
112309
+ const dataRoot = process.env.XDG_DATA_HOME ?? join147(homeDir, ".local", "share");
112310
+ return join147(dataRoot, "opencode", "auth.json");
111917
112311
  }
111918
112312
  async function readAuthedProviders(homeDir) {
111919
112313
  const authPath = resolveOpenCodeAuthPath(homeDir);
@@ -112015,9 +112409,9 @@ function messageForReason(reason) {
112015
112409
  }
112016
112410
  function getOpenCodeConfigPath(options2) {
112017
112411
  if (options2.global) {
112018
- return join147(options2.homeDir ?? homedir51(), ".config", "opencode", "opencode.json");
112412
+ return join148(options2.homeDir ?? homedir51(), ".config", "opencode", "opencode.json");
112019
112413
  }
112020
- return join147(options2.cwd ?? process.cwd(), "opencode.json");
112414
+ return join148(options2.cwd ?? process.cwd(), "opencode.json");
112021
112415
  }
112022
112416
  function makeCatalogOpts(options2) {
112023
112417
  return {
@@ -112890,7 +113284,7 @@ function appendFallbackSkillActionsToPlan(plan, skills, selectedProviders, insta
112890
113284
  reason: "New item, not previously installed",
112891
113285
  reasonCode: "new-item",
112892
113286
  reasonCopy: "New - not previously installed",
112893
- targetPath: join148(basePath, skill.name),
113287
+ targetPath: join149(basePath, skill.name),
112894
113288
  type: "skill"
112895
113289
  });
112896
113290
  }
@@ -113045,9 +113439,9 @@ function shouldExecuteAction2(action) {
113045
113439
  }
113046
113440
  async function executeDeleteAction(action, options2) {
113047
113441
  const preservePaths = options2?.preservePaths ?? new Set;
113048
- const shouldPreserveTarget = action.targetPath.length > 0 && preservePaths.has(resolve48(action.targetPath));
113442
+ const shouldPreserveTarget = action.targetPath.length > 0 && preservePaths.has(resolve50(action.targetPath));
113049
113443
  try {
113050
- if (!shouldPreserveTarget && action.targetPath && existsSync71(action.targetPath)) {
113444
+ if (!shouldPreserveTarget && action.targetPath && existsSync72(action.targetPath)) {
113051
113445
  await rm18(action.targetPath, { recursive: true, force: true });
113052
113446
  }
113053
113447
  await removePortableInstallation(action.item, action.type, action.provider, action.global, action.targetPath ? { path: action.targetPath } : undefined);
@@ -113076,7 +113470,7 @@ async function executeDeleteAction(action, options2) {
113076
113470
  }
113077
113471
  }
113078
113472
  function hasSuccessfulReplacementWrite(action, results) {
113079
- return results.some((result) => result.success && !result.skipped && result.provider === action.provider && replacementTypeMatches(action.type, result.portableType) && replacementItemMatches(action, result) && result.path.length > 0 && resolve48(result.path) !== resolve48(action.targetPath));
113473
+ return results.some((result) => result.success && !result.skipped && result.provider === action.provider && replacementTypeMatches(action.type, result.portableType) && replacementItemMatches(action, result) && result.path.length > 0 && resolve50(result.path) !== resolve50(action.targetPath));
113080
113474
  }
113081
113475
  function replacementTypeMatches(actionType, resultType) {
113082
113476
  return resultType === actionType || actionType === "command" && resultType === "skill";
@@ -113118,9 +113512,9 @@ function resolveHookTargetPath(item, provider, global3) {
113118
113512
  const converted = convertItem(item, pathConfig.format, provider, { global: global3 });
113119
113513
  if (converted.error)
113120
113514
  return null;
113121
- const targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join148(basePath, converted.filename);
113122
- const resolvedTarget = resolve48(targetPath).replace(/\\/g, "/");
113123
- const resolvedBase = resolve48(basePath).replace(/\\/g, "/").replace(/\/+$/, "");
113515
+ const targetPath = pathConfig.writeStrategy === "single-file" ? basePath : join149(basePath, converted.filename);
113516
+ const resolvedTarget = resolve50(targetPath).replace(/\\/g, "/");
113517
+ const resolvedBase = resolve50(basePath).replace(/\\/g, "/").replace(/\/+$/, "");
113124
113518
  if (resolvedTarget !== resolvedBase && !resolvedTarget.startsWith(`${resolvedBase}/`)) {
113125
113519
  return null;
113126
113520
  }
@@ -113129,8 +113523,8 @@ function resolveHookTargetPath(item, provider, global3) {
113129
113523
  async function processMetadataDeletions(skillSourcePath, installGlobally) {
113130
113524
  if (!skillSourcePath)
113131
113525
  return;
113132
- const sourceMetadataPath = join148(resolve48(skillSourcePath, ".."), "metadata.json");
113133
- if (!existsSync71(sourceMetadataPath))
113526
+ const sourceMetadataPath = join149(resolve50(skillSourcePath, ".."), "metadata.json");
113527
+ if (!existsSync72(sourceMetadataPath))
113134
113528
  return;
113135
113529
  let sourceMetadata;
113136
113530
  try {
@@ -113142,8 +113536,8 @@ async function processMetadataDeletions(skillSourcePath, installGlobally) {
113142
113536
  }
113143
113537
  if (!sourceMetadata.deletions || sourceMetadata.deletions.length === 0)
113144
113538
  return;
113145
- const claudeDir3 = installGlobally ? join148(homedir52(), ".claude") : join148(process.cwd(), ".claude");
113146
- if (!existsSync71(claudeDir3))
113539
+ const claudeDir3 = installGlobally ? join149(homedir52(), ".claude") : join149(process.cwd(), ".claude");
113540
+ if (!existsSync72(claudeDir3))
113147
113541
  return;
113148
113542
  try {
113149
113543
  const result = await handleDeletions(sourceMetadata, claudeDir3, inferKitTypeFromSourceMetadata(sourceMetadata));
@@ -113270,8 +113664,8 @@ async function migrateCommand(options2) {
113270
113664
  let requestedGlobal = options2.global ?? false;
113271
113665
  let installGlobally = requestedGlobal;
113272
113666
  if (options2.global === undefined && !options2.yes) {
113273
- const projectTarget = join148(process.cwd(), ".claude");
113274
- const globalTarget = join148(homedir52(), ".claude");
113667
+ const projectTarget = join149(process.cwd(), ".claude");
113668
+ const globalTarget = join149(homedir52(), ".claude");
113275
113669
  const scopeChoice = await ie({
113276
113670
  message: "Installation scope",
113277
113671
  options: [
@@ -113344,7 +113738,7 @@ async function migrateCommand(options2) {
113344
113738
  }).join(`
113345
113739
  `));
113346
113740
  if (sourceGlobalOnly) {
113347
- f2.info(import_picocolors30.default.dim(` Scope: global (--global / -g) - reading from ${formatDisplayPath(join148(homedir52(), ".claude"))}`));
113741
+ f2.info(import_picocolors30.default.dim(` Scope: global (--global / -g) - reading from ${formatDisplayPath(join149(homedir52(), ".claude"))}`));
113348
113742
  } else {
113349
113743
  f2.info(import_picocolors30.default.dim(` CWD: ${process.cwd()}`));
113350
113744
  }
@@ -113435,7 +113829,7 @@ async function migrateCommand(options2) {
113435
113829
  const interactive = process.stdout.isTTY && !options2.yes;
113436
113830
  const conflictActions = plan.actions.filter((a3) => a3.action === "conflict");
113437
113831
  for (const action of conflictActions) {
113438
- if (!action.diff && action.targetPath && existsSync71(action.targetPath)) {
113832
+ if (!action.diff && action.targetPath && existsSync72(action.targetPath)) {
113439
113833
  try {
113440
113834
  const targetContent = await readFile67(action.targetPath, "utf-8");
113441
113835
  const sourceItem = effectiveAgents.find((a3) => a3.name === action.item) || effectiveCommands.find((c2) => c2.name === action.item) || (effectiveConfigItem?.name === action.item ? effectiveConfigItem : null) || effectiveRuleItems.find((r2) => r2.name === action.item) || effectiveHookItems.find((h2) => h2.name === action.item);
@@ -113534,9 +113928,9 @@ async function migrateCommand(options2) {
113534
113928
  const progressSink = createMigrateProgressSink(writeTasks.length + plannedDeleteActions.length);
113535
113929
  const writtenPaths = new Set;
113536
113930
  const recordHookTargetForSettings = (provider, global3, targetPath) => {
113537
- if (targetPath.length === 0 || !existsSync71(targetPath))
113931
+ if (targetPath.length === 0 || !existsSync72(targetPath))
113538
113932
  return;
113539
- const resolvedPath = resolve48(targetPath);
113933
+ const resolvedPath = resolve50(targetPath);
113540
113934
  const entry = successfulHookFiles.get(provider) ?? {
113541
113935
  files: [],
113542
113936
  global: global3
@@ -113554,7 +113948,7 @@ async function migrateCommand(options2) {
113554
113948
  const recordSuccessfulWrites = (task, taskResults) => {
113555
113949
  for (const result of taskResults.filter((entry) => entry.success)) {
113556
113950
  if (!result.skipped && result.path.length > 0) {
113557
- writtenPaths.add(resolve48(result.path));
113951
+ writtenPaths.add(resolve50(result.path));
113558
113952
  }
113559
113953
  if (task.type === "hooks") {
113560
113954
  recordHookTargetForSettings(task.provider, task.global, result.path);
@@ -113653,7 +114047,7 @@ async function migrateCommand(options2) {
113653
114047
  for (const [hooksProvider, entry] of successfulHookFiles) {
113654
114048
  if (entry.files.length === 0)
113655
114049
  continue;
113656
- const sourceSettingsPath = hooksSource ? join148(dirname49(hooksSource), "settings.json") : undefined;
114050
+ const sourceSettingsPath = hooksSource ? join149(dirname49(hooksSource), "settings.json") : undefined;
113657
114051
  const mergeResult = await migrateHooksSettings({
113658
114052
  sourceProvider: "claude-code",
113659
114053
  targetProvider: hooksProvider,
@@ -113718,7 +114112,7 @@ async function migrateCommand(options2) {
113718
114112
  }
113719
114113
  }
113720
114114
  try {
113721
- const kitRoot = (agentSource ? resolve48(agentSource, "..") : null) ?? (commandSource ? resolve48(commandSource, "..") : null) ?? (skillSource ? resolve48(skillSource, "..") : null) ?? null;
114115
+ const kitRoot = (agentSource ? resolve50(agentSource, "..") : null) ?? (commandSource ? resolve50(commandSource, "..") : null) ?? (skillSource ? resolve50(skillSource, "..") : null) ?? null;
113722
114116
  const manifest = kitRoot ? await loadPortableManifest(kitRoot) : null;
113723
114117
  if (manifest?.cliVersion) {
113724
114118
  await updateAppliedManifestVersion(manifest.cliVersion);
@@ -113766,7 +114160,7 @@ async function migrateCommand(options2) {
113766
114160
  async function rollbackResults(results) {
113767
114161
  const rolledBackPaths = new Set;
113768
114162
  for (const result of results) {
113769
- if (!result.path || !existsSync71(result.path))
114163
+ if (!result.path || !existsSync72(result.path))
113770
114164
  continue;
113771
114165
  try {
113772
114166
  if (result.overwritten)
@@ -113889,7 +114283,7 @@ var import_picocolors31 = __toESM(require_picocolors(), 1);
113889
114283
 
113890
114284
  // src/commands/new/phases/directory-setup.ts
113891
114285
  init_config_manager();
113892
- import { resolve as resolve49 } from "node:path";
114286
+ import { resolve as resolve51 } from "node:path";
113893
114287
  init_logger();
113894
114288
  init_path_resolver();
113895
114289
  init_types3();
@@ -113974,7 +114368,7 @@ async function directorySetup(validOptions, prompts) {
113974
114368
  targetDir = await prompts.getDirectory(targetDir);
113975
114369
  }
113976
114370
  }
113977
- const resolvedDir = resolve49(targetDir);
114371
+ const resolvedDir = resolve51(targetDir);
113978
114372
  logger.info(`Target directory: ${resolvedDir}`);
113979
114373
  if (PathResolver.isLocalSameAsGlobal(resolvedDir)) {
113980
114374
  logger.warning("You're creating a project at HOME directory.");
@@ -114031,7 +114425,7 @@ async function handleDirectorySetup(ctx) {
114031
114425
  // src/commands/new/phases/project-creation.ts
114032
114426
  init_config_manager();
114033
114427
  init_github_client();
114034
- import { join as join149 } from "node:path";
114428
+ import { join as join150 } from "node:path";
114035
114429
  init_logger();
114036
114430
  init_output_manager();
114037
114431
  init_types3();
@@ -114157,7 +114551,7 @@ async function projectCreation(kit, resolvedDir, validOptions, isNonInteractive2
114157
114551
  output.section("Installing");
114158
114552
  logger.verbose("Installation target", { directory: resolvedDir });
114159
114553
  const merger = new FileMerger;
114160
- const claudeDir3 = join149(resolvedDir, ".claude");
114554
+ const claudeDir3 = join150(resolvedDir, ".claude");
114161
114555
  merger.setMultiKitContext(claudeDir3, kit);
114162
114556
  if (validOptions.exclude && validOptions.exclude.length > 0) {
114163
114557
  merger.addIgnorePatterns(validOptions.exclude);
@@ -114204,7 +114598,7 @@ async function handleProjectCreation(ctx) {
114204
114598
  }
114205
114599
  // src/commands/new/phases/post-setup.ts
114206
114600
  init_projects_registry();
114207
- import { join as join150 } from "node:path";
114601
+ import { join as join151 } from "node:path";
114208
114602
  init_package_installer();
114209
114603
  init_logger();
114210
114604
  init_path_resolver();
@@ -114236,9 +114630,9 @@ async function postSetup(resolvedDir, validOptions, isNonInteractive2, prompts)
114236
114630
  withSudo: validOptions.withSudo
114237
114631
  });
114238
114632
  }
114239
- const claudeDir3 = join150(resolvedDir, ".claude");
114633
+ const claudeDir3 = join151(resolvedDir, ".claude");
114240
114634
  await promptSetupWizardIfNeeded({
114241
- envPath: join150(claudeDir3, ".env"),
114635
+ envPath: join151(claudeDir3, ".env"),
114242
114636
  claudeDir: claudeDir3,
114243
114637
  isGlobal: false,
114244
114638
  isNonInteractive: isNonInteractive2,
@@ -114307,8 +114701,8 @@ Please use only one download method.`);
114307
114701
  }
114308
114702
  // src/commands/plan/plan-command.ts
114309
114703
  init_output_manager();
114310
- import { existsSync as existsSync74, statSync as statSync13 } from "node:fs";
114311
- import { dirname as dirname53, isAbsolute as isAbsolute15, join as join153, parse as parse7, resolve as resolve53 } from "node:path";
114704
+ import { existsSync as existsSync75, statSync as statSync13 } from "node:fs";
114705
+ import { dirname as dirname53, isAbsolute as isAbsolute15, join as join154, parse as parse7, resolve as resolve55 } from "node:path";
114312
114706
 
114313
114707
  // src/commands/plan/plan-read-handlers.ts
114314
114708
  init_config();
@@ -114317,15 +114711,15 @@ init_plans_registry();
114317
114711
  init_logger();
114318
114712
  init_output_manager();
114319
114713
  var import_picocolors32 = __toESM(require_picocolors(), 1);
114320
- import { existsSync as existsSync73, statSync as statSync12 } from "node:fs";
114321
- import { basename as basename31, dirname as dirname51, join as join152, relative as relative32, resolve as resolve51 } from "node:path";
114714
+ import { existsSync as existsSync74, statSync as statSync12 } from "node:fs";
114715
+ import { basename as basename31, dirname as dirname51, join as join153, relative as relative34, resolve as resolve53 } from "node:path";
114322
114716
 
114323
114717
  // src/commands/plan/plan-dependencies.ts
114324
114718
  init_config();
114325
114719
  init_plan_parser();
114326
114720
  init_plans_registry();
114327
- import { existsSync as existsSync72 } from "node:fs";
114328
- import { dirname as dirname50, join as join151 } from "node:path";
114721
+ import { existsSync as existsSync73 } from "node:fs";
114722
+ import { dirname as dirname50, join as join152 } from "node:path";
114329
114723
  async function resolvePlanDependencies(references, currentPlanFile, options2 = {}) {
114330
114724
  if (references.length === 0)
114331
114725
  return [];
@@ -114345,9 +114739,9 @@ async function resolvePlanDependencies(references, currentPlanFile, options2 = {
114345
114739
  };
114346
114740
  }
114347
114741
  const scopeRoot = resolvePlanDirForScope(scope, projectRoot, config);
114348
- const planFile = join151(scopeRoot, planId, "plan.md");
114742
+ const planFile = join152(scopeRoot, planId, "plan.md");
114349
114743
  const isSelfReference = planFile === currentPlanFile;
114350
- if (!existsSync72(planFile)) {
114744
+ if (!existsSync73(planFile)) {
114351
114745
  return {
114352
114746
  reference,
114353
114747
  scope,
@@ -114376,14 +114770,14 @@ init_config();
114376
114770
  init_plan_parser();
114377
114771
  init_plan_scope();
114378
114772
  init_plans_registry();
114379
- import { isAbsolute as isAbsolute14, resolve as resolve50 } from "node:path";
114773
+ import { isAbsolute as isAbsolute14, resolve as resolve52 } from "node:path";
114380
114774
  async function getGlobalPlansDirFromCwd() {
114381
114775
  const projectRoot = findProjectRoot(process.cwd());
114382
114776
  const { config } = await CkConfigManager.loadFull(projectRoot);
114383
114777
  return resolveGlobalPlansDir(config);
114384
114778
  }
114385
114779
  function resolveTargetFromBase(target, baseDir) {
114386
- const resolvedTarget = isAbsolute14(target) ? resolve50(target) : resolve50(baseDir, target);
114780
+ const resolvedTarget = isAbsolute14(target) ? resolve52(target) : resolve52(baseDir, target);
114387
114781
  return isWithinDir(resolvedTarget, baseDir) ? resolvedTarget : null;
114388
114782
  }
114389
114783
 
@@ -114413,7 +114807,7 @@ async function handleParse(target, options2) {
114413
114807
  return;
114414
114808
  }
114415
114809
  if (isJsonOutput(options2)) {
114416
- console.log(JSON.stringify({ file: relative32(process.cwd(), planFile), frontmatter, phases }, null, 2));
114810
+ console.log(JSON.stringify({ file: relative34(process.cwd(), planFile), frontmatter, phases }, null, 2));
114417
114811
  return;
114418
114812
  }
114419
114813
  const title = typeof frontmatter.title === "string" ? frontmatter.title : basename31(dirname51(planFile));
@@ -114486,8 +114880,8 @@ async function handleStatus(target, options2) {
114486
114880
  return;
114487
114881
  }
114488
114882
  const effectiveTarget = !resolvedTarget && globalBaseDir ? globalBaseDir : resolvedTarget;
114489
- const t = effectiveTarget ? resolve51(effectiveTarget) : null;
114490
- const plansDir = t && existsSync73(t) && statSync12(t).isDirectory() && !existsSync73(join152(t, "plan.md")) ? t : null;
114883
+ const t = effectiveTarget ? resolve53(effectiveTarget) : null;
114884
+ const plansDir = t && existsSync74(t) && statSync12(t).isDirectory() && !existsSync74(join153(t, "plan.md")) ? t : null;
114491
114885
  if (plansDir) {
114492
114886
  const planFiles = scanPlanDir(plansDir);
114493
114887
  if (planFiles.length === 0) {
@@ -114671,12 +115065,12 @@ init_plan_parser();
114671
115065
  init_plans_registry();
114672
115066
  init_output_manager();
114673
115067
  var import_picocolors33 = __toESM(require_picocolors(), 1);
114674
- import { basename as basename32, dirname as dirname52, relative as relative33, resolve as resolve52 } from "node:path";
115068
+ import { basename as basename32, dirname as dirname52, relative as relative35, resolve as resolve54 } from "node:path";
114675
115069
  function quoteReadTarget(filePath) {
114676
115070
  return `"${filePath.replace(/\\/g, "/").replace(/"/g, "\\\"")}"`;
114677
115071
  }
114678
115072
  function buildPlanCreateReadReminder(planFile, phaseFiles, cwd2 = process.cwd()) {
114679
- const files = [planFile, ...phaseFiles].map((file) => quoteReadTarget(relative33(cwd2, file)));
115073
+ const files = [planFile, ...phaseFiles].map((file) => quoteReadTarget(relative35(cwd2, file)));
114680
115074
  return [
114681
115075
  " [i] Claude Code agents: read plan.md and every phase-*.md before editing.",
114682
115076
  " These files already exist; Write/Edit without Read may be rejected after wasting tokens.",
@@ -114714,13 +115108,13 @@ async function handleCreate(target, options2) {
114714
115108
  return;
114715
115109
  }
114716
115110
  const globalBaseDir = options2.global ? await getGlobalPlansDirFromCwd() : undefined;
114717
- const resolvedDir = globalBaseDir ? resolveTargetFromBase(dir, globalBaseDir) : resolve52(dir);
115111
+ const resolvedDir = globalBaseDir ? resolveTargetFromBase(dir, globalBaseDir) : resolve54(dir);
114718
115112
  if (globalBaseDir && !resolvedDir) {
114719
115113
  output.error("[X] Target directory must stay within the configured global plans root");
114720
115114
  process.exitCode = 1;
114721
115115
  return;
114722
115116
  }
114723
- const safeResolvedDir = resolvedDir ?? resolve52(dir);
115117
+ const safeResolvedDir = resolvedDir ?? resolve54(dir);
114724
115118
  const result = scaffoldPlan({
114725
115119
  title: options2.title,
114726
115120
  phases: phaseNames.map((name2) => ({ name: name2 })),
@@ -114748,8 +115142,8 @@ async function handleCreate(target, options2) {
114748
115142
  if (isJsonOutput(options2)) {
114749
115143
  const cwd2 = process.cwd();
114750
115144
  console.log(JSON.stringify({
114751
- planFile: relative33(cwd2, result.planFile),
114752
- phaseFiles: result.phaseFiles.map((f3) => relative33(cwd2, f3))
115145
+ planFile: relative35(cwd2, result.planFile),
115146
+ phaseFiles: result.phaseFiles.map((f3) => relative35(cwd2, f3))
114753
115147
  }, null, 2));
114754
115148
  return;
114755
115149
  }
@@ -114808,7 +115202,7 @@ async function handleCheck(target, options2) {
114808
115202
  console.log(JSON.stringify({
114809
115203
  phaseId: target,
114810
115204
  status: newStatus,
114811
- planFile: relative33(process.cwd(), planFile)
115205
+ planFile: relative35(process.cwd(), planFile)
114812
115206
  }));
114813
115207
  return;
114814
115208
  }
@@ -114852,7 +115246,7 @@ async function handleUncheck(target, options2) {
114852
115246
  console.log(JSON.stringify({
114853
115247
  phaseId: target,
114854
115248
  status: "pending",
114855
- planFile: relative33(process.cwd(), planFile)
115249
+ planFile: relative35(process.cwd(), planFile)
114856
115250
  }));
114857
115251
  return;
114858
115252
  }
@@ -114884,7 +115278,7 @@ async function handleAddPhase(target, options2) {
114884
115278
  if (isJsonOutput(options2)) {
114885
115279
  console.log(JSON.stringify({
114886
115280
  phaseId: result.phaseId,
114887
- phaseFile: relative33(process.cwd(), result.phaseFile)
115281
+ phaseFile: relative35(process.cwd(), result.phaseFile)
114888
115282
  }));
114889
115283
  return;
114890
115284
  }
@@ -114899,33 +115293,33 @@ async function handleAddPhase(target, options2) {
114899
115293
  // src/commands/plan/plan-command.ts
114900
115294
  function resolveTargetPath(target, baseDir) {
114901
115295
  if (!baseDir) {
114902
- return resolve53(target);
115296
+ return resolve55(target);
114903
115297
  }
114904
115298
  if (isAbsolute15(target)) {
114905
- return resolve53(target);
115299
+ return resolve55(target);
114906
115300
  }
114907
- const cwdCandidate = resolve53(target);
114908
- if (existsSync74(cwdCandidate)) {
115301
+ const cwdCandidate = resolve55(target);
115302
+ if (existsSync75(cwdCandidate)) {
114909
115303
  return cwdCandidate;
114910
115304
  }
114911
- return resolve53(baseDir, target);
115305
+ return resolve55(baseDir, target);
114912
115306
  }
114913
115307
  function resolvePlanFile(target, baseDir) {
114914
- const t = target ? resolveTargetPath(target, baseDir) : baseDir ? resolve53(baseDir) : process.cwd();
114915
- if (existsSync74(t)) {
115308
+ const t = target ? resolveTargetPath(target, baseDir) : baseDir ? resolve55(baseDir) : process.cwd();
115309
+ if (existsSync75(t)) {
114916
115310
  const stat24 = statSync13(t);
114917
115311
  if (stat24.isFile())
114918
115312
  return t;
114919
- const candidate = join153(t, "plan.md");
114920
- if (existsSync74(candidate))
115313
+ const candidate = join154(t, "plan.md");
115314
+ if (existsSync75(candidate))
114921
115315
  return candidate;
114922
115316
  }
114923
115317
  if (!target && !baseDir) {
114924
115318
  let dir = process.cwd();
114925
115319
  const root = parse7(dir).root;
114926
115320
  while (dir !== root) {
114927
- const candidate = join153(dir, "plan.md");
114928
- if (existsSync74(candidate))
115321
+ const candidate = join154(dir, "plan.md");
115322
+ if (existsSync75(candidate))
114929
115323
  return candidate;
114930
115324
  dir = dirname53(dir);
114931
115325
  }
@@ -114975,7 +115369,7 @@ async function planCommand(action, target, options2) {
114975
115369
  let resolvedTarget = target;
114976
115370
  if (resolvedAction && !knownActions.has(resolvedAction)) {
114977
115371
  const looksLikePath = resolvedAction.includes("/") || resolvedAction.includes("\\") || resolvedAction.endsWith(".md") || resolvedAction === "." || resolvedAction === "..";
114978
- const existsOnDisk = !looksLikePath && existsSync74(resolve53(resolvedAction));
115372
+ const existsOnDisk = !looksLikePath && existsSync75(resolve55(resolvedAction));
114979
115373
  if (looksLikePath || existsOnDisk) {
114980
115374
  resolvedTarget = resolvedAction;
114981
115375
  resolvedAction = undefined;
@@ -115017,13 +115411,13 @@ init_claudekit_data2();
115017
115411
  init_logger();
115018
115412
  init_safe_prompts();
115019
115413
  var import_picocolors34 = __toESM(require_picocolors(), 1);
115020
- import { existsSync as existsSync75 } from "node:fs";
115021
- import { resolve as resolve54 } from "node:path";
115414
+ import { existsSync as existsSync76 } from "node:fs";
115415
+ import { resolve as resolve56 } from "node:path";
115022
115416
  async function handleAdd(projectPath, options2) {
115023
115417
  logger.debug(`Adding project: ${projectPath}, options: ${JSON.stringify(options2)}`);
115024
115418
  intro("Add Project");
115025
- const absolutePath = resolve54(projectPath);
115026
- if (!existsSync75(absolutePath)) {
115419
+ const absolutePath = resolve56(projectPath);
115420
+ if (!existsSync76(absolutePath)) {
115027
115421
  log.error(`Path does not exist: ${absolutePath}`);
115028
115422
  process.exitCode = 1;
115029
115423
  return;
@@ -115384,6 +115778,7 @@ async function handleKitSelection(ctx) {
115384
115778
  refresh: false,
115385
115779
  sync: false,
115386
115780
  useGit: false,
115781
+ installMode: "auto",
115387
115782
  verbose: false,
115388
115783
  json: false
115389
115784
  });
@@ -115444,10 +115839,10 @@ init_agents();
115444
115839
  var import_gray_matter12 = __toESM(require_gray_matter(), 1);
115445
115840
  var import_picocolors37 = __toESM(require_picocolors(), 1);
115446
115841
  import { readFile as readFile68 } from "node:fs/promises";
115447
- import { join as join155 } from "node:path";
115842
+ import { join as join156 } from "node:path";
115448
115843
 
115449
115844
  // src/commands/skills/installed-skills-inventory.ts
115450
- import { join as join154, resolve as resolve55 } from "node:path";
115845
+ import { join as join155, resolve as resolve57 } from "node:path";
115451
115846
  init_path_resolver();
115452
115847
  var SCOPE_SORT_ORDER = {
115453
115848
  project: 0,
@@ -115455,12 +115850,12 @@ var SCOPE_SORT_ORDER = {
115455
115850
  };
115456
115851
  async function getActiveClaudeSkillInstallations(options2 = {}) {
115457
115852
  const projectDir = options2.projectDir ?? process.cwd();
115458
- const globalDir = resolve55(options2.globalDir ?? PathResolver.getGlobalKitDir());
115459
- const projectClaudeDir = resolve55(projectDir, ".claude");
115853
+ const globalDir = resolve57(options2.globalDir ?? PathResolver.getGlobalKitDir());
115854
+ const projectClaudeDir = resolve57(projectDir, ".claude");
115460
115855
  const projectScopeAliasesGlobal = projectClaudeDir === globalDir;
115461
115856
  const [projectSkills, globalSkills] = await Promise.all([
115462
- projectScopeAliasesGlobal ? Promise.resolve([]) : scanSkills2(join154(projectClaudeDir, "skills")),
115463
- scanSkills2(join154(globalDir, "skills"))
115857
+ projectScopeAliasesGlobal ? Promise.resolve([]) : scanSkills2(join155(projectClaudeDir, "skills")),
115858
+ scanSkills2(join155(globalDir, "skills"))
115464
115859
  ]);
115465
115860
  const projectIds = new Set(projectSkills.map((skill) => skill.id));
115466
115861
  const globalIds = new Set(globalSkills.map((skill) => skill.id));
@@ -115621,7 +116016,7 @@ async function handleValidate2(sourcePath) {
115621
116016
  spinner.stop(`Checked ${skills.length} skill(s)`);
115622
116017
  let hasIssues = false;
115623
116018
  for (const skill of skills) {
115624
- const skillMdPath = join155(skill.path, "SKILL.md");
116019
+ const skillMdPath = join156(skill.path, "SKILL.md");
115625
116020
  try {
115626
116021
  const content = await readFile68(skillMdPath, "utf-8");
115627
116022
  const { data } = import_gray_matter12.default(content, {
@@ -116154,31 +116549,6 @@ init_skills_installer();
116154
116549
  init_skills_registry();
116155
116550
  init_skills_uninstaller();
116156
116551
 
116157
- // src/domains/installation/plugin/uninstall-plugin.ts
116158
- init_install_mode_detector();
116159
- import { existsSync as existsSync76, rmSync as rmSync6 } from "node:fs";
116160
- import { join as join156 } from "node:path";
116161
- init_path_resolver();
116162
- async function uninstallEnginePlugin(opts = {}) {
116163
- const claudeDir3 = opts.claudeDir ?? PathResolver.getGlobalKitDir();
116164
- const installer = opts.installer ?? new PluginInstaller(undefined, claudeDir3);
116165
- const state = detectPluginState(claudeDir3);
116166
- let uninstalled = false;
116167
- if (state.installed) {
116168
- await installer.uninstall();
116169
- await installer.marketplaceRemove(state.marketplace ?? CK_MARKETPLACE_NAME);
116170
- uninstalled = true;
116171
- }
116172
- let staleCacheRemoved = false;
116173
- const marketplace = state.marketplace ?? CK_MARKETPLACE_NAME;
116174
- const cacheDir = join156(claudeDir3, "plugins", "cache", marketplace, CK_PLUGIN_NAME);
116175
- if (existsSync76(cacheDir)) {
116176
- rmSync6(cacheDir, { recursive: true, force: true });
116177
- staleCacheRemoved = true;
116178
- }
116179
- return { uninstalled, staleCacheRemoved };
116180
- }
116181
-
116182
116552
  // src/commands/uninstall/uninstall-command.ts
116183
116553
  init_metadata_migration();
116184
116554
  init_logger();
@@ -116228,8 +116598,8 @@ async function detectInstallations() {
116228
116598
  }
116229
116599
 
116230
116600
  // src/commands/uninstall/removal-handler.ts
116231
- import { readdirSync as readdirSync13, rmSync as rmSync8 } from "node:fs";
116232
- import { basename as basename33, join as join159, resolve as resolve56, sep as sep14 } from "node:path";
116601
+ import { readdirSync as readdirSync14, rmSync as rmSync8 } from "node:fs";
116602
+ import { basename as basename33, join as join159, resolve as resolve58, sep as sep14 } from "node:path";
116233
116603
  init_logger();
116234
116604
  init_safe_prompts();
116235
116605
  init_safe_spinner();
@@ -116237,7 +116607,7 @@ var import_fs_extra44 = __toESM(require_lib(), 1);
116237
116607
 
116238
116608
  // src/commands/uninstall/analysis-handler.ts
116239
116609
  init_metadata_migration();
116240
- import { readdirSync as readdirSync12, rmSync as rmSync7 } from "node:fs";
116610
+ import { readdirSync as readdirSync13, rmSync as rmSync7 } from "node:fs";
116241
116611
  import { dirname as dirname54, join as join157 } from "node:path";
116242
116612
  init_logger();
116243
116613
  init_safe_prompts();
@@ -116263,7 +116633,7 @@ async function cleanupEmptyDirectories3(filePath, installationRoot) {
116263
116633
  let currentDir = dirname54(filePath);
116264
116634
  while (currentDir !== installationRoot && currentDir.startsWith(installationRoot)) {
116265
116635
  try {
116266
- const entries = readdirSync12(currentDir);
116636
+ const entries = readdirSync13(currentDir);
116267
116637
  if (entries.length === 0) {
116268
116638
  rmSync7(currentDir, { recursive: true });
116269
116639
  cleaned++;
@@ -116593,8 +116963,8 @@ async function restoreUninstallBackup(backup) {
116593
116963
  }
116594
116964
  async function isPathSafeToRemove(filePath, baseDir) {
116595
116965
  try {
116596
- const resolvedPath = resolve56(filePath);
116597
- const resolvedBase = resolve56(baseDir);
116966
+ const resolvedPath = resolve58(filePath);
116967
+ const resolvedBase = resolve58(baseDir);
116598
116968
  if (!resolvedPath.startsWith(resolvedBase + sep14) && resolvedPath !== resolvedBase) {
116599
116969
  logger.debug(`Path outside installation directory: ${filePath}`);
116600
116970
  return false;
@@ -116602,7 +116972,7 @@ async function isPathSafeToRemove(filePath, baseDir) {
116602
116972
  const stats = await import_fs_extra44.lstat(filePath);
116603
116973
  if (stats.isSymbolicLink()) {
116604
116974
  const realPath = await import_fs_extra44.realpath(filePath);
116605
- const resolvedReal = resolve56(realPath);
116975
+ const resolvedReal = resolve58(realPath);
116606
116976
  if (!resolvedReal.startsWith(resolvedBase + sep14) && resolvedReal !== resolvedBase) {
116607
116977
  logger.debug(`Symlink points outside installation directory: ${filePath} -> ${realPath}`);
116608
116978
  return false;
@@ -116700,7 +117070,7 @@ async function removeInstallations(installations, options2) {
116700
117070
  });
116701
117071
  logSettingsCleanup(settingsCleanup, false);
116702
117072
  try {
116703
- const remaining = readdirSync13(installation.path);
117073
+ const remaining = readdirSync14(installation.path);
116704
117074
  if (remaining.length === 0) {
116705
117075
  rmSync8(installation.path, { recursive: true });
116706
117076
  logger.debug(`Removed empty installation directory: ${installation.path}`);
@@ -117166,7 +117536,7 @@ function getDisclaimerMarker() {
117166
117536
  return AI_DISCLAIMER;
117167
117537
  }
117168
117538
  function spawnAndCollect2(command, args) {
117169
- return new Promise((resolve57, reject) => {
117539
+ return new Promise((resolve59, reject) => {
117170
117540
  const child = spawn6(command, args, { stdio: ["ignore", "pipe", "pipe"] });
117171
117541
  const chunks = [];
117172
117542
  const stderrChunks = [];
@@ -117179,7 +117549,7 @@ function spawnAndCollect2(command, args) {
117179
117549
  reject(new Error(`${command} exited with code ${code2}: ${stderr}`));
117180
117550
  return;
117181
117551
  }
117182
- resolve57(Buffer.concat(chunks).toString("utf-8"));
117552
+ resolve59(Buffer.concat(chunks).toString("utf-8"));
117183
117553
  });
117184
117554
  });
117185
117555
  }
@@ -117287,7 +117657,7 @@ function formatResponse(content, showBranding) {
117287
117657
  return disclaimer + formatted + branding;
117288
117658
  }
117289
117659
  async function postViaGh(owner, repo, issueNumber, body) {
117290
- return new Promise((resolve57, reject) => {
117660
+ return new Promise((resolve59, reject) => {
117291
117661
  const args = [
117292
117662
  "issue",
117293
117663
  "comment",
@@ -117309,7 +117679,7 @@ async function postViaGh(owner, repo, issueNumber, body) {
117309
117679
  reject(new Error(`gh exited with code ${code2}: ${stderr}`));
117310
117680
  return;
117311
117681
  }
117312
- resolve57();
117682
+ resolve59();
117313
117683
  });
117314
117684
  });
117315
117685
  }
@@ -117427,7 +117797,7 @@ After completing the implementation:
117427
117797
  "--allowedTools",
117428
117798
  tools
117429
117799
  ];
117430
- await new Promise((resolve57, reject) => {
117800
+ await new Promise((resolve59, reject) => {
117431
117801
  const child = spawn8("claude", args, { cwd: cwd2, stdio: ["pipe", "pipe", "pipe"], detached: false });
117432
117802
  child.stdin.write(prompt);
117433
117803
  child.stdin.end();
@@ -117452,7 +117822,7 @@ After completing the implementation:
117452
117822
  reject(new Error(`Claude exited ${code2}: ${stderr.slice(0, 500)}`));
117453
117823
  return;
117454
117824
  }
117455
- resolve57();
117825
+ resolve59();
117456
117826
  });
117457
117827
  });
117458
117828
  }
@@ -117596,7 +117966,7 @@ function checkRateLimit2(processedThisHour, maxPerHour) {
117596
117966
  return processedThisHour < maxPerHour;
117597
117967
  }
117598
117968
  function spawnAndCollect3(command, args) {
117599
- return new Promise((resolve57, reject) => {
117969
+ return new Promise((resolve59, reject) => {
117600
117970
  const child = spawn9(command, args, { stdio: ["ignore", "pipe", "pipe"] });
117601
117971
  const chunks = [];
117602
117972
  const stderrChunks = [];
@@ -117609,7 +117979,7 @@ function spawnAndCollect3(command, args) {
117609
117979
  reject(new Error(`${command} exited with code ${code2}: ${stderr}`));
117610
117980
  return;
117611
117981
  }
117612
- resolve57(Buffer.concat(chunks).toString("utf-8"));
117982
+ resolve59(Buffer.concat(chunks).toString("utf-8"));
117613
117983
  });
117614
117984
  });
117615
117985
  }
@@ -117661,7 +118031,7 @@ async function invokeClaude(options2) {
117661
118031
  return collectClaudeOutput(child, options2.timeoutSec, verbose);
117662
118032
  }
117663
118033
  function collectClaudeOutput(child, timeoutSec, verbose = false) {
117664
- return new Promise((resolve57, reject) => {
118034
+ return new Promise((resolve59, reject) => {
117665
118035
  const chunks = [];
117666
118036
  const stderrChunks = [];
117667
118037
  child.stdout?.on("data", (chunk) => {
@@ -117691,7 +118061,7 @@ function collectClaudeOutput(child, timeoutSec, verbose = false) {
117691
118061
  reject(new Error(`Claude exited with code ${code2}: ${stderr}`));
117692
118062
  return;
117693
118063
  }
117694
- resolve57(verbose ? parseStreamJsonOutput(stdout2) : parseClaudeOutput(stdout2));
118064
+ resolve59(verbose ? parseStreamJsonOutput(stdout2) : parseClaudeOutput(stdout2));
117695
118065
  });
117696
118066
  });
117697
118067
  }
@@ -118955,7 +119325,7 @@ function formatQueueInfo(state) {
118955
119325
  return "idle";
118956
119326
  }
118957
119327
  function sleep(ms) {
118958
- return new Promise((resolve57) => setTimeout(resolve57, ms));
119328
+ return new Promise((resolve59) => setTimeout(resolve59, ms));
118959
119329
  }
118960
119330
  // src/cli/command-registry.ts
118961
119331
  init_logger();
@@ -118966,7 +119336,7 @@ function registerCommands(cli) {
118966
119336
  }
118967
119337
  await newCommand(options2);
118968
119338
  });
118969
- cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use: engineer, marketing, all, or comma-separated").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove CK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--restore-ck-hooks", "Restore CK-managed hook registrations during update self-heal").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").action(async (options2) => {
119339
+ cli.command("init", "Initialize or update ClaudeKit project (with interactive version selection)").option("--dir <dir>", "Target directory (default: .)").option("--kit <kit>", "Kit to use: engineer, marketing, all, or comma-separated").option("-r, --release <version>", "Skip version selection, use specific version (e.g., latest, v1.0.0)").option("--exclude <pattern>", "Exclude files matching glob pattern (can be used multiple times)").option("--only <pattern>", "Include only files matching glob pattern (can be used multiple times)").option("-g, --global", "Use platform-specific user configuration directory").option("--fresh", "Full reset: remove CK files, replace settings.json and CLAUDE.md, reinstall from scratch").option("--force", "Force reinstall even if already at latest version (use with --yes; re-onboards missing files without full reset)").option("--install-skills", "Install skills dependencies (non-interactive mode)").option("--with-sudo", "Include system packages requiring sudo (Linux: ffmpeg, imagemagick)").option("--prefix", "Add /ck: prefix to all slash commands by moving them to commands/ck/ subdirectory").option("--beta", "Show beta versions in selection prompt").option("--refresh", "Bypass release cache to fetch latest versions from GitHub").option("--dry-run", "Preview changes without applying them (requires --prefix)").option("--force-overwrite", "Override ownership protections and delete user-modified files (requires --prefix)").option("--force-overwrite-settings", "Fully replace settings.json instead of selective merge (destroys user customizations)").option("--restore-ck-hooks", "Restore CK-managed hook registrations during update self-heal").option("--skip-setup", "Skip interactive configuration wizard").option("--docs-dir <name>", "Custom docs folder name (default: docs)").option("--plans-dir <name>", "Custom plans folder name (default: plans)").option("-y, --yes", "Non-interactive mode with sensible defaults (skip all prompts)").option("--sync", "Sync config files from upstream with interactive hunk-by-hunk merge").option("--install-mode <mode>", "Engineer global install mode: auto, plugin, or legacy (default: auto)").option("--use-git", "Use git clone instead of GitHub API (uses SSH/HTTPS credentials)").option("--archive <path>", "Use local archive file instead of downloading (zip/tar.gz)").option("--kit-path <path>", "Use local kit directory instead of downloading").action(async (options2) => {
118970
119340
  if (options2.exclude && !Array.isArray(options2.exclude)) {
118971
119341
  options2.exclude = [options2.exclude];
118972
119342
  }