@orchid-labs/pluxx 0.1.19 → 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";
@@ -24455,17 +24508,18 @@ function renderInstallerUserConfigSnippet(config, platform, installDirVariable)
24455
24508
  if (entries.length === 0) return "";
24456
24509
  const promptLines = entries.map((entry) => {
24457
24510
  const functionName = entry.type === "secret" ? "pluxx_prompt_secret_config" : "pluxx_prompt_text_config";
24458
- return `${functionName} ${JSON.stringify(entry.envVar)} ${JSON.stringify(entry.title)} ${entry.required ? "1" : "0"}`;
24511
+ return `${functionName} ${JSON.stringify(entry.key)} ${JSON.stringify(entry.envVar)} ${JSON.stringify(entry.title)} ${entry.required ? "1" : "0"}`;
24459
24512
  });
24460
24513
  return `
24461
24514
  PLUXX_USER_CONFIG_SPEC="$(cat <<'PLUXX_USER_CONFIG_JSON'
24462
24515
  ${JSON.stringify(entries)}
24463
24516
  PLUXX_USER_CONFIG_JSON
24464
24517
  )"
24518
+ PLUXX_REUSED_USER_CONFIG=0
24465
24519
 
24466
24520
  pluxx_is_placeholder_secret() {
24467
24521
  case "$1" in
24468
- *dummy*|*Dummy*|*DUMMY*|*placeholder*|*Placeholder*|*PLACEHOLDER*|*changeme*|*CHANGE_ME*|*replace*me*|*Replace*Me*|*your*key*|*YOUR*KEY*|*api*key*here*|*API*KEY*HERE*|*token*here*|*TOKEN*HERE*)
24522
+ *dummy*|*Dummy*|*DUMMY*|*placeholder*|*Placeholder*|*PLACEHOLDER*|*example*|*Example*|*EXAMPLE*|*changeme*|*CHANGE_ME*|*replace*me*|*Replace*Me*|*your*key*|*YOUR*KEY*|*api*key*here*|*API*KEY*HERE*|*token*here*|*TOKEN*HERE*)
24469
24523
  return 0
24470
24524
  ;;
24471
24525
  *)
@@ -24474,12 +24528,61 @@ pluxx_is_placeholder_secret() {
24474
24528
  esac
24475
24529
  }
24476
24530
 
24531
+ pluxx_saved_config_value() {
24532
+ local key="$1"
24533
+ local env_var="$2"
24534
+
24535
+ if [[ -z "\${PLUXX_SAVED_USER_CONFIG_PATH:-}" || ! -f "$PLUXX_SAVED_USER_CONFIG_PATH" ]]; then
24536
+ return 1
24537
+ fi
24538
+
24539
+ PLUXX_SAVED_CONFIG_KEY="$key" PLUXX_SAVED_CONFIG_ENV_VAR="$env_var" node <<'NODE'
24540
+ const fs = require('fs')
24541
+
24542
+ const filepath = process.env.PLUXX_SAVED_USER_CONFIG_PATH
24543
+ const key = process.env.PLUXX_SAVED_CONFIG_KEY
24544
+ const envVar = process.env.PLUXX_SAVED_CONFIG_ENV_VAR
24545
+
24546
+ try {
24547
+ const payload = JSON.parse(fs.readFileSync(filepath, 'utf8'))
24548
+ const candidates = [
24549
+ payload && payload.env && envVar ? payload.env[envVar] : undefined,
24550
+ payload && payload.values && key ? payload.values[key] : undefined,
24551
+ ]
24552
+
24553
+ for (const candidate of candidates) {
24554
+ if (candidate === undefined || candidate === null) continue
24555
+ if (!['string', 'number', 'boolean'].includes(typeof candidate)) continue
24556
+ const value = String(candidate)
24557
+ if (value === '') continue
24558
+ process.stdout.write(value)
24559
+ process.exit(0)
24560
+ }
24561
+ } catch {}
24562
+
24563
+ process.exit(1)
24564
+ NODE
24565
+ }
24566
+
24477
24567
  pluxx_prompt_secret_config() {
24478
- local env_var="$1"
24479
- local label="$2"
24480
- local required="$3"
24568
+ local key="$1"
24569
+ local env_var="$2"
24570
+ local label="$3"
24571
+ local required="$4"
24481
24572
  local current_value="\${!env_var:-}"
24482
24573
 
24574
+ if [[ -z "$current_value" && "\${PLUXX_RECONFIGURE:-0}" != "1" ]]; then
24575
+ local saved_value=""
24576
+ if saved_value="$(pluxx_saved_config_value "$key" "$env_var")"; then
24577
+ if pluxx_is_placeholder_secret "$saved_value"; then
24578
+ echo "Ignoring placeholder-looking saved config for $env_var." >&2
24579
+ else
24580
+ current_value="$saved_value"
24581
+ PLUXX_REUSED_USER_CONFIG=1
24582
+ fi
24583
+ fi
24584
+ fi
24585
+
24483
24586
  if [[ -z "$current_value" && "$required" == "1" ]]; then
24484
24587
  if [[ -t 0 || -r /dev/tty ]]; then
24485
24588
  read -r -s -p "$label [$env_var]: " current_value </dev/tty
@@ -24499,11 +24602,20 @@ pluxx_prompt_secret_config() {
24499
24602
  }
24500
24603
 
24501
24604
  pluxx_prompt_text_config() {
24502
- local env_var="$1"
24503
- local label="$2"
24504
- local required="$3"
24605
+ local key="$1"
24606
+ local env_var="$2"
24607
+ local label="$3"
24608
+ local required="$4"
24505
24609
  local current_value="\${!env_var:-}"
24506
24610
 
24611
+ if [[ -z "$current_value" && "\${PLUXX_RECONFIGURE:-0}" != "1" ]]; then
24612
+ local saved_value=""
24613
+ if saved_value="$(pluxx_saved_config_value "$key" "$env_var")"; then
24614
+ current_value="$saved_value"
24615
+ PLUXX_REUSED_USER_CONFIG=1
24616
+ fi
24617
+ fi
24618
+
24507
24619
  if [[ -z "$current_value" && "$required" == "1" ]]; then
24508
24620
  if [[ -t 0 || -r /dev/tty ]]; then
24509
24621
  read -r -p "$label [$env_var]: " current_value </dev/tty
@@ -24518,6 +24630,10 @@ pluxx_prompt_text_config() {
24518
24630
 
24519
24631
  ${promptLines.join("\n")}
24520
24632
 
24633
+ if [[ "$PLUXX_REUSED_USER_CONFIG" == "1" ]]; then
24634
+ echo "Found existing plugin config; reusing saved install values."
24635
+ fi
24636
+
24521
24637
  export PLUXX_USER_CONFIG_SPEC
24522
24638
  export PLUXX_INSTALL_DIR="${installDirVariable}"
24523
24639
 
@@ -24613,6 +24729,17 @@ NODE
24613
24729
  function hasInstallerUserConfig(config, platform) {
24614
24730
  return collectUserConfigEntries(config, [platform]).length > 0;
24615
24731
  }
24732
+ function renderInstallerSavedUserConfigCaptureSnippet(config, platform, installDirVariable) {
24733
+ if (!hasInstallerUserConfig(config, platform)) return "";
24734
+ return `
24735
+ PLUXX_SAVED_USER_CONFIG_PATH=""
24736
+ if [[ "\${PLUXX_RECONFIGURE:-0}" != "1" && -f "${installDirVariable}/.pluxx-user.json" ]]; then
24737
+ PLUXX_SAVED_USER_CONFIG_PATH="$TMP_DIR/pluxx-saved-user-config.json"
24738
+ cp "${installDirVariable}/.pluxx-user.json" "$PLUXX_SAVED_USER_CONFIG_PATH"
24739
+ fi
24740
+ export PLUXX_SAVED_USER_CONFIG_PATH
24741
+ `;
24742
+ }
24616
24743
  function renderInstallerMcpPathMaterializationSnippet(platform, installDirVariable) {
24617
24744
  if (platform !== "codex") return "";
24618
24745
  return `
@@ -24983,6 +25110,7 @@ VERSION="$(grep -E '"version"' "$PLUGIN_MANIFEST" | head -n1 | sed -E 's/.*"vers
24983
25110
  DESCRIPTION="$(grep -E '"description"' "$PLUGIN_MANIFEST" | head -n1 | sed -E 's/.*"description"[[:space:]]*:[[:space:]]*"([^"]+)".*/\\1/')"
24984
25111
 
24985
25112
  mkdir -p "$INSTALL_ROOT/.claude-plugin" "$INSTALL_ROOT/plugins"
25113
+ ${renderInstallerSavedUserConfigCaptureSnippet(config, "claude-code", "$INSTALL_ROOT/plugins/$PLUGIN_NAME")}
24986
25114
  rm -rf "$INSTALL_ROOT/plugins/$PLUGIN_NAME"
24987
25115
  cp -R "$BUNDLE_DIR" "$INSTALL_ROOT/plugins/$PLUGIN_NAME"
24988
25116
  ${renderInstallerUserConfigSnippet(config, "claude-code", "$INSTALL_ROOT/plugins/$PLUGIN_NAME")}
@@ -25078,6 +25206,7 @@ if [[ ! -f "$PLUGIN_MANIFEST" ]]; then
25078
25206
  fi
25079
25207
 
25080
25208
  mkdir -p "$(dirname "$INSTALL_DIR")"
25209
+ ${renderInstallerSavedUserConfigCaptureSnippet(config, "cursor", "$INSTALL_DIR")}
25081
25210
  rm -rf "$INSTALL_DIR"
25082
25211
  cp -R "$BUNDLE_DIR" "$INSTALL_DIR"
25083
25212
  ${renderInstallerUserConfigSnippet(config, "cursor", "$INSTALL_DIR")}
@@ -25138,6 +25267,7 @@ if [[ ! -f "$PLUGIN_MANIFEST" ]]; then
25138
25267
  fi
25139
25268
 
25140
25269
  mkdir -p "$(dirname "$INSTALL_DIR")"
25270
+ ${renderInstallerSavedUserConfigCaptureSnippet(config, "codex", "$INSTALL_DIR")}
25141
25271
  rm -rf "$INSTALL_DIR"
25142
25272
  cp -R "$BUNDLE_DIR" "$INSTALL_DIR"
25143
25273
  ${renderInstallerUserConfigSnippet(config, "codex", "$INSTALL_DIR")}
@@ -25256,6 +25386,7 @@ if [[ ! -f "$PLUGIN_PACKAGE" ]]; then
25256
25386
  fi
25257
25387
 
25258
25388
  mkdir -p "$(dirname "$INSTALL_DIR")" "$SKILLS_ROOT"
25389
+ ${renderInstallerSavedUserConfigCaptureSnippet(config, "opencode", "$INSTALL_DIR")}
25259
25390
  rm -rf "$INSTALL_DIR"
25260
25391
  cp -R "$BUNDLE_DIR" "$INSTALL_DIR"
25261
25392
  ${renderInstallerUserConfigSnippet(config, "opencode", "$INSTALL_DIR")}
@@ -25776,10 +25907,10 @@ import { resolve as resolve27 } from "path";
25776
25907
  import { existsSync as existsSync28, readFileSync as readFileSync19 } from "fs";
25777
25908
  import { mkdtemp as mkdtemp2, rm as rm3 } from "fs/promises";
25778
25909
  import { tmpdir as tmpdir4 } from "os";
25779
- import { basename as basename8, resolve as resolve26 } from "path";
25910
+ import { basename as basename9, resolve as resolve26 } from "path";
25780
25911
  import { spawn as spawn4 } from "child_process";
25781
25912
  async function executeCodexExecCommand(command2, options) {
25782
- if (basename8(command2[0]) !== "codex" || command2[1] !== "exec") {
25913
+ if (basename9(command2[0]) !== "codex" || command2[1] !== "exec") {
25783
25914
  throw new Error("Codex exec runner requires a command beginning with `codex exec`.");
25784
25915
  }
25785
25916
  const outputDir = await mkdtemp2(resolve26(tmpdir4(), options.outputDirPrefix ?? "pluxx-codex-exec-"));
@@ -26183,7 +26314,7 @@ function shellQuote2(value) {
26183
26314
  // src/cli/discover-installed-mcp.ts
26184
26315
  import { existsSync as existsSync30, readFileSync as readFileSync21, realpathSync as realpathSync3 } from "fs";
26185
26316
  import { homedir as homedir3 } from "os";
26186
- 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";
26187
26318
  var INSTALLED_MCP_HOSTS = ["claude-code", "cursor", "codex", "opencode"];
26188
26319
  function discoverInstalledMcpServers(options = {}) {
26189
26320
  const rootDir = options.rootDir ?? process.cwd();
@@ -26322,13 +26453,13 @@ function buildClaudeProjectSourceScope(projectPath, rootDir, homeDir) {
26322
26453
  return `projects/absolute/${normalizeScopePath(projectPath)}`;
26323
26454
  }
26324
26455
  function buildRelativeScopePath(baseDir, targetPath) {
26325
- const relativePath = relative13(baseDir, targetPath);
26456
+ const relativePath = relative14(baseDir, targetPath);
26326
26457
  if (!relativePath.startsWith("..") && !isAbsolute2(relativePath)) {
26327
26458
  return normalizeScopePath(relativePath);
26328
26459
  }
26329
26460
  if (!existsSync30(baseDir) || !existsSync30(targetPath)) return void 0;
26330
26461
  try {
26331
- const realRelativePath = relative13(realpathSync3(baseDir), realpathSync3(targetPath));
26462
+ const realRelativePath = relative14(realpathSync3(baseDir), realpathSync3(targetPath));
26332
26463
  if (realRelativePath.startsWith("..") || isAbsolute2(realRelativePath)) return void 0;
26333
26464
  return normalizeScopePath(realRelativePath);
26334
26465
  } catch {
@@ -26528,7 +26659,7 @@ function buildInstalledMcpSourceLabel(discovered, rootDir, homeDir) {
26528
26659
  return discovered.sourceScope ? `${base}:${discovered.sourceScope}` : base;
26529
26660
  }
26530
26661
  function buildRelativeSelectorLabel(prefix, baseDir, sourcePath) {
26531
- const relativePath = relative13(baseDir, sourcePath);
26662
+ const relativePath = relative14(baseDir, sourcePath);
26532
26663
  if (relativePath === "") return `${prefix}:.`;
26533
26664
  if (relativePath.startsWith("..") || isAbsolute2(relativePath)) return void 0;
26534
26665
  return `${prefix}:${relativePath.replace(/\\/g, "/")}`;
@@ -27452,7 +27583,7 @@ async function runInit() {
27452
27583
  if (!runtime.isInteractive) {
27453
27584
  throw new Error("pluxx init requires an interactive terminal unless you use `pluxx init --from-mcp ... --yes`.");
27454
27585
  }
27455
- 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, "-");
27456
27587
  console.log("");
27457
27588
  console.log(" pluxx init \u2014 Create a new plugin");
27458
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":"publish.d.ts","sourceRoot":"","sources":["../../src/cli/publish.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/cli/publish.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAI7D,KAAK,cAAc,GAAG,KAAK,GAAG,gBAAgB,CAAA;AAC9C,KAAK,gBAAgB,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAA;AACzE,KAAK,qBAAqB,GAAG,WAAW,GAAG,QAAQ,CAAA;AAEnD,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,KAAK,aAAa,GAAG,CACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,KACvB,aAAa,CAAA;AAElB,MAAM,WAAW,kBAAkB;IACjC,iBAAiB,CAAC,EAAE,cAAc,EAAE,CAAA;IACpC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,aAAa,CAAA;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,gBAAgB,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,OAAO,CAAC,EAAE,qBAAqB,CAAA;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,OAAO,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,SAAS,CAAA;IAClB,MAAM,EAAE,OAAO,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE;QACR,GAAG,EAAE;YACH,OAAO,EAAE,OAAO,CAAA;YAChB,QAAQ,EAAE,OAAO,CAAA;YACjB,WAAW,CAAC,EAAE,MAAM,CAAA;YACpB,UAAU,CAAC,EAAE,MAAM,CAAA;YACnB,YAAY,EAAE,OAAO,CAAA;SACtB,CAAA;QACD,aAAa,EAAE;YACb,OAAO,EAAE,OAAO,CAAA;YAChB,QAAQ,EAAE,OAAO,CAAA;YACjB,IAAI,CAAC,EAAE,MAAM,CAAA;YACb,UAAU,CAAC,EAAE,MAAM,CAAA;YACnB,kBAAkB,EAAE,OAAO,CAAA;YAC3B,MAAM,EAAE,gBAAgB,EAAE,CAAA;SAC3B,CAAA;KACF,CAAA;IACD,MAAM,EAAE,YAAY,EAAE,CAAA;CACvB;AAED,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,EAAE,EAAE,OAAO,CAAA;IACX,SAAS,CAAC,EAAE;QACV,GAAG,CAAC,EAAE;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;QACtC,aAAa,CAAC,EAAE;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAA;KACjD,CAAA;CACF;AAwPD,wBAAgB,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,kBAAuB,GAAG,WAAW,CAmD/F;AA6sCD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,EAAE,CAoC7D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE,kBAAuB,GAAG,gBAAgB,CA8EnG"}
@@ -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
@@ -9449,17 +9449,18 @@ function renderInstallerUserConfigSnippet(config, platform, installDirVariable)
9449
9449
  if (entries.length === 0) return "";
9450
9450
  const promptLines = entries.map((entry) => {
9451
9451
  const functionName = entry.type === "secret" ? "pluxx_prompt_secret_config" : "pluxx_prompt_text_config";
9452
- return `${functionName} ${JSON.stringify(entry.envVar)} ${JSON.stringify(entry.title)} ${entry.required ? "1" : "0"}`;
9452
+ return `${functionName} ${JSON.stringify(entry.key)} ${JSON.stringify(entry.envVar)} ${JSON.stringify(entry.title)} ${entry.required ? "1" : "0"}`;
9453
9453
  });
9454
9454
  return `
9455
9455
  PLUXX_USER_CONFIG_SPEC="$(cat <<'PLUXX_USER_CONFIG_JSON'
9456
9456
  ${JSON.stringify(entries)}
9457
9457
  PLUXX_USER_CONFIG_JSON
9458
9458
  )"
9459
+ PLUXX_REUSED_USER_CONFIG=0
9459
9460
 
9460
9461
  pluxx_is_placeholder_secret() {
9461
9462
  case "$1" in
9462
- *dummy*|*Dummy*|*DUMMY*|*placeholder*|*Placeholder*|*PLACEHOLDER*|*changeme*|*CHANGE_ME*|*replace*me*|*Replace*Me*|*your*key*|*YOUR*KEY*|*api*key*here*|*API*KEY*HERE*|*token*here*|*TOKEN*HERE*)
9463
+ *dummy*|*Dummy*|*DUMMY*|*placeholder*|*Placeholder*|*PLACEHOLDER*|*example*|*Example*|*EXAMPLE*|*changeme*|*CHANGE_ME*|*replace*me*|*Replace*Me*|*your*key*|*YOUR*KEY*|*api*key*here*|*API*KEY*HERE*|*token*here*|*TOKEN*HERE*)
9463
9464
  return 0
9464
9465
  ;;
9465
9466
  *)
@@ -9468,12 +9469,61 @@ pluxx_is_placeholder_secret() {
9468
9469
  esac
9469
9470
  }
9470
9471
 
9472
+ pluxx_saved_config_value() {
9473
+ local key="$1"
9474
+ local env_var="$2"
9475
+
9476
+ if [[ -z "\${PLUXX_SAVED_USER_CONFIG_PATH:-}" || ! -f "$PLUXX_SAVED_USER_CONFIG_PATH" ]]; then
9477
+ return 1
9478
+ fi
9479
+
9480
+ PLUXX_SAVED_CONFIG_KEY="$key" PLUXX_SAVED_CONFIG_ENV_VAR="$env_var" node <<'NODE'
9481
+ const fs = require('fs')
9482
+
9483
+ const filepath = process.env.PLUXX_SAVED_USER_CONFIG_PATH
9484
+ const key = process.env.PLUXX_SAVED_CONFIG_KEY
9485
+ const envVar = process.env.PLUXX_SAVED_CONFIG_ENV_VAR
9486
+
9487
+ try {
9488
+ const payload = JSON.parse(fs.readFileSync(filepath, 'utf8'))
9489
+ const candidates = [
9490
+ payload && payload.env && envVar ? payload.env[envVar] : undefined,
9491
+ payload && payload.values && key ? payload.values[key] : undefined,
9492
+ ]
9493
+
9494
+ for (const candidate of candidates) {
9495
+ if (candidate === undefined || candidate === null) continue
9496
+ if (!['string', 'number', 'boolean'].includes(typeof candidate)) continue
9497
+ const value = String(candidate)
9498
+ if (value === '') continue
9499
+ process.stdout.write(value)
9500
+ process.exit(0)
9501
+ }
9502
+ } catch {}
9503
+
9504
+ process.exit(1)
9505
+ NODE
9506
+ }
9507
+
9471
9508
  pluxx_prompt_secret_config() {
9472
- local env_var="$1"
9473
- local label="$2"
9474
- local required="$3"
9509
+ local key="$1"
9510
+ local env_var="$2"
9511
+ local label="$3"
9512
+ local required="$4"
9475
9513
  local current_value="\${!env_var:-}"
9476
9514
 
9515
+ if [[ -z "$current_value" && "\${PLUXX_RECONFIGURE:-0}" != "1" ]]; then
9516
+ local saved_value=""
9517
+ if saved_value="$(pluxx_saved_config_value "$key" "$env_var")"; then
9518
+ if pluxx_is_placeholder_secret "$saved_value"; then
9519
+ echo "Ignoring placeholder-looking saved config for $env_var." >&2
9520
+ else
9521
+ current_value="$saved_value"
9522
+ PLUXX_REUSED_USER_CONFIG=1
9523
+ fi
9524
+ fi
9525
+ fi
9526
+
9477
9527
  if [[ -z "$current_value" && "$required" == "1" ]]; then
9478
9528
  if [[ -t 0 || -r /dev/tty ]]; then
9479
9529
  read -r -s -p "$label [$env_var]: " current_value </dev/tty
@@ -9493,11 +9543,20 @@ pluxx_prompt_secret_config() {
9493
9543
  }
9494
9544
 
9495
9545
  pluxx_prompt_text_config() {
9496
- local env_var="$1"
9497
- local label="$2"
9498
- local required="$3"
9546
+ local key="$1"
9547
+ local env_var="$2"
9548
+ local label="$3"
9549
+ local required="$4"
9499
9550
  local current_value="\${!env_var:-}"
9500
9551
 
9552
+ if [[ -z "$current_value" && "\${PLUXX_RECONFIGURE:-0}" != "1" ]]; then
9553
+ local saved_value=""
9554
+ if saved_value="$(pluxx_saved_config_value "$key" "$env_var")"; then
9555
+ current_value="$saved_value"
9556
+ PLUXX_REUSED_USER_CONFIG=1
9557
+ fi
9558
+ fi
9559
+
9501
9560
  if [[ -z "$current_value" && "$required" == "1" ]]; then
9502
9561
  if [[ -t 0 || -r /dev/tty ]]; then
9503
9562
  read -r -p "$label [$env_var]: " current_value </dev/tty
@@ -9512,6 +9571,10 @@ pluxx_prompt_text_config() {
9512
9571
 
9513
9572
  ${promptLines.join("\n")}
9514
9573
 
9574
+ if [[ "$PLUXX_REUSED_USER_CONFIG" == "1" ]]; then
9575
+ echo "Found existing plugin config; reusing saved install values."
9576
+ fi
9577
+
9515
9578
  export PLUXX_USER_CONFIG_SPEC
9516
9579
  export PLUXX_INSTALL_DIR="${installDirVariable}"
9517
9580
 
@@ -9607,6 +9670,17 @@ NODE
9607
9670
  function hasInstallerUserConfig(config, platform) {
9608
9671
  return collectUserConfigEntries(config, [platform]).length > 0;
9609
9672
  }
9673
+ function renderInstallerSavedUserConfigCaptureSnippet(config, platform, installDirVariable) {
9674
+ if (!hasInstallerUserConfig(config, platform)) return "";
9675
+ return `
9676
+ PLUXX_SAVED_USER_CONFIG_PATH=""
9677
+ if [[ "\${PLUXX_RECONFIGURE:-0}" != "1" && -f "${installDirVariable}/.pluxx-user.json" ]]; then
9678
+ PLUXX_SAVED_USER_CONFIG_PATH="$TMP_DIR/pluxx-saved-user-config.json"
9679
+ cp "${installDirVariable}/.pluxx-user.json" "$PLUXX_SAVED_USER_CONFIG_PATH"
9680
+ fi
9681
+ export PLUXX_SAVED_USER_CONFIG_PATH
9682
+ `;
9683
+ }
9610
9684
  function renderInstallerMcpPathMaterializationSnippet(platform, installDirVariable) {
9611
9685
  if (platform !== "codex") return "";
9612
9686
  return `
@@ -9977,6 +10051,7 @@ VERSION="$(grep -E '"version"' "$PLUGIN_MANIFEST" | head -n1 | sed -E 's/.*"vers
9977
10051
  DESCRIPTION="$(grep -E '"description"' "$PLUGIN_MANIFEST" | head -n1 | sed -E 's/.*"description"[[:space:]]*:[[:space:]]*"([^"]+)".*/\\1/')"
9978
10052
 
9979
10053
  mkdir -p "$INSTALL_ROOT/.claude-plugin" "$INSTALL_ROOT/plugins"
10054
+ ${renderInstallerSavedUserConfigCaptureSnippet(config, "claude-code", "$INSTALL_ROOT/plugins/$PLUGIN_NAME")}
9980
10055
  rm -rf "$INSTALL_ROOT/plugins/$PLUGIN_NAME"
9981
10056
  cp -R "$BUNDLE_DIR" "$INSTALL_ROOT/plugins/$PLUGIN_NAME"
9982
10057
  ${renderInstallerUserConfigSnippet(config, "claude-code", "$INSTALL_ROOT/plugins/$PLUGIN_NAME")}
@@ -10072,6 +10147,7 @@ if [[ ! -f "$PLUGIN_MANIFEST" ]]; then
10072
10147
  fi
10073
10148
 
10074
10149
  mkdir -p "$(dirname "$INSTALL_DIR")"
10150
+ ${renderInstallerSavedUserConfigCaptureSnippet(config, "cursor", "$INSTALL_DIR")}
10075
10151
  rm -rf "$INSTALL_DIR"
10076
10152
  cp -R "$BUNDLE_DIR" "$INSTALL_DIR"
10077
10153
  ${renderInstallerUserConfigSnippet(config, "cursor", "$INSTALL_DIR")}
@@ -10132,6 +10208,7 @@ if [[ ! -f "$PLUGIN_MANIFEST" ]]; then
10132
10208
  fi
10133
10209
 
10134
10210
  mkdir -p "$(dirname "$INSTALL_DIR")"
10211
+ ${renderInstallerSavedUserConfigCaptureSnippet(config, "codex", "$INSTALL_DIR")}
10135
10212
  rm -rf "$INSTALL_DIR"
10136
10213
  cp -R "$BUNDLE_DIR" "$INSTALL_DIR"
10137
10214
  ${renderInstallerUserConfigSnippet(config, "codex", "$INSTALL_DIR")}
@@ -10250,6 +10327,7 @@ if [[ ! -f "$PLUGIN_PACKAGE" ]]; then
10250
10327
  fi
10251
10328
 
10252
10329
  mkdir -p "$(dirname "$INSTALL_DIR")" "$SKILLS_ROOT"
10330
+ ${renderInstallerSavedUserConfigCaptureSnippet(config, "opencode", "$INSTALL_DIR")}
10253
10331
  rm -rf "$INSTALL_DIR"
10254
10332
  cp -R "$BUNDLE_DIR" "$INSTALL_DIR"
10255
10333
  ${renderInstallerUserConfigSnippet(config, "opencode", "$INSTALL_DIR")}
@@ -10543,7 +10621,7 @@ import { resolve as resolve5 } from "path";
10543
10621
  import { spawn, spawnSync as spawnSync2 } from "child_process";
10544
10622
  import { accessSync, constants, existsSync as existsSync4, lstatSync, readFileSync as readFileSync4, readdirSync as readdirSync2, realpathSync } from "fs";
10545
10623
  import { homedir } from "os";
10546
- import { basename, dirname as dirname2, resolve as resolve4 } from "path";
10624
+ import { basename as basename2, dirname as dirname2, resolve as resolve4 } from "path";
10547
10625
 
10548
10626
  // node_modules/jiti/lib/jiti.mjs
10549
10627
  var import_jiti = __toESM(require_jiti(), 1);
@@ -10556,7 +10634,7 @@ var CONFIG_FILES = [
10556
10634
  ];
10557
10635
 
10558
10636
  // src/cli/install.ts
10559
- import { resolve as resolve3, dirname } from "path";
10637
+ import { resolve as resolve3, dirname, basename, relative } from "path";
10560
10638
  import { existsSync as existsSync3, symlinkSync, mkdirSync as mkdirSync2, rmSync as rmSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2, cpSync, readdirSync } from "fs";
10561
10639
 
10562
10640
  // src/mcp-stdio-paths.ts
@@ -10701,7 +10779,7 @@ function resolveBundleReference(rootDir, value) {
10701
10779
  if (isRelativeBundlePath(value)) {
10702
10780
  return resolve3(rootDir, value);
10703
10781
  }
10704
- 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)\}[\\/](.+)$/);
10705
10783
  if (pluginRootMatch) {
10706
10784
  return resolve3(rootDir, pluginRootMatch[1]);
10707
10785
  }
@@ -10744,9 +10822,43 @@ function collectHookCommandStrings(value, commands) {
10744
10822
  }
10745
10823
  }
10746
10824
  function extractBundleCommandTargets(command) {
10747
- 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);
10748
10826
  return matches ?? [];
10749
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
+ }
10750
10862
  function resolveInstalledHooksReference(rootDir, platform, manifest) {
10751
10863
  const manifestReference = typeof manifest.hooks === "string" ? manifest.hooks : void 0;
10752
10864
  if (manifestReference) {
@@ -10784,6 +10896,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10784
10896
  return {
10785
10897
  missingManifestPaths: [],
10786
10898
  missingHookTargets: [],
10899
+ cwdUnsafeHookCommands: [],
10787
10900
  invalidRuntimeScripts: []
10788
10901
  };
10789
10902
  }
@@ -10793,6 +10906,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10793
10906
  manifestIssue: `missing plugin manifest at ${manifestPath}`,
10794
10907
  missingManifestPaths: [],
10795
10908
  missingHookTargets: [],
10909
+ cwdUnsafeHookCommands: [],
10796
10910
  invalidRuntimeScripts: []
10797
10911
  };
10798
10912
  }
@@ -10804,6 +10918,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10804
10918
  manifestIssue: `plugin manifest at ${manifestPath} is not parseable: ${error instanceof Error ? error.message : String(error)}`,
10805
10919
  missingManifestPaths: [],
10806
10920
  missingHookTargets: [],
10921
+ cwdUnsafeHookCommands: [],
10807
10922
  invalidRuntimeScripts: []
10808
10923
  };
10809
10924
  }
@@ -10818,6 +10933,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10818
10933
  ...manifestIssue ? { manifestIssue } : {},
10819
10934
  missingManifestPaths,
10820
10935
  missingHookTargets: [],
10936
+ cwdUnsafeHookCommands: [],
10821
10937
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
10822
10938
  };
10823
10939
  }
@@ -10826,6 +10942,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10826
10942
  ...manifestIssue ? { manifestIssue } : {},
10827
10943
  missingManifestPaths,
10828
10944
  missingHookTargets: [],
10945
+ cwdUnsafeHookCommands: [],
10829
10946
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
10830
10947
  };
10831
10948
  }
@@ -10839,10 +10956,12 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10839
10956
  return resolved !== void 0 && !existsSync3(resolved);
10840
10957
  })
10841
10958
  )].sort();
10959
+ const cwdUnsafeHookCommands = platform === "codex" ? findCodexCwdUnsafeHookCommands(rootDir, commands) : [];
10842
10960
  return {
10843
10961
  ...manifestIssue ? { manifestIssue } : {},
10844
10962
  missingManifestPaths,
10845
10963
  missingHookTargets,
10964
+ cwdUnsafeHookCommands,
10846
10965
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
10847
10966
  };
10848
10967
  } catch (error) {
@@ -10851,6 +10970,7 @@ function findInstalledBundleIntegrityIssues(rootDir, platform) {
10851
10970
  hookConfigIssue: `hooks config at ${hooksReference} is not parseable: ${error instanceof Error ? error.message : String(error)}`,
10852
10971
  missingManifestPaths,
10853
10972
  missingHookTargets: [],
10973
+ cwdUnsafeHookCommands: [],
10854
10974
  invalidRuntimeScripts: findInstalledRuntimeScriptIssues(rootDir, manifest)
10855
10975
  };
10856
10976
  }
@@ -11560,7 +11680,7 @@ function listClaudeSettingsCandidates(projectRoot) {
11560
11680
  });
11561
11681
  }
11562
11682
  function readClaudeDisableAllHooks(filePath) {
11563
- const parsed = readJsonFile(dirname2(filePath), basename(filePath));
11683
+ const parsed = readJsonFile(dirname2(filePath), basename2(filePath));
11564
11684
  return typeof parsed.disableAllHooks === "boolean" ? parsed.disableAllHooks : void 0;
11565
11685
  }
11566
11686
  function probeClaudeDisableAllHooks(projectRoot) {
@@ -11903,6 +12023,9 @@ function checkInstalledBundleIntegrity(checks, rootDir, layout) {
11903
12023
  if (issues.missingHookTargets.length > 0) {
11904
12024
  details.push(`hook commands reference missing bundle target${issues.missingHookTargets.length === 1 ? "" : "s"}: ${issues.missingHookTargets.join(", ")}`);
11905
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
+ }
11906
12029
  if (issues.invalidRuntimeScripts.length > 0) {
11907
12030
  details.push(`runtime startup still depends on installer-owned validation: ${issues.invalidRuntimeScripts.join(", ")}`);
11908
12031
  }
@@ -11922,7 +12045,7 @@ function checkInstalledBundleIntegrity(checks, rootDir, layout) {
11922
12045
  code: "consumer-bundle-integrity-invalid",
11923
12046
  title: "Installed bundle integrity is broken",
11924
12047
  detail: details.join("; "),
11925
- 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.",
11926
12049
  path: layout.manifestPath
11927
12050
  });
11928
12051
  }
@@ -12004,7 +12127,7 @@ function checkInstalledCodexHooksFeatureFlag(checks, rootDir, layout, options) {
12004
12127
  path: generalOnlyProbes[0].path
12005
12128
  });
12006
12129
  }
12007
- const legacyOnlyProbes = probes.filter((probe) => probe.alternateEnabled && !probe.recommendedEnabled);
12130
+ const legacyOnlyProbes = probes.filter((probe) => !probe.pluginBundledEnabled && probe.alternateEnabled && !probe.recommendedEnabled);
12008
12131
  if (legacyOnlyProbes.length > 0) {
12009
12132
  addCheck(checks, {
12010
12133
  level: "warning",
@@ -12395,7 +12518,7 @@ function isLikelyLocalRuntimePath(value) {
12395
12518
  function isLikelyOpenCodeInstallPath(rootDir) {
12396
12519
  const parent = dirname2(rootDir);
12397
12520
  const grandparent = dirname2(parent);
12398
- return basename(parent) === "plugins" && basename(grandparent) === "opencode";
12521
+ return basename2(parent) === "plugins" && basename2(grandparent) === "opencode";
12399
12522
  }
12400
12523
  function checkInstalledOpenCodeHostBridge(checks, rootDir) {
12401
12524
  if (!isLikelyOpenCodeInstallPath(rootDir)) {
@@ -12409,7 +12532,7 @@ function checkInstalledOpenCodeHostBridge(checks, rootDir) {
12409
12532
  });
12410
12533
  return;
12411
12534
  }
12412
- const pluginName = basename(rootDir);
12535
+ const pluginName = basename2(rootDir);
12413
12536
  const entryPath = `${rootDir}.ts`;
12414
12537
  const entryRelativePath = `${pluginName}.ts`;
12415
12538
  if (!existsSync4(entryPath)) {
@@ -12450,7 +12573,7 @@ function checkInstalledOpenCodeSkills(checks, rootDir) {
12450
12573
  if (!isLikelyOpenCodeInstallPath(rootDir)) {
12451
12574
  return;
12452
12575
  }
12453
- const pluginName = basename(rootDir);
12576
+ const pluginName = basename2(rootDir);
12454
12577
  const sourceSkillsDir = resolve4(rootDir, "skills");
12455
12578
  if (!existsSync4(sourceSkillsDir)) {
12456
12579
  addCheck(checks, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orchid-labs/pluxx",
3
- "version": "0.1.19",
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",