@x-code-cli/core 0.2.9 → 0.3.0

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 (255) hide show
  1. package/dist/agent/compression.d.ts +12 -2
  2. package/dist/agent/compression.d.ts.map +1 -1
  3. package/dist/agent/compression.js +51 -2
  4. package/dist/agent/compression.js.map +1 -1
  5. package/dist/agent/file-ingest.js +2 -2
  6. package/dist/agent/file-ingest.js.map +1 -1
  7. package/dist/agent/loop-state.d.ts +3 -2
  8. package/dist/agent/loop-state.d.ts.map +1 -1
  9. package/dist/agent/loop-state.js.map +1 -1
  10. package/dist/agent/loop.d.ts.map +1 -1
  11. package/dist/agent/loop.js +140 -9
  12. package/dist/agent/loop.js.map +1 -1
  13. package/dist/agent/memory-extractor.js +5 -5
  14. package/dist/agent/memory-extractor.js.map +1 -1
  15. package/dist/agent/plan-storage.js +1 -1
  16. package/dist/agent/plan-storage.js.map +1 -1
  17. package/dist/agent/sub-agents/index.d.ts +2 -1
  18. package/dist/agent/sub-agents/index.d.ts.map +1 -1
  19. package/dist/agent/sub-agents/index.js +1 -1
  20. package/dist/agent/sub-agents/index.js.map +1 -1
  21. package/dist/agent/sub-agents/loader.d.ts +13 -3
  22. package/dist/agent/sub-agents/loader.d.ts.map +1 -1
  23. package/dist/agent/sub-agents/loader.js +36 -9
  24. package/dist/agent/sub-agents/loader.js.map +1 -1
  25. package/dist/agent/sub-agents/registry.d.ts +18 -1
  26. package/dist/agent/sub-agents/registry.d.ts.map +1 -1
  27. package/dist/agent/sub-agents/registry.js +38 -5
  28. package/dist/agent/sub-agents/registry.js.map +1 -1
  29. package/dist/agent/sub-agents/runner.d.ts.map +1 -1
  30. package/dist/agent/sub-agents/runner.js +45 -1
  31. package/dist/agent/sub-agents/runner.js.map +1 -1
  32. package/dist/agent/sub-agents/types.d.ts +4 -1
  33. package/dist/agent/sub-agents/types.d.ts.map +1 -1
  34. package/dist/agent/system-prompt.d.ts +21 -0
  35. package/dist/agent/system-prompt.d.ts.map +1 -1
  36. package/dist/agent/system-prompt.js +68 -2
  37. package/dist/agent/system-prompt.js.map +1 -1
  38. package/dist/agent/tool-execution.d.ts.map +1 -1
  39. package/dist/agent/tool-execution.js +220 -1
  40. package/dist/agent/tool-execution.js.map +1 -1
  41. package/dist/commands/index.d.ts +6 -0
  42. package/dist/commands/index.d.ts.map +1 -0
  43. package/dist/commands/index.js +3 -0
  44. package/dist/commands/index.js.map +1 -0
  45. package/dist/commands/loader.d.ts +13 -0
  46. package/dist/commands/loader.d.ts.map +1 -0
  47. package/dist/commands/loader.js +93 -0
  48. package/dist/commands/loader.js.map +1 -0
  49. package/dist/commands/registry.d.ts +44 -0
  50. package/dist/commands/registry.d.ts.map +1 -0
  51. package/dist/commands/registry.js +102 -0
  52. package/dist/commands/registry.js.map +1 -0
  53. package/dist/commands/types.d.ts +23 -0
  54. package/dist/commands/types.d.ts.map +1 -0
  55. package/dist/commands/types.js +26 -0
  56. package/dist/commands/types.js.map +1 -0
  57. package/dist/config/index.d.ts +9 -0
  58. package/dist/config/index.d.ts.map +1 -1
  59. package/dist/config/index.js +12 -10
  60. package/dist/config/index.js.map +1 -1
  61. package/dist/hooks/bus.d.ts +54 -0
  62. package/dist/hooks/bus.d.ts.map +1 -0
  63. package/dist/hooks/bus.js +165 -0
  64. package/dist/hooks/bus.js.map +1 -0
  65. package/dist/hooks/config-schema.d.ts +854 -0
  66. package/dist/hooks/config-schema.d.ts.map +1 -0
  67. package/dist/hooks/config-schema.js +79 -0
  68. package/dist/hooks/config-schema.js.map +1 -0
  69. package/dist/hooks/executor.d.ts +16 -0
  70. package/dist/hooks/executor.d.ts.map +1 -0
  71. package/dist/hooks/executor.js +183 -0
  72. package/dist/hooks/executor.js.map +1 -0
  73. package/dist/hooks/index.d.ts +10 -0
  74. package/dist/hooks/index.d.ts.map +1 -0
  75. package/dist/hooks/index.js +6 -0
  76. package/dist/hooks/index.js.map +1 -0
  77. package/dist/hooks/registry.d.ts +23 -0
  78. package/dist/hooks/registry.d.ts.map +1 -0
  79. package/dist/hooks/registry.js +49 -0
  80. package/dist/hooks/registry.js.map +1 -0
  81. package/dist/hooks/types.d.ts +165 -0
  82. package/dist/hooks/types.d.ts.map +1 -0
  83. package/dist/hooks/types.js +25 -0
  84. package/dist/hooks/types.js.map +1 -0
  85. package/dist/hooks/variables.d.ts +22 -0
  86. package/dist/hooks/variables.d.ts.map +1 -0
  87. package/dist/hooks/variables.js +80 -0
  88. package/dist/hooks/variables.js.map +1 -0
  89. package/dist/index.d.ts +56 -1
  90. package/dist/index.d.ts.map +1 -1
  91. package/dist/index.js +37 -1
  92. package/dist/index.js.map +1 -1
  93. package/dist/knowledge/auto-memory.d.ts +1 -1
  94. package/dist/knowledge/auto-memory.d.ts.map +1 -1
  95. package/dist/knowledge/auto-memory.js +10 -10
  96. package/dist/knowledge/auto-memory.js.map +1 -1
  97. package/dist/knowledge/loader.js +12 -12
  98. package/dist/knowledge/loader.js.map +1 -1
  99. package/dist/mcp/arg-parser.d.ts +49 -0
  100. package/dist/mcp/arg-parser.d.ts.map +1 -0
  101. package/dist/mcp/arg-parser.js +357 -0
  102. package/dist/mcp/arg-parser.js.map +1 -0
  103. package/dist/mcp/client.d.ts +73 -0
  104. package/dist/mcp/client.d.ts.map +1 -0
  105. package/dist/mcp/client.js +376 -0
  106. package/dist/mcp/client.js.map +1 -0
  107. package/dist/mcp/config-schema.d.ts +64 -0
  108. package/dist/mcp/config-schema.d.ts.map +1 -0
  109. package/dist/mcp/config-schema.js +86 -0
  110. package/dist/mcp/config-schema.js.map +1 -0
  111. package/dist/mcp/config-writer.d.ts +41 -0
  112. package/dist/mcp/config-writer.d.ts.map +1 -0
  113. package/dist/mcp/config-writer.js +138 -0
  114. package/dist/mcp/config-writer.js.map +1 -0
  115. package/dist/mcp/env-safety.d.ts +12 -0
  116. package/dist/mcp/env-safety.d.ts.map +1 -0
  117. package/dist/mcp/env-safety.js +80 -0
  118. package/dist/mcp/env-safety.js.map +1 -0
  119. package/dist/mcp/expand-env.d.ts +14 -0
  120. package/dist/mcp/expand-env.d.ts.map +1 -0
  121. package/dist/mcp/expand-env.js +52 -0
  122. package/dist/mcp/expand-env.js.map +1 -0
  123. package/dist/mcp/loader.d.ts +81 -0
  124. package/dist/mcp/loader.d.ts.map +1 -0
  125. package/dist/mcp/loader.js +223 -0
  126. package/dist/mcp/loader.js.map +1 -0
  127. package/dist/mcp/name-mangling.d.ts +11 -0
  128. package/dist/mcp/name-mangling.d.ts.map +1 -0
  129. package/dist/mcp/name-mangling.js +82 -0
  130. package/dist/mcp/name-mangling.js.map +1 -0
  131. package/dist/mcp/oauth/callback-server.d.ts +25 -0
  132. package/dist/mcp/oauth/callback-server.d.ts.map +1 -0
  133. package/dist/mcp/oauth/callback-server.js +118 -0
  134. package/dist/mcp/oauth/callback-server.js.map +1 -0
  135. package/dist/mcp/oauth/provider.d.ts +80 -0
  136. package/dist/mcp/oauth/provider.d.ts.map +1 -0
  137. package/dist/mcp/oauth/provider.js +292 -0
  138. package/dist/mcp/oauth/provider.js.map +1 -0
  139. package/dist/mcp/oauth/token-storage.d.ts +42 -0
  140. package/dist/mcp/oauth/token-storage.d.ts.map +1 -0
  141. package/dist/mcp/oauth/token-storage.js +121 -0
  142. package/dist/mcp/oauth/token-storage.js.map +1 -0
  143. package/dist/mcp/permissions.d.ts +28 -0
  144. package/dist/mcp/permissions.d.ts.map +1 -0
  145. package/dist/mcp/permissions.js +105 -0
  146. package/dist/mcp/permissions.js.map +1 -0
  147. package/dist/mcp/registry.d.ts +150 -0
  148. package/dist/mcp/registry.d.ts.map +1 -0
  149. package/dist/mcp/registry.js +334 -0
  150. package/dist/mcp/registry.js.map +1 -0
  151. package/dist/mcp/resources.d.ts +7 -0
  152. package/dist/mcp/resources.d.ts.map +1 -0
  153. package/dist/mcp/resources.js +40 -0
  154. package/dist/mcp/resources.js.map +1 -0
  155. package/dist/mcp/tool-bridge.d.ts +16 -0
  156. package/dist/mcp/tool-bridge.d.ts.map +1 -0
  157. package/dist/mcp/tool-bridge.js +56 -0
  158. package/dist/mcp/tool-bridge.js.map +1 -0
  159. package/dist/mcp/trust.d.ts +31 -0
  160. package/dist/mcp/trust.d.ts.map +1 -0
  161. package/dist/mcp/trust.js +103 -0
  162. package/dist/mcp/trust.js.map +1 -0
  163. package/dist/mcp/types.d.ts +73 -0
  164. package/dist/mcp/types.d.ts.map +1 -0
  165. package/dist/mcp/types.js +13 -0
  166. package/dist/mcp/types.js.map +1 -0
  167. package/dist/permissions/session-store.d.ts +13 -2
  168. package/dist/permissions/session-store.d.ts.map +1 -1
  169. package/dist/permissions/session-store.js +264 -62
  170. package/dist/permissions/session-store.js.map +1 -1
  171. package/dist/plugins/consent.d.ts +87 -0
  172. package/dist/plugins/consent.d.ts.map +1 -0
  173. package/dist/plugins/consent.js +181 -0
  174. package/dist/plugins/consent.js.map +1 -0
  175. package/dist/plugins/enable-state.d.ts +34 -0
  176. package/dist/plugins/enable-state.d.ts.map +1 -0
  177. package/dist/plugins/enable-state.js +159 -0
  178. package/dist/plugins/enable-state.js.map +1 -0
  179. package/dist/plugins/installer.d.ts +64 -0
  180. package/dist/plugins/installer.d.ts.map +1 -0
  181. package/dist/plugins/installer.js +416 -0
  182. package/dist/plugins/installer.js.map +1 -0
  183. package/dist/plugins/integration.d.ts +91 -0
  184. package/dist/plugins/integration.d.ts.map +1 -0
  185. package/dist/plugins/integration.js +233 -0
  186. package/dist/plugins/integration.js.map +1 -0
  187. package/dist/plugins/loader.d.ts +69 -0
  188. package/dist/plugins/loader.d.ts.map +1 -0
  189. package/dist/plugins/loader.js +243 -0
  190. package/dist/plugins/loader.js.map +1 -0
  191. package/dist/plugins/manifest.d.ts +23 -0
  192. package/dist/plugins/manifest.d.ts.map +1 -0
  193. package/dist/plugins/manifest.js +143 -0
  194. package/dist/plugins/manifest.js.map +1 -0
  195. package/dist/plugins/marketplace.d.ts +100 -0
  196. package/dist/plugins/marketplace.d.ts.map +1 -0
  197. package/dist/plugins/marketplace.js +529 -0
  198. package/dist/plugins/marketplace.js.map +1 -0
  199. package/dist/plugins/paths.d.ts +44 -0
  200. package/dist/plugins/paths.d.ts.map +1 -0
  201. package/dist/plugins/paths.js +89 -0
  202. package/dist/plugins/paths.js.map +1 -0
  203. package/dist/plugins/refresh.d.ts +61 -0
  204. package/dist/plugins/refresh.d.ts.map +1 -0
  205. package/dist/plugins/refresh.js +98 -0
  206. package/dist/plugins/refresh.js.map +1 -0
  207. package/dist/plugins/registry.d.ts +40 -0
  208. package/dist/plugins/registry.d.ts.map +1 -0
  209. package/dist/plugins/registry.js +80 -0
  210. package/dist/plugins/registry.js.map +1 -0
  211. package/dist/plugins/types.d.ts +225 -0
  212. package/dist/plugins/types.d.ts.map +1 -0
  213. package/dist/plugins/types.js +16 -0
  214. package/dist/plugins/types.js.map +1 -0
  215. package/dist/plugins/user-config.d.ts +22 -0
  216. package/dist/plugins/user-config.d.ts.map +1 -0
  217. package/dist/plugins/user-config.js +96 -0
  218. package/dist/plugins/user-config.js.map +1 -0
  219. package/dist/providers/cache-control.d.ts +9 -0
  220. package/dist/providers/cache-control.d.ts.map +1 -1
  221. package/dist/providers/cache-control.js +31 -4
  222. package/dist/providers/cache-control.js.map +1 -1
  223. package/dist/skills/loader.d.ts +19 -0
  224. package/dist/skills/loader.d.ts.map +1 -0
  225. package/dist/skills/loader.js +197 -0
  226. package/dist/skills/loader.js.map +1 -0
  227. package/dist/skills/registry.d.ts +74 -0
  228. package/dist/skills/registry.d.ts.map +1 -0
  229. package/dist/skills/registry.js +136 -0
  230. package/dist/skills/registry.js.map +1 -0
  231. package/dist/skills/settings.d.ts +13 -0
  232. package/dist/skills/settings.d.ts.map +1 -0
  233. package/dist/skills/settings.js +100 -0
  234. package/dist/skills/settings.js.map +1 -0
  235. package/dist/tools/activate-skill.d.ts +5 -0
  236. package/dist/tools/activate-skill.d.ts.map +1 -0
  237. package/dist/tools/activate-skill.js +33 -0
  238. package/dist/tools/activate-skill.js.map +1 -0
  239. package/dist/tools/index.d.ts +1 -1
  240. package/dist/tools/todo-write.d.ts +1 -1
  241. package/dist/tools/web-fetch.d.ts.map +1 -1
  242. package/dist/tools/web-fetch.js +2 -1
  243. package/dist/tools/web-fetch.js.map +1 -1
  244. package/dist/types/index.d.ts +46 -1
  245. package/dist/types/index.d.ts.map +1 -1
  246. package/dist/types/index.js.map +1 -1
  247. package/dist/utils.d.ts +23 -2
  248. package/dist/utils.d.ts.map +1 -1
  249. package/dist/utils.js +76 -20
  250. package/dist/utils.js.map +1 -1
  251. package/dist/version.d.ts +2 -0
  252. package/dist/version.d.ts.map +1 -0
  253. package/dist/version.js +47 -0
  254. package/dist/version.js.map +1 -0
  255. package/package.json +2 -1
@@ -0,0 +1,89 @@
1
+ // @x-code-cli/core — Plugin filesystem layout
2
+ //
3
+ // Centralised path helpers for the plugin subsystem. Every other plugin
4
+ // module asks here rather than re-deriving paths so that the
5
+ // `XC_PLUGINS_DIR` test override has a single chokepoint.
6
+ //
7
+ // Layout (under ~/.x-code/plugins/ by default):
8
+ //
9
+ // known_marketplaces.json — subscribed marketplaces registry
10
+ // marketplaces/<name>/marketplace.json
11
+ // — cached marketplace index
12
+ // cache/<marketplace>/<plugin>/<version>/
13
+ // — actual installed plugin contents
14
+ // data/<plugin-id>/ — plugin's persistent data dir
15
+ // (survives upgrades; plugin-id is
16
+ // "name@marketplace" with path
17
+ // separators sanitised)
18
+ // installed_plugins.json — bookkeeping of installed plugins
19
+ import path from 'node:path';
20
+ import { XCODE_DIR, userXcodeDir } from '../utils.js';
21
+ const PLUGINS_DIR_NAME = 'plugins';
22
+ /** Root of the plugin subsystem. Two override knobs, checked in order:
23
+ * - `XC_PLUGINS_DIR` — plugin-specific override (parallels
24
+ * `XC_AGENTS_DIR` / `XC_SKILLS_DIR`; preferred when tests want to
25
+ * isolate JUST plugins without redirecting MCP / config / OAuth).
26
+ * - `X_CODE_HOME` — broad override of the whole `~/.x-code/` root
27
+ * (resolved via {@link userXcodeDir}). Reroutes plugins along with
28
+ * config, MCP state, etc. */
29
+ export function pluginsRoot() {
30
+ const override = process.env.XC_PLUGINS_DIR;
31
+ if (override)
32
+ return override;
33
+ return path.join(userXcodeDir(), PLUGINS_DIR_NAME);
34
+ }
35
+ /** ~/.x-code/plugins/known_marketplaces.json */
36
+ export function knownMarketplacesPath() {
37
+ return path.join(pluginsRoot(), 'known_marketplaces.json');
38
+ }
39
+ /** ~/.x-code/plugins/marketplaces/<name>/ */
40
+ export function marketplaceDir(name) {
41
+ return path.join(pluginsRoot(), 'marketplaces', name);
42
+ }
43
+ /** ~/.x-code/plugins/marketplaces/<name>/marketplace.json */
44
+ export function marketplaceIndexPath(name) {
45
+ return path.join(marketplaceDir(name), 'marketplace.json');
46
+ }
47
+ /** ~/.x-code/plugins/cache/<marketplace>/<plugin>/ — all versions live
48
+ * under this directory; the active version is whichever the installer
49
+ * recorded most recently in installed_plugins.json. */
50
+ export function pluginCacheParent(marketplace, plugin) {
51
+ return path.join(pluginsRoot(), 'cache', marketplace, plugin);
52
+ }
53
+ /** ~/.x-code/plugins/cache/<marketplace>/<plugin>/<version>/ */
54
+ export function pluginCacheDir(marketplace, plugin, version) {
55
+ return path.join(pluginCacheParent(marketplace, plugin), version);
56
+ }
57
+ /** ~/.x-code/plugins/data/<sanitised-plugin-id>/ — persistent per-plugin
58
+ * data dir that survives upgrades. Plugin IDs ("name@marketplace") are
59
+ * sanitised so the `@` and any accidental path separators don't break
60
+ * on Windows. */
61
+ export function pluginDataDir(pluginId) {
62
+ const safe = pluginId.replace(/[/\\:]/g, '_');
63
+ return path.join(pluginsRoot(), 'data', safe);
64
+ }
65
+ /** ~/.x-code/plugins/installed_plugins.json */
66
+ export function installedPluginsPath() {
67
+ return path.join(pluginsRoot(), 'installed_plugins.json');
68
+ }
69
+ /** <cwd>/.x-code/plugins/ — rare; used when a project ships its own
70
+ * plugins committed to the repo (vs. installing from a marketplace).
71
+ * The loader scans this in addition to the user-scope cache. */
72
+ export function projectPluginsDir(cwd) {
73
+ return path.join(cwd, XCODE_DIR, 'plugins');
74
+ }
75
+ // ── Manifest discovery within a plugin root ─────────────────────────────
76
+ /** Relative manifest paths the loader probes, in priority order. The first
77
+ * one found wins. We deliberately accept Claude Code's path so plugins
78
+ * authored for Claude Code install in x-code-cli without modification —
79
+ * see [[plugin-marketplace-design]] §3 (cross-product compatibility). */
80
+ export const MANIFEST_CANDIDATES = [
81
+ { format: 'native', rel: '.x-code-plugin/plugin.json' },
82
+ { format: 'claude', rel: '.claude-plugin/plugin.json' },
83
+ { format: 'bare', rel: 'plugin.json' },
84
+ ];
85
+ /** Gemini's manifest filename. Probed only to produce a helpful error
86
+ * message when a user tries to install a Gemini-only extension —
87
+ * installer rejects with a pointer to the design doc. */
88
+ export const GEMINI_MANIFEST_REL = 'gemini-extension.json';
89
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/plugins/paths.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,wEAAwE;AACxE,6DAA6D;AAC7D,0DAA0D;AAC1D,EAAE;AACF,gDAAgD;AAChD,EAAE;AACF,wEAAwE;AACxE,yCAAyC;AACzC,gEAAgE;AAChE,4CAA4C;AAC5C,wEAAwE;AACxE,oEAAoE;AACpE,wEAAwE;AACxE,oEAAoE;AACpE,6DAA6D;AAC7D,wEAAwE;AACxE,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAErD,MAAM,gBAAgB,GAAG,SAAS,CAAA;AAElC;;;;;;gCAMgC;AAChC,MAAM,UAAU,WAAW;IACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAA;IAC3C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAA;IAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,gBAAgB,CAAC,CAAA;AACpD,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,qBAAqB;IACnC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,yBAAyB,CAAC,CAAA;AAC5D,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,CAAA;AACvD,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,EAAE,kBAAkB,CAAC,CAAA;AAC5D,CAAC;AAED;;wDAEwD;AACxD,MAAM,UAAU,iBAAiB,CAAC,WAAmB,EAAE,MAAc;IACnE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;AAC/D,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,cAAc,CAAC,WAAmB,EAAE,MAAc,EAAE,OAAe;IACjF,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,CAAA;AACnE,CAAC;AAED;;;kBAGkB;AAClB,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAA;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;AAC/C,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,oBAAoB;IAClC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,wBAAwB,CAAC,CAAA;AAC3D,CAAC;AAED;;iEAEiE;AACjE,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;AAC7C,CAAC;AAED,2EAA2E;AAE3E;;;0EAG0E;AAC1E,MAAM,CAAC,MAAM,mBAAmB,GAAyE;IACvG,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,4BAA4B,EAAE;IACvD,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,4BAA4B,EAAE;IACvD,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE;CACvC,CAAA;AAED;;0DAE0D;AAC1D,MAAM,CAAC,MAAM,mBAAmB,GAAG,uBAAuB,CAAA"}
@@ -0,0 +1,61 @@
1
+ import type { SubAgentRegistry, SubAgentReloadSummary } from '../agent/sub-agents/registry.js';
2
+ import type { CommandRegistry, CommandReloadSummary } from '../commands/registry.js';
3
+ import type { HookBus } from '../hooks/bus.js';
4
+ import { type LoadOptions } from '../mcp/loader.js';
5
+ import type { McpRegistry, RestartSummary } from '../mcp/registry.js';
6
+ import type { SkillRegistry, SkillReloadSummary } from '../skills/registry.js';
7
+ import type { PluginRegistry, PluginReloadSummary } from './registry.js';
8
+ export interface PluginRefreshSummary {
9
+ /** Plugin-level diff — what plugins appeared / disappeared / changed.
10
+ * This is the headline the /plugin refresh message renders. */
11
+ plugins: PluginReloadSummary;
12
+ /** Per-sub-registry diffs — useful for /plugin doctor-style detail.
13
+ * Each is optional because a caller may not have wired every registry
14
+ * (e.g. tests skip them). */
15
+ skills?: SkillReloadSummary;
16
+ subAgents?: SubAgentReloadSummary;
17
+ commands?: CommandReloadSummary;
18
+ /** Number of hook entries registered after refresh — surfaced for
19
+ * user feedback. We don't compute a per-event diff because hooks
20
+ * don't have a stable identity (no name field); the count alone is
21
+ * enough to confirm "hooks reloaded". */
22
+ hookCount: number;
23
+ /** MCP restart summary when an mcpRegistry was wired. `undefined` when
24
+ * the caller didn't pass one (tests / `--no-plugins` reload paths). */
25
+ mcp?: RestartSummary;
26
+ /** Trust-gate decisions for project MCP servers, if any were skipped
27
+ * during the merged-config load. Surfaced so the UI can warn the user. */
28
+ mcpProjectSkipped?: boolean;
29
+ /** Per-server MCP config parse errors during the merged-config load.
30
+ * These don't abort the refresh; they're shown alongside the summary
31
+ * so the user knows which server entry was ignored. */
32
+ mcpConfigErrors?: Array<{
33
+ name: string;
34
+ message: string;
35
+ }>;
36
+ }
37
+ export interface PluginRefreshTargets {
38
+ pluginRegistry: PluginRegistry;
39
+ /** Sub-registries that should fold in the new plugin contributions.
40
+ * Pass whichever ones the caller has wired. */
41
+ skillRegistry?: SkillRegistry;
42
+ subAgentRegistry?: SubAgentRegistry;
43
+ commandRegistry?: CommandRegistry;
44
+ hookBus?: HookBus;
45
+ /** MCP registry to restart with the new merged config (user + plugin +
46
+ * project). When set, `askUser` must also be supplied for the
47
+ * project-trust gate; when omitted, MCP is left untouched (matches
48
+ * the pre-existing behaviour). */
49
+ mcpRegistry?: McpRegistry;
50
+ /** Required when `mcpRegistry` is set — used by the trust dialog inside
51
+ * loadMergedConfigsFromDisk for new project-level MCP servers. */
52
+ askUser?: LoadOptions['askUser'];
53
+ /** cwd defaults to process.cwd(); overridable for tests. */
54
+ cwd?: string;
55
+ }
56
+ /** Re-scan installed plugins and fold the new state into every wired
57
+ * registry. Caller is responsible for invalidating systemPromptCache
58
+ * afterwards (we'd need the cache reference here, which sits one layer
59
+ * up in the agent options). */
60
+ export declare function refreshPluginContributions(targets: PluginRefreshTargets): Promise<PluginRefreshSummary>;
61
+ //# sourceMappingURL=refresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../src/plugins/refresh.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAE9F,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAA;AACpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAE9C,OAAO,EAAE,KAAK,WAAW,EAA6B,MAAM,kBAAkB,CAAA;AAC9E,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAErE,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAG9E,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAExE,MAAM,WAAW,oBAAoB;IACnC;oEACgE;IAChE,OAAO,EAAE,mBAAmB,CAAA;IAC5B;;kCAE8B;IAC9B,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,SAAS,CAAC,EAAE,qBAAqB,CAAA;IACjC,QAAQ,CAAC,EAAE,oBAAoB,CAAA;IAC/B;;;8CAG0C;IAC1C,SAAS,EAAE,MAAM,CAAA;IACjB;4EACwE;IACxE,GAAG,CAAC,EAAE,cAAc,CAAA;IACpB;+EAC2E;IAC3E,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B;;4DAEwD;IACxD,eAAe,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC3D;AAED,MAAM,WAAW,oBAAoB;IACnC,cAAc,EAAE,cAAc,CAAA;IAC9B;oDACgD;IAChD,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IACnC,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;uCAGmC;IACnC,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB;uEACmE;IACnE,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAA;IAChC,4DAA4D;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAA;CACb;AAED;;;gCAGgC;AAChC,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAqD7G"}
@@ -0,0 +1,98 @@
1
+ // @x-code-cli/core — Plugin hot-reload orchestrator
2
+ //
3
+ // `/plugin refresh` enters here. The job is to re-scan installed plugins
4
+ // from disk and propagate the new state to every downstream registry
5
+ // without restarting xc.
6
+ //
7
+ // Why this is its own module and not a method on PluginRegistry:
8
+ // reloading the plugin registry itself is one line — the work is folding
9
+ // the new contributions into the FIVE sub-registries the rest of the
10
+ // agent loop captured at startup (skill / sub-agent / command / hook /
11
+ // mcp). Each captured reference must stay stable, so each registry
12
+ // exposes a reload-in-place method instead of returning a new instance.
13
+ //
14
+ // MCP servers are restarted here when the caller wires an mcpRegistry +
15
+ // askUser callback (needed by the trust-gate check for project servers).
16
+ // Plugin-contributed MCP servers are merged with user + project servers
17
+ // and the whole set goes through `McpRegistry.restartAll(...)` — the same
18
+ // path `/mcp refresh` uses. Callers that don't wire an mcpRegistry get
19
+ // the pre-existing behaviour (only skill/agent/command/hook reload).
20
+ import { reloadSubAgentRegistry } from '../agent/sub-agents/registry.js';
21
+ import { reloadCommandRegistry } from '../commands/registry.js';
22
+ import { loadMergedConfigsFromDisk } from '../mcp/loader.js';
23
+ import { reloadSkillRegistry } from '../skills/registry.js';
24
+ import { buildPluginIntegration } from './integration.js';
25
+ import { loadAllPlugins } from './loader.js';
26
+ /** Re-scan installed plugins and fold the new state into every wired
27
+ * registry. Caller is responsible for invalidating systemPromptCache
28
+ * afterwards (we'd need the cache reference here, which sits one layer
29
+ * up in the agent options). */
30
+ export async function refreshPluginContributions(targets) {
31
+ const cwd = targets.cwd ?? process.cwd();
32
+ // 1. Re-scan plugins from disk. loadAllPlugins builds its own internal
33
+ // registry — we pull the plugin list + load errors out of it and
34
+ // feed them into the caller's long-lived registry via reload().
35
+ const load = await loadAllPlugins({ cwd });
36
+ // 2. Swap into the caller's plugin registry, capture the headline diff.
37
+ const pluginsSummary = targets.pluginRegistry.reload(load.registry.listAll(), [...load.registry.loadErrors()]);
38
+ // 3. Recompute downstream integration (skills dirs, agents dirs,
39
+ // commands dirs, mcp servers, hook registry) from the new
40
+ // plugin set.
41
+ const integration = await buildPluginIntegration(load);
42
+ // 4. Fold into each sub-registry the caller wired up.
43
+ const out = { plugins: pluginsSummary, hookCount: 0 };
44
+ if (targets.skillRegistry) {
45
+ out.skills = await reloadSkillRegistry(targets.skillRegistry, { extraDirs: integration.skillsDirs });
46
+ }
47
+ if (targets.subAgentRegistry) {
48
+ out.subAgents = await reloadSubAgentRegistry(targets.subAgentRegistry, { extraDirs: integration.agentsDirs });
49
+ }
50
+ if (targets.commandRegistry) {
51
+ out.commands = await reloadCommandRegistry(targets.commandRegistry, { extraDirs: integration.commandsDirs });
52
+ }
53
+ if (targets.hookBus) {
54
+ targets.hookBus.replaceRegistry(integration.hookRegistry);
55
+ // Count by summing entry counts across the new registry's events.
56
+ // Used for the user message — exact diff isn't worth the complexity.
57
+ out.hookCount = countHooks(integration.hookRegistry);
58
+ }
59
+ // 5. MCP restart — only when both mcpRegistry AND askUser are wired.
60
+ // Re-reads user + project config files from disk and merges in the
61
+ // fresh plugin-contributed extraServers, then tears down + reconnects
62
+ // the whole MCP set. Same code path as /mcp refresh. Doing this
63
+ // inside /plugin refresh means installing a plugin with an MCP
64
+ // server takes effect in one command instead of two.
65
+ if (targets.mcpRegistry && targets.askUser) {
66
+ const merged = await loadMergedConfigsFromDisk({
67
+ cwd,
68
+ askUser: targets.askUser,
69
+ extraServers: integration.mcpServers,
70
+ });
71
+ out.mcpProjectSkipped = merged.projectSkipped;
72
+ out.mcpConfigErrors = merged.configErrors;
73
+ out.mcp = await targets.mcpRegistry.restartAll(merged.configs);
74
+ }
75
+ return out;
76
+ }
77
+ function countHooks(registry) {
78
+ // HookRegistry exposes get(eventName) → array; iterate the known event
79
+ // names. Names are duplicated from types.ts but importing them here
80
+ // would create a circular dependency, so we hardcode the small list.
81
+ const eventNames = [
82
+ 'SessionStart',
83
+ 'UserPromptSubmit',
84
+ 'PreToolUse',
85
+ 'PostToolUse',
86
+ 'PreCompact',
87
+ 'PostCompact',
88
+ 'SubagentStart',
89
+ 'SubagentStop',
90
+ 'TurnComplete',
91
+ 'SessionEnd',
92
+ ];
93
+ let n = 0;
94
+ for (const e of eventNames)
95
+ n += registry.get(e).length;
96
+ return n;
97
+ }
98
+ //# sourceMappingURL=refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../src/plugins/refresh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { LoadedPlugin, PluginLoadError } from './types.js';
2
+ /** Summary of what changed between two registry snapshots — used by
3
+ * `/plugin refresh` to render an "added / removed / changed" message
4
+ * the same way `/mcp refresh` and `/skill refresh` do. */
5
+ export interface PluginReloadSummary {
6
+ added: string[];
7
+ removed: string[];
8
+ changed: string[];
9
+ unchanged: string[];
10
+ }
11
+ export declare class PluginRegistry {
12
+ private byId;
13
+ private errors;
14
+ constructor(plugins: LoadedPlugin[], errors?: PluginLoadError[]);
15
+ /** Enabled plugin by id. Disabled plugins are hidden from this lookup —
16
+ * use [[getEntry]] when you need to inspect the disabled flag (e.g.
17
+ * `/plugin list`). */
18
+ get(id: string): LoadedPlugin | undefined;
19
+ /** Plugin by id including disabled ones. */
20
+ getEntry(id: string): LoadedPlugin | undefined;
21
+ /** Enabled plugins only — what the agent loop sees. */
22
+ list(): LoadedPlugin[];
23
+ /** Every loaded plugin, with the disabled ones. */
24
+ listAll(): LoadedPlugin[];
25
+ /** Plugin ids only (enabled). */
26
+ ids(): string[];
27
+ /** Non-fatal errors collected during load. Surfaced by `/plugin doctor`. */
28
+ loadErrors(): readonly PluginLoadError[];
29
+ /** Replace the in-memory plugin list with a fresh load. Used by
30
+ * `/plugin refresh` — keeps the same PluginRegistry object identity
31
+ * so every cached reference stays valid. Returns a diff summary so
32
+ * the caller can render an "added / removed / changed / unchanged"
33
+ * message. */
34
+ reload(plugins: LoadedPlugin[], errors?: PluginLoadError[]): PluginReloadSummary;
35
+ }
36
+ /** Empty registry — used when plugin loading is disabled (e.g.
37
+ * `--no-plugins` startup flag) or no plugins are installed. Cheaper than
38
+ * null-checking the registry everywhere downstream. */
39
+ export declare function emptyPluginRegistry(): PluginRegistry;
40
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE/D;;2DAE2D;AAC3D,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,EAAE,MAAM,EAAE,CAAA;CACpB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,MAAM,CAAmB;gBAErB,OAAO,EAAE,YAAY,EAAE,EAAE,MAAM,GAAE,eAAe,EAAO;IAMnE;;2BAEuB;IACvB,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAMzC,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAI9C,uDAAuD;IACvD,IAAI,IAAI,YAAY,EAAE;IAItB,mDAAmD;IACnD,OAAO,IAAI,YAAY,EAAE;IAIzB,iCAAiC;IACjC,GAAG,IAAI,MAAM,EAAE;IAIf,4EAA4E;IAC5E,UAAU,IAAI,SAAS,eAAe,EAAE;IAIxC;;;;mBAIe;IACf,MAAM,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,MAAM,GAAE,eAAe,EAAO,GAAG,mBAAmB;CA6BrF;AAED;;wDAEwD;AACxD,wBAAgB,mBAAmB,IAAI,cAAc,CAEpD"}
@@ -0,0 +1,80 @@
1
+ export class PluginRegistry {
2
+ byId;
3
+ errors;
4
+ constructor(plugins, errors = []) {
5
+ this.byId = new Map();
6
+ for (const p of plugins)
7
+ this.byId.set(p.id, p);
8
+ this.errors = [...errors];
9
+ }
10
+ /** Enabled plugin by id. Disabled plugins are hidden from this lookup —
11
+ * use [[getEntry]] when you need to inspect the disabled flag (e.g.
12
+ * `/plugin list`). */
13
+ get(id) {
14
+ const p = this.byId.get(id);
15
+ if (!p || !p.enabled)
16
+ return undefined;
17
+ return p;
18
+ }
19
+ /** Plugin by id including disabled ones. */
20
+ getEntry(id) {
21
+ return this.byId.get(id);
22
+ }
23
+ /** Enabled plugins only — what the agent loop sees. */
24
+ list() {
25
+ return [...this.byId.values()].filter((p) => p.enabled);
26
+ }
27
+ /** Every loaded plugin, with the disabled ones. */
28
+ listAll() {
29
+ return [...this.byId.values()];
30
+ }
31
+ /** Plugin ids only (enabled). */
32
+ ids() {
33
+ return this.list().map((p) => p.id);
34
+ }
35
+ /** Non-fatal errors collected during load. Surfaced by `/plugin doctor`. */
36
+ loadErrors() {
37
+ return this.errors;
38
+ }
39
+ /** Replace the in-memory plugin list with a fresh load. Used by
40
+ * `/plugin refresh` — keeps the same PluginRegistry object identity
41
+ * so every cached reference stays valid. Returns a diff summary so
42
+ * the caller can render an "added / removed / changed / unchanged"
43
+ * message. */
44
+ reload(plugins, errors = []) {
45
+ const previous = this.byId;
46
+ const next = new Map();
47
+ for (const p of plugins)
48
+ next.set(p.id, p);
49
+ const summary = { added: [], removed: [], changed: [], unchanged: [] };
50
+ for (const [id, plugin] of next) {
51
+ const prev = previous.get(id);
52
+ if (!prev) {
53
+ summary.added.push(id);
54
+ }
55
+ else if (prev.manifest.version !== plugin.manifest.version ||
56
+ prev.rootDir !== plugin.rootDir ||
57
+ prev.enabled !== plugin.enabled ||
58
+ prev.scope !== plugin.scope) {
59
+ summary.changed.push(id);
60
+ }
61
+ else {
62
+ summary.unchanged.push(id);
63
+ }
64
+ }
65
+ for (const id of previous.keys()) {
66
+ if (!next.has(id))
67
+ summary.removed.push(id);
68
+ }
69
+ this.byId = next;
70
+ this.errors = [...errors];
71
+ return summary;
72
+ }
73
+ }
74
+ /** Empty registry — used when plugin loading is disabled (e.g.
75
+ * `--no-plugins` startup flag) or no plugins are installed. Cheaper than
76
+ * null-checking the registry everywhere downstream. */
77
+ export function emptyPluginRegistry() {
78
+ return new PluginRegistry([], []);
79
+ }
80
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/plugins/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,225 @@
1
+ /** Where a plugin was installed from — the internal canonical form used
2
+ * by the installer and recorded in `installed_plugins.json`. Marketplace
3
+ * entries arrive in a different on-disk wire format (string shortcut,
4
+ * `git-subdir`, `url`) and are normalised to this shape by
5
+ * [[normalizeMarketplaceSource]]. `subdir` is supported on both git and
6
+ * github so monorepo-published plugins (common in real Claude Code
7
+ * marketplaces like `anthropics/claude-plugins-official`) install
8
+ * correctly.
9
+ *
10
+ * `expectedSha` is an optional integrity pin propagated from the
11
+ * marketplace.json's `sha` field on git-backed sources. When set, the
12
+ * installer clones, runs `git rev-parse HEAD`, and aborts with
13
+ * `InstallError` on mismatch. Defends against the upstream ref being
14
+ * force-pushed or the repo being compromised between when the
15
+ * marketplace author reviewed it and when a user installs. Absent
16
+ * field skips the check (so marketplaces that haven't pinned shas
17
+ * still install). */
18
+ export type PluginSource = {
19
+ kind: 'git';
20
+ url: string;
21
+ ref?: string;
22
+ subdir?: string;
23
+ expectedSha?: string;
24
+ } | {
25
+ kind: 'github';
26
+ owner: string;
27
+ repo: string;
28
+ ref?: string;
29
+ subdir?: string;
30
+ expectedSha?: string;
31
+ } | {
32
+ kind: 'local';
33
+ path: string;
34
+ };
35
+ /** Two-scope plugin enablement, mirroring the convention used by mcp and
36
+ * skill (see packages/core/src/skills/settings.ts):
37
+ *
38
+ * 'user' → ~/.x-code/settings.json
39
+ * 'project' → <cwd>/.x-code/settings.local.json (gitignored)
40
+ *
41
+ * `'project'` reading a `.local.json` file is a slight naming quirk
42
+ * inherited from skills — it's a per-user override scoped to one repo,
43
+ * not a team-shared file. A separate team-shared scope (committed) can
44
+ * be layered on later without changing this union. */
45
+ export type PluginScope = 'user' | 'project';
46
+ export interface PluginAuthor {
47
+ name?: string;
48
+ email?: string;
49
+ url?: string;
50
+ }
51
+ /** A single user-prompted config item (API key, base URL, etc.). When
52
+ * `sensitive: true`, the value lives in the system keyring rather than
53
+ * settings.json. Schema mirrors Claude Code's so the same plugin works
54
+ * in either CLI without authors writing a separate config block. */
55
+ export interface UserConfigItem {
56
+ key: string;
57
+ type: 'string' | 'number' | 'boolean';
58
+ sensitive?: boolean;
59
+ prompt?: string;
60
+ required?: boolean;
61
+ default?: string | number | boolean;
62
+ description?: string;
63
+ }
64
+ /** Inline hook configuration (the alternative to a hooks file path).
65
+ * Loose shape here — full validation lives in
66
+ * packages/core/src/hooks/config-schema.ts so that hooks-only changes
67
+ * don't reach into the plugin layer. */
68
+ export type InlineHookConfig = Record<string, unknown>;
69
+ /** Inline mcpServers record (the alternative to a path string). Matches
70
+ * the shape of `mcpServers` in ~/.x-code/config.json — validated by
71
+ * the existing mcp config-schema, not duplicated here. */
72
+ export type InlineMcpServers = Record<string, unknown>;
73
+ /** The plugin manifest as parsed from disk. All paths are STORED RAW —
74
+ * resolution against the plugin root happens in [[loader]]. Unknown
75
+ * fields in the source JSON are silently stripped (zod default) so that
76
+ * newer Claude Code manifests with fields we don't understand still
77
+ * load cleanly. */
78
+ export interface PluginManifest {
79
+ /** Schema version. Defaults to "1" when missing. Bumped by us only on
80
+ * breaking changes to the manifest contract; older plugins still load
81
+ * as long as their fields validate. */
82
+ schemaVersion: string;
83
+ name: string;
84
+ version: string;
85
+ description?: string;
86
+ author?: PluginAuthor;
87
+ keywords?: string[];
88
+ homepage?: string;
89
+ license?: string;
90
+ /** Path to a directory of skills, each in `<name>/SKILL.md` form (same
91
+ * layout as `~/.x-code/skills/`). Or a single file path. */
92
+ skills?: string;
93
+ /** Path to a directory of sub-agent `.md` files (same layout as
94
+ * `~/.x-code/agents/`). */
95
+ agents?: string;
96
+ /** Path to a directory of slash command `.md` files. */
97
+ commands?: string;
98
+ /** Either a path to a JSON file with `{ mcpServers: { ... } }` OR an
99
+ * inline `mcpServers` record. Inline form matches the shape used in
100
+ * ~/.x-code/config.json. */
101
+ mcpServers?: string | InlineMcpServers;
102
+ /** Either a path to a hooks.json OR an inline hook config. */
103
+ hooks?: string | InlineHookConfig;
104
+ userConfig?: UserConfigItem[];
105
+ /** Dependencies as `name@marketplace` IDs. Bare `name` resolves against
106
+ * the same marketplace as the dependent plugin. */
107
+ dependencies?: string[];
108
+ engines?: {
109
+ 'x-code'?: string;
110
+ };
111
+ }
112
+ /** Which manifest file we loaded. `'gemini'` is never reached — Gemini
113
+ * extensions are rejected at install time by design (see plugin-marketplace-design.md
114
+ * §3.4) and the value is only used in error reporting to say "this looks
115
+ * like a Gemini extension, we don't support those". */
116
+ export type ManifestFormat = 'native' | 'claude' | 'bare' | 'gemini';
117
+ export interface LoadedPlugin {
118
+ /** Composite id `name@marketplace`. `marketplace` is `"local"` for
119
+ * plugins installed from a local path (i.e. authored in-tree). */
120
+ id: string;
121
+ manifest: PluginManifest;
122
+ /** Absolute path to the plugin's root directory. */
123
+ rootDir: string;
124
+ /** Absolute path to the manifest file we loaded. */
125
+ manifestPath: string;
126
+ manifestFormat: ManifestFormat;
127
+ /** Where this plugin originally came from. `undefined` only for the
128
+ * rare case of a plugin manually dropped into cache without metadata. */
129
+ source: PluginSource | undefined;
130
+ /** Marketplace name this plugin belongs to. `"local"` for plugins
131
+ * installed from a local path / authored in-tree. */
132
+ marketplace: string;
133
+ scope: PluginScope;
134
+ /** Effective enabled state after merging all three scopes. */
135
+ enabled: boolean;
136
+ }
137
+ /** A non-fatal load error — collected by the loader and surfaced via
138
+ * `/plugin doctor`. One broken plugin must never crash the CLI. */
139
+ export interface PluginLoadError {
140
+ /** `name@marketplace` if we got far enough to know it. */
141
+ id?: string;
142
+ /** Filesystem path that triggered the error, even if no manifest parsed. */
143
+ path: string;
144
+ message: string;
145
+ }
146
+ /** One plugin listing within a marketplace. `source` tells the installer
147
+ * where to fetch the plugin from. */
148
+ export interface MarketplaceEntry {
149
+ name: string;
150
+ description?: string;
151
+ category?: string;
152
+ /** Marketplace-curator's claim of vetted-ness. We surface this in the UI
153
+ * but never grant additional trust based on it — install consent still
154
+ * runs. */
155
+ verified?: boolean;
156
+ source: PluginSource;
157
+ /** Pinned version, if any. Otherwise installer reads version from the
158
+ * fetched manifest. */
159
+ version?: string;
160
+ homepage?: string;
161
+ keywords?: string[];
162
+ }
163
+ export interface Marketplace {
164
+ schemaVersion: string;
165
+ /** The user-facing canonical identity of this marketplace — the
166
+ * subscription alias the user typed (e.g. `anthropic-marketplace`).
167
+ * Storage paths, install ids (`<plugin>@<name>`), and lookups all key
168
+ * off this. */
169
+ name: string;
170
+ /** The marketplace's own self-declared `name` from its `marketplace.json`
171
+ * (e.g. `claude-plugins-official`). Kept so `info` can show users what
172
+ * the upstream calls itself when it differs from their subscription
173
+ * alias. Never used as an identity for lookup. */
174
+ upstreamName?: string;
175
+ displayName?: string;
176
+ description?: string;
177
+ owner?: {
178
+ name?: string;
179
+ url?: string;
180
+ };
181
+ plugins: MarketplaceEntry[];
182
+ }
183
+ /** One entry in `~/.x-code/plugins/known_marketplaces.json` — a
184
+ * marketplace the user has subscribed to. The `source` string can be a
185
+ * git URL (`github:owner/repo`, `https://...`) or a direct HTTPS URL
186
+ * to the marketplace.json. */
187
+ export interface KnownMarketplace {
188
+ name: string;
189
+ source: string;
190
+ /** Set on built-in entries (e.g., the default `anthropic-marketplace`).
191
+ * Reserved names only accept their canonical source — see
192
+ * RESERVED_MARKETPLACE_NAMES in [[marketplace]]. */
193
+ reservedName?: boolean;
194
+ /** Expected GitHub org for reserved names. The installer rejects any
195
+ * attempt to register a reserved name pointing elsewhere. */
196
+ officialSource?: string;
197
+ }
198
+ export interface KnownMarketplaces {
199
+ marketplaces: KnownMarketplace[];
200
+ /** When true, plugins can only be installed from a marketplace in the
201
+ * `marketplaces` list. Off by default; enterprise admins flip it on. */
202
+ strictKnownMarketplaces?: boolean;
203
+ /** Plugin IDs (`name@marketplace`) that are force-disabled regardless of
204
+ * user settings. Admin-style block list. */
205
+ blockedPlugins?: string[];
206
+ }
207
+ /** One entry in the installed registry — the bookkeeping we keep about
208
+ * each cached install so updates / uninstalls / scope changes work
209
+ * without re-reading every manifest. */
210
+ export interface InstalledPluginRecord {
211
+ id: string;
212
+ name: string;
213
+ marketplace: string;
214
+ version: string;
215
+ source: PluginSource;
216
+ installedAt: string;
217
+ /** Which scope's settings.json triggered the install (where to record
218
+ * the enable). User scope is the default. */
219
+ installScope: PluginScope;
220
+ }
221
+ export interface InstalledPlugins {
222
+ schemaVersion: string;
223
+ plugins: InstalledPluginRecord[];
224
+ }
225
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/plugins/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ // @x-code-cli/core — Plugin system core types
2
+ //
3
+ // A plugin bundles skills / sub-agents / slash commands / MCP servers /
4
+ // hooks behind a single manifest and namespace. Plugins are discovered
5
+ // at CLI startup, frozen for the session (same byte-stability constraint
6
+ // as skills + sub-agents — see CLAUDE.md on systemPromptCache), and
7
+ // re-loaded only via `/plugin refresh` which explicitly invalidates the
8
+ // prompt cache.
9
+ //
10
+ // Manifest format is intentionally byte-compatible with Claude Code's
11
+ // `.claude-plugin/plugin.json` so the same plugin tarball can be installed
12
+ // in either CLI. The native `.x-code-plugin/plugin.json` path is also
13
+ // accepted (preferred for newly-authored x-code-only plugins) and a bare
14
+ // `plugin.json` in the root is tolerated.
15
+ export {};
16
+ //# sourceMappingURL=types.js.map