plugnz 0.0.24 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/plugnz.mjs +187 -75
  2. package/package.json +1 -1
package/dist/plugnz.mjs CHANGED
@@ -9852,7 +9852,7 @@ function escapeRegExp(value) {
9852
9852
 
9853
9853
  // src/hosts/cursor.ts
9854
9854
  import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync as statSync5 } from "node:fs";
9855
- import { join as join8 } from "node:path";
9855
+ import { delimiter as delimiter3, join as join8 } from "node:path";
9856
9856
  var cursorTargetProfile = {
9857
9857
  kind: "cursor",
9858
9858
  parseSyncTarget(value, label) {
@@ -9901,7 +9901,10 @@ var cursor = {
9901
9901
  id: "cursor",
9902
9902
  gui: true,
9903
9903
  detect() {
9904
- return existsSync5(cursorRoot());
9904
+ return locateCursorProbeBinary().kind === "path" || existsSync5(cursorRoot());
9905
+ },
9906
+ detectInstalled() {
9907
+ return locateCursorProbeBinary().kind === "path";
9905
9908
  },
9906
9909
  stores() {
9907
9910
  return [localDir()];
@@ -9944,6 +9947,48 @@ var cursor = {
9944
9947
  return entries;
9945
9948
  }
9946
9949
  };
9950
+ function locateCursorProbeBinary() {
9951
+ const override = process.env["OPEN_PLUGIN_CURSOR_BIN"];
9952
+ if (override !== undefined) {
9953
+ if (override.length === 0 || !isExecutableFile(override))
9954
+ return { kind: "refused" };
9955
+ return { kind: "path", path: override };
9956
+ }
9957
+ const found = cursorProbeCandidates().find(isExecutableFile);
9958
+ return found === undefined ? { kind: "absent" } : { kind: "path", path: found };
9959
+ }
9960
+ function cursorProbePath(env = process.env) {
9961
+ const isolated = env["OPEN_PLUGIN_HOME"];
9962
+ if (isolated !== undefined && isolated.length > 0)
9963
+ return join8(homeRoot(), "bin");
9964
+ return env["PATH"] ?? "";
9965
+ }
9966
+ function cursorProbeCandidates(env = process.env) {
9967
+ const candidates = [];
9968
+ const pathDirs = cursorProbePath(env).split(delimiter3).filter((dir) => dir.length > 0);
9969
+ for (const name of process.platform === "win32" ? ["cursor.exe", "cursor-agent.exe"] : ["cursor", "cursor-agent"]) {
9970
+ candidates.push(...pathDirs.map((dir) => join8(dir, name)));
9971
+ }
9972
+ const isolated = env["OPEN_PLUGIN_HOME"];
9973
+ const isolatedRun = isolated !== undefined && isolated.length > 0;
9974
+ if (process.platform === "darwin") {
9975
+ candidates.push(join8(homeRoot(), "Applications", "Cursor.app", "Contents", "MacOS", "Cursor"));
9976
+ if (!isolatedRun)
9977
+ candidates.push("/Applications/Cursor.app/Contents/MacOS/Cursor");
9978
+ } else if (process.platform === "linux") {
9979
+ candidates.push(join8(homeRoot(), ".local", "bin", "cursor"), join8(homeRoot(), ".local", "bin", "cursor-agent"));
9980
+ if (!isolatedRun)
9981
+ candidates.push("/usr/local/bin/cursor", "/usr/local/bin/cursor-agent", "/usr/bin/cursor", "/usr/bin/cursor-agent", "/usr/share/cursor/cursor", "/usr/lib/cursor/cursor", "/opt/Cursor/cursor", "/opt/cursor/cursor");
9982
+ } else if (process.platform === "win32") {
9983
+ const localAppData = env["LOCALAPPDATA"];
9984
+ const programFiles = env["ProgramFiles"];
9985
+ if (localAppData !== undefined)
9986
+ candidates.push(join8(localAppData, "Programs", "cursor", "Cursor.exe"));
9987
+ if (!isolatedRun && programFiles !== undefined)
9988
+ candidates.push(join8(programFiles, "Cursor", "Cursor.exe"));
9989
+ }
9990
+ return candidates.filter((path, index, all) => all.indexOf(path) === index);
9991
+ }
9947
9992
  function ownershipMarketplace(dir, name) {
9948
9993
  const marker = join8(dir, ".plgnz-install.json");
9949
9994
  if (!existsSync5(marker))
@@ -10675,7 +10720,7 @@ function namesOf(repo) {
10675
10720
 
10676
10721
  // src/hosts/zcode-cli.ts
10677
10722
  import { existsSync as existsSync12, lstatSync as lstatSync5, readFileSync as readFileSync10, realpathSync as realpathSync2 } from "node:fs";
10678
- import { delimiter as delimiter3, dirname as dirname3, join as join15, resolve as resolve7 } from "node:path";
10723
+ import { delimiter as delimiter4, dirname as dirname3, join as join15, resolve as resolve7 } from "node:path";
10679
10724
  var zcodeCliTargetProfile = singleInstanceTargetProfile("zcode-cli");
10680
10725
  function zcodeRegistryFile() {
10681
10726
  return join15(zcodeCliRoot(), "plugins", "installed_plugins.json");
@@ -10697,7 +10742,7 @@ function zcodeCliBinaryCandidates(env = process.env) {
10697
10742
  if (isolatedHome === undefined || isolatedHome.length === 0)
10698
10743
  candidates.push("/Applications/ZCode.app/Contents/Resources/glm/zcode.cjs");
10699
10744
  }
10700
- const pathBinary = (env["PATH"] ?? "").split(delimiter3).filter((dir) => dir.length > 0).map((dir) => join15(dir, "zcode")).find(isExecutableFile);
10745
+ const pathBinary = (env["PATH"] ?? "").split(delimiter4).filter((dir) => dir.length > 0).map((dir) => join15(dir, "zcode")).find(isExecutableFile);
10701
10746
  if (pathBinary !== undefined)
10702
10747
  candidates.push(pathBinary);
10703
10748
  return candidates.filter((path, index, all) => all.indexOf(path) === index);
@@ -11181,7 +11226,8 @@ function yamlStringify(value) {
11181
11226
  var hermesProvenManagedRevisions = [
11182
11227
  "c0d7294769a38c17ceae51d8f7995e66e1dcae27",
11183
11228
  "dce1e9b37581dd62e480a9064dc04a709c2940d3",
11184
- "6e7b83a2f1c093e992a8d838ed77ea320fbd8e51"
11229
+ "6e7b83a2f1c093e992a8d838ed77ea320fbd8e51",
11230
+ "7dbbb0f4a6ebeec9a8714ec37fa41340fe9e4e00"
11185
11231
  ];
11186
11232
  var hermesTargetProfile = {
11187
11233
  kind: "hermes",
@@ -17933,6 +17979,7 @@ function stagePlugin(source, stage, fallbackName, fallbackVersion) {
17933
17979
  mkdirSync6(dirname8(native), { recursive: true });
17934
17980
  writeFileSync6(native, JSON.stringify({ name: canonicalManifest.name, version: canonicalManifest.version ?? fallbackVersion, description: canonicalManifest.description, skills: "./skills/" }));
17935
17981
  }
17982
+ projectNativeMcp(stage);
17936
17983
  projectRootCommandsToNative(stage);
17937
17984
  projectNativeCommands(stage, native);
17938
17985
  const nativeManifest = parseManifest(native, "Claude Code");
@@ -17945,6 +17992,43 @@ function stagePlugin(source, stage, fallbackName, fallbackVersion) {
17945
17992
  if (fallbackName.length === 0)
17946
17993
  throw new Error("Claude Code plugin name is empty");
17947
17994
  }
17995
+ function projectNativeMcp(stage) {
17996
+ const canonical = join27(stage, "mcp.json");
17997
+ const native = join27(stage, ".mcp.json");
17998
+ const declarations = [canonical, native].filter(existsSync21).map((file) => {
17999
+ const value = JSON.parse(readFileSync21(file, "utf8"));
18000
+ if (value === null || typeof value !== "object" || Array.isArray(value))
18001
+ throw new Error(`Claude Code MCP declaration must be an object: ${file}`);
18002
+ const servers = value["mcpServers"];
18003
+ if (servers === null || typeof servers !== "object" || Array.isArray(servers))
18004
+ throw new Error(`Claude Code MCP declaration must contain a server object: ${file}`);
18005
+ return { file, value, servers };
18006
+ });
18007
+ const projectedCanonical = declarations[0]?.file === canonical ? claudeNativeMcpValue(declarations[0].servers) : undefined;
18008
+ const nativeServers = declarations.find((declaration) => declaration.file === native)?.servers;
18009
+ if (projectedCanonical !== undefined && nativeServers !== undefined && canonicalJson2(projectedCanonical) !== canonicalJson2(nativeServers)) {
18010
+ throw new Error("conflicting Claude Code canonical and native MCP declarations");
18011
+ }
18012
+ if (declarations[0]?.file === canonical && !existsSync21(native)) {
18013
+ writeFileSync6(native, JSON.stringify(claudeNativeMcpValue(declarations[0].value), null, 2));
18014
+ }
18015
+ }
18016
+ function claudeNativeMcpValue(value) {
18017
+ if (typeof value === "string")
18018
+ return value.replaceAll("${PLUGIN_ROOT}", "${CLAUDE_PLUGIN_ROOT}");
18019
+ if (Array.isArray(value))
18020
+ return value.map(claudeNativeMcpValue);
18021
+ if (value !== null && typeof value === "object")
18022
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, claudeNativeMcpValue(item)]));
18023
+ return value;
18024
+ }
18025
+ function canonicalJson2(value) {
18026
+ if (Array.isArray(value))
18027
+ return JSON.stringify(value.map(canonicalJson2));
18028
+ if (value !== null && typeof value === "object")
18029
+ return JSON.stringify(Object.entries(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(([key, item]) => [key, canonicalJson2(item)]));
18030
+ return JSON.stringify(value) ?? "null";
18031
+ }
17948
18032
  function projectRootCommandsToNative(stage) {
17949
18033
  const nativeCommands = join27(stage, ".claude", "commands");
17950
18034
  if (existsSync21(nativeCommands))
@@ -18713,11 +18797,11 @@ function claudeVersionObservation(observed) {
18713
18797
  return { kind: "detected", version: observed.version, probeId: observed.probeId };
18714
18798
  return { kind: observed.kind };
18715
18799
  }
18716
- var CLAUDE_MANAGED_RELEASES = new Set(["2.1.275", "2.1.295", "2.1.296"]);
18800
+ var CLAUDE_MANAGED_RELEASES = new Set(["2.1.275", "2.1.285", "2.1.295", "2.1.296"]);
18717
18801
  function claudeEvidenceProfiles(version, contracts) {
18718
18802
  if (version === undefined)
18719
18803
  return [];
18720
- const managed = CLAUDE_MANAGED_RELEASES.has(version) ? [claudeProfile(version, "managed", ["local", "git"], ["install", "update", "disable", "retire"])] : [];
18804
+ const managed = CLAUDE_MANAGED_RELEASES.has(version) ? [claudeProfile(version, "managed", ["local", "git"], version === "2.1.285" ? ["install", "update", "retire"] : ["install", "update", "disable", "retire"])] : [];
18721
18805
  const native = contracts.filter((contract) => contract.version === version && sandboxPasses(contract));
18722
18806
  if (native.length > 1)
18723
18807
  throw new Error(`ambiguous Claude Code native update contract for ${version}`);
@@ -18742,7 +18826,8 @@ function claudeProfile(version, route, sourceTypes, operations) {
18742
18826
  "docs/evidence/claude-code-2.1.296-native-20261013.json",
18743
18827
  "docs/evidence/claude-code-2.1.296-invocation-20261013.json",
18744
18828
  "docs/evidence/claude-code-2.1.296-agents-20261013.json"
18745
- ] : []
18829
+ ] : [],
18830
+ ...version === "2.1.285" ? ["docs/evidence/oh-my-ai-native-host-compat-20261015.json"] : []
18746
18831
  ]
18747
18832
  });
18748
18833
  }
@@ -18760,11 +18845,23 @@ var CLAUDE_PROJECTED_SEMANTICS = new Set([
18760
18845
  "reversible-disable"
18761
18846
  ]);
18762
18847
  function claudeSemantics(version) {
18848
+ const supported = version === "2.1.285" ? OH_MY_AI_INSTALL_SEMANTICS : CLAUDE_PROJECTED_SEMANTICS;
18763
18849
  return Object.fromEntries(PACKAGE_SEMANTICS.map((semantic) => [
18764
18850
  semantic,
18765
- CLAUDE_PROJECTED_SEMANTICS.has(semantic) || version === "2.1.296" && (semantic === "model-invocation-control" || semantic === "agents") ? "supported" : "unsupported"
18851
+ supported.has(semantic) || version === "2.1.296" && (semantic === "model-invocation-control" || semantic === "agents") ? "supported" : "unsupported"
18766
18852
  ]));
18767
18853
  }
18854
+ var OH_MY_AI_INSTALL_SEMANTICS = new Set([
18855
+ "ordinary-skills",
18856
+ "mcp",
18857
+ "resources",
18858
+ "auto-update-control",
18859
+ "readback",
18860
+ "rollback",
18861
+ "activation-reload",
18862
+ "retirement",
18863
+ "retention-safety"
18864
+ ]);
18768
18865
  function observeClaudeInstallations(target, version) {
18769
18866
  assertLifecycleMarketplaceEnvelope(version);
18770
18867
  const registry = readRegistry(join27(pluginsDir(), "installed_plugins.json"));
@@ -20053,7 +20150,8 @@ function wins(left, right) {
20053
20150
  }
20054
20151
  return left > right;
20055
20152
  }
20056
- var CODEX_ROUTE_VERSION = "0.162.0";
20153
+ var CODEX_NATIVE_ROUTE_VERSION = "0.162.0";
20154
+ var CODEX_MANAGED_ROUTE_VERSIONS = ["0.161.0", "0.162.0"];
20057
20155
  var NATIVE_UPGRADE_TIMEOUT_MS = 120000;
20058
20156
  var codexMarketplaceCheckoutRollback = "unverified";
20059
20157
  function nativeUpgradeTimeout() {
@@ -20068,15 +20166,17 @@ function nativeUpgradeTimeout() {
20068
20166
  var RELOAD_EFFECTIVE = { requirement: "reload", status: "effective" };
20069
20167
  var UPDATE_SEMANTICS = ["ordinary-skills", "resources", "auto-update-control", "readback", "rollback", "activation-reload"];
20070
20168
  var MANAGED_SEMANTICS = [...UPDATE_SEMANTICS, "retirement", "retention-safety", "model-invocation-control", "commands", "mcp"];
20169
+ var OH_MY_AI_INSTALL_SEMANTICS2 = ["ordinary-skills", "mcp", "resources", "auto-update-control", "readback", "rollback", "activation-reload"];
20071
20170
  var codexEvidenceProfiles = [
20072
20171
  portableHookProfile(hookAdapter2, "managed", ["install", "update", "retire"]),
20073
- codexRouteProfile("native", ["update"], UPDATE_SEMANTICS, ["docs/research/native-plugin-update-capabilities-2026-10-09.md", "docs/evidence/codex-native-released-20261011.md"]),
20074
- codexRouteProfile("managed", ["install", "update", "retire"], MANAGED_SEMANTICS, [
20172
+ codexRouteProfile(CODEX_NATIVE_ROUTE_VERSION, "native", ["update"], UPDATE_SEMANTICS, ["docs/research/native-plugin-update-capabilities-2026-10-09.md", "docs/evidence/codex-native-released-20261011.md"]),
20173
+ ...CODEX_MANAGED_ROUTE_VERSIONS.map((version) => codexRouteProfile(version, "managed", ["install", "update", "retire"], version === "0.161.0" ? [...OH_MY_AI_INSTALL_SEMANTICS2, "retirement", "retention-safety"] : MANAGED_SEMANTICS, [
20075
20174
  "docs/hosts/codex.md",
20076
20175
  "docs/adr/0004-retain-plugin-state-on-removal.md",
20077
20176
  "docs/evidence/codex-policy-mcp-20261013.json",
20078
- "docs/evidence/codex-native-released-20261011.md"
20079
- ])
20177
+ "docs/evidence/codex-native-released-20261011.md",
20178
+ ...version === "0.161.0" ? ["docs/evidence/oh-my-ai-native-host-compat-20261015.json"] : []
20179
+ ]))
20080
20180
  ];
20081
20181
  var codexLifecycleDefinition = {
20082
20182
  id: "codex",
@@ -20116,7 +20216,7 @@ var codexLifecycleDefinition = {
20116
20216
  cleanup: async (reference) => cleanupCodexStage(reference)
20117
20217
  };
20118
20218
  var codexLifecycle = createLifecycleHostAdapter(codexLifecycleDefinition);
20119
- function codexRouteProfile(route, operations, supportedSemantics, evidence) {
20219
+ function codexRouteProfile(detectedVersion, route, operations, supportedSemantics, evidence) {
20120
20220
  const checkoutRollback = route === "native" ? codexMarketplaceCheckoutRollback : "supported";
20121
20221
  if (checkoutRollback !== "unverified" && route === "native") {
20122
20222
  throw new Error("codex marketplace checkout rollback must stay unverified");
@@ -20127,7 +20227,7 @@ function codexRouteProfile(route, operations, supportedSemantics, evidence) {
20127
20227
  semantics[semantic] = supported.has(semantic) ? "supported" : "unsupported";
20128
20228
  return createCapabilityEvidenceProfile({
20129
20229
  host: "codex",
20130
- detectedVersion: CODEX_ROUTE_VERSION,
20230
+ detectedVersion,
20131
20231
  sourceTypes: ["git", "local"],
20132
20232
  operations,
20133
20233
  route,
@@ -22212,8 +22312,8 @@ function unexposed(phase) {
22212
22312
  }
22213
22313
 
22214
22314
  // src/hosts/cursor-writer.ts
22215
- import { accessSync as accessSync5, constants as constants5, cpSync as cpSync8, existsSync as existsSync24, lstatSync as lstatSync18, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync8, readFileSync as readFileSync26, readdirSync as readdirSync17, renameSync as renameSync6, rmSync as rmSync9, statSync as statSync12, writeFileSync as writeFileSync9 } from "node:fs";
22216
- import { delimiter as delimiter4, join as join32, resolve as resolve19 } from "node:path";
22315
+ import { cpSync as cpSync8, existsSync as existsSync24, lstatSync as lstatSync18, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync8, readFileSync as readFileSync26, readdirSync as readdirSync17, renameSync as renameSync6, rmSync as rmSync9, statSync as statSync12, writeFileSync as writeFileSync9 } from "node:fs";
22316
+ import { join as join32, resolve as resolve19 } from "node:path";
22217
22317
  import { tmpdir as tmpdir5 } from "node:os";
22218
22318
 
22219
22319
  // src/hosts/cursor-adoption.ts
@@ -23065,37 +23165,6 @@ function probeCursorVersion() {
23065
23165
  return { kind: "unparseable" };
23066
23166
  return { kind: "detected", version, probeId: `cursor-${version}` };
23067
23167
  }
23068
- function locateCursorProbeBinary() {
23069
- const override = process.env["OPEN_PLUGIN_CURSOR_BIN"];
23070
- if (override !== undefined) {
23071
- if (override.length === 0 || !existsSync24(override))
23072
- return { kind: "refused" };
23073
- return { kind: "path", path: override };
23074
- }
23075
- const found = whichOnPath(cursorProbePath(), "cursor");
23076
- return found === undefined ? { kind: "absent" } : { kind: "path", path: found };
23077
- }
23078
- function cursorProbePath() {
23079
- const isolated = process.env["OPEN_PLUGIN_HOME"];
23080
- if (isolated !== undefined && isolated.length > 0)
23081
- return join32(homeRoot(), "bin");
23082
- return process.env["PATH"] ?? "";
23083
- }
23084
- function whichOnPath(pathEnv, name) {
23085
- for (const dir of pathEnv.split(delimiter4)) {
23086
- if (dir.length === 0)
23087
- continue;
23088
- const candidate = join32(dir, name);
23089
- try {
23090
- accessSync5(candidate, constants5.X_OK);
23091
- if (statSync12(candidate).isFile())
23092
- return candidate;
23093
- } catch {
23094
- continue;
23095
- }
23096
- }
23097
- return;
23098
- }
23099
23168
  function cursorVersion(stdout) {
23100
23169
  const line = stdout.split(/\r?\n/u).map((item) => item.trim()).find((item) => item.length > 0);
23101
23170
  if (line === undefined)
@@ -23776,16 +23845,30 @@ var supportedSemantics = new Set([
23776
23845
  "activation-reload",
23777
23846
  "reversible-disable"
23778
23847
  ]);
23779
- var ompManagedProfiles = ["18.1.4", "18.10.3"].map((detectedVersion) => createCapabilityEvidenceProfile({
23848
+ var ohMyAiInstallSemantics = new Set([
23849
+ "ordinary-skills",
23850
+ "mcp",
23851
+ "resources",
23852
+ "auto-update-control",
23853
+ "readback",
23854
+ "rollback",
23855
+ "activation-reload",
23856
+ "retirement",
23857
+ "retention-safety"
23858
+ ]);
23859
+ var ompManagedProfiles = ["18.1.4", "18.8.7", "18.10.3"].map((detectedVersion) => createCapabilityEvidenceProfile({
23780
23860
  host: "omp",
23781
23861
  detectedVersion,
23782
23862
  sourceTypes: ["local", "git"],
23783
- operations: ["install", "update", "disable", "retire"],
23863
+ operations: detectedVersion === "18.8.7" ? ["install", "update", "retire"] : ["install", "update", "disable", "retire"],
23784
23864
  route: "managed",
23785
23865
  operationStatus: "supported",
23786
- semantics: Object.fromEntries(PACKAGE_SEMANTICS.map((semantic) => [semantic, supportedSemantics.has(semantic) ? "supported" : "unsupported"])),
23866
+ semantics: Object.fromEntries(PACKAGE_SEMANTICS.map((semantic) => [
23867
+ semantic,
23868
+ (detectedVersion === "18.8.7" ? ohMyAiInstallSemantics : supportedSemantics).has(semantic) ? "supported" : "unsupported"
23869
+ ])),
23787
23870
  evidence: [
23788
- detectedVersion === "18.10.3" ? "docs/evidence/omp-native-extension-package-20261013.json" : "docs/evidence/omp-native-extension-package-20260923.json",
23871
+ detectedVersion === "18.10.3" ? "docs/evidence/omp-native-extension-package-20261013.json" : detectedVersion === "18.8.7" ? "docs/evidence/oh-my-ai-native-host-compat-20261015.json" : "docs/evidence/omp-native-extension-package-20260923.json",
23789
23872
  "docs/hosts/omp.md",
23790
23873
  "docs/research/native-plugin-update-capabilities-2026-10-09.md"
23791
23874
  ]
@@ -26151,11 +26234,11 @@ var digest6 = (value) => {
26151
26234
  hash.update(value);
26152
26235
  return hash.digest("hex").slice(0, 16);
26153
26236
  };
26154
- function canonicalJson2(value) {
26237
+ function canonicalJson3(value) {
26155
26238
  if (Array.isArray(value))
26156
- return `array:${JSON.stringify(value.map((item) => canonicalJson2(item)))}`;
26239
+ return `array:${JSON.stringify(value.map((item) => canonicalJson3(item)))}`;
26157
26240
  if (value !== null && typeof value === "object")
26158
- return `object:${JSON.stringify(Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => [key, canonicalJson2(item)]))}`;
26241
+ return `object:${JSON.stringify(Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => [key, canonicalJson3(item)]))}`;
26159
26242
  return JSON.stringify(value);
26160
26243
  }
26161
26244
  var grokWriter = {
@@ -26502,7 +26585,7 @@ ${doc.prompt}`);
26502
26585
  }
26503
26586
  const legacyMcp = join38(dir, "mcp.json");
26504
26587
  const nativeMcp = join38(dir, ".mcp.json");
26505
- if (existsSync30(legacyMcp) && existsSync30(nativeMcp) && canonicalJson2(JSON.parse(readFileSync32(legacyMcp, "utf8")).mcpServers) !== canonicalJson2(JSON.parse(readFileSync32(nativeMcp, "utf8")).mcpServers))
26588
+ if (existsSync30(legacyMcp) && existsSync30(nativeMcp) && canonicalJson3(JSON.parse(readFileSync32(legacyMcp, "utf8")).mcpServers) !== canonicalJson3(JSON.parse(readFileSync32(nativeMcp, "utf8")).mcpServers))
26506
26589
  throw new Error(`conflicting Grok MCP declarations: ${legacyMcp} and ${nativeMcp}`);
26507
26590
  if (existsSync30(legacyMcp) && !existsSync30(nativeMcp))
26508
26591
  cpSync13(legacyMcp, nativeMcp);
@@ -27821,11 +27904,11 @@ async function probeZcodeVersion(target) {
27821
27904
  function zcodePluginDataDir(nativeId) {
27822
27905
  return join40(zcodeCliRoot(), "plugins", "data", nativeId.replace(/[^a-zA-Z0-9_.@-]/g, "-"));
27823
27906
  }
27824
- function canonicalJson3(value) {
27907
+ function canonicalJson4(value) {
27825
27908
  if (Array.isArray(value))
27826
- return `[${value.map((item) => canonicalJson3(item)).join(",")}]`;
27909
+ return `[${value.map((item) => canonicalJson4(item)).join(",")}]`;
27827
27910
  if (isObject4(value))
27828
- return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson3(value[key])}`).join(",")}}`;
27911
+ return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson4(value[key])}`).join(",")}}`;
27829
27912
  return JSON.stringify(value) ?? "null";
27830
27913
  }
27831
27914
  function sha2562(text) {
@@ -27866,7 +27949,7 @@ function assertStageCleanupAuthority(stage, reference) {
27866
27949
  } else if (!artifact?.startsWith("sha256:"))
27867
27950
  throw new Error("ZCode cleanup stage has no captured artifact authority");
27868
27951
  const exactEntries = (root, expected) => {
27869
- if (canonicalJson3(readdirSync24(root).sort()) !== canonicalJson3(expected.sort()))
27952
+ if (canonicalJson4(readdirSync24(root).sort()) !== canonicalJson4(expected.sort()))
27870
27953
  throw new Error("ZCode cleanup stage layout changed");
27871
27954
  };
27872
27955
  exactEntries(stage, ["marketplace", "resources", "stage-receipt.json"]);
@@ -27887,10 +27970,10 @@ function assertStageCleanupAuthority(stage, reference) {
27887
27970
  if (marker.resourcePath !== join40(realpathSync6(zcodeCliRoot()), "plgnz-resources", marketplaceName2(marker.nativeId), marker.fingerprint))
27888
27971
  throw new Error("ZCode cleanup stage native root was redirected");
27889
27972
  const expectedReceipt = { attemptId: reference.attemptId, operationId: reference.operationId, sourceRevision: marker.source, packageFingerprint: marker.fingerprint, projectedFingerprint: digest };
27890
- if (canonicalJson3(readJson3(join40(stage, "stage-receipt.json"))) !== canonicalJson3(expectedReceipt))
27973
+ if (canonicalJson4(readJson3(join40(stage, "stage-receipt.json"))) !== canonicalJson4(expectedReceipt))
27891
27974
  throw new Error("ZCode cleanup stage receipt changed");
27892
27975
  const expectedMarket = { name: marketplaceName2(marker.nativeId), plugins: [{ name, source: `./plugins/${name}` }] };
27893
- if (canonicalJson3(readJson3(join40(market, "marketplace.json"))) !== canonicalJson3(expectedMarket))
27976
+ if (canonicalJson4(readJson3(join40(market, "marketplace.json"))) !== canonicalJson4(expectedMarket))
27894
27977
  throw new Error("ZCode cleanup stage marketplace changed");
27895
27978
  }
27896
27979
  function readConfigObject() {
@@ -27915,7 +27998,7 @@ function retainedState(nativeId) {
27915
27998
  const dataDir = zcodePluginDataDir(nativeId);
27916
27999
  const pluginData = existsSync31(dataDir) && statSync13(dataDir).isDirectory() ? { state: "present", fingerprint: fingerprintTree(dataDir) } : { state: "absent", fingerprint: null };
27917
28000
  const options = optionValue(nativeId);
27918
- const inactiveMetadata = options === undefined ? { state: "absent", fingerprint: null } : { state: "present", fingerprint: sha2562(canonicalJson3(options)) };
28001
+ const inactiveMetadata = options === undefined ? { state: "absent", fingerprint: null } : { state: "present", fingerprint: sha2562(canonicalJson4(options)) };
27919
28002
  return { pluginData, inactiveMetadata };
27920
28003
  }
27921
28004
  function installationFor(native) {
@@ -28774,6 +28857,30 @@ if __name__ == "__main__":
28774
28857
  sys.argv[0] = sys.argv[0][:-4]
28775
28858
  sys.exit(main())
28776
28859
  `;
28860
+ var hermesNativeBootstrap7dbbb0f = `import os, re, sys
28861
+ os.environ.pop('PYTHONHOME', None)
28862
+ os.environ.pop('PYTHONPATH', None)
28863
+ sys.path.insert(0, '/__PLUGNZ_HERMES_ROOT__')
28864
+ if sys.argv[1:2] == ['--print-runtime-command']: sys.dont_write_bytecode = True
28865
+ from hermes_constants import get_default_hermes_root
28866
+ os.environ['HERMES_HOME'] = os.environ.get('HERMES_HOME') or str(get_default_hermes_root())
28867
+ if sys.argv[1:2] == ['--print-runtime-command']:
28868
+ from pathlib import Path
28869
+ from hermes_cli._launchers import print_runtime_command
28870
+ print_runtime_command(Path('/__PLUGNZ_HERMES_ROOT__'), sys.argv[2:])
28871
+ sys.exit(0)
28872
+ import hermes_bootstrap
28873
+ if sys.argv[1:2] == ['--run-module']:
28874
+ import runpy
28875
+ if len(sys.argv) < 3: sys.exit('hermes: --run-module needs a module')
28876
+ module = sys.argv.pop(2)
28877
+ del sys.argv[1]
28878
+ runpy.run_module(module, run_name='__main__', alter_sys=True)
28879
+ sys.exit(0)
28880
+ from hermes_cli.main import main
28881
+ sys.argv[0] = re.sub(r'(-script\\.pyw|\\.exe)?$', '', sys.argv[0])
28882
+ sys.exit(main())
28883
+ `;
28777
28884
 
28778
28885
  // src/hosts/hermes-writer.ts
28779
28886
  var MARKER11 = ".plgnz-install.json";
@@ -29277,7 +29384,7 @@ exec `.length));
29277
29384
  if (bindings.length !== 1)
29278
29385
  return;
29279
29386
  const root = literalPythonPath(bindings[0][1]);
29280
- if (root === undefined || code.replaceAll(bindings[0][1], "'/__PLUGNZ_HERMES_ROOT__'") !== hermesNativeBootstrap)
29387
+ if (root === undefined || ![hermesNativeBootstrap, hermesNativeBootstrap7dbbb0f].includes(code.replaceAll(bindings[0][1], "'/__PLUGNZ_HERMES_ROOT__'")))
29281
29388
  return;
29282
29389
  return root !== undefined && isAbsolute12(root) && existsSync32(join41(root, "hermes_cli", "main.py")) && realpathSync7(join41(root, "hermes_cli", "main.py")).startsWith(`${realpathSync7(root)}/`) && verifiedSourceImportClosure(realpathSync7(root)) ? realpathSync7(root) : undefined;
29283
29390
  }
@@ -29407,12 +29514,12 @@ var hermesManagedProfiles = hermesProvenManagedRevisions.map((detectedVersion) =
29407
29514
  host: "hermes",
29408
29515
  detectedVersion,
29409
29516
  sourceTypes: ["local", "git"],
29410
- operations: ["install", "update", "disable", "retire"],
29517
+ operations: detectedVersion === "7dbbb0f4a6ebeec9a8714ec37fa41340fe9e4e00" ? ["install", "update", "retire"] : ["install", "update", "disable", "retire"],
29411
29518
  route: "managed",
29412
29519
  operationStatus: "supported",
29413
- semantics: Object.fromEntries(PACKAGE_SEMANTICS.map((semantic) => [semantic, HERMES_SUPPORTED.has(semantic) ? "supported" : "unsupported"])),
29520
+ semantics: Object.fromEntries(PACKAGE_SEMANTICS.map((semantic) => [semantic, HERMES_SUPPORTED.has(semantic) && !(detectedVersion === "7dbbb0f4a6ebeec9a8714ec37fa41340fe9e4e00" && semantic === "reversible-disable") ? "supported" : "unsupported"])),
29414
29521
  evidence: [
29415
- detectedVersion === "c0d7294769a38c17ceae51d8f7995e66e1dcae27" ? "docs/evidence/hermes-native-loader-c0d7294-20260923.json" : detectedVersion === "6e7b83a2f1c093e992a8d838ed77ea320fbd8e51" ? "docs/evidence/hermes-native-loader-6e7b83a-20261013.json" : "docs/evidence/hermes-native-loader-dce1e9b-20261011.json",
29522
+ detectedVersion === "c0d7294769a38c17ceae51d8f7995e66e1dcae27" ? "docs/evidence/hermes-native-loader-c0d7294-20260923.json" : detectedVersion === "6e7b83a2f1c093e992a8d838ed77ea320fbd8e51" ? "docs/evidence/hermes-native-loader-6e7b83a-20261013.json" : detectedVersion === "7dbbb0f4a6ebeec9a8714ec37fa41340fe9e4e00" ? "docs/evidence/hermes-native-loader-7dbbb0f-20261015.json" : "docs/evidence/hermes-native-loader-dce1e9b-20261011.json",
29416
29523
  "docs/hosts/hermes.md",
29417
29524
  "docs/research/native-plugin-update-capabilities-2026-10-09.md"
29418
29525
  ]
@@ -34021,7 +34128,7 @@ function legacyCommandAction(command) {
34021
34128
  // package.json
34022
34129
  var package_default = {
34023
34130
  name: "plugnz",
34024
- version: "0.0.24",
34131
+ version: "0.0.25",
34025
34132
  description: "Install, diagnose and update agent plugins (Agent Plugins spec) and MCP configs across Claude Code, Codex, Cursor, Kimi and more",
34026
34133
  license: "MIT",
34027
34134
  type: "module",
@@ -34493,17 +34600,22 @@ function select(available, targets) {
34493
34600
  for (const target of targets)
34494
34601
  if (!known.has(target))
34495
34602
  return { selected: [], error: `unknown target '${target}' (known: ${[...known.keys()].join(", ")})` };
34496
- const selected = targets.length === 0 ? [...available] : targets.map((target) => known.get(target));
34603
+ if (targets.length === 0)
34604
+ return { selected: available.filter(detectInstalled) };
34605
+ const selected = targets.map((target) => known.get(target));
34497
34606
  const absent = selected.find((host) => !host.detect());
34498
- if (absent !== undefined && targets.length > 0)
34607
+ if (absent !== undefined)
34499
34608
  return { selected: [], error: `requested target '${absent.id}' is not present on this machine` };
34500
34609
  return { selected: selected.filter((host) => host.detect()) };
34501
34610
  }
34611
+ function detectInstalled(host) {
34612
+ return host.detectInstalled?.() ?? host.detect();
34613
+ }
34502
34614
  function selectProfiles(targets) {
34503
34615
  const duplicate = targets.find((target, index) => targets.indexOf(target) !== index);
34504
34616
  if (duplicate !== undefined)
34505
34617
  return { selected: [], error: `duplicate target '${duplicate}'` };
34506
- const selected = targets.length === 0 ? writers.filter((writer) => writer.detect()).map((writer) => findConsumerProfile(writer.id)).filter((profile) => profile !== undefined) : targets.map(findConsumerProfile);
34618
+ const selected = targets.length === 0 ? writers.filter(detectInstalled).map((writer) => findConsumerProfile(writer.id)).filter((profile) => profile !== undefined) : targets.map(findConsumerProfile);
34507
34619
  const unknownIndex = selected.findIndex((profile) => profile === undefined);
34508
34620
  if (unknownIndex !== -1)
34509
34621
  return { selected: [], error: `unknown target '${targets[unknownIndex]}' (known: ${consumerProfiles.map((profile) => profile.id).join(", ")})` };
@@ -34631,7 +34743,7 @@ function splitAddTargets(requested, dryRun) {
34631
34743
  }
34632
34744
  let detected;
34633
34745
  try {
34634
- detected = writers.filter((writer) => writer.detect());
34746
+ detected = writers.filter(detectInstalled);
34635
34747
  } catch (error) {
34636
34748
  return { kind: "refused", report: reportFor("add", dryRun, [], [], {
34637
34749
  terminalPhase: "preflight",
@@ -35425,7 +35537,7 @@ async function main(argv) {
35425
35537
  const disallowed = rejectDisallowed(flags, new Set(["all"]));
35426
35538
  if (disallowed || flags.positionals.length > 0)
35427
35539
  fail4(`plugnz targets: ${disallowed ?? "unexpected argument"}`, 2);
35428
- const present = hosts.filter((h) => h.detect());
35540
+ const present = hosts.filter(detectInstalled);
35429
35541
  if (json) {
35430
35542
  console.log(JSON.stringify(flags.all ? consumerProfiles : present.map((h) => h.id), null, 2));
35431
35543
  } else {
@@ -35764,7 +35876,7 @@ async function main(argv) {
35764
35876
  }
35765
35877
  }
35766
35878
  const candidates = flags.targets.length > 0 ? writers.filter((writer) => flags.targets.includes(writer.id)) : flags.all ? [...writers] : writers.filter((writer) => writer.gui);
35767
- const detected = candidates.filter((writer) => writer.detect());
35879
+ const detected = candidates.filter((writer) => flags.targets.length > 0 ? writer.detect() : detectInstalled(writer));
35768
35880
  if (detected.length === 0) {
35769
35881
  console.error("plugnz pin: No detected writer targets");
35770
35882
  return 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plugnz",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "description": "Install, diagnose and update agent plugins (Agent Plugins spec) and MCP configs across Claude Code, Codex, Cursor, Kimi and more",
5
5
  "license": "MIT",
6
6
  "type": "module",