context-mode 2.0.0-next.5 → 2.0.0-next.7

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.
@@ -9,7 +9,7 @@
9
9
  "name": "context-mode",
10
10
  "skills": "./claude-code/skills",
11
11
  "source": "./",
12
- "version": "2.0.0-next.5"
12
+ "version": "2.0.0-next.7"
13
13
  }
14
14
  ]
15
15
  }
@@ -12,5 +12,5 @@
12
12
  },
13
13
  "name": "context-mode",
14
14
  "skills": "./claude-code/skills",
15
- "version": "2.0.0-next.5"
15
+ "version": "2.0.0-next.7"
16
16
  }
@@ -0,0 +1,50 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "command": "node \"${PLUGIN_ROOT}/hook.mjs\" --agent codex",
8
+ "timeout": 5,
9
+ "type": "command"
10
+ }
11
+ ],
12
+ "matcher": "^(Bash|apply_patch|mcp__context_mode__ctx_.*)$"
13
+ }
14
+ ],
15
+ "PreToolUse": [
16
+ {
17
+ "hooks": [
18
+ {
19
+ "command": "node \"${PLUGIN_ROOT}/hook.mjs\" --agent codex",
20
+ "timeout": 5,
21
+ "type": "command"
22
+ }
23
+ ],
24
+ "matcher": "^(Bash|apply_patch|mcp__context_mode__ctx_.*)$"
25
+ }
26
+ ],
27
+ "SessionStart": [
28
+ {
29
+ "hooks": [
30
+ {
31
+ "command": "node \"${PLUGIN_ROOT}/hook.mjs\" --agent codex",
32
+ "timeout": 5,
33
+ "type": "command"
34
+ }
35
+ ]
36
+ }
37
+ ],
38
+ "UserPromptSubmit": [
39
+ {
40
+ "hooks": [
41
+ {
42
+ "command": "node \"${PLUGIN_ROOT}/hook.mjs\" --agent codex",
43
+ "timeout": 5,
44
+ "type": "command"
45
+ }
46
+ ]
47
+ }
48
+ ]
49
+ }
50
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "mcpServers": {
3
+ "context-mode": {
4
+ "args": [
5
+ "./server.mjs",
6
+ "--agent",
7
+ "codex"
8
+ ],
9
+ "command": "node",
10
+ "cwd": ".",
11
+ "default_tools_approval_mode": "approve"
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "description": "Context Mode for Codex",
3
+ "hooks": "./.codex-plugin/hooks.json",
4
+ "interface": {
5
+ "category": "Productivity",
6
+ "displayName": "context-mode"
7
+ },
8
+ "mcpServers": "./.codex-plugin/mcp.json",
9
+ "name": "context-mode",
10
+ "skills": "./codex/skills/",
11
+ "version": "2.0.0-next.7"
12
+ }
package/SHA256SUMS CHANGED
@@ -1,13 +1,19 @@
1
- b56b6785a4a93ab800598c09605bf52ecf59448102978e6486d96eaf7ebba716 .claude-plugin/marketplace.json
2
- 6dbd4097855d694477f3145086a727cab30cfeaf6ba65c9a4ba45e61095c1a00 .claude-plugin/plugin.json
1
+ 7362028009067c6db76e755a639e87a1e3cfe4dfc8d913fcefd5169d55103080 .claude-plugin/marketplace.json
2
+ e5d35796110662348715d11a79e794fbbe9e61e62902cd76cd68486da635f1a3 .claude-plugin/plugin.json
3
+ 187503e1455560d4ab5a72e3b8cd2f274abd4ccc5faa60dd66c37e44bb5f10c2 .codex-plugin/hooks.json
4
+ 4edea851775bc3f0418f8d9cf6ead74f2767c3a9e3b8c05749eacb78ebb3b896 .codex-plugin/mcp.json
5
+ f96f490f057000cab1f5c56496c0fc3de446a637b6f954d6d853663e9b03197c .codex-plugin/plugin.json
3
6
  1773e40a89384dd1af9023ba533da1908f3e2435dbaaa7cc941edf0514148313 claude-code/skills/ctx-doctor/SKILL.md
4
7
  34fffb9c76d69c551f07036230bec0fbaca7a69177a5a47f89ddb9a9990a1fa2 claude-code/skills/ctx-stats/SKILL.md
5
8
  d8f835d2f2b3eb70c5902f8707e7c5857977cec9e20ace76c499378a04e178e0 claude-code/skills/ctx-upgrade/SKILL.md
6
- 363b624a157ba796a4ae73481c5159fb3bf4a54ec18570ac54f43f82f3ca7897 cli.mjs
7
- 1c7ea3030f85ce4990c69e1aba7eaa4c5e52e0ca023d923e3f63fb339fa76ea0 copilot/plugin.json
9
+ 4716b2bc1bce3752f140f6b8f2b276f53b36960ac724eb7f03e1c93318fee4f1 cli.mjs
10
+ 83c297020ed0c592fc68c9c482546a6999d41df5d06d8a329498f10edb1bd38e codex/skills/ctx-doctor/SKILL.md
11
+ adc2c374f699d3698110920bb48411965de09fc6e7232ce59c913f6d58c0d738 codex/skills/ctx-stats/SKILL.md
12
+ 5c12cdd19a5e3ed7d9ba3a47b24d03864a28d36cf7006876284ee07cd4221ec4 codex/skills/ctx-upgrade/SKILL.md
13
+ 83ba9e9cfc9ed07b404f2afd55f65c04a2716e428559c5264ceb97bdfcf3cdae copilot/plugin.json
8
14
  832bf0d31c37a448f3904bc41c7df071777aec2f8fce9d667f1fcf5b03a52a91 fixtures/hook-roundtrip.json
9
- 8a32cfefc76b23e6fb317e5caa869f0c01d5132f16648f0d3aac9a5dbb61f763 gemini-extension.json
10
- 77e6322222838ac99fa8d320c2a358b488d9060660ba574cf60a2f1e27c47cd4 hook.mjs
15
+ d28e323da98711de50112f1e7a1242c22133cd3490e0109d6824732cfd494c4e gemini-extension.json
16
+ ccab1edf7d21b15976b3523acecca1f485f4b0822b265e27c7a0df821e097c1c hook.mjs
11
17
  1f8d8650d2b38737522cab6b875878e8baf84a74acf98cd924c7af22852d873f hooks/claude-code.json
12
18
  2524a0eb52683b65c65943c5097db513e9845ba14e84324b39e9a8ea2bb43193 hooks/codex.json
13
19
  b656fed2b754ebcfd4c156bee81d5879c21a8083fc0d6b8e3241462b63a214b6 hooks/copilot-cli.json
@@ -16,16 +22,16 @@ f336d1db67de49e641687bbd41ba1a9424e31dfe2377b2284bf44358288ebd8b hooks/kiro.jso
16
22
  017c9cc3997dd53231b8548b1a1609fddc51177af53501565a4f334602039860 hooks/qwen.json
17
23
  33f69267645338d0dc392ce551dcd7c69a0b508113469d6ea637d3f34239ef1d hooks/vscode.json
18
24
  085630bccf2073ac9a62be24ef91dfc47d106092dc82c822db70890b7d3ae1c0 hooks/zcode.json
19
- 65293aa65a8f05605354128530bd9a46d2fdb2b6aeb784b482b0e67e50fc9047 opencode/plugin.js
20
- 5f605e530767e65e9dae61545d2e3a29637e85f160d1c932d8901b71bfecf872 package.json
21
- 5b254ae726b8d92bd083069d54ea3a92465d07655d8cf0bb321585572c5d6044 pi/index.js
25
+ 8dfb464afb21d1548e5c1368fac5fd8d43838a2d8111bc3ec82cac8a09c977e3 opencode/plugin.js
26
+ d38b8f717169353ff603f6b22ee66d25c01e1670a64583e28ccec3862f29e215 package.json
27
+ d8784f4a18e478f7176189d9c45ab28843e3dbfa7e4c50103c1f20036961e8d0 pi/index.js
22
28
  8712881622c9905aa4836af50d903042d34a91506264e459bc7839331f6f0192 pi/skills/ctx-doctor/SKILL.md
23
29
  8d6e8e2a82eb079bddc60727f52d9f9a6e0bf9e15391357fed82ee76ab5fe76c pi/skills/ctx-stats/SKILL.md
24
30
  db6f9c006bc864a7271f1eeffb1e316ebb537a3414f1c22f8b9de0a896e8e3c5 pi/skills/ctx-upgrade/SKILL.md
25
- 60c29a65f5cc4f08a81944c38252ff5c57d49516cf0a0058c4fd5f4885e4ac3a qwen-extension.json
26
- 52add685290c12127664d24753f897b81350ec44453f91330b332027bc56b52a run.mjs
27
- 52add685290c12127664d24753f897b81350ec44453f91330b332027bc56b52a search.mjs
28
- 02bfde857e38769a5f643d73564a817acdc526a796f5f49af45521d0230d7818 server.mjs
29
- 6a7fdf30ff29c57a0edbcbe508b77151cc71dd78ef3b6ee90d957ce0c8d28d6f skills/ctx-doctor/SKILL.md
30
- 81be076a843f0b352075c73a09ec0fa62adea4f3bc01409f516d26891b32e835 skills/ctx-stats/SKILL.md
31
- df85a77653622d23d8851fb7eb16f977e5f8646aa54ca5ede0db811dcd950916 skills/ctx-upgrade/SKILL.md
31
+ 6a8c387c281796e0f90309e730424e60191471ea0f26585dde7a4f22124c8ed4 qwen-extension.json
32
+ 54f4ec9ac9cc26814e7e548b8bafb05bf2610eb0ed0bab2f1e9576e2c99a799d run.mjs
33
+ 54f4ec9ac9cc26814e7e548b8bafb05bf2610eb0ed0bab2f1e9576e2c99a799d search.mjs
34
+ f8929b0cb819af7a2e6989efb34da39ff46a4e3a53702e717903442bdc8874b5 server.mjs
35
+ e5503a22a6238901484d123efc11d2d933aa9a54c6ac2018812cfa65ec4e53e3 skills/ctx-doctor/SKILL.md
36
+ 1044587a1906c69f2467c089a25e19819a290ea5728389bd1f086c6dfc0d0c51 skills/ctx-stats/SKILL.md
37
+ c1cac75b7506ee0d06089ce611ac6dc9314cf12435da318ce88ad50e2c5debbf skills/ctx-upgrade/SKILL.md
package/cli.mjs CHANGED
@@ -442,8 +442,12 @@ var UPGRADE_REPORT_ONLY_REASONS = Object.freeze([V1_REASON.statusLine, V1_REASON
442
442
  var OPENCODE_TOOL_PREFIX = SERVER_KEY + "_";
443
443
  var JSON_INDENT_UNIT = " ";
444
444
  var ZCODE_MCP_FEATURE_KEY = Object.freeze(["features", "mcp"]);
445
+ var CODEX_OMIT_TOOLS_FROM_FIELD = "omit_tools_from";
446
+ var CODEX_OMIT_DEFERRED = Object.freeze(["deferred"]);
447
+ var CODEX_APPROVAL_MODE_FIELD = "default_tools_approval_mode";
448
+ var CODEX_APPROVAL_APPROVE = "approve";
445
449
  var OWN_MCP_ENTRY = Object.freeze({
446
- codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY] },
450
+ codex: { file: [".codex", "config.toml"], key: ["mcp_servers", SERVER_KEY], fields: { [CODEX_OMIT_TOOLS_FROM_FIELD]: CODEX_OMIT_DEFERRED, [CODEX_APPROVAL_MODE_FIELD]: CODEX_APPROVAL_APPROVE } },
447
451
  vscode: { file: [".vscode", "mcp.json"], key: ["servers", SERVER_KEY] },
448
452
  kiro: { file: [".kiro", "settings", "mcp.json"], key: ["mcpServers", SERVER_KEY] },
449
453
  zcode: {
@@ -830,9 +834,62 @@ function readResult4(resp) {
830
834
  const isError = typeof resp === "object" && resp !== null && resp.is_error === true;
831
835
  return { isError, bytes: Buffer.byteLength(text2), text: text2 };
832
836
  }
837
+ var CAMEL_EVENTS = {
838
+ sessionStart: "SessionStart",
839
+ userPromptSubmitted: "UserPromptSubmit",
840
+ preToolUse: "PreToolUse",
841
+ postToolUse: "PostToolUse",
842
+ preCompact: "PreCompact"
843
+ };
844
+ var EVENT_BY_KEY2 = [
845
+ ["toolResult", "postToolUse"],
846
+ ["toolName", "preToolUse"],
847
+ ["prompt", "userPromptSubmitted"],
848
+ ["source", "sessionStart"],
849
+ ["trigger", "preCompact"]
850
+ ];
851
+ var SESSION_SOURCES = { new: "startup", startup: "startup", resume: "resume" };
852
+ var RESULT_SUCCESS2 = "success";
853
+ function isRecord2(v) {
854
+ return typeof v === "object" && v !== null && !Array.isArray(v);
855
+ }
856
+ function readArgs2(v) {
857
+ if (isRecord2(v)) return v;
858
+ if (typeof v !== "string") return {};
859
+ try {
860
+ const parsed = JSON.parse(v);
861
+ return isRecord2(parsed) ? parsed : {};
862
+ } catch {
863
+ return {};
864
+ }
865
+ }
866
+ function readCamelResult(v) {
867
+ const r2 = isRecord2(v) ? v : {};
868
+ const text2 = typeof r2.textResultForLlm === "string" ? r2.textResultForLlm : "";
869
+ return { isError: typeof r2.resultType === "string" && r2.resultType !== RESULT_SUCCESS2, bytes: Buffer.byteLength(text2), text: text2 };
870
+ }
871
+ function decodeCamel(p3, name) {
872
+ const event = typeof name === "string" ? CAMEL_EVENTS[name] ?? VSCODE_EVENTS.find((e) => e === name) : void 0;
873
+ if (event === void 0) throw new Error("vscode: unknown hook event " + String(name));
874
+ const ev = { event, agent: "vscode", sessionId: String(p3.sessionId ?? ""), cwd: String(p3.cwd ?? "") };
875
+ if (event === "SessionStart" && typeof p3.source === "string" && SESSION_SOURCES[p3.source] !== void 0) ev.source = SESSION_SOURCES[p3.source];
876
+ if (event === "UserPromptSubmit" && typeof p3.prompt === "string") ev.prompt = p3.prompt;
877
+ if (event === "PreToolUse" || event === "PostToolUse") {
878
+ const toolName = String(p3.toolName ?? "");
879
+ ev.tool = { name: toolName, canonicalName: canonicalName4(toolName), input: readArgs2(p3.toolArgs) };
880
+ }
881
+ if (event === "PostToolUse") ev.result = readCamelResult(p3.toolResult);
882
+ return ev;
883
+ }
833
884
  function decode6(raw) {
834
885
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new Error("vscode: hook payload is not a JSON object");
835
886
  const p3 = raw;
887
+ if (p3.hookEventName !== void 0) return decodeCamel(p3, p3.hookEventName);
888
+ if (p3.hook_event_name === void 0) {
889
+ const byKey = EVENT_BY_KEY2.find(([key]) => Object.hasOwn(p3, key))?.[1];
890
+ if (byKey === void 0) throw new Error("vscode: missing required field hook_event_name");
891
+ return decodeCamel(p3, byKey);
892
+ }
836
893
  const event = VSCODE_EVENTS.find((e) => e === p3.hook_event_name);
837
894
  if (event === void 0) throw new Error("vscode: unknown hook event " + String(p3.hook_event_name));
838
895
  const ev = { event, agent: "vscode", sessionId: String(p3.session_id ?? ""), cwd: String(p3.cwd ?? "") };
@@ -840,7 +897,7 @@ function decode6(raw) {
840
897
  if (event === "UserPromptSubmit" && typeof p3.prompt === "string") ev.prompt = p3.prompt;
841
898
  if (event === "PreToolUse" || event === "PostToolUse") {
842
899
  const name = String(p3.tool_name ?? "");
843
- const input = typeof p3.tool_input === "object" && p3.tool_input !== null && !Array.isArray(p3.tool_input) ? p3.tool_input : {};
900
+ const input = isRecord2(p3.tool_input) ? p3.tool_input : {};
844
901
  ev.tool = { name, canonicalName: canonicalName4(name), input };
845
902
  }
846
903
  if (event === "PostToolUse") ev.result = readResult4(p3.tool_response);
@@ -859,12 +916,14 @@ var KIRO_EVENTS = {
859
916
  PromptSubmit: "UserPromptSubmit",
860
917
  userPromptSubmit: "UserPromptSubmit",
861
918
  PreToolUse: "PreToolUse",
862
- PostToolUse: "PostToolUse"
919
+ preToolUse: "PreToolUse",
920
+ PostToolUse: "PostToolUse",
921
+ postToolUse: "PostToolUse"
863
922
  };
864
923
  var PROMPT_ENV = "USER_PROMPT";
865
924
  var MCP_PREFIX3 = "mcp_";
866
- var SHELL_TOOL_NAME2 = "execute_bash";
867
- var NATIVE_TO_CANONICAL5 = { [SHELL_TOOL_NAME2]: "Bash" };
925
+ var SHELL_TOOL_NAMES = Object.freeze(["execute_bash", "execute_pwsh", "shell"]);
926
+ var NATIVE_TO_CANONICAL5 = Object.fromEntries(SHELL_TOOL_NAMES.map((n3) => [n3, "Bash"]));
868
927
  var MCP_SEP3 = "_";
869
928
  var KIRO_SOURCES = { startup: "startup", resume: "resume", clear: "clear", compact: "compact" };
870
929
  function canonicalName5(name) {
@@ -1005,8 +1064,8 @@ var OPENCODE_EVENTS = {
1005
1064
  compaction: "PreCompact",
1006
1065
  "step-finish": "Usage"
1007
1066
  };
1008
- var SHELL_TOOL_NAME3 = "bash";
1009
- var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [SHELL_TOOL_NAME3]: "Bash" };
1067
+ var SHELL_TOOL_NAME2 = "bash";
1068
+ var NATIVE_TO_CANONICAL7 = { webfetch: "WebFetch", [SHELL_TOOL_NAME2]: "Bash" };
1010
1069
  function toCanonicalTool(name) {
1011
1070
  if (name.startsWith(OWN_WIRE_PREFIX)) return name.slice(OWN_WIRE_PREFIX.length);
1012
1071
  return Object.prototype.hasOwnProperty.call(NATIVE_TO_CANONICAL7, name) ? NATIVE_TO_CANONICAL7[name] : name;
@@ -1126,8 +1185,8 @@ var ADAPTERS = Object.freeze([
1126
1185
  hookTimeoutMs: HOOK_TIMEOUT_MS,
1127
1186
  denyChannel: "deny-reason",
1128
1187
  hookChannel: { kind: "package", path: "hooks/qwen.json" },
1129
- skillChannel: { kind: "home-dir", path: ".qwen/skills" },
1130
- // ADR-0020
1188
+ skillChannel: { kind: "package", path: "skills" },
1189
+ // ADR-0020, D-HQ-SKILLS-3: qwen loads <extension>/skills, shared with gemini
1131
1190
  decode: decode4,
1132
1191
  encode: encode4
1133
1192
  },
@@ -1163,8 +1222,8 @@ var ADAPTERS = Object.freeze([
1163
1222
  hookTimeoutMs: HOOK_TIMEOUT_MS,
1164
1223
  denyChannel: "deny-reason",
1165
1224
  hookChannel: { kind: "home-file", path: ".copilot/hooks/context-mode-vscode.json" },
1166
- skillChannel: { kind: "home-dir", path: ".copilot/skills" },
1167
- // ADR-0020
1225
+ skillChannel: { kind: "home-dir", path: ".agents/skills" },
1226
+ // ADR-0020, D-HQ-COPILOT-NAMES-3: Copilot CLI owns ~/.copilot/skills
1168
1227
  decode: decode6,
1169
1228
  encode: encode6
1170
1229
  },
@@ -1173,9 +1232,9 @@ var ADAPTERS = Object.freeze([
1173
1232
  installMode: "mcp-entry",
1174
1233
  projectSource: "arg:--agent+cwd",
1175
1234
  toolNamePrefix: TOOL_NAME_PREFIX7,
1176
- nativeTools: { shell: [SHELL_TOOL_NAME2] },
1235
+ nativeTools: { shell: [...SHELL_TOOL_NAMES] },
1177
1236
  execReadOnlyHint: false,
1178
- // D-HF-KIRO-SHELL-1
1237
+ // D-HF-KIRO-SHELL-1, D-N7-KIRO-1
1179
1238
  eventMap: { SessionStart: "SessionStart", UserPromptSubmit: "UserPromptSubmit", PreToolUse: "PreToolUse", PostToolUse: "PostToolUse" },
1180
1239
  compactDelivery: "none",
1181
1240
  compactSummary: "none",
@@ -1188,7 +1247,7 @@ var ADAPTERS = Object.freeze([
1188
1247
  encode: encode7
1189
1248
  },
1190
1249
  {
1191
- // toolNamePrefix and nativeTools unverified until T-ZC (DECISIONS-r9 R3, R4: Claude names).
1250
+ // toolNamePrefix is the documented ZCode name mcp__<server>__<tool> (D-N7-ZCODE-NAMES-1); nativeTools are Claude names.
1192
1251
  id: "zcode",
1193
1252
  installMode: "hooks+mcp",
1194
1253
  projectSource: "spawn-cwd",
@@ -1230,7 +1289,7 @@ var ADAPTERS = Object.freeze([
1230
1289
  installMode: "in-process",
1231
1290
  projectSource: "spawn-cwd",
1232
1291
  toolNamePrefix: TOOL_NAME_PREFIX10,
1233
- nativeTools: { shell: [SHELL_TOOL_NAME3] },
1292
+ nativeTools: { shell: [SHELL_TOOL_NAME2] },
1234
1293
  execReadOnlyHint: false,
1235
1294
  // D-HF-OPENCODE-SHELL-1
1236
1295
  // Usage: step-finish cost row (DEVIATIONS D-M5-arch-2).
@@ -5151,6 +5210,7 @@ var STATE_DIR = ".context-mode";
5151
5210
  var LOCK_FILE = "setup.lock";
5152
5211
  var BACKUP_DIR = "backups";
5153
5212
  var PLUGIN_ID = `${SERVER_KEY}@${SERVER_KEY}`;
5213
+ var SKILLS_DIR_NAME = "skills";
5154
5214
  var INSTRUCTION_FILES = Object.freeze([
5155
5215
  "CLAUDE.md",
5156
5216
  "AGENTS.md",
@@ -5164,10 +5224,17 @@ function configEdits(c3) {
5164
5224
  return [[c3.key, c3.value], ...c3.also ?? []];
5165
5225
  }
5166
5226
  var COMMAND_SKILLS = Object.freeze(["ctx-doctor", "ctx-stats", "ctx-upgrade"]);
5167
- var SKILLS_DIR = "skills";
5168
5227
  var SKILL_FILE = "SKILL.md";
5169
5228
  var OPENCODE_PLUGIN = ["opencode", "plugin.js"];
5170
5229
  var CODEX_CONFIG_FILE = "config.toml";
5230
+ var CODEX_HOME_ENV2 = "CODEX_HOME";
5231
+ var CODEX_DIR = ".codex";
5232
+ function agentPath(ctx, id, rel) {
5233
+ const segs = typeof rel === "string" ? rel.split("/") : [...rel];
5234
+ const codexHome = ctx.env[CODEX_HOME_ENV2];
5235
+ if (id === "codex" && segs[0] === CODEX_DIR && codexHome !== void 0 && codexHome !== "") return path2.join(codexHome, ...segs.slice(1));
5236
+ return path2.join(ctx.home, ...segs);
5237
+ }
5171
5238
  function renderSkill(text2, prefix) {
5172
5239
  const prefixes = typeof prefix === "string" ? [prefix] : prefix;
5173
5240
  if (prefixes.length === 1 && prefixes[0] === "") return text2;
@@ -5183,6 +5250,23 @@ function skillDirPrefixes(dirPath) {
5183
5250
  }
5184
5251
  return out2;
5185
5252
  }
5253
+ var EXTENSION_LIST = ["extensions", "list"];
5254
+ function extensionPlugin(bin, id) {
5255
+ return {
5256
+ bin,
5257
+ args: EXTENSION_LIST,
5258
+ plugin: SERVER_KEY,
5259
+ hooksVia: getAdapter(id).hookChannel.path,
5260
+ skillsVia: SKILLS_DIR_NAME,
5261
+ format: "extension",
5262
+ enable: ["extensions", "enable", SERVER_KEY]
5263
+ };
5264
+ }
5265
+ var NATIVE_PLUGIN = {
5266
+ codex: { bin: "codex", args: ["plugin", "list"], plugin: PLUGIN_ID, hooksVia: ".codex-plugin", skillsVia: path2.join("codex", SKILLS_DIR_NAME), format: "table" },
5267
+ qwen: extensionPlugin("qwen", "qwen"),
5268
+ gemini: extensionPlugin("gemini", "gemini")
5269
+ };
5186
5270
  function serverCmd(ctx, id) {
5187
5271
  return [process.execPath, path2.join(ctx.pkgDir, SERVER_BUNDLE), AGENT_FLAG, id];
5188
5272
  }
@@ -5205,7 +5289,7 @@ function configFor(ctx, id) {
5205
5289
  const [node, server, flag, agent] = serverCmd(ctx, id);
5206
5290
  const own2 = OWN_MCP_ENTRY[id];
5207
5291
  if (own2) {
5208
- const file = path2.join(ctx.home, ...own2.file);
5292
+ const file = agentPath(ctx, id, own2.file);
5209
5293
  const format = file.endsWith(".toml") ? "toml" : id === "vscode" ? "jsonc" : "json";
5210
5294
  const args = id === "vscode" ? [server, flag, agent, WORKSPACE_FOLDER_FLAG, VSCODE_WORKSPACE_VAR] : [server, flag, agent];
5211
5295
  const also = own2.also?.map(([k, v]) => [k, v]);
@@ -5255,10 +5339,11 @@ var LIST = {
5255
5339
  // D-HF-OPENCODE-LIST-1: --pure skips external plugins, so a fresh HOME does not wait on the @opencode-ai/plugin install.
5256
5340
  opencode: { bin: "opencode", args: ["mcp", "list", "--pure"] }
5257
5341
  };
5258
- function hookFilesFor(home, id) {
5342
+ function hookFilesFor(ctx, id) {
5343
+ const home = ctx.home;
5259
5344
  switch (id) {
5260
5345
  case "codex":
5261
- return [{ file: path2.join(home, ".codex", "hooks.json"), mode: "rewrite" }];
5346
+ return [{ file: agentPath(ctx, id, [CODEX_DIR, "hooks.json"]), mode: "rewrite" }];
5262
5347
  case "copilot-cli":
5263
5348
  return [{ file: path2.join(home, ".copilot", "hooks", "context-mode.json"), mode: "rewrite" }];
5264
5349
  case "claude-code":
@@ -5276,7 +5361,7 @@ function hookInstallFor(ctx, row, command) {
5276
5361
  if (ch.kind === "home-file") {
5277
5362
  const shape = HOOK_SHAPES[row.id];
5278
5363
  if (!shape) throw new Error(`setup: ${row.id} has a home-file hook channel and no hook shape`);
5279
- const file = path2.join(ctx.home, ch.path);
5364
+ const file = agentPath(ctx, row.id, ch.path);
5280
5365
  if (row.id === "codex") return { kind: "file", file, shape: shape(row, command), command, trust: path2.join(path2.dirname(file), CODEX_CONFIG_FILE) };
5281
5366
  return { kind: "file", file, shape: shape(row, command), command };
5282
5367
  }
@@ -5290,13 +5375,19 @@ function hookInstallFor(ctx, row, command) {
5290
5375
  }
5291
5376
  return { kind: "package", via: ch.path };
5292
5377
  }
5378
+ function bareSkillDir() {
5379
+ const row = ADAPTERS.find((r2) => r2.skillChannel.kind === "package" && r2.toolNamePrefix === "");
5380
+ if (row === void 0) throw new Error("setup: no package skill channel holds the bare tool names");
5381
+ return row.skillChannel.path;
5382
+ }
5293
5383
  function skillInstallFor(ctx, row) {
5294
5384
  const ch = row.skillChannel;
5295
5385
  if (ch.kind === "package") return { kind: "package", via: ch.path };
5296
- const dir = path2.join(ctx.home, ch.path);
5386
+ const dir = agentPath(ctx, row.id, ch.path);
5387
+ const src = path2.join(ctx.pkgDir, bareSkillDir());
5297
5388
  return { kind: "dir", dir, prefixes: skillDirPrefixes(ch.path), files: COMMAND_SKILLS.map((name) => ({
5298
5389
  name,
5299
- src: path2.join(ctx.pkgDir, SKILLS_DIR, name, SKILL_FILE),
5390
+ src: path2.join(src, name, SKILL_FILE),
5300
5391
  file: path2.join(dir, name, SKILL_FILE)
5301
5392
  })) };
5302
5393
  }
@@ -5304,7 +5395,7 @@ function buildRegistry(ctx) {
5304
5395
  return ADAPTERS.map((row) => {
5305
5396
  const id = row.id;
5306
5397
  const config = configFor(ctx, id);
5307
- const hookFiles = hookFilesFor(ctx.home, id);
5398
+ const hookFiles = hookFilesFor(ctx, id);
5308
5399
  const hookCommand = [process.execPath, path2.join(ctx.pkgDir, HOOK_BUNDLE), AGENT_FLAG, id];
5309
5400
  const command = `"${hookCommand[0]}" "${hookCommand[1]}" ${AGENT_FLAG} ${id}`;
5310
5401
  const hookInstall = hookInstallFor(ctx, getAdapter(id), command);
@@ -5333,6 +5424,8 @@ function buildRegistry(ctx) {
5333
5424
  if (row.installMode !== "in-process") out2.hookCommand = hookCommand;
5334
5425
  const copy = copyFor(ctx, id);
5335
5426
  if (copy) out2.copy = copy;
5427
+ const native = NATIVE_PLUGIN[id];
5428
+ if (native) out2.nativePlugin = native;
5336
5429
  return out2;
5337
5430
  });
5338
5431
  }
@@ -5935,6 +6028,79 @@ function skillsCheck(row, pkgDir) {
5935
6028
  const bad = s.files.filter((f2) => readOr(f2.file) !== (existsSync6(f2.src) ? renderSkill(readFileSync3(f2.src, "utf8"), s.prefixes) : void 0));
5936
6029
  return { name: "skills", ok: bad.length === 0, detail: bad.length ? `${bad.map((f2) => f2.file).join(", ")} missing or without the ${s.prefixes.join(" / ") || "plain"} tool prefix` : void 0 };
5937
6030
  }
6031
+ var PLUGIN_ENABLED = "enabled";
6032
+ var WORD_TRIM = ",;";
6033
+ var EXT_ENABLED_USER = "Enabled (User):";
6034
+ var EXT_TRUE = "true";
6035
+ function tableState(n3, text2) {
6036
+ const line = text2.split("\n").find((l2) => l2.split(" ").includes(n3.plugin));
6037
+ if (line === void 0) return void 0;
6038
+ return line.split(" ").map((w) => trimChars(w, WORD_TRIM)).includes(PLUGIN_ENABLED) ? "enabled" : "disabled";
6039
+ }
6040
+ function extensionState(n3, text2) {
6041
+ let mine = false;
6042
+ for (const raw of text2.split("\n")) {
6043
+ const line = raw.trimEnd();
6044
+ if (line.length && !line.startsWith(" ")) {
6045
+ mine = line.split(" ")[1] === n3.plugin;
6046
+ continue;
6047
+ }
6048
+ const t2 = line.trim();
6049
+ if (mine && t2.startsWith(EXT_ENABLED_USER)) return t2.slice(EXT_ENABLED_USER.length).trim() === EXT_TRUE ? "enabled" : "disabled";
6050
+ }
6051
+ return void 0;
6052
+ }
6053
+ function nativeState(row, env) {
6054
+ const n3 = row.nativePlugin;
6055
+ if (!n3 || !hostBin(n3.bin, env).file) return void 0;
6056
+ const r2 = runBin(n3.bin, n3.args, env);
6057
+ if (r2.status !== 0) return void 0;
6058
+ return n3.format === "extension" ? extensionState(n3, `${r2.stdout}${r2.stderr}`) : tableState(n3, `${r2.stdout}`);
6059
+ }
6060
+ function nativeRow(row, n3) {
6061
+ return {
6062
+ ...row,
6063
+ config: void 0,
6064
+ cli: void 0,
6065
+ copy: void 0,
6066
+ hookFiles: [],
6067
+ listCommand: { bin: n3.bin, args: n3.args },
6068
+ hookInstall: { kind: "package", via: n3.hooksVia },
6069
+ skillInstall: { kind: "package", via: n3.skillsVia }
6070
+ };
6071
+ }
6072
+ function trimChars(w, chars) {
6073
+ let a2 = 0;
6074
+ let b3 = w.length;
6075
+ while (a2 < b3 && chars.includes(w.charAt(a2))) a2++;
6076
+ while (b3 > a2 && chars.includes(w.charAt(b3 - 1))) b3--;
6077
+ return w.slice(a2, b3);
6078
+ }
6079
+ async function nativeResult(row, ctx) {
6080
+ const n3 = row.nativePlugin;
6081
+ const state = nativeState(row, ctx.env);
6082
+ if (!n3 || state === void 0) return void 0;
6083
+ const bin = hostBin(n3.bin, ctx.env).file;
6084
+ if (state === "disabled") {
6085
+ if (!n3.enable) return void 0;
6086
+ return {
6087
+ id: row.id,
6088
+ status: "FAIL",
6089
+ v1: [],
6090
+ changes: [],
6091
+ checks: [],
6092
+ bin,
6093
+ reason: `context-mode is installed but disabled in ${n3.bin}, run ${n3.bin} ${n3.enable.join(" ")}`
6094
+ };
6095
+ }
6096
+ const res = { id: row.id, status: "PASS", v1: [], changes: [], checks: await verifyRow(nativeRow(row, n3), ctx), bin };
6097
+ const bad = res.checks.filter((c3) => !c3.ok);
6098
+ if (bad.length) {
6099
+ res.status = "FAIL";
6100
+ res.reason = bad.map((c3) => `${c3.name}: ${c3.detail}`).join("; ");
6101
+ }
6102
+ return res;
6103
+ }
5938
6104
  async function verifyRow(row, ctx) {
5939
6105
  const env = ctx.env;
5940
6106
  const checks = [parseCheck(row)];
@@ -6042,7 +6208,7 @@ async function runSetup(opts) {
6042
6208
  }
6043
6209
  current = id;
6044
6210
  opts.onAgent?.(id, "start");
6045
- const res = await setupRow(row, ctx, run, !!opts.dryRun);
6211
+ const res = await nativeResult(row, ctx) ?? await setupRow(row, ctx, run, !!opts.dryRun);
6046
6212
  current = void 0;
6047
6213
  agents.push(res);
6048
6214
  opts.onAgent?.(id, "done", res);
@@ -6117,6 +6283,12 @@ async function runDoctor(opts) {
6117
6283
  continue;
6118
6284
  }
6119
6285
  opts.onAgent?.(id, "start");
6286
+ const native = await nativeResult(row, ctx);
6287
+ if (native) {
6288
+ agents.push(native);
6289
+ opts.onAgent?.(id, "done", native);
6290
+ continue;
6291
+ }
6120
6292
  const res = await setupRow(row, ctx, run, true);
6121
6293
  if (res.status === "PASS") {
6122
6294
  if (res.v1.some((f2) => !UPGRADE_REPORT_ONLY_REASONS.includes(f2.reason))) {
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: ctx-doctor
3
+ description: Check that context-mode is installed and working, as a table.
4
+ disable-model-invocation: true
5
+ ---
6
+ Call the mcp__context_mode__ctx_doctor tool and show its table to the user unchanged. If a row failed, list the fixes it names, in order.
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: ctx-stats
3
+ description: Show how much context context-mode saved, as a table.
4
+ disable-model-invocation: true
5
+ ---
6
+ Call the mcp__context_mode__ctx_stats tool and show its table to the user unchanged. Add one sentence under the table that names the largest saving.
@@ -0,0 +1,6 @@
1
+ ---
2
+ name: ctx-upgrade
3
+ description: Update context-mode to the latest release.
4
+ disable-model-invocation: true
5
+ ---
6
+ Call the mcp__context_mode__ctx_upgrade tool and show its table to the user. Then call mcp__context_mode__ctx_doctor and show its table. If a restart is needed, say so in one sentence.
@@ -10,5 +10,5 @@
10
10
  }
11
11
  },
12
12
  "name": "context-mode",
13
- "version": "2.0.0-next.5"
13
+ "version": "2.0.0-next.7"
14
14
  }
@@ -10,5 +10,5 @@
10
10
  }
11
11
  },
12
12
  "name": "context-mode",
13
- "version": "2.0.0-next.5"
13
+ "version": "2.0.0-next.7"
14
14
  }