claudekit-cli 4.5.0-dev.3 → 4.5.0-dev.4

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/cli-manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "4.5.0-dev.3",
3
- "generatedAt": "2026-06-24T03:41:00.177Z",
2
+ "version": "4.5.0-dev.4",
3
+ "generatedAt": "2026-06-24T22:46:20.222Z",
4
4
  "commands": {
5
5
  "agents": {
6
6
  "name": "agents",
package/dist/index.js CHANGED
@@ -64421,7 +64421,7 @@ var package_default;
64421
64421
  var init_package = __esm(() => {
64422
64422
  package_default = {
64423
64423
  name: "claudekit-cli",
64424
- version: "4.5.0-dev.3",
64424
+ version: "4.5.0-dev.4",
64425
64425
  description: "CLI tool for bootstrapping and updating ClaudeKit projects",
64426
64426
  type: "module",
64427
64427
  repository: {
@@ -66589,6 +66589,118 @@ This is a bug. Please open an issue at https://github.com/mrgoonie/claudekit-cli
66589
66589
  };
66590
66590
  });
66591
66591
 
66592
+ // src/domains/installation/plugin/codex-plugin-installer.ts
66593
+ import { execFile as execFile8 } from "node:child_process";
66594
+ import { promisify as promisify9 } from "node:util";
66595
+ function resolveCodexExecutable(platformName = process.platform) {
66596
+ return platformName === "win32" ? "codex.cmd" : "codex";
66597
+ }
66598
+ function shouldRunCodexInShell(platformName = process.platform) {
66599
+ return platformName === "win32";
66600
+ }
66601
+
66602
+ class CodexPluginInstaller {
66603
+ run;
66604
+ codexHome;
66605
+ constructor(run = defaultCodexRunner, codexHome) {
66606
+ this.run = run;
66607
+ this.codexHome = codexHome;
66608
+ }
66609
+ opts(timeoutMs) {
66610
+ return { codexHome: this.codexHome, timeoutMs };
66611
+ }
66612
+ async isCodexAvailable() {
66613
+ return (await this.run(["--version"], this.opts(15000))).ok;
66614
+ }
66615
+ async isPluginSupported() {
66616
+ const r2 = await this.run(["plugin", "--help"], this.opts(15000));
66617
+ return r2.ok && /marketplace/i.test(r2.stdout + r2.stderr);
66618
+ }
66619
+ async marketplaceAdd(source) {
66620
+ return this.run(["plugin", "marketplace", "add", source], this.opts());
66621
+ }
66622
+ async add() {
66623
+ return this.run(["plugin", "add", `${CK_PLUGIN_NAME}@${CK_MARKETPLACE_NAME}`], this.opts());
66624
+ }
66625
+ async listJson() {
66626
+ return this.run(["plugin", "list", "--json"], this.opts(15000));
66627
+ }
66628
+ async verifyInstalled() {
66629
+ const r2 = await this.listJson();
66630
+ if (!r2.ok)
66631
+ return false;
66632
+ try {
66633
+ const parsed = JSON.parse(r2.stdout);
66634
+ return (parsed.installed ?? []).some((plugin) => plugin.pluginId === `${CK_PLUGIN_NAME}@${CK_MARKETPLACE_NAME}` && plugin.installed === true && plugin.enabled === true);
66635
+ } catch {
66636
+ return false;
66637
+ }
66638
+ }
66639
+ }
66640
+ async function installCodexPlugin(opts) {
66641
+ const installer = opts.installer ?? new CodexPluginInstaller(undefined, opts.codexHome);
66642
+ if (!await installer.isCodexAvailable() || !await installer.isPluginSupported()) {
66643
+ return { action: "skipped-codex-unsupported", pluginVerified: false };
66644
+ }
66645
+ const added = await installer.marketplaceAdd(opts.pluginSourceDir);
66646
+ if (!added.ok) {
66647
+ return {
66648
+ action: "install-failed",
66649
+ pluginVerified: false,
66650
+ error: `codex marketplace add failed: ${added.stderr.trim()}`
66651
+ };
66652
+ }
66653
+ const installed = await installer.add();
66654
+ if (!installed.ok) {
66655
+ return {
66656
+ action: "install-failed",
66657
+ pluginVerified: false,
66658
+ error: `codex plugin add failed: ${installed.stderr.trim()}`
66659
+ };
66660
+ }
66661
+ const verified = await installer.verifyInstalled();
66662
+ if (!verified) {
66663
+ return {
66664
+ action: "install-failed",
66665
+ pluginVerified: false,
66666
+ error: "codex plugin did not verify after install"
66667
+ };
66668
+ }
66669
+ return { action: "installed", pluginVerified: true };
66670
+ }
66671
+ async function shouldRefreshCodexPlugin(installer = new CodexPluginInstaller) {
66672
+ if (!await installer.isCodexAvailable() || !await installer.isPluginSupported()) {
66673
+ return false;
66674
+ }
66675
+ return !await installer.verifyInstalled();
66676
+ }
66677
+ var execFileAsync6, DEFAULT_TIMEOUT_MS2 = 120000, defaultCodexRunner = async (args, opts) => {
66678
+ const env2 = { ...process.env };
66679
+ if (opts?.codexHome)
66680
+ env2.CODEX_HOME = opts.codexHome;
66681
+ try {
66682
+ const { stdout, stderr } = await execFileAsync6(resolveCodexExecutable(), args, {
66683
+ env: env2,
66684
+ shell: shouldRunCodexInShell(),
66685
+ timeout: opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
66686
+ maxBuffer: 10 * 1024 * 1024
66687
+ });
66688
+ return { ok: true, stdout: String(stdout), stderr: String(stderr), code: 0 };
66689
+ } catch (err) {
66690
+ const e2 = err;
66691
+ return {
66692
+ ok: false,
66693
+ stdout: e2.stdout ? String(e2.stdout) : "",
66694
+ stderr: e2.stderr ? String(e2.stderr) : e2.message ?? "",
66695
+ code: typeof e2.code === "number" ? e2.code : null
66696
+ };
66697
+ }
66698
+ };
66699
+ var init_codex_plugin_installer = __esm(() => {
66700
+ init_install_mode_detector();
66701
+ execFileAsync6 = promisify9(execFile8);
66702
+ });
66703
+
66592
66704
  // src/domains/migration/metadata-migration.ts
66593
66705
  import { join as join66 } from "node:path";
66594
66706
  async function detectMetadataFormat(claudeDir3) {
@@ -68358,7 +68470,7 @@ import { existsSync as existsSync48 } from "node:fs";
68358
68470
  import { readdir as readdir19 } from "node:fs/promises";
68359
68471
  import { builtinModules } from "node:module";
68360
68472
  import { dirname as dirname30, join as join69 } from "node:path";
68361
- import { promisify as promisify9 } from "node:util";
68473
+ import { promisify as promisify10 } from "node:util";
68362
68474
  function selectKitForUpdate(params) {
68363
68475
  const { hasLocal, hasGlobal, localKits, globalKits } = params;
68364
68476
  const hasLocalKit = localKits.length > 0 || hasLocal;
@@ -68567,6 +68679,7 @@ async function promptKitUpdate(beta, yes, deps) {
68567
68679
  const findMissingHookDepsFn = deps?.findMissingHookDependenciesFn ?? findMissingHookDependencies;
68568
68680
  const detectInstallModeFn = deps?.detectInstallModeFn ?? detectInstallMode;
68569
68681
  const hasTrackedPluginSuppliedLegacyFilesFn = deps?.hasTrackedPluginSuppliedLegacyFilesFn ?? hasTrackedPluginSuppliedLegacyFiles;
68682
+ const shouldRefreshCodexPluginFn = deps?.shouldRefreshCodexPluginFn ?? shouldRefreshCodexPlugin;
68570
68683
  const setup = await getSetupFn();
68571
68684
  const hasLocal = !!setup.project.metadata;
68572
68685
  const hasGlobal = !!setup.global.metadata;
@@ -68637,6 +68750,10 @@ async function promptKitUpdate(beta, yes, deps) {
68637
68750
  logger.warning(`Detected ${installMode.mode} global Engineer install; migrating to plugin format`);
68638
68751
  forceKitReinstall = true;
68639
68752
  }
68753
+ if (await shouldRefreshCodexPluginFn()) {
68754
+ logger.warning("Detected missing Codex ClaudeKit plugin; reinstalling global Engineer content");
68755
+ forceKitReinstall = true;
68756
+ }
68640
68757
  }
68641
68758
  } catch (error) {
68642
68759
  logger.verbose(`Plugin install-mode self-heal check skipped: ${error instanceof Error ? error.message : "unknown"}`);
@@ -68927,6 +69044,7 @@ var import_fs_extra8, execAsync2, SAFE_PROVIDER_NAME, HOOK_DEPENDENCY_EXTENSIONS
68927
69044
  var init_post_update_handler = __esm(() => {
68928
69045
  init_ck_config_manager();
68929
69046
  init_hook_health_checker();
69047
+ init_codex_plugin_installer();
68930
69048
  init_install_mode_detector();
68931
69049
  init_metadata_migration();
68932
69050
  init_version_utils();
@@ -68937,7 +69055,7 @@ var init_post_update_handler = __esm(() => {
68937
69055
  init_codex_sync_notice();
68938
69056
  init_version_comparator();
68939
69057
  import_fs_extra8 = __toESM(require_lib(), 1);
68940
- execAsync2 = promisify9(exec2);
69058
+ execAsync2 = promisify10(exec2);
68941
69059
  SAFE_PROVIDER_NAME = /^[a-z0-9-]+$/;
68942
69060
  HOOK_DEPENDENCY_EXTENSIONS = [".js", ".cjs", ".mjs", ".json"];
68943
69061
  });
@@ -68948,8 +69066,8 @@ function getDefaultUpdateCliCommandDeps() {
68948
69066
  currentVersion: package_default.version,
68949
69067
  execAsyncFn: async (cmd, opts) => {
68950
69068
  const { exec: exec3 } = await import("node:child_process");
68951
- const { promisify: promisify10 } = await import("node:util");
68952
- const result = await promisify10(exec3)(cmd, opts);
69069
+ const { promisify: promisify11 } = await import("node:util");
69070
+ const result = await promisify11(exec3)(cmd, opts);
68953
69071
  return { stdout: String(result.stdout ?? ""), stderr: String(result.stderr ?? "") };
68954
69072
  },
68955
69073
  packageManagerDetector: PackageManagerDetector,
@@ -69335,14 +69453,14 @@ var init_config_version_checker = __esm(() => {
69335
69453
 
69336
69454
  // src/domains/web-server/routes/system-routes.ts
69337
69455
  import { spawn as spawn3 } from "node:child_process";
69338
- import { execFile as execFile8 } from "node:child_process";
69456
+ import { execFile as execFile9 } from "node:child_process";
69339
69457
  import { existsSync as existsSync49 } from "node:fs";
69340
69458
  import { readFile as readFile40 } from "node:fs/promises";
69341
69459
  import { cpus, homedir as homedir42, totalmem } from "node:os";
69342
69460
  import { join as join71 } from "node:path";
69343
69461
  function runCommand(cmd, args, fallback2) {
69344
69462
  return new Promise((resolve35) => {
69345
- execFile8(cmd, args, { timeout: 5000 }, (err, stdout) => {
69463
+ execFile9(cmd, args, { timeout: 5000 }, (err, stdout) => {
69346
69464
  if (err) {
69347
69465
  resolve35(fallback2);
69348
69466
  } else {
@@ -74607,8 +74725,8 @@ var require_picomatch2 = __commonJS((exports, module) => {
74607
74725
  });
74608
74726
 
74609
74727
  // src/services/package-installer/process-executor.ts
74610
- import { exec as exec7, execFile as execFile9, spawn as spawn4 } from "node:child_process";
74611
- import { promisify as promisify14 } from "node:util";
74728
+ import { exec as exec7, execFile as execFile10, spawn as spawn4 } from "node:child_process";
74729
+ import { promisify as promisify15 } from "node:util";
74612
74730
  function executeInteractiveScript(command, args, options2) {
74613
74731
  return new Promise((resolve38, reject) => {
74614
74732
  const child = spawn4(command, args, {
@@ -74645,10 +74763,10 @@ function getNpmCommand() {
74645
74763
  const platform10 = process.platform;
74646
74764
  return platform10 === "win32" ? "npm.cmd" : "npm";
74647
74765
  }
74648
- var execAsync7, execFileAsync6;
74766
+ var execAsync7, execFileAsync7;
74649
74767
  var init_process_executor = __esm(() => {
74650
- execAsync7 = promisify14(exec7);
74651
- execFileAsync6 = promisify14(execFile9);
74768
+ execAsync7 = promisify15(exec7);
74769
+ execFileAsync7 = promisify15(execFile10);
74652
74770
  });
74653
74771
 
74654
74772
  // src/services/package-installer/validators.ts
@@ -74879,14 +74997,14 @@ async function installOpenCode() {
74879
74997
  const tempScriptPath = join90(tmpdir4(), "opencode-install.sh");
74880
74998
  try {
74881
74999
  logger.info("Downloading OpenCode installation script...");
74882
- await execFileAsync6("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
75000
+ await execFileAsync7("curl", ["-fsSL", "https://opencode.ai/install", "-o", tempScriptPath], {
74883
75001
  timeout: 30000
74884
75002
  });
74885
- await execFileAsync6("chmod", ["+x", tempScriptPath], {
75003
+ await execFileAsync7("chmod", ["+x", tempScriptPath], {
74886
75004
  timeout: 5000
74887
75005
  });
74888
75006
  logger.info("Executing OpenCode installation script...");
74889
- await execFileAsync6("bash", [tempScriptPath], {
75007
+ await execFileAsync7("bash", [tempScriptPath], {
74890
75008
  timeout: 120000
74891
75009
  });
74892
75010
  } finally {
@@ -75077,8 +75195,8 @@ async function checkNeedsSudoPackages() {
75077
75195
  return false;
75078
75196
  }
75079
75197
  const { exec: exec8 } = await import("node:child_process");
75080
- const { promisify: promisify15 } = await import("node:util");
75081
- const execAsync8 = promisify15(exec8);
75198
+ const { promisify: promisify16 } = await import("node:util");
75199
+ const execAsync8 = promisify16(exec8);
75082
75200
  try {
75083
75201
  await Promise.all([
75084
75202
  execAsync8("which ffmpeg", { timeout: WHICH_COMMAND_TIMEOUT_MS }),
@@ -75649,7 +75767,7 @@ __export(exports_package_installer, {
75649
75767
  getPackageVersion: () => getPackageVersion,
75650
75768
  getNpmCommand: () => getNpmCommand,
75651
75769
  executeInteractiveScript: () => executeInteractiveScript,
75652
- execFileAsync: () => execFileAsync6,
75770
+ execFileAsync: () => execFileAsync7,
75653
75771
  execAsync: () => execAsync7,
75654
75772
  PARTIAL_INSTALL_VERSION: () => PARTIAL_INSTALL_VERSION,
75655
75773
  EXIT_CODE_PARTIAL_SUCCESS: () => EXIT_CODE_PARTIAL_SUCCESS,
@@ -77576,11 +77694,11 @@ var require_extract_zip = __commonJS((exports, module) => {
77576
77694
  var { createWriteStream: createWriteStream3, promises: fs19 } = __require("fs");
77577
77695
  var getStream = require_get_stream();
77578
77696
  var path15 = __require("path");
77579
- var { promisify: promisify15 } = __require("util");
77697
+ var { promisify: promisify16 } = __require("util");
77580
77698
  var stream = __require("stream");
77581
77699
  var yauzl = require_yauzl();
77582
- var openZip = promisify15(yauzl.open);
77583
- var pipeline = promisify15(stream.pipeline);
77700
+ var openZip = promisify16(yauzl.open);
77701
+ var pipeline = promisify16(stream.pipeline);
77584
77702
 
77585
77703
  class Extractor {
77586
77704
  constructor(zipPath, opts) {
@@ -77665,7 +77783,7 @@ var require_extract_zip = __commonJS((exports, module) => {
77665
77783
  if (isDir2)
77666
77784
  return;
77667
77785
  debug("opening read stream", dest);
77668
- const readStream = await promisify15(this.zipfile.openReadStream.bind(this.zipfile))(entry);
77786
+ const readStream = await promisify16(this.zipfile.openReadStream.bind(this.zipfile))(entry);
77669
77787
  if (symlink4) {
77670
77788
  const link = await getStream(readStream);
77671
77789
  debug("creating symlink", link, dest);
@@ -78117,7 +78235,7 @@ var init_content_validator = __esm(() => {
78117
78235
 
78118
78236
  // src/commands/content/phases/context-cache-manager.ts
78119
78237
  import { createHash as createHash9 } from "node:crypto";
78120
- import { existsSync as existsSync83, mkdirSync as mkdirSync7, readFileSync as readFileSync21, readdirSync as readdirSync14, statSync as statSync15 } from "node:fs";
78238
+ import { existsSync as existsSync83, mkdirSync as mkdirSync7, readFileSync as readFileSync22, readdirSync as readdirSync14, statSync as statSync15 } from "node:fs";
78121
78239
  import { rename as rename16, writeFile as writeFile42 } from "node:fs/promises";
78122
78240
  import { homedir as homedir54 } from "node:os";
78123
78241
  import { basename as basename34, join as join165 } from "node:path";
@@ -78126,7 +78244,7 @@ function getCachedContext(repoPath) {
78126
78244
  if (!existsSync83(cachePath))
78127
78245
  return null;
78128
78246
  try {
78129
- const raw2 = readFileSync21(cachePath, "utf-8");
78247
+ const raw2 = readFileSync22(cachePath, "utf-8");
78130
78248
  const cache5 = JSON.parse(raw2);
78131
78249
  const age = Date.now() - new Date(cache5.createdAt).getTime();
78132
78250
  if (age >= CACHE_TTL_MS5)
@@ -78374,7 +78492,7 @@ function extractContentFromResponse(response) {
78374
78492
 
78375
78493
  // src/commands/content/phases/docs-summarizer.ts
78376
78494
  import { execSync as execSync7 } from "node:child_process";
78377
- import { existsSync as existsSync84, readFileSync as readFileSync22, readdirSync as readdirSync15 } from "node:fs";
78495
+ import { existsSync as existsSync84, readFileSync as readFileSync23, readdirSync as readdirSync15 } from "node:fs";
78378
78496
  import { join as join166 } from "node:path";
78379
78497
  async function summarizeProjectDocs(repoPath, contentLogger) {
78380
78498
  const rawContent = collectRawDocs(repoPath);
@@ -78423,7 +78541,7 @@ function collectRawDocs(repoPath) {
78423
78541
  return "";
78424
78542
  if (totalChars >= MAX_RAW_CONTENT_CHARS)
78425
78543
  return "";
78426
- const content = readFileSync22(filePath, "utf-8");
78544
+ const content = readFileSync23(filePath, "utf-8");
78427
78545
  const capped = content.slice(0, Math.min(maxChars, MAX_RAW_CONTENT_CHARS - totalChars));
78428
78546
  totalChars += capped.length;
78429
78547
  return capped;
@@ -79104,7 +79222,7 @@ function isNoiseCommit(title, author) {
79104
79222
 
79105
79223
  // src/commands/content/phases/change-detector.ts
79106
79224
  import { execSync as execSync10, spawnSync as spawnSync9 } from "node:child_process";
79107
- import { existsSync as existsSync88, readFileSync as readFileSync23, readdirSync as readdirSync17, statSync as statSync17 } from "node:fs";
79225
+ import { existsSync as existsSync88, readFileSync as readFileSync24, readdirSync as readdirSync17, statSync as statSync17 } from "node:fs";
79108
79226
  import { join as join169 } from "node:path";
79109
79227
  function detectCommits(repo, since) {
79110
79228
  try {
@@ -79231,7 +79349,7 @@ function detectCompletedPlans(repo, since) {
79231
79349
  const stat26 = statSync17(planFile);
79232
79350
  if (stat26.mtimeMs < sinceMs)
79233
79351
  continue;
79234
- const content = readFileSync23(planFile, "utf-8");
79352
+ const content = readFileSync24(planFile, "utf-8");
79235
79353
  const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
79236
79354
  if (!frontmatterMatch)
79237
79355
  continue;
@@ -79996,7 +80114,7 @@ async function loadContentConfig(projectDir) {
79996
80114
  }
79997
80115
  async function saveContentConfig(projectDir, config) {
79998
80116
  const configPath = join171(projectDir, CK_CONFIG_FILE2);
79999
- const json = await readJsonSafe3(configPath);
80117
+ const json = await readJsonSafe4(configPath);
80000
80118
  json.content = { ...json.content, ...config };
80001
80119
  await atomicWrite3(configPath, json);
80002
80120
  }
@@ -80021,14 +80139,14 @@ async function saveContentState(projectDir, state) {
80021
80139
  }
80022
80140
  }
80023
80141
  ContentStateSchema.parse(state);
80024
- const json = await readJsonSafe3(configPath);
80142
+ const json = await readJsonSafe4(configPath);
80025
80143
  if (!json.content || typeof json.content !== "object") {
80026
80144
  json.content = {};
80027
80145
  }
80028
80146
  json.content.state = state;
80029
80147
  await atomicWrite3(configPath, json);
80030
80148
  }
80031
- async function readJsonSafe3(filePath) {
80149
+ async function readJsonSafe4(filePath) {
80032
80150
  try {
80033
80151
  const raw2 = await readFile71(filePath, "utf-8");
80034
80152
  return JSON.parse(raw2);
@@ -80503,7 +80621,7 @@ __export(exports_content_subcommands, {
80503
80621
  logsContent: () => logsContent,
80504
80622
  approveContentCmd: () => approveContentCmd
80505
80623
  });
80506
- import { existsSync as existsSync91, readFileSync as readFileSync24, unlinkSync as unlinkSync6 } from "node:fs";
80624
+ import { existsSync as existsSync91, readFileSync as readFileSync25, unlinkSync as unlinkSync6 } from "node:fs";
80507
80625
  import { homedir as homedir58 } from "node:os";
80508
80626
  import { join as join173 } from "node:path";
80509
80627
  function isDaemonRunning() {
@@ -80511,7 +80629,7 @@ function isDaemonRunning() {
80511
80629
  if (!existsSync91(lockFile))
80512
80630
  return { running: false, pid: null };
80513
80631
  try {
80514
- const pidStr = readFileSync24(lockFile, "utf-8").trim();
80632
+ const pidStr = readFileSync25(lockFile, "utf-8").trim();
80515
80633
  const pid = Number.parseInt(pidStr, 10);
80516
80634
  if (Number.isNaN(pid)) {
80517
80635
  unlinkSync6(lockFile);
@@ -80545,7 +80663,7 @@ async function stopContent() {
80545
80663
  return;
80546
80664
  }
80547
80665
  try {
80548
- const pidStr = readFileSync24(lockFile, "utf-8").trim();
80666
+ const pidStr = readFileSync25(lockFile, "utf-8").trim();
80549
80667
  const pid = Number.parseInt(pidStr, 10);
80550
80668
  if (!Number.isNaN(pid)) {
80551
80669
  process.kill(pid, "SIGTERM");
@@ -80593,7 +80711,7 @@ async function logsContent(options2) {
80593
80711
  process.exit(0);
80594
80712
  });
80595
80713
  } else {
80596
- const content = readFileSync24(logPath, "utf-8");
80714
+ const content = readFileSync25(logPath, "utf-8");
80597
80715
  console.log(content);
80598
80716
  }
80599
80717
  }
@@ -87963,7 +88081,7 @@ class CheckRunner {
87963
88081
  }
87964
88082
  // src/domains/health-checks/system-checker.ts
87965
88083
  import { exec as exec6 } from "node:child_process";
87966
- import { promisify as promisify13 } from "node:util";
88084
+ import { promisify as promisify14 } from "node:util";
87967
88085
 
87968
88086
  // src/domains/github/gh-cli-utils.ts
87969
88087
  init_environment();
@@ -88031,8 +88149,8 @@ function getGhUpgradeInstructions(currentVersion) {
88031
88149
  init_environment();
88032
88150
  init_logger();
88033
88151
  import { exec as exec3 } from "node:child_process";
88034
- import { promisify as promisify10 } from "node:util";
88035
- var execAsync3 = promisify10(exec3);
88152
+ import { promisify as promisify11 } from "node:util";
88153
+ var execAsync3 = promisify11(exec3);
88036
88154
  function getOSInfo() {
88037
88155
  const platform8 = process.platform;
88038
88156
  const arch2 = process.arch;
@@ -88253,7 +88371,7 @@ async function checkAllDependencies() {
88253
88371
  // src/services/package-installer/dependency-installer.ts
88254
88372
  init_logger();
88255
88373
  import { exec as exec5 } from "node:child_process";
88256
- import { promisify as promisify12 } from "node:util";
88374
+ import { promisify as promisify13 } from "node:util";
88257
88375
 
88258
88376
  // src/services/package-installer/dependencies/node-installer.ts
88259
88377
  var NODEJS_INSTALLERS = [
@@ -88347,8 +88465,8 @@ var PYTHON_INSTALLERS = [
88347
88465
  init_logger();
88348
88466
  import { exec as exec4 } from "node:child_process";
88349
88467
  import * as fs7 from "node:fs";
88350
- import { promisify as promisify11 } from "node:util";
88351
- var execAsync4 = promisify11(exec4);
88468
+ import { promisify as promisify12 } from "node:util";
88469
+ var execAsync4 = promisify12(exec4);
88352
88470
  async function detectOS() {
88353
88471
  const platform8 = process.platform;
88354
88472
  const info = { platform: platform8 };
@@ -88418,7 +88536,7 @@ var CLAUDE_INSTALLERS = [
88418
88536
  ];
88419
88537
 
88420
88538
  // src/services/package-installer/dependency-installer.ts
88421
- var execAsync5 = promisify12(exec5);
88539
+ var execAsync5 = promisify13(exec5);
88422
88540
  function getInstallerMethods(dependency, osInfo) {
88423
88541
  let installers = dependency === "claude" ? CLAUDE_INSTALLERS : dependency === "python" || dependency === "pip" ? PYTHON_INSTALLERS : dependency === "nodejs" ? NODEJS_INSTALLERS : [];
88424
88542
  installers = installers.filter((m2) => m2.platform === osInfo.platform);
@@ -88474,7 +88592,7 @@ async function installDependency(dependency, method) {
88474
88592
 
88475
88593
  // src/domains/health-checks/system-checker.ts
88476
88594
  init_logger();
88477
- var execAsync6 = promisify13(exec6);
88595
+ var execAsync6 = promisify14(exec6);
88478
88596
 
88479
88597
  class SystemChecker {
88480
88598
  group = "system";
@@ -101939,10 +102057,10 @@ class TarExtractor {
101939
102057
  // src/domains/installation/extraction/zip-extractor.ts
101940
102058
  init_logger();
101941
102059
  var import_extract_zip = __toESM(require_extract_zip(), 1);
101942
- import { execFile as execFile10 } from "node:child_process";
102060
+ import { execFile as execFile11 } from "node:child_process";
101943
102061
  import { copyFile as copyFile5, mkdir as mkdir29, readdir as readdir26, rm as rm12, stat as stat16 } from "node:fs/promises";
101944
102062
  import { join as join103 } from "node:path";
101945
- import { promisify as promisify15 } from "node:util";
102063
+ import { promisify as promisify16 } from "node:util";
101946
102064
 
101947
102065
  // src/domains/installation/extraction/native-zip-commands.ts
101948
102066
  var NATIVE_EXTRACT_TIMEOUT_MS = 120000;
@@ -101981,7 +102099,7 @@ function getNativeZipCommands(archivePath, destDir, platformName = process.platf
101981
102099
  }
101982
102100
 
101983
102101
  // src/domains/installation/extraction/zip-extractor.ts
101984
- var execFileAsync7 = promisify15(execFile10);
102102
+ var execFileAsync8 = promisify16(execFile11);
101985
102103
 
101986
102104
  class ZipExtractor {
101987
102105
  async tryNativeExtraction(archivePath, destDir) {
@@ -101993,7 +102111,7 @@ class ZipExtractor {
101993
102111
  try {
101994
102112
  await rm12(destDir, { recursive: true, force: true });
101995
102113
  await mkdir29(destDir, { recursive: true });
101996
- await execFileAsync7(nativeCommand.command, nativeCommand.args, {
102114
+ await execFileAsync8(nativeCommand.command, nativeCommand.args, {
101997
102115
  timeout: NATIVE_EXTRACT_TIMEOUT_MS,
101998
102116
  windowsHide: true
101999
102117
  });
@@ -108818,7 +108936,8 @@ async function handlePostInstall(ctx) {
108818
108936
  };
108819
108937
  }
108820
108938
  // src/commands/init/phases/plugin-install-handler.ts
108821
- import { cpSync as cpSync2, existsSync as existsSync69, mkdirSync as mkdirSync6, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
108939
+ init_codex_plugin_installer();
108940
+ import { cpSync as cpSync2, existsSync as existsSync69, mkdirSync as mkdirSync6, readFileSync as readFileSync21, rmSync as rmSync4, writeFileSync as writeFileSync8 } from "node:fs";
108822
108941
  import { join as join135 } from "node:path";
108823
108942
 
108824
108943
  // src/domains/installation/plugin/migrate-legacy-to-plugin.ts
@@ -108828,18 +108947,18 @@ import { dirname as dirname43, join as join134 } from "node:path";
108828
108947
 
108829
108948
  // src/domains/installation/plugin/plugin-installer.ts
108830
108949
  init_install_mode_detector();
108831
- import { execFile as execFile11 } from "node:child_process";
108832
- import { promisify as promisify16 } from "node:util";
108833
- var execFileAsync8 = promisify16(execFile11);
108834
- var DEFAULT_TIMEOUT_MS2 = 120000;
108950
+ import { execFile as execFile12 } from "node:child_process";
108951
+ import { promisify as promisify17 } from "node:util";
108952
+ var execFileAsync9 = promisify17(execFile12);
108953
+ var DEFAULT_TIMEOUT_MS3 = 120000;
108835
108954
  var defaultClaudeRunner = async (args, opts) => {
108836
108955
  const env2 = { ...process.env };
108837
108956
  if (opts?.configDir)
108838
108957
  env2.CLAUDE_CONFIG_DIR = opts.configDir;
108839
108958
  try {
108840
- const { stdout: stdout2, stderr } = await execFileAsync8("claude", args, {
108959
+ const { stdout: stdout2, stderr } = await execFileAsync9("claude", args, {
108841
108960
  env: env2,
108842
- timeout: opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
108961
+ timeout: opts?.timeoutMs ?? DEFAULT_TIMEOUT_MS3,
108843
108962
  maxBuffer: 10 * 1024 * 1024
108844
108963
  });
108845
108964
  return { ok: true, stdout: String(stdout2), stderr: String(stderr), code: 0 };
@@ -109065,12 +109184,23 @@ async function handlePluginInstall(ctx, deps = {}) {
109065
109184
  return ctx;
109066
109185
  }
109067
109186
  const migrate = deps.migrate ?? migrateLegacyToPlugin;
109187
+ const installCodex = deps.installCodex ?? installCodexPlugin;
109068
109188
  try {
109069
109189
  const pluginSourceDir = stagePluginSource(ctx.extractDir, deps.stageBaseDir);
109070
- const result = await migrate({ pluginSourceDir, claudeDir: ctx.claudeDir });
109071
- logPluginResult(result);
109190
+ try {
109191
+ const result = await migrate({ pluginSourceDir, claudeDir: ctx.claudeDir });
109192
+ logPluginResult(result);
109193
+ } catch (err) {
109194
+ logger.verbose(`Claude plugin install skipped (legacy copy retained): ${err.message}`);
109195
+ }
109196
+ try {
109197
+ const result = await installCodex({ pluginSourceDir });
109198
+ logCodexPluginResult(result);
109199
+ } catch (err) {
109200
+ logger.verbose(`Codex plugin install skipped: ${err.message}`);
109201
+ }
109072
109202
  } catch (err) {
109073
- logger.verbose(`Plugin install skipped (legacy copy retained): ${err.message}`);
109203
+ logger.verbose(`Plugin staging skipped (legacy copy retained): ${err.message}`);
109074
109204
  }
109075
109205
  return ctx;
109076
109206
  }
@@ -109082,17 +109212,88 @@ function stagePluginSource(extractDir, stageBaseDir) {
109082
109212
  }
109083
109213
  rmSync4(base2, { recursive: true, force: true });
109084
109214
  mkdirSync6(base2, { recursive: true });
109085
- cpSync2(payloadSrc, join135(base2, ".claude"), { recursive: true });
109086
- const marketplace = {
109215
+ const stagedPayload = join135(base2, ".claude");
109216
+ cpSync2(payloadSrc, stagedPayload, { recursive: true });
109217
+ ensureCodexPluginManifest(stagedPayload);
109218
+ const claudeMarketplace = {
109087
109219
  name: "claudekit",
109088
109220
  owner: { name: "ClaudeKit" },
109089
109221
  plugins: [{ name: "ck", source: "./.claude", description: "ClaudeKit Engineer" }]
109090
109222
  };
109091
109223
  mkdirSync6(join135(base2, ".claude-plugin"), { recursive: true });
109092
- writeFileSync8(join135(base2, ".claude-plugin", "marketplace.json"), `${JSON.stringify(marketplace, null, 2)}
109224
+ writeFileSync8(join135(base2, ".claude-plugin", "marketplace.json"), `${JSON.stringify(claudeMarketplace, null, 2)}
109225
+ `, "utf-8");
109226
+ const codexMarketplace = {
109227
+ name: "claudekit",
109228
+ interface: { displayName: "ClaudeKit" },
109229
+ plugins: [
109230
+ {
109231
+ name: "ck",
109232
+ source: { source: "local", path: "./.claude" },
109233
+ policy: { installation: "AVAILABLE", authentication: "ON_INSTALL" },
109234
+ category: "Productivity"
109235
+ }
109236
+ ]
109237
+ };
109238
+ mkdirSync6(join135(base2, ".agents", "plugins"), { recursive: true });
109239
+ writeFileSync8(join135(base2, ".agents", "plugins", "marketplace.json"), `${JSON.stringify(codexMarketplace, null, 2)}
109093
109240
  `, "utf-8");
109094
109241
  return base2;
109095
109242
  }
109243
+ function ensureCodexPluginManifest(pluginRoot) {
109244
+ const manifestPath = join135(pluginRoot, ".codex-plugin", "plugin.json");
109245
+ if (existsSync69(manifestPath))
109246
+ return;
109247
+ const claudeManifest = readJsonSafe3(join135(pluginRoot, ".claude-plugin", "plugin.json"));
109248
+ const manifest = pruneUndefined({
109249
+ name: stringField(claudeManifest, "name") ?? "ck",
109250
+ version: stringField(claudeManifest, "version") ?? "0.0.0",
109251
+ description: stringField(claudeManifest, "description") ?? "ClaudeKit Engineer — multi-agent planning, code review, debugging, and workflow skills for Codex.",
109252
+ author: authorField(claudeManifest),
109253
+ homepage: stringField(claudeManifest, "homepage"),
109254
+ repository: stringField(claudeManifest, "repository"),
109255
+ license: stringField(claudeManifest, "license"),
109256
+ keywords: ["claudekit", "codex", "skills", "agents", "workflow"],
109257
+ skills: "./skills/",
109258
+ interface: {
109259
+ displayName: "ClaudeKit Engineer",
109260
+ shortDescription: "ClaudeKit planning, review, debugging, and workflow skills.",
109261
+ longDescription: "ClaudeKit Engineer provides planning, code review, debugging, testing, browser workflow, and implementation skills for Codex.",
109262
+ developerName: "ClaudeKit",
109263
+ category: "Productivity",
109264
+ capabilities: ["Skills"],
109265
+ websiteURL: "https://github.com/claudekit/claudekit-engineer"
109266
+ }
109267
+ });
109268
+ mkdirSync6(join135(pluginRoot, ".codex-plugin"), { recursive: true });
109269
+ writeFileSync8(manifestPath, `${JSON.stringify(manifest, null, 2)}
109270
+ `, "utf-8");
109271
+ }
109272
+ function readJsonSafe3(filePath) {
109273
+ try {
109274
+ const parsed = JSON.parse(readFileSync21(filePath, "utf-8"));
109275
+ return isRecord3(parsed) ? parsed : null;
109276
+ } catch {
109277
+ return null;
109278
+ }
109279
+ }
109280
+ function stringField(source, key) {
109281
+ const value = source?.[key];
109282
+ return typeof value === "string" && value.trim() !== "" ? value : undefined;
109283
+ }
109284
+ function authorField(source) {
109285
+ const author = source?.author;
109286
+ if (isRecord3(author) && typeof author.name === "string" && author.name.trim() !== "") {
109287
+ return { name: author.name };
109288
+ }
109289
+ return { name: "ClaudeKit" };
109290
+ }
109291
+ function pruneUndefined(value) {
109292
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));
109293
+ }
109294
+ function isRecord3(value) {
109295
+ return typeof value === "object" && value !== null && !Array.isArray(value);
109296
+ }
109096
109297
  function logPluginResult(result) {
109097
109298
  switch (result.action) {
109098
109299
  case "migrated-from-legacy":
@@ -109112,6 +109313,19 @@ function logPluginResult(result) {
109112
109313
  break;
109113
109314
  }
109114
109315
  }
109316
+ function logCodexPluginResult(result) {
109317
+ switch (result.action) {
109318
+ case "installed":
109319
+ logger.info("Installed ClaudeKit Engineer as a Codex plugin.");
109320
+ break;
109321
+ case "skipped-codex-unsupported":
109322
+ logger.verbose("Codex plugin support unavailable; skipped Codex plugin install.");
109323
+ break;
109324
+ case "install-failed":
109325
+ logger.verbose(`Codex plugin install did not verify. ${result.error ?? ""}`);
109326
+ break;
109327
+ }
109328
+ }
109115
109329
  // src/commands/init/phases/selection-handler.ts
109116
109330
  init_config_manager();
109117
109331
  init_github_client();
@@ -109187,8 +109401,8 @@ async function detectAccessibleKits() {
109187
109401
  // src/domains/github/preflight-checker.ts
109188
109402
  init_logger();
109189
109403
  import { exec as exec8 } from "node:child_process";
109190
- import { promisify as promisify17 } from "node:util";
109191
- var execAsync8 = promisify17(exec8);
109404
+ import { promisify as promisify18 } from "node:util";
109405
+ var execAsync8 = promisify18(exec8);
109192
109406
  function createSuccessfulPreflightResult() {
109193
109407
  return {
109194
109408
  success: true,
@@ -118456,7 +118670,7 @@ function registerCommands(cli) {
118456
118670
  // src/cli/version-display.ts
118457
118671
  init_package();
118458
118672
  init_config_version_checker();
118459
- import { existsSync as existsSync94, readFileSync as readFileSync25 } from "node:fs";
118673
+ import { existsSync as existsSync94, readFileSync as readFileSync26 } from "node:fs";
118460
118674
  import { join as join176 } from "node:path";
118461
118675
 
118462
118676
  // src/domains/versioning/version-checker.ts
@@ -118796,7 +119010,7 @@ async function displayVersion() {
118796
119010
  const isLocalSameAsGlobal = localMetadataPath === globalMetadataPath;
118797
119011
  if (!isLocalSameAsGlobal && existsSync94(localMetadataPath)) {
118798
119012
  try {
118799
- const rawMetadata = JSON.parse(readFileSync25(localMetadataPath, "utf-8"));
119013
+ const rawMetadata = JSON.parse(readFileSync26(localMetadataPath, "utf-8"));
118800
119014
  const metadata = MetadataSchema.parse(rawMetadata);
118801
119015
  const kitsDisplay = formatInstalledKits(metadata);
118802
119016
  if (kitsDisplay) {
@@ -118810,7 +119024,7 @@ async function displayVersion() {
118810
119024
  }
118811
119025
  if (existsSync94(globalMetadataPath)) {
118812
119026
  try {
118813
- const rawMetadata = JSON.parse(readFileSync25(globalMetadataPath, "utf-8"));
119027
+ const rawMetadata = JSON.parse(readFileSync26(globalMetadataPath, "utf-8"));
118814
119028
  const metadata = MetadataSchema.parse(rawMetadata);
118815
119029
  const kitsDisplay = formatInstalledKits(metadata);
118816
119030
  if (kitsDisplay) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudekit-cli",
3
- "version": "4.5.0-dev.3",
3
+ "version": "4.5.0-dev.4",
4
4
  "description": "CLI tool for bootstrapping and updating ClaudeKit projects",
5
5
  "type": "module",
6
6
  "repository": {