@orchid-labs/pluxx 0.1.20 → 0.1.21

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.
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAUA,OAAO,EAAuE,KAAK,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AA+B3I,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;AAElE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,gBAAgB,CAAC,EAAE,2BAA2B,CAAA;CAC/C;AAuCD,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AA4qED,wBAAsB,cAAc,CAClC,OAAO,GAAE,MAAsB,EAC/B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,YAAY,CAAC,CAkEvB;AAED,wBAAsB,aAAa,CAAC,OAAO,GAAE,MAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkF1F;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAyB5D"}
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAUA,OAAO,EAAuE,KAAK,2BAA2B,EAAE,MAAM,qBAAqB,CAAA;AA+B3I,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAA;AAElE,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,gBAAgB,CAAC,EAAE,2BAA2B,CAAA;CAC/C;AAuCD,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AA+qED,wBAAsB,cAAc,CAClC,OAAO,GAAE,MAAsB,EAC/B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,YAAY,CAAC,CAkEvB;AAED,wBAAsB,aAAa,CAAC,OAAO,GAAE,MAAsB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkF1F;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAyB5D"}
package/dist/cli/index.js CHANGED
@@ -5386,9 +5386,9 @@ var Generator = class {
5386
5386
  for (const configPath of this.config.passthrough ?? []) {
5387
5387
  const src = this.resolveConfigPath(configPath, "passthrough");
5388
5388
  if (!existsSync4(src)) continue;
5389
- const basename10 = src.split("/").filter(Boolean).pop();
5390
- if (!basename10) continue;
5391
- this.copyDir(configPath, `${basename10}/`, "passthrough");
5389
+ const basename11 = src.split("/").filter(Boolean).pop();
5390
+ if (!basename11) continue;
5391
+ this.copyDir(configPath, `${basename11}/`, "passthrough");
5392
5392
  }
5393
5393
  }
5394
5394
  /** Build canonical MCP server configs for target-specific output shaping. */
@@ -6151,18 +6151,18 @@ function getRuntimeReadinessCapability(platform, pluginRootVar = "PLUGIN_ROOT")
6151
6151
  {
6152
6152
  gate: "session-start",
6153
6153
  event: "SessionStart",
6154
- command: "node ./.codex/pluxx-readiness.mjs session-start"
6154
+ command: `node "\${${pluginRootVar}}/.codex/pluxx-readiness.mjs" session-start`
6155
6155
  },
6156
6156
  {
6157
6157
  gate: "mcp-gate",
6158
6158
  event: "PreToolUse",
6159
6159
  matcher: "MCP",
6160
- command: "node ./.codex/pluxx-readiness.mjs mcp-gate"
6160
+ command: `node "\${${pluginRootVar}}/.codex/pluxx-readiness.mjs" mcp-gate`
6161
6161
  },
6162
6162
  {
6163
6163
  gate: "prompt-gate",
6164
6164
  event: "UserPromptSubmit",
6165
- command: "node ./.codex/pluxx-readiness.mjs prompt-gate"
6165
+ command: `node "\${${pluginRootVar}}/.codex/pluxx-readiness.mjs" prompt-gate`
6166
6166
  }
6167
6167
  ],
6168
6168
  notes: CODEX_EXTERNAL_NOTE
@@ -6378,6 +6378,9 @@ function shellSingleQuote(value) {
6378
6378
  return `'${value.replace(/'/g, `'"'"'`)}'`;
6379
6379
  }
6380
6380
  function buildHookCommandWrapperScript(command2, pluginRootVar, envFileVar) {
6381
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(pluginRootVar)) {
6382
+ throw new Error(`Invalid plugin root environment variable name: ${pluginRootVar}`);
6383
+ }
6381
6384
  const serializedCommand = shellSingleQuote(command2);
6382
6385
  const exportLoader = [
6383
6386
  'import { readFileSync } from "node:fs"',
@@ -6406,6 +6409,8 @@ function buildHookCommandWrapperScript(command2, pluginRootVar, envFileVar) {
6406
6409
  "set -euo pipefail",
6407
6410
  "",
6408
6411
  `PLUXX_PLUGIN_ROOT="\${${pluginRootVar}:-$(cd "$(dirname "$0")/.." && pwd)}"`,
6412
+ `export ${pluginRootVar}="$PLUXX_PLUGIN_ROOT"`,
6413
+ 'export PLUGIN_ROOT="$PLUXX_PLUGIN_ROOT"',
6409
6414
  'PLUXX_USER_CONFIG_PATH="$PLUXX_PLUGIN_ROOT/.pluxx-user.json"',
6410
6415
  "",
6411
6416
  'if [ -f "$PLUXX_USER_CONFIG_PATH" ]; then',
@@ -10145,7 +10150,7 @@ var CodexGenerator = class extends Generator {
10145
10150
  }
10146
10151
  async generateHooksCompanion() {
10147
10152
  const readinessPlan = getRuntimeReadinessPlan(this.config.readiness);
10148
- const readinessCapability = getRuntimeReadinessCapability("codex");
10153
+ const readinessCapability = getRuntimeReadinessCapability("codex", "CODEX_PLUGIN_ROOT");
10149
10154
  if (!this.config.hooks && !readinessPlan.hasReadiness) return;
10150
10155
  const hooks = {};
10151
10156
  const unsupported = [];
@@ -10193,12 +10198,12 @@ var CodexGenerator = class extends Generator {
10193
10198
  const relativePath = `hooks/pluxx-hook-command-${nextWrapperIndex}.sh`;
10194
10199
  await this.writeFile(
10195
10200
  relativePath,
10196
- buildHookCommandWrapperScript(entry.command.replace("${PLUGIN_ROOT}", "."), "CODEX_PLUGIN_ROOT")
10201
+ buildHookCommandWrapperScript(entry.command.replace("${PLUGIN_ROOT}", "${PLUXX_PLUGIN_ROOT}"), "CODEX_PLUGIN_ROOT")
10197
10202
  );
10198
10203
  const matcher = typeof entry.matcher === "string" && isHookFieldPreserved("codex", "matcher", codexEvent) ? entry.matcher : void 0;
10199
10204
  mappedEntries.push(this.buildCodexCommandHookGroup(
10200
10205
  codexEvent,
10201
- `bash ./${relativePath}`,
10206
+ `bash "\${CODEX_PLUGIN_ROOT}/${relativePath}"`,
10202
10207
  matcher,
10203
10208
  entry.timeout
10204
10209
  ));
@@ -10227,7 +10232,7 @@ var CodexGenerator = class extends Generator {
10227
10232
  }
10228
10233
  async generateReadinessCompanion() {
10229
10234
  const readinessPlan = getRuntimeReadinessPlan(this.config.readiness);
10230
- const readinessCapability = getRuntimeReadinessCapability("codex");
10235
+ const readinessCapability = getRuntimeReadinessCapability("codex", "CODEX_PLUGIN_ROOT");
10231
10236
  if (!readinessPlan.hasReadiness || !this.config.readiness) return;
10232
10237
  const translatedHooks = Object.fromEntries(
10233
10238
  getEnabledRuntimeReadinessBindings(readinessCapability, readinessPlan).map((binding) => [
@@ -17987,10 +17992,10 @@ ${additions.map((block) => `- ${block.replace(/\n/g, "\n ")}`).join("\n")}
17987
17992
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
17988
17993
  import { accessSync, constants, existsSync as existsSync24, lstatSync as lstatSync3, readFileSync as readFileSync14, readdirSync as readdirSync10, realpathSync } from "fs";
17989
17994
  import { homedir as homedir2 } from "os";
17990
- import { basename as basename6, dirname as dirname7, resolve as resolve20 } from "path";
17995
+ import { basename as basename7, dirname as dirname7, resolve as resolve20 } from "path";
17991
17996
 
17992
17997
  // src/cli/install.ts
17993
- import { resolve as resolve19, dirname as dirname6 } from "path";
17998
+ import { resolve as resolve19, dirname as dirname6, basename as basename6, relative as relative11 } from "path";
17994
17999
  import { existsSync as existsSync23, symlinkSync, mkdirSync as mkdirSync4, rmSync as rmSync3, readFileSync as readFileSync13, writeFileSync as writeFileSync4, cpSync as cpSync3, readdirSync as readdirSync9 } from "fs";
17995
18000
  import { spawnSync } from "child_process";
17996
18001
  import * as readline2 from "readline";
@@ -18676,7 +18681,7 @@ function resolveBundleReference(rootDir, value) {
18676
18681
  if (isRelativeBundlePath(value)) {
18677
18682
  return resolve19(rootDir, value);
18678
18683
  }
18679
- const pluginRootMatch = value.match(/^\$\{(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|PLUGIN_ROOT)\}[\\/](.+)$/);
18684
+ const pluginRootMatch = value.match(/^\$\{(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|CODEX_PLUGIN_ROOT|OPENCODE_PLUGIN_ROOT|PLUGIN_ROOT|PLUXX_PLUGIN_ROOT)\}[\\/](.+)$/);
18680
18685
  if (pluginRootMatch) {
18681
18686
  return resolve19(rootDir, pluginRootMatch[1]);
18682
18687
  }
@@ -18719,9 +18724,43 @@ function collectHookCommandStrings(value, commands) {
18719
18724
  }
18720
18725
  }
18721
18726
  function extractBundleCommandTargets(command2) {
18722
- const matches = command2.match(/\$\{(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|PLUGIN_ROOT)\}[\\/][^\s"'`;$|&<>]+|\.\.?[\\/][^\s"'`;$|&<>]+/g);
18727
+ const matches = command2.match(/\$\{(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|CODEX_PLUGIN_ROOT|OPENCODE_PLUGIN_ROOT|PLUGIN_ROOT|PLUXX_PLUGIN_ROOT)\}[\\/][^\s"'`;$|&<>]+|\.\.?[\\/][^\s"'`;$|&<>]+/g);
18723
18728
  return matches ?? [];
18724
18729
  }
18730
+ function extractRelativeBundleCommandTargets(command2) {
18731
+ return extractBundleCommandTargets(command2).filter(isRelativeBundlePath);
18732
+ }
18733
+ function commandChangesToKnownPluginRoot(command2) {
18734
+ return /\bcd\s+["']?\$\{?(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|CODEX_PLUGIN_ROOT|OPENCODE_PLUGIN_ROOT|PLUGIN_ROOT|PLUXX_PLUGIN_ROOT)\}?/.test(command2);
18735
+ }
18736
+ function formatBundleRelativePath(rootDir, filePath) {
18737
+ const relativePath = relative11(rootDir, filePath);
18738
+ return relativePath && !relativePath.startsWith("..") ? relativePath : filePath;
18739
+ }
18740
+ function findHookWrapperPaths(rootDir, command2) {
18741
+ return extractBundleCommandTargets(command2).map((target) => resolveBundleReference(rootDir, target)).filter((target) => {
18742
+ if (!target) return false;
18743
+ return existsSync23(target) && basename6(target).startsWith("pluxx-hook-command-") && target.endsWith(".sh");
18744
+ });
18745
+ }
18746
+ function findCodexCwdUnsafeHookCommands(rootDir, commands) {
18747
+ const issues = /* @__PURE__ */ new Set();
18748
+ for (const command2 of commands) {
18749
+ const relativeTargets = extractRelativeBundleCommandTargets(command2);
18750
+ if (relativeTargets.length > 0 && !commandChangesToKnownPluginRoot(command2)) {
18751
+ issues.add(`${command2} uses cwd-relative bundle target(s): ${relativeTargets.join(", ")}`);
18752
+ }
18753
+ for (const wrapperPath of findHookWrapperPaths(rootDir, command2)) {
18754
+ const wrapper = readFileSync13(wrapperPath, "utf-8");
18755
+ const hookCommand = wrapper.match(/^PLUXX_HOOK_COMMAND=(.*)$/m)?.[1] ?? "";
18756
+ const wrapperRelativeTargets = extractRelativeBundleCommandTargets(hookCommand);
18757
+ if (wrapperRelativeTargets.length > 0 && !commandChangesToKnownPluginRoot(wrapper)) {
18758
+ issues.add(`${formatBundleRelativePath(rootDir, wrapperPath)} evaluates cwd-relative bundle target(s): ${wrapperRelativeTargets.join(", ")}`);
18759
+ }
18760
+ }
18761
+ }
18762
+ return [...issues].sort();
18763
+ }
18725
18764
  function resolveInstalledHooksReference(rootDir, platform, manifest) {
18726
18765
  const manifestReference = typeof manifest.hooks === "string" ? manifest.hooks : void 0;
18727
18766
  if (manifestReference) {
@@ -18759,6 +18798,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
18759
18798
  return {
18760
18799
  missingManifestPaths: [],
18761
18800
  missingHookTargets: [],
18801
+ cwdUnsafeHookCommands: [],
18762
18802
  invalidRuntimeScripts: []
18763
18803
  };
18764
18804
  }
@@ -18768,6 +18808,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
18768
18808
  manifestIssue: `missing plugin manifest at ${manifestPath}`,
18769
18809
  missingManifestPaths: [],
18770
18810
  missingHookTargets: [],
18811
+ cwdUnsafeHookCommands: [],
18771
18812
  invalidRuntimeScripts: []
18772
18813
  };
18773
18814
  }
@@ -18779,6 +18820,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
18779
18820
  manifestIssue: `plugin manifest at ${manifestPath} is not parseable: ${error instanceof Error ? error.message : String(error)}`,
18780
18821
  missingManifestPaths: [],
18781
18822
  missingHookTargets: [],
18823
+ cwdUnsafeHookCommands: [],
18782
18824
  invalidRuntimeScripts: []
18783
18825
  };
18784
18826
  }
@@ -18793,6 +18835,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
18793
18835
  ...manifestIssue ? { manifestIssue } : {},
18794
18836
  missingManifestPaths,
18795
18837
  missingHookTargets: [],
18838
+ cwdUnsafeHookCommands: [],
18796
18839
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
18797
18840
  };
18798
18841
  }
@@ -18801,6 +18844,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
18801
18844
  ...manifestIssue ? { manifestIssue } : {},
18802
18845
  missingManifestPaths,
18803
18846
  missingHookTargets: [],
18847
+ cwdUnsafeHookCommands: [],
18804
18848
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
18805
18849
  };
18806
18850
  }
@@ -18814,10 +18858,12 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
18814
18858
  return resolved !== void 0 && !existsSync23(resolved);
18815
18859
  })
18816
18860
  )].sort();
18861
+ const cwdUnsafeHookCommands = platform === "codex" ? findCodexCwdUnsafeHookCommands(rootDir, commands) : [];
18817
18862
  return {
18818
18863
  ...manifestIssue ? { manifestIssue } : {},
18819
18864
  missingManifestPaths,
18820
18865
  missingHookTargets,
18866
+ cwdUnsafeHookCommands,
18821
18867
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
18822
18868
  };
18823
18869
  } catch (error) {
@@ -18826,6 +18872,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
18826
18872
  hookConfigIssue: `hooks config at ${hooksReference} is not parseable: ${error instanceof Error ? error.message : String(error)}`,
18827
18873
  missingManifestPaths,
18828
18874
  missingHookTargets: [],
18875
+ cwdUnsafeHookCommands: [],
18829
18876
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
18830
18877
  };
18831
18878
  }
@@ -18875,6 +18922,9 @@ function assertInstalledBundleIntegrity(rootDir, platform, label) {
18875
18922
  if (issues.missingHookTargets.length > 0) {
18876
18923
  details.push(`hook targets missing: ${issues.missingHookTargets.join(", ")}`);
18877
18924
  }
18925
+ if (issues.cwdUnsafeHookCommands.length > 0) {
18926
+ details.push(`hook commands require plugin-root cwd: ${issues.cwdUnsafeHookCommands.join("; ")}`);
18927
+ }
18878
18928
  if (issues.invalidRuntimeScripts.length > 0) {
18879
18929
  details.push(`runtime script issues: ${issues.invalidRuntimeScripts.join(", ")}`);
18880
18930
  }
@@ -19961,7 +20011,7 @@ function listClaudeSettingsCandidates(projectRoot) {
19961
20011
  });
19962
20012
  }
19963
20013
  function readClaudeDisableAllHooks(filePath) {
19964
- const parsed = readJsonFile2(dirname7(filePath), basename6(filePath));
20014
+ const parsed = readJsonFile2(dirname7(filePath), basename7(filePath));
19965
20015
  return typeof parsed.disableAllHooks === "boolean" ? parsed.disableAllHooks : void 0;
19966
20016
  }
19967
20017
  function probeClaudeDisableAllHooks(projectRoot) {
@@ -20304,6 +20354,9 @@ function checkInstalledBundleIntegrity(checks, rootDir, layout) {
20304
20354
  if (issues.missingHookTargets.length > 0) {
20305
20355
  details.push(`hook commands reference missing bundle target${issues.missingHookTargets.length === 1 ? "" : "s"}: ${issues.missingHookTargets.join(", ")}`);
20306
20356
  }
20357
+ if (issues.cwdUnsafeHookCommands.length > 0) {
20358
+ details.push(`Codex hook command${issues.cwdUnsafeHookCommands.length === 1 ? " depends" : "s depend"} on plugin-root cwd: ${issues.cwdUnsafeHookCommands.join("; ")}`);
20359
+ }
20307
20360
  if (issues.invalidRuntimeScripts.length > 0) {
20308
20361
  details.push(`runtime startup still depends on installer-owned validation: ${issues.invalidRuntimeScripts.join(", ")}`);
20309
20362
  }
@@ -20323,7 +20376,7 @@ function checkInstalledBundleIntegrity(checks, rootDir, layout) {
20323
20376
  code: "consumer-bundle-integrity-invalid",
20324
20377
  title: "Installed bundle integrity is broken",
20325
20378
  detail: details.join("; "),
20326
- fix: "Reinstall the plugin or rebuild the bundle so every manifest path, hook config, and hook target is valid inside the installed plugin.",
20379
+ fix: "Reinstall the plugin or rebuild the bundle so every manifest path, hook config, and hook command resolves from the installed plugin root.",
20327
20380
  path: layout.manifestPath
20328
20381
  });
20329
20382
  }
@@ -20405,7 +20458,7 @@ function checkInstalledCodexHooksFeatureFlag(checks, rootDir, layout, options) {
20405
20458
  path: generalOnlyProbes[0].path
20406
20459
  });
20407
20460
  }
20408
- const legacyOnlyProbes = probes.filter((probe) => probe.alternateEnabled && !probe.recommendedEnabled);
20461
+ const legacyOnlyProbes = probes.filter((probe) => !probe.pluginBundledEnabled && probe.alternateEnabled && !probe.recommendedEnabled);
20409
20462
  if (legacyOnlyProbes.length > 0) {
20410
20463
  addCheck2(checks, {
20411
20464
  level: "warning",
@@ -20796,7 +20849,7 @@ function isLikelyLocalRuntimePath3(value) {
20796
20849
  function isLikelyOpenCodeInstallPath(rootDir) {
20797
20850
  const parent = dirname7(rootDir);
20798
20851
  const grandparent = dirname7(parent);
20799
- return basename6(parent) === "plugins" && basename6(grandparent) === "opencode";
20852
+ return basename7(parent) === "plugins" && basename7(grandparent) === "opencode";
20800
20853
  }
20801
20854
  function checkInstalledOpenCodeHostBridge(checks, rootDir) {
20802
20855
  if (!isLikelyOpenCodeInstallPath(rootDir)) {
@@ -20810,7 +20863,7 @@ function checkInstalledOpenCodeHostBridge(checks, rootDir) {
20810
20863
  });
20811
20864
  return;
20812
20865
  }
20813
- const pluginName = basename6(rootDir);
20866
+ const pluginName = basename7(rootDir);
20814
20867
  const entryPath = `${rootDir}.ts`;
20815
20868
  const entryRelativePath = `${pluginName}.ts`;
20816
20869
  if (!existsSync24(entryPath)) {
@@ -20851,7 +20904,7 @@ function checkInstalledOpenCodeSkills(checks, rootDir) {
20851
20904
  if (!isLikelyOpenCodeInstallPath(rootDir)) {
20852
20905
  return;
20853
20906
  }
20854
- const pluginName = basename6(rootDir);
20907
+ const pluginName = basename7(rootDir);
20855
20908
  const sourceSkillsDir = resolve20(rootDir, "skills");
20856
20909
  if (!existsSync24(sourceSkillsDir)) {
20857
20910
  addCheck2(checks, {
@@ -21079,7 +21132,7 @@ function printDoctorReport(report) {
21079
21132
 
21080
21133
  // src/cli/dev.ts
21081
21134
  import { watch } from "fs";
21082
- import { relative as relative11, resolve as resolve21 } from "path";
21135
+ import { relative as relative12, resolve as resolve21 } from "path";
21083
21136
  var WATCH_PATTERNS = [
21084
21137
  /^pluxx\.config\.(ts|js|json)$/,
21085
21138
  /^skills\//,
@@ -21105,7 +21158,7 @@ async function runDev(args2) {
21105
21158
  let pendingFile = null;
21106
21159
  const watcher = watch(rootDir, { recursive: true }, (_event, filename) => {
21107
21160
  if (!filename) return;
21108
- const rel = relative11(rootDir, resolve21(rootDir, filename));
21161
+ const rel = relative12(rootDir, resolve21(rootDir, filename));
21109
21162
  if (rel.startsWith("dist/") || rel.startsWith(".") || rel.includes("node_modules")) {
21110
21163
  return;
21111
21164
  }
@@ -21160,7 +21213,7 @@ async function runBuild(rootDir, targets) {
21160
21213
  }
21161
21214
 
21162
21215
  // src/cli/migrate.ts
21163
- import { basename as basename7, dirname as dirname8, relative as relative12, resolve as resolve22 } from "path";
21216
+ import { basename as basename8, dirname as dirname8, relative as relative13, resolve as resolve22 } from "path";
21164
21217
  import { existsSync as existsSync25, readdirSync as readdirSync11, mkdirSync as mkdirSync5, cpSync as cpSync4, readFileSync as readFileSync15, writeFileSync as writeFileSync5 } from "fs";
21165
21218
  function detectPlatform(pluginDir) {
21166
21219
  const checks = [
@@ -21525,7 +21578,7 @@ function parseCursorRuleFile(pluginDir, filePath) {
21525
21578
  const content = readFileSync15(filePath, "utf-8");
21526
21579
  const { hasFrontmatter, frontmatterLines, body } = splitMarkdownFrontmatter5(content);
21527
21580
  if (!hasFrontmatter) return null;
21528
- const description = parseTopLevelStringFrontmatter(frontmatterLines, "description") ?? titleCaseFromDirName(basename7(filePath, ".mdc"));
21581
+ const description = parseTopLevelStringFrontmatter(frontmatterLines, "description") ?? titleCaseFromDirName(basename8(filePath, ".mdc"));
21529
21582
  const globs = parseTopLevelStringOrStringArrayFrontmatter(frontmatterLines, "globs");
21530
21583
  const alwaysApply = parseTopLevelBooleanFrontmatter(frontmatterLines, "alwaysApply");
21531
21584
  return {
@@ -21533,7 +21586,7 @@ function parseCursorRuleFile(pluginDir, filePath) {
21533
21586
  ...globs !== void 0 ? { globs } : {},
21534
21587
  ...alwaysApply !== void 0 ? { alwaysApply } : {},
21535
21588
  ...body.trim() ? { content: body.trim() } : {},
21536
- path: `./${relative12(pluginDir, filePath).replace(/\\/g, "/")}`
21589
+ path: `./${relative13(pluginDir, filePath).replace(/\\/g, "/")}`
21537
21590
  };
21538
21591
  }
21539
21592
  function collectFiles(dir, predicate) {
@@ -21578,7 +21631,7 @@ function findInstructionSources(pluginDir, detection) {
21578
21631
  const extraPaths = /* @__PURE__ */ new Set();
21579
21632
  const platformOverrides = {};
21580
21633
  if (detection.platform === "cursor") {
21581
- const nestedAgents = collectFiles(pluginDir, (entry) => entry === "AGENTS.md").map((path) => `./${relative12(pluginDir, path).replace(/\\/g, "/")}`).filter((path) => path !== primary);
21634
+ const nestedAgents = collectFiles(pluginDir, (entry) => entry === "AGENTS.md").map((path) => `./${relative13(pluginDir, path).replace(/\\/g, "/")}`).filter((path) => path !== primary);
21582
21635
  if (nestedAgents.length > 0) {
21583
21636
  platformOverrides.cursor = {
21584
21637
  ...platformOverrides.cursor ?? {},
@@ -22241,7 +22294,7 @@ function hasTopLevelFrontmatterKey(frontmatterLines, key) {
22241
22294
  function normalizeMigratedOpenCodeAgentFile(agentPath) {
22242
22295
  const original = readFileSync15(agentPath, "utf-8");
22243
22296
  const parsed = splitMarkdownFrontmatter5(original);
22244
- const fileStem = toKebabCase2(basename7(agentPath, ".md")) || "agent";
22297
+ const fileStem = toKebabCase2(basename8(agentPath, ".md")) || "agent";
22245
22298
  const fallbackDescription = buildFallbackAgentDescription(fileStem);
22246
22299
  if (!parsed.hasFrontmatter) {
22247
22300
  const rewritten2 = [
@@ -22297,7 +22350,7 @@ function normalizeMigratedOpenCodeAgents(destDir) {
22297
22350
  const normalized = [];
22298
22351
  for (const filePath of walkMarkdownFiles3(destDir)) {
22299
22352
  if (normalizeMigratedOpenCodeAgentFile(filePath)) {
22300
- normalized.push(relative12(destDir, filePath).replace(/\\/g, "/"));
22353
+ normalized.push(relative13(destDir, filePath).replace(/\\/g, "/"));
22301
22354
  }
22302
22355
  }
22303
22356
  return normalized.sort();
@@ -24135,7 +24188,7 @@ ${c2}
24135
24188
  } }).prompt();
24136
24189
 
24137
24190
  // src/cli/index.ts
24138
- import { basename as basename9, resolve as resolve29 } from "path";
24191
+ import { basename as basename10, resolve as resolve29 } from "path";
24139
24192
  import { mkdir as mkdir4, mkdtemp as mkdtemp3, rm as rm4 } from "fs/promises";
24140
24193
  import { tmpdir as tmpdir5 } from "os";
24141
24194
  import { spawn as spawn6, spawnSync as spawnSync4 } from "child_process";
@@ -25854,10 +25907,10 @@ import { resolve as resolve27 } from "path";
25854
25907
  import { existsSync as existsSync28, readFileSync as readFileSync19 } from "fs";
25855
25908
  import { mkdtemp as mkdtemp2, rm as rm3 } from "fs/promises";
25856
25909
  import { tmpdir as tmpdir4 } from "os";
25857
- import { basename as basename8, resolve as resolve26 } from "path";
25910
+ import { basename as basename9, resolve as resolve26 } from "path";
25858
25911
  import { spawn as spawn4 } from "child_process";
25859
25912
  async function executeCodexExecCommand(command2, options) {
25860
- if (basename8(command2[0]) !== "codex" || command2[1] !== "exec") {
25913
+ if (basename9(command2[0]) !== "codex" || command2[1] !== "exec") {
25861
25914
  throw new Error("Codex exec runner requires a command beginning with `codex exec`.");
25862
25915
  }
25863
25916
  const outputDir = await mkdtemp2(resolve26(tmpdir4(), options.outputDirPrefix ?? "pluxx-codex-exec-"));
@@ -26261,7 +26314,7 @@ function shellQuote2(value) {
26261
26314
  // src/cli/discover-installed-mcp.ts
26262
26315
  import { existsSync as existsSync30, readFileSync as readFileSync21, realpathSync as realpathSync3 } from "fs";
26263
26316
  import { homedir as homedir3 } from "os";
26264
- import { isAbsolute as isAbsolute2, relative as relative13, resolve as resolve28 } from "path";
26317
+ import { isAbsolute as isAbsolute2, relative as relative14, resolve as resolve28 } from "path";
26265
26318
  var INSTALLED_MCP_HOSTS = ["claude-code", "cursor", "codex", "opencode"];
26266
26319
  function discoverInstalledMcpServers(options = {}) {
26267
26320
  const rootDir = options.rootDir ?? process.cwd();
@@ -26400,13 +26453,13 @@ function buildClaudeProjectSourceScope(projectPath, rootDir, homeDir) {
26400
26453
  return `projects/absolute/${normalizeScopePath(projectPath)}`;
26401
26454
  }
26402
26455
  function buildRelativeScopePath(baseDir, targetPath) {
26403
- const relativePath = relative13(baseDir, targetPath);
26456
+ const relativePath = relative14(baseDir, targetPath);
26404
26457
  if (!relativePath.startsWith("..") && !isAbsolute2(relativePath)) {
26405
26458
  return normalizeScopePath(relativePath);
26406
26459
  }
26407
26460
  if (!existsSync30(baseDir) || !existsSync30(targetPath)) return void 0;
26408
26461
  try {
26409
- const realRelativePath = relative13(realpathSync3(baseDir), realpathSync3(targetPath));
26462
+ const realRelativePath = relative14(realpathSync3(baseDir), realpathSync3(targetPath));
26410
26463
  if (realRelativePath.startsWith("..") || isAbsolute2(realRelativePath)) return void 0;
26411
26464
  return normalizeScopePath(realRelativePath);
26412
26465
  } catch {
@@ -26606,7 +26659,7 @@ function buildInstalledMcpSourceLabel(discovered, rootDir, homeDir) {
26606
26659
  return discovered.sourceScope ? `${base}:${discovered.sourceScope}` : base;
26607
26660
  }
26608
26661
  function buildRelativeSelectorLabel(prefix, baseDir, sourcePath) {
26609
- const relativePath = relative13(baseDir, sourcePath);
26662
+ const relativePath = relative14(baseDir, sourcePath);
26610
26663
  if (relativePath === "") return `${prefix}:.`;
26611
26664
  if (relativePath.startsWith("..") || isAbsolute2(relativePath)) return void 0;
26612
26665
  return `${prefix}:${relativePath.replace(/\\/g, "/")}`;
@@ -27530,7 +27583,7 @@ async function runInit() {
27530
27583
  if (!runtime.isInteractive) {
27531
27584
  throw new Error("pluxx init requires an interactive terminal unless you use `pluxx init --from-mcp ... --yes`.");
27532
27585
  }
27533
- const dirName = positionalName ? toKebabCase3(positionalName) : basename9(process.cwd()).toLowerCase().replace(/[^a-z0-9-]/g, "-");
27586
+ const dirName = positionalName ? toKebabCase3(positionalName) : basename10(process.cwd()).toLowerCase().replace(/[^a-z0-9-]/g, "-");
27534
27587
  console.log("");
27535
27588
  console.log(" pluxx init \u2014 Create a new plugin");
27536
27589
  console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
@@ -15,6 +15,7 @@ interface BundleIntegrityIssues {
15
15
  hookConfigIssue?: string;
16
16
  missingManifestPaths: string[];
17
17
  missingHookTargets: string[];
18
+ cwdUnsafeHookCommands: string[];
18
19
  invalidRuntimeScripts: string[];
19
20
  }
20
21
  interface CommandResult {
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/cli/install.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/cli/install.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"hook-command-env.d.ts","sourceRoot":"","sources":["../src/hook-command-env.ts"],"names":[],"mappings":"AAIA,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAkDjH"}
1
+ {"version":3,"file":"hook-command-env.d.ts","sourceRoot":"","sources":["../src/hook-command-env.ts"],"names":[],"mappings":"AAIA,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAwDjH"}
package/dist/index.js CHANGED
@@ -2203,7 +2203,7 @@ var require_jiti = __commonJS({
2203
2203
  }, pathe_M_eThtNZ_dirname = function(e3) {
2204
2204
  const t3 = pathe_M_eThtNZ_normalizeWindowsPath(e3).replace(/\/$/, "").split("/").slice(0, -1);
2205
2205
  return 1 === t3.length && ve.test(t3[0]) && (t3[0] += "/"), t3.join("/") || (isAbsolute(e3) ? "/" : ".");
2206
- }, basename2 = function(e3, t3) {
2206
+ }, basename3 = function(e3, t3) {
2207
2207
  const i2 = pathe_M_eThtNZ_normalizeWindowsPath(e3).split("/");
2208
2208
  let s2 = "";
2209
2209
  for (let e4 = i2.length - 1; e4 >= 0; e4--) {
@@ -2911,7 +2911,7 @@ Default "index" lookups for the main are deprecated for ES modules.`, "Deprecati
2911
2911
  if (!e3.opts.fsCache || !t3.filename) return i2();
2912
2912
  const s2 = ` /* v${zt}-${utils_hash(t3.source, 16)} */
2913
2913
  `;
2914
- let r2 = `${basename2(pathe_M_eThtNZ_dirname(t3.filename))}-${(function(e4) {
2914
+ let r2 = `${basename3(pathe_M_eThtNZ_dirname(t3.filename))}-${(function(e4) {
2915
2915
  const t4 = e4.split(lt).pop();
2916
2916
  if (!t4) return;
2917
2917
  const i3 = t4.lastIndexOf(".");
@@ -2957,7 +2957,7 @@ Default "index" lookups for the main are deprecated for ES modules.`, "Deprecati
2957
2957
  return i2.startsWith("#!") && (i2 = "// " + i2), i2;
2958
2958
  }
2959
2959
  function eval_evalModule(e3, t3, i2 = {}) {
2960
- const s2 = i2.id || (i2.filename ? basename2(i2.filename) : `_jitiEval.${i2.ext || (i2.async ? "mjs" : "js")}`), r2 = i2.filename || jitiResolve(e3, s2, { async: i2.async }), n2 = i2.ext || extname(r2), a2 = i2.cache || e3.parentCache || {}, o2 = /\.[cm]?tsx?$/.test(n2), h2 = ".mjs" === n2 || ".js" === n2 && "module" === (function(e4) {
2960
+ const s2 = i2.id || (i2.filename ? basename3(i2.filename) : `_jitiEval.${i2.ext || (i2.async ? "mjs" : "js")}`), r2 = i2.filename || jitiResolve(e3, s2, { async: i2.async }), n2 = i2.ext || extname(r2), a2 = i2.cache || e3.parentCache || {}, o2 = /\.[cm]?tsx?$/.test(n2), h2 = ".mjs" === n2 || ".js" === n2 && "module" === (function(e4) {
2961
2961
  for (; e4 && "." !== e4 && "/" !== e4; ) {
2962
2962
  e4 = pathe_M_eThtNZ_join(e4, "..");
2963
2963
  try {
@@ -7929,18 +7929,18 @@ function getRuntimeReadinessCapability(platform, pluginRootVar = "PLUGIN_ROOT")
7929
7929
  {
7930
7930
  gate: "session-start",
7931
7931
  event: "SessionStart",
7932
- command: "node ./.codex/pluxx-readiness.mjs session-start"
7932
+ command: `node "\${${pluginRootVar}}/.codex/pluxx-readiness.mjs" session-start`
7933
7933
  },
7934
7934
  {
7935
7935
  gate: "mcp-gate",
7936
7936
  event: "PreToolUse",
7937
7937
  matcher: "MCP",
7938
- command: "node ./.codex/pluxx-readiness.mjs mcp-gate"
7938
+ command: `node "\${${pluginRootVar}}/.codex/pluxx-readiness.mjs" mcp-gate`
7939
7939
  },
7940
7940
  {
7941
7941
  gate: "prompt-gate",
7942
7942
  event: "UserPromptSubmit",
7943
- command: "node ./.codex/pluxx-readiness.mjs prompt-gate"
7943
+ command: `node "\${${pluginRootVar}}/.codex/pluxx-readiness.mjs" prompt-gate`
7944
7944
  }
7945
7945
  ],
7946
7946
  notes: CODEX_EXTERNAL_NOTE
@@ -10621,7 +10621,7 @@ import { resolve as resolve5 } from "path";
10621
10621
  import { spawn, spawnSync as spawnSync2 } from "child_process";
10622
10622
  import { accessSync, constants, existsSync as existsSync4, lstatSync, readFileSync as readFileSync4, readdirSync as readdirSync2, realpathSync } from "fs";
10623
10623
  import { homedir } from "os";
10624
- import { basename, dirname as dirname2, resolve as resolve4 } from "path";
10624
+ import { basename as basename2, dirname as dirname2, resolve as resolve4 } from "path";
10625
10625
 
10626
10626
  // node_modules/jiti/lib/jiti.mjs
10627
10627
  var import_jiti = __toESM(require_jiti(), 1);
@@ -10634,7 +10634,7 @@ var CONFIG_FILES = [
10634
10634
  ];
10635
10635
 
10636
10636
  // src/cli/install.ts
10637
- import { resolve as resolve3, dirname } from "path";
10637
+ import { resolve as resolve3, dirname, basename, relative } from "path";
10638
10638
  import { existsSync as existsSync3, symlinkSync, mkdirSync as mkdirSync2, rmSync as rmSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, cpSync, readdirSync } from "fs";
10639
10639
 
10640
10640
  // src/mcp-stdio-paths.ts
@@ -10779,7 +10779,7 @@ function resolveBundleReference(rootDir, value) {
10779
10779
  if (isRelativeBundlePath(value)) {
10780
10780
  return resolve3(rootDir, value);
10781
10781
  }
10782
- const pluginRootMatch = value.match(/^\$\{(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|PLUGIN_ROOT)\}[\\/](.+)$/);
10782
+ const pluginRootMatch = value.match(/^\$\{(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|CODEX_PLUGIN_ROOT|OPENCODE_PLUGIN_ROOT|PLUGIN_ROOT|PLUXX_PLUGIN_ROOT)\}[\\/](.+)$/);
10783
10783
  if (pluginRootMatch) {
10784
10784
  return resolve3(rootDir, pluginRootMatch[1]);
10785
10785
  }
@@ -10822,9 +10822,43 @@ function collectHookCommandStrings(value, commands) {
10822
10822
  }
10823
10823
  }
10824
10824
  function extractBundleCommandTargets(command) {
10825
- const matches = command.match(/\$\{(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|PLUGIN_ROOT)\}[\\/][^\s"'`;$|&<>]+|\.\.?[\\/][^\s"'`;$|&<>]+/g);
10825
+ const matches = command.match(/\$\{(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|CODEX_PLUGIN_ROOT|OPENCODE_PLUGIN_ROOT|PLUGIN_ROOT|PLUXX_PLUGIN_ROOT)\}[\\/][^\s"'`;$|&<>]+|\.\.?[\\/][^\s"'`;$|&<>]+/g);
10826
10826
  return matches ?? [];
10827
10827
  }
10828
+ function extractRelativeBundleCommandTargets(command) {
10829
+ return extractBundleCommandTargets(command).filter(isRelativeBundlePath);
10830
+ }
10831
+ function commandChangesToKnownPluginRoot(command) {
10832
+ return /\bcd\s+["']?\$\{?(?:CLAUDE_PLUGIN_ROOT|CURSOR_PLUGIN_ROOT|CODEX_PLUGIN_ROOT|OPENCODE_PLUGIN_ROOT|PLUGIN_ROOT|PLUXX_PLUGIN_ROOT)\}?/.test(command);
10833
+ }
10834
+ function formatBundleRelativePath(rootDir, filePath) {
10835
+ const relativePath = relative(rootDir, filePath);
10836
+ return relativePath && !relativePath.startsWith("..") ? relativePath : filePath;
10837
+ }
10838
+ function findHookWrapperPaths(rootDir, command) {
10839
+ return extractBundleCommandTargets(command).map((target) => resolveBundleReference(rootDir, target)).filter((target) => {
10840
+ if (!target) return false;
10841
+ return existsSync3(target) && basename(target).startsWith("pluxx-hook-command-") && target.endsWith(".sh");
10842
+ });
10843
+ }
10844
+ function findCodexCwdUnsafeHookCommands(rootDir, commands) {
10845
+ const issues = /* @__PURE__ */ new Set();
10846
+ for (const command of commands) {
10847
+ const relativeTargets = extractRelativeBundleCommandTargets(command);
10848
+ if (relativeTargets.length > 0 && !commandChangesToKnownPluginRoot(command)) {
10849
+ issues.add(`${command} uses cwd-relative bundle target(s): ${relativeTargets.join(", ")}`);
10850
+ }
10851
+ for (const wrapperPath of findHookWrapperPaths(rootDir, command)) {
10852
+ const wrapper = readFileSync3(wrapperPath, "utf-8");
10853
+ const hookCommand = wrapper.match(/^PLUXX_HOOK_COMMAND=(.*)$/m)?.[1] ?? "";
10854
+ const wrapperRelativeTargets = extractRelativeBundleCommandTargets(hookCommand);
10855
+ if (wrapperRelativeTargets.length > 0 && !commandChangesToKnownPluginRoot(wrapper)) {
10856
+ issues.add(`${formatBundleRelativePath(rootDir, wrapperPath)} evaluates cwd-relative bundle target(s): ${wrapperRelativeTargets.join(", ")}`);
10857
+ }
10858
+ }
10859
+ }
10860
+ return [...issues].sort();
10861
+ }
10828
10862
  function resolveInstalledHooksReference(rootDir, platform, manifest) {
10829
10863
  const manifestReference = typeof manifest.hooks === "string" ? manifest.hooks : void 0;
10830
10864
  if (manifestReference) {
@@ -10862,6 +10896,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10862
10896
  return {
10863
10897
  missingManifestPaths: [],
10864
10898
  missingHookTargets: [],
10899
+ cwdUnsafeHookCommands: [],
10865
10900
  invalidRuntimeScripts: []
10866
10901
  };
10867
10902
  }
@@ -10871,6 +10906,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10871
10906
  manifestIssue: `missing plugin manifest at ${manifestPath}`,
10872
10907
  missingManifestPaths: [],
10873
10908
  missingHookTargets: [],
10909
+ cwdUnsafeHookCommands: [],
10874
10910
  invalidRuntimeScripts: []
10875
10911
  };
10876
10912
  }
@@ -10882,6 +10918,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10882
10918
  manifestIssue: `plugin manifest at ${manifestPath} is not parseable: ${error instanceof Error ? error.message : String(error)}`,
10883
10919
  missingManifestPaths: [],
10884
10920
  missingHookTargets: [],
10921
+ cwdUnsafeHookCommands: [],
10885
10922
  invalidRuntimeScripts: []
10886
10923
  };
10887
10924
  }
@@ -10896,6 +10933,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10896
10933
  ...manifestIssue ? { manifestIssue } : {},
10897
10934
  missingManifestPaths,
10898
10935
  missingHookTargets: [],
10936
+ cwdUnsafeHookCommands: [],
10899
10937
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
10900
10938
  };
10901
10939
  }
@@ -10904,6 +10942,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10904
10942
  ...manifestIssue ? { manifestIssue } : {},
10905
10943
  missingManifestPaths,
10906
10944
  missingHookTargets: [],
10945
+ cwdUnsafeHookCommands: [],
10907
10946
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
10908
10947
  };
10909
10948
  }
@@ -10917,10 +10956,12 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10917
10956
  return resolved !== void 0 && !existsSync3(resolved);
10918
10957
  })
10919
10958
  )].sort();
10959
+ const cwdUnsafeHookCommands = platform === "codex" ? findCodexCwdUnsafeHookCommands(rootDir, commands) : [];
10920
10960
  return {
10921
10961
  ...manifestIssue ? { manifestIssue } : {},
10922
10962
  missingManifestPaths,
10923
10963
  missingHookTargets,
10964
+ cwdUnsafeHookCommands,
10924
10965
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
10925
10966
  };
10926
10967
  } catch (error) {
@@ -10929,6 +10970,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10929
10970
  hookConfigIssue: `hooks config at ${hooksReference} is not parseable: ${error instanceof Error ? error.message : String(error)}`,
10930
10971
  missingManifestPaths,
10931
10972
  missingHookTargets: [],
10973
+ cwdUnsafeHookCommands: [],
10932
10974
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
10933
10975
  };
10934
10976
  }
@@ -11638,7 +11680,7 @@ function listClaudeSettingsCandidates(projectRoot) {
11638
11680
  });
11639
11681
  }
11640
11682
  function readClaudeDisableAllHooks(filePath) {
11641
- const parsed = readJsonFile(dirname2(filePath), basename(filePath));
11683
+ const parsed = readJsonFile(dirname2(filePath), basename2(filePath));
11642
11684
  return typeof parsed.disableAllHooks === "boolean" ? parsed.disableAllHooks : void 0;
11643
11685
  }
11644
11686
  function probeClaudeDisableAllHooks(projectRoot) {
@@ -11981,6 +12023,9 @@ function checkInstalledBundleIntegrity(checks, rootDir, layout) {
11981
12023
  if (issues.missingHookTargets.length > 0) {
11982
12024
  details.push(`hook commands reference missing bundle target${issues.missingHookTargets.length === 1 ? "" : "s"}: ${issues.missingHookTargets.join(", ")}`);
11983
12025
  }
12026
+ if (issues.cwdUnsafeHookCommands.length > 0) {
12027
+ details.push(`Codex hook command${issues.cwdUnsafeHookCommands.length === 1 ? " depends" : "s depend"} on plugin-root cwd: ${issues.cwdUnsafeHookCommands.join("; ")}`);
12028
+ }
11984
12029
  if (issues.invalidRuntimeScripts.length > 0) {
11985
12030
  details.push(`runtime startup still depends on installer-owned validation: ${issues.invalidRuntimeScripts.join(", ")}`);
11986
12031
  }
@@ -12000,7 +12045,7 @@ function checkInstalledBundleIntegrity(checks, rootDir, layout) {
12000
12045
  code: "consumer-bundle-integrity-invalid",
12001
12046
  title: "Installed bundle integrity is broken",
12002
12047
  detail: details.join("; "),
12003
- fix: "Reinstall the plugin or rebuild the bundle so every manifest path, hook config, and hook target is valid inside the installed plugin.",
12048
+ fix: "Reinstall the plugin or rebuild the bundle so every manifest path, hook config, and hook command resolves from the installed plugin root.",
12004
12049
  path: layout.manifestPath
12005
12050
  });
12006
12051
  }
@@ -12082,7 +12127,7 @@ function checkInstalledCodexHooksFeatureFlag(checks, rootDir, layout, options) {
12082
12127
  path: generalOnlyProbes[0].path
12083
12128
  });
12084
12129
  }
12085
- const legacyOnlyProbes = probes.filter((probe) => probe.alternateEnabled && !probe.recommendedEnabled);
12130
+ const legacyOnlyProbes = probes.filter((probe) => !probe.pluginBundledEnabled && probe.alternateEnabled && !probe.recommendedEnabled);
12086
12131
  if (legacyOnlyProbes.length > 0) {
12087
12132
  addCheck(checks, {
12088
12133
  level: "warning",
@@ -12473,7 +12518,7 @@ function isLikelyLocalRuntimePath(value) {
12473
12518
  function isLikelyOpenCodeInstallPath(rootDir) {
12474
12519
  const parent = dirname2(rootDir);
12475
12520
  const grandparent = dirname2(parent);
12476
- return basename(parent) === "plugins" && basename(grandparent) === "opencode";
12521
+ return basename2(parent) === "plugins" && basename2(grandparent) === "opencode";
12477
12522
  }
12478
12523
  function checkInstalledOpenCodeHostBridge(checks, rootDir) {
12479
12524
  if (!isLikelyOpenCodeInstallPath(rootDir)) {
@@ -12487,7 +12532,7 @@ function checkInstalledOpenCodeHostBridge(checks, rootDir) {
12487
12532
  });
12488
12533
  return;
12489
12534
  }
12490
- const pluginName = basename(rootDir);
12535
+ const pluginName = basename2(rootDir);
12491
12536
  const entryPath = `${rootDir}.ts`;
12492
12537
  const entryRelativePath = `${pluginName}.ts`;
12493
12538
  if (!existsSync4(entryPath)) {
@@ -12528,7 +12573,7 @@ function checkInstalledOpenCodeSkills(checks, rootDir) {
12528
12573
  if (!isLikelyOpenCodeInstallPath(rootDir)) {
12529
12574
  return;
12530
12575
  }
12531
- const pluginName = basename(rootDir);
12576
+ const pluginName = basename2(rootDir);
12532
12577
  const sourceSkillsDir = resolve4(rootDir, "skills");
12533
12578
  if (!existsSync4(sourceSkillsDir)) {
12534
12579
  addCheck(checks, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchid-labs/pluxx",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Build AI agent plugins once. Prime-time on Claude Code, Cursor, Codex, and OpenCode, with beta generators for additional hosts.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",