claudeup 1.7.0 → 3.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 (302) hide show
  1. package/bin/claudeup.js +20 -2
  2. package/package.json +10 -19
  3. package/src/data/cli-tools.js +123 -0
  4. package/src/data/cli-tools.ts +140 -0
  5. package/{dist → src}/data/marketplaces.js +23 -24
  6. package/src/data/marketplaces.ts +95 -0
  7. package/src/data/mcp-servers.js +509 -0
  8. package/src/data/mcp-servers.ts +526 -0
  9. package/src/data/statuslines.js +159 -0
  10. package/src/data/statuslines.ts +188 -0
  11. package/src/index.js +4 -0
  12. package/src/index.ts +5 -0
  13. package/{dist → src}/main.js +46 -47
  14. package/src/main.tsx +145 -0
  15. package/src/opentui.d.ts +191 -0
  16. package/src/prerunner/index.js +87 -0
  17. package/src/prerunner/index.ts +124 -0
  18. package/{dist → src}/services/claude-runner.js +9 -10
  19. package/src/services/claude-runner.ts +31 -0
  20. package/{dist → src}/services/claude-settings.js +72 -33
  21. package/src/services/claude-settings.ts +934 -0
  22. package/src/services/local-marketplace.js +339 -0
  23. package/src/services/local-marketplace.ts +489 -0
  24. package/{dist → src}/services/mcp-registry.js +13 -14
  25. package/src/services/mcp-registry.ts +105 -0
  26. package/{dist → src}/services/plugin-manager.js +61 -13
  27. package/src/services/plugin-manager.ts +693 -0
  28. package/{dist → src}/services/plugin-mcp-config.js +19 -18
  29. package/src/services/plugin-mcp-config.ts +242 -0
  30. package/{dist → src}/services/update-cache.js +7 -8
  31. package/src/services/update-cache.ts +78 -0
  32. package/{dist → src}/services/version-check.js +15 -14
  33. package/src/services/version-check.ts +122 -0
  34. package/src/types/index.js +1 -0
  35. package/src/types/index.ts +141 -0
  36. package/src/ui/App.js +213 -0
  37. package/src/ui/App.tsx +359 -0
  38. package/src/ui/components/CategoryHeader.js +9 -0
  39. package/src/ui/components/CategoryHeader.tsx +41 -0
  40. package/{dist → src}/ui/components/ScrollableList.js +19 -6
  41. package/src/ui/components/ScrollableList.tsx +98 -0
  42. package/src/ui/components/SearchInput.js +19 -0
  43. package/src/ui/components/SearchInput.tsx +56 -0
  44. package/src/ui/components/StyledText.js +39 -0
  45. package/src/ui/components/StyledText.tsx +70 -0
  46. package/src/ui/components/TabBar.js +38 -0
  47. package/src/ui/components/TabBar.tsx +88 -0
  48. package/src/ui/components/layout/Panel.js +6 -0
  49. package/src/ui/components/layout/Panel.tsx +62 -0
  50. package/src/ui/components/layout/ProgressBar.js +14 -0
  51. package/src/ui/components/layout/ProgressBar.tsx +47 -0
  52. package/src/ui/components/layout/ScopeTabs.js +6 -0
  53. package/src/ui/components/layout/ScopeTabs.tsx +53 -0
  54. package/src/ui/components/layout/ScreenLayout.js +21 -0
  55. package/src/ui/components/layout/ScreenLayout.tsx +147 -0
  56. package/src/ui/components/layout/index.js +4 -0
  57. package/src/ui/components/layout/index.ts +4 -0
  58. package/src/ui/components/modals/ConfirmModal.js +14 -0
  59. package/src/ui/components/modals/ConfirmModal.tsx +59 -0
  60. package/src/ui/components/modals/InputModal.js +16 -0
  61. package/src/ui/components/modals/InputModal.tsx +68 -0
  62. package/src/ui/components/modals/LoadingModal.js +14 -0
  63. package/src/ui/components/modals/LoadingModal.tsx +40 -0
  64. package/src/ui/components/modals/MessageModal.js +16 -0
  65. package/src/ui/components/modals/MessageModal.tsx +64 -0
  66. package/src/ui/components/modals/ModalContainer.js +56 -0
  67. package/src/ui/components/modals/ModalContainer.tsx +104 -0
  68. package/src/ui/components/modals/SelectModal.js +26 -0
  69. package/src/ui/components/modals/SelectModal.tsx +82 -0
  70. package/src/ui/components/modals/index.js +6 -0
  71. package/src/ui/components/modals/index.ts +6 -0
  72. package/src/ui/hooks/index.js +3 -0
  73. package/src/ui/hooks/index.ts +3 -0
  74. package/{dist → src}/ui/hooks/useAsyncData.js +21 -22
  75. package/src/ui/hooks/useAsyncData.ts +127 -0
  76. package/src/ui/hooks/useKeyboard.js +13 -0
  77. package/src/ui/hooks/useKeyboard.ts +26 -0
  78. package/src/ui/hooks/useKeyboardHandler.js +39 -0
  79. package/src/ui/hooks/useKeyboardHandler.ts +63 -0
  80. package/{dist → src}/ui/screens/CliToolsScreen.js +60 -54
  81. package/src/ui/screens/CliToolsScreen.tsx +468 -0
  82. package/src/ui/screens/EnvVarsScreen.js +154 -0
  83. package/src/ui/screens/EnvVarsScreen.tsx +269 -0
  84. package/{dist → src}/ui/screens/McpRegistryScreen.js +56 -55
  85. package/src/ui/screens/McpRegistryScreen.tsx +331 -0
  86. package/{dist → src}/ui/screens/McpScreen.js +46 -47
  87. package/src/ui/screens/McpScreen.tsx +392 -0
  88. package/src/ui/screens/ModelSelectorScreen.js +292 -0
  89. package/src/ui/screens/ModelSelectorScreen.tsx +441 -0
  90. package/{dist → src}/ui/screens/PluginsScreen.js +305 -293
  91. package/src/ui/screens/PluginsScreen.tsx +1231 -0
  92. package/src/ui/screens/StatusLineScreen.js +200 -0
  93. package/src/ui/screens/StatusLineScreen.tsx +411 -0
  94. package/src/ui/screens/index.js +7 -0
  95. package/src/ui/screens/index.ts +7 -0
  96. package/src/ui/state/AnimationContext.js +34 -0
  97. package/src/ui/state/AnimationContext.tsx +76 -0
  98. package/{dist → src}/ui/state/AppContext.js +31 -32
  99. package/src/ui/state/AppContext.tsx +235 -0
  100. package/{dist → src}/ui/state/DimensionsContext.js +16 -17
  101. package/src/ui/state/DimensionsContext.tsx +144 -0
  102. package/{dist → src}/ui/state/reducer.js +89 -90
  103. package/src/ui/state/reducer.ts +467 -0
  104. package/src/ui/state/types.js +1 -0
  105. package/src/ui/state/types.ts +273 -0
  106. package/{dist → src}/utils/command-utils.js +3 -4
  107. package/src/utils/command-utils.ts +20 -0
  108. package/{dist → src}/utils/fuzzy-search.js +2 -3
  109. package/src/utils/fuzzy-search.ts +138 -0
  110. package/{dist → src}/utils/string-utils.js +6 -6
  111. package/src/utils/string-utils.ts +88 -0
  112. package/dist/data/cli-tools.d.ts +0 -13
  113. package/dist/data/cli-tools.d.ts.map +0 -1
  114. package/dist/data/cli-tools.js +0 -124
  115. package/dist/data/cli-tools.js.map +0 -1
  116. package/dist/data/marketplaces.d.ts +0 -6
  117. package/dist/data/marketplaces.d.ts.map +0 -1
  118. package/dist/data/marketplaces.js.map +0 -1
  119. package/dist/data/mcp-servers.d.ts +0 -8
  120. package/dist/data/mcp-servers.d.ts.map +0 -1
  121. package/dist/data/mcp-servers.js +0 -503
  122. package/dist/data/mcp-servers.js.map +0 -1
  123. package/dist/data/statuslines.d.ts +0 -10
  124. package/dist/data/statuslines.d.ts.map +0 -1
  125. package/dist/data/statuslines.js +0 -160
  126. package/dist/data/statuslines.js.map +0 -1
  127. package/dist/index.d.ts +0 -3
  128. package/dist/index.d.ts.map +0 -1
  129. package/dist/index.js +0 -90
  130. package/dist/index.js.map +0 -1
  131. package/dist/main.d.ts +0 -3
  132. package/dist/main.d.ts.map +0 -1
  133. package/dist/main.js.map +0 -1
  134. package/dist/prerunner/index.d.ts +0 -7
  135. package/dist/prerunner/index.d.ts.map +0 -1
  136. package/dist/prerunner/index.js +0 -64
  137. package/dist/prerunner/index.js.map +0 -1
  138. package/dist/services/claude-runner.d.ts +0 -7
  139. package/dist/services/claude-runner.d.ts.map +0 -1
  140. package/dist/services/claude-runner.js.map +0 -1
  141. package/dist/services/claude-settings.d.ts +0 -73
  142. package/dist/services/claude-settings.d.ts.map +0 -1
  143. package/dist/services/claude-settings.js.map +0 -1
  144. package/dist/services/local-marketplace.d.ts +0 -111
  145. package/dist/services/local-marketplace.d.ts.map +0 -1
  146. package/dist/services/local-marketplace.js +0 -599
  147. package/dist/services/local-marketplace.js.map +0 -1
  148. package/dist/services/mcp-registry.d.ts +0 -10
  149. package/dist/services/mcp-registry.d.ts.map +0 -1
  150. package/dist/services/mcp-registry.js.map +0 -1
  151. package/dist/services/plugin-manager.d.ts +0 -65
  152. package/dist/services/plugin-manager.d.ts.map +0 -1
  153. package/dist/services/plugin-manager.js.map +0 -1
  154. package/dist/services/plugin-mcp-config.d.ts +0 -52
  155. package/dist/services/plugin-mcp-config.d.ts.map +0 -1
  156. package/dist/services/plugin-mcp-config.js.map +0 -1
  157. package/dist/services/update-cache.d.ts +0 -16
  158. package/dist/services/update-cache.d.ts.map +0 -1
  159. package/dist/services/update-cache.js.map +0 -1
  160. package/dist/services/version-check.d.ts +0 -20
  161. package/dist/services/version-check.d.ts.map +0 -1
  162. package/dist/services/version-check.js.map +0 -1
  163. package/dist/types/index.d.ts +0 -105
  164. package/dist/types/index.d.ts.map +0 -1
  165. package/dist/types/index.js +0 -2
  166. package/dist/types/index.js.map +0 -1
  167. package/dist/ui/InkApp.d.ts +0 -5
  168. package/dist/ui/InkApp.d.ts.map +0 -1
  169. package/dist/ui/InkApp.js +0 -188
  170. package/dist/ui/InkApp.js.map +0 -1
  171. package/dist/ui/components/CategoryHeader.d.ts +0 -16
  172. package/dist/ui/components/CategoryHeader.d.ts.map +0 -1
  173. package/dist/ui/components/CategoryHeader.js +0 -11
  174. package/dist/ui/components/CategoryHeader.js.map +0 -1
  175. package/dist/ui/components/ScrollableList.d.ts +0 -16
  176. package/dist/ui/components/ScrollableList.d.ts.map +0 -1
  177. package/dist/ui/components/ScrollableList.js.map +0 -1
  178. package/dist/ui/components/SearchInput.d.ts +0 -18
  179. package/dist/ui/components/SearchInput.d.ts.map +0 -1
  180. package/dist/ui/components/SearchInput.js +0 -30
  181. package/dist/ui/components/SearchInput.js.map +0 -1
  182. package/dist/ui/components/TabBar.d.ts +0 -8
  183. package/dist/ui/components/TabBar.d.ts.map +0 -1
  184. package/dist/ui/components/TabBar.js +0 -18
  185. package/dist/ui/components/TabBar.js.map +0 -1
  186. package/dist/ui/components/layout/Footer.d.ts +0 -14
  187. package/dist/ui/components/layout/Footer.d.ts.map +0 -1
  188. package/dist/ui/components/layout/Footer.js +0 -23
  189. package/dist/ui/components/layout/Footer.js.map +0 -1
  190. package/dist/ui/components/layout/Header.d.ts +0 -4
  191. package/dist/ui/components/layout/Header.d.ts.map +0 -1
  192. package/dist/ui/components/layout/Header.js +0 -25
  193. package/dist/ui/components/layout/Header.js.map +0 -1
  194. package/dist/ui/components/layout/Panel.d.ts +0 -22
  195. package/dist/ui/components/layout/Panel.d.ts.map +0 -1
  196. package/dist/ui/components/layout/Panel.js +0 -8
  197. package/dist/ui/components/layout/Panel.js.map +0 -1
  198. package/dist/ui/components/layout/ProgressBar.d.ts +0 -12
  199. package/dist/ui/components/layout/ProgressBar.d.ts.map +0 -1
  200. package/dist/ui/components/layout/ProgressBar.js +0 -16
  201. package/dist/ui/components/layout/ProgressBar.js.map +0 -1
  202. package/dist/ui/components/layout/ScopeTabs.d.ts +0 -12
  203. package/dist/ui/components/layout/ScopeTabs.d.ts.map +0 -1
  204. package/dist/ui/components/layout/ScopeTabs.js +0 -8
  205. package/dist/ui/components/layout/ScopeTabs.js.map +0 -1
  206. package/dist/ui/components/layout/ScreenLayout.d.ts +0 -30
  207. package/dist/ui/components/layout/ScreenLayout.d.ts.map +0 -1
  208. package/dist/ui/components/layout/ScreenLayout.js +0 -23
  209. package/dist/ui/components/layout/ScreenLayout.js.map +0 -1
  210. package/dist/ui/components/layout/index.d.ts +0 -7
  211. package/dist/ui/components/layout/index.d.ts.map +0 -1
  212. package/dist/ui/components/layout/index.js +0 -7
  213. package/dist/ui/components/layout/index.js.map +0 -1
  214. package/dist/ui/components/modals/ConfirmModal.d.ts +0 -14
  215. package/dist/ui/components/modals/ConfirmModal.d.ts.map +0 -1
  216. package/dist/ui/components/modals/ConfirmModal.js +0 -15
  217. package/dist/ui/components/modals/ConfirmModal.js.map +0 -1
  218. package/dist/ui/components/modals/InputModal.d.ts +0 -16
  219. package/dist/ui/components/modals/InputModal.d.ts.map +0 -1
  220. package/dist/ui/components/modals/InputModal.js +0 -23
  221. package/dist/ui/components/modals/InputModal.js.map +0 -1
  222. package/dist/ui/components/modals/LoadingModal.d.ts +0 -8
  223. package/dist/ui/components/modals/LoadingModal.d.ts.map +0 -1
  224. package/dist/ui/components/modals/LoadingModal.js +0 -8
  225. package/dist/ui/components/modals/LoadingModal.js.map +0 -1
  226. package/dist/ui/components/modals/MessageModal.d.ts +0 -14
  227. package/dist/ui/components/modals/MessageModal.d.ts.map +0 -1
  228. package/dist/ui/components/modals/MessageModal.js +0 -17
  229. package/dist/ui/components/modals/MessageModal.js.map +0 -1
  230. package/dist/ui/components/modals/ModalContainer.d.ts +0 -7
  231. package/dist/ui/components/modals/ModalContainer.d.ts.map +0 -1
  232. package/dist/ui/components/modals/ModalContainer.js +0 -38
  233. package/dist/ui/components/modals/ModalContainer.js.map +0 -1
  234. package/dist/ui/components/modals/SelectModal.d.ts +0 -17
  235. package/dist/ui/components/modals/SelectModal.d.ts.map +0 -1
  236. package/dist/ui/components/modals/SelectModal.js +0 -33
  237. package/dist/ui/components/modals/SelectModal.js.map +0 -1
  238. package/dist/ui/components/modals/index.d.ts +0 -7
  239. package/dist/ui/components/modals/index.d.ts.map +0 -1
  240. package/dist/ui/components/modals/index.js +0 -7
  241. package/dist/ui/components/modals/index.js.map +0 -1
  242. package/dist/ui/hooks/index.d.ts +0 -3
  243. package/dist/ui/hooks/index.d.ts.map +0 -1
  244. package/dist/ui/hooks/index.js +0 -3
  245. package/dist/ui/hooks/index.js.map +0 -1
  246. package/dist/ui/hooks/useAsyncData.d.ts +0 -40
  247. package/dist/ui/hooks/useAsyncData.d.ts.map +0 -1
  248. package/dist/ui/hooks/useAsyncData.js.map +0 -1
  249. package/dist/ui/hooks/useKeyboardNavigation.d.ts +0 -27
  250. package/dist/ui/hooks/useKeyboardNavigation.d.ts.map +0 -1
  251. package/dist/ui/hooks/useKeyboardNavigation.js +0 -82
  252. package/dist/ui/hooks/useKeyboardNavigation.js.map +0 -1
  253. package/dist/ui/screens/CliToolsScreen.d.ts +0 -4
  254. package/dist/ui/screens/CliToolsScreen.d.ts.map +0 -1
  255. package/dist/ui/screens/CliToolsScreen.js.map +0 -1
  256. package/dist/ui/screens/EnvVarsScreen.d.ts +0 -4
  257. package/dist/ui/screens/EnvVarsScreen.d.ts.map +0 -1
  258. package/dist/ui/screens/EnvVarsScreen.js +0 -145
  259. package/dist/ui/screens/EnvVarsScreen.js.map +0 -1
  260. package/dist/ui/screens/McpRegistryScreen.d.ts +0 -4
  261. package/dist/ui/screens/McpRegistryScreen.d.ts.map +0 -1
  262. package/dist/ui/screens/McpRegistryScreen.js.map +0 -1
  263. package/dist/ui/screens/McpScreen.d.ts +0 -4
  264. package/dist/ui/screens/McpScreen.d.ts.map +0 -1
  265. package/dist/ui/screens/McpScreen.js.map +0 -1
  266. package/dist/ui/screens/ModelSelectorScreen.d.ts +0 -4
  267. package/dist/ui/screens/ModelSelectorScreen.d.ts.map +0 -1
  268. package/dist/ui/screens/ModelSelectorScreen.js +0 -143
  269. package/dist/ui/screens/ModelSelectorScreen.js.map +0 -1
  270. package/dist/ui/screens/PluginsScreen.d.ts +0 -4
  271. package/dist/ui/screens/PluginsScreen.d.ts.map +0 -1
  272. package/dist/ui/screens/PluginsScreen.js.map +0 -1
  273. package/dist/ui/screens/StatusLineScreen.d.ts +0 -4
  274. package/dist/ui/screens/StatusLineScreen.d.ts.map +0 -1
  275. package/dist/ui/screens/StatusLineScreen.js +0 -197
  276. package/dist/ui/screens/StatusLineScreen.js.map +0 -1
  277. package/dist/ui/screens/index.d.ts +0 -8
  278. package/dist/ui/screens/index.d.ts.map +0 -1
  279. package/dist/ui/screens/index.js +0 -8
  280. package/dist/ui/screens/index.js.map +0 -1
  281. package/dist/ui/state/AppContext.d.ts +0 -40
  282. package/dist/ui/state/AppContext.d.ts.map +0 -1
  283. package/dist/ui/state/AppContext.js.map +0 -1
  284. package/dist/ui/state/DimensionsContext.d.ts +0 -27
  285. package/dist/ui/state/DimensionsContext.d.ts.map +0 -1
  286. package/dist/ui/state/DimensionsContext.js.map +0 -1
  287. package/dist/ui/state/reducer.d.ts +0 -4
  288. package/dist/ui/state/reducer.d.ts.map +0 -1
  289. package/dist/ui/state/reducer.js.map +0 -1
  290. package/dist/ui/state/types.d.ts +0 -266
  291. package/dist/ui/state/types.d.ts.map +0 -1
  292. package/dist/ui/state/types.js +0 -2
  293. package/dist/ui/state/types.js.map +0 -1
  294. package/dist/utils/command-utils.d.ts +0 -8
  295. package/dist/utils/command-utils.d.ts.map +0 -1
  296. package/dist/utils/command-utils.js.map +0 -1
  297. package/dist/utils/fuzzy-search.d.ts +0 -33
  298. package/dist/utils/fuzzy-search.d.ts.map +0 -1
  299. package/dist/utils/fuzzy-search.js.map +0 -1
  300. package/dist/utils/string-utils.d.ts +0 -24
  301. package/dist/utils/string-utils.d.ts.map +0 -1
  302. package/dist/utils/string-utils.js.map +0 -1
@@ -1,30 +1,32 @@
1
- import fs from 'fs-extra';
2
- import path from 'node:path';
3
- import os from 'node:os';
4
- const CLAUDE_PLUGINS_DIR = path.join(os.homedir(), '.claude', 'plugins', 'marketplaces');
1
+ import fs from "fs-extra";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+ const CLAUDE_PLUGINS_DIR = path.join(os.homedir(), ".claude", "plugins", "marketplaces");
5
5
  /**
6
6
  * Extract ${VAR_NAME} patterns from a value
7
7
  * @param value - The value to search for env var references
8
8
  * @returns Array of env var names found
9
9
  */
10
10
  function extractEnvVarReferences(value) {
11
- if (typeof value !== 'string')
11
+ if (typeof value !== "string")
12
12
  return [];
13
13
  const matches = value.match(/\$\{([A-Z_][A-Z0-9_]*)\}/g);
14
14
  if (!matches)
15
15
  return [];
16
- return matches.map(match => {
16
+ return matches
17
+ .map((match) => {
17
18
  // Extract VAR_NAME from ${VAR_NAME}
18
19
  const innerMatch = match.match(/\$\{([A-Z_][A-Z0-9_]*)\}/);
19
- return innerMatch ? innerMatch[1] : '';
20
- }).filter(Boolean);
20
+ return innerMatch ? innerMatch[1] : "";
21
+ })
22
+ .filter(Boolean);
21
23
  }
22
24
  /**
23
25
  * Recursively extract all env var references from an object
24
26
  */
25
27
  function extractAllEnvVarReferences(obj) {
26
28
  const vars = [];
27
- if (typeof obj === 'string') {
29
+ if (typeof obj === "string") {
28
30
  vars.push(...extractEnvVarReferences(obj));
29
31
  }
30
32
  else if (Array.isArray(obj)) {
@@ -32,7 +34,7 @@ function extractAllEnvVarReferences(obj) {
32
34
  vars.push(...extractAllEnvVarReferences(item));
33
35
  }
34
36
  }
35
- else if (obj && typeof obj === 'object') {
37
+ else if (obj && typeof obj === "object") {
36
38
  for (const value of Object.values(obj)) {
37
39
  vars.push(...extractAllEnvVarReferences(value));
38
40
  }
@@ -49,8 +51,8 @@ function getPluginMcpConfigPath(marketplaceName, pluginSource) {
49
51
  if (!pluginSource)
50
52
  return undefined;
51
53
  const marketplacePath = path.join(CLAUDE_PLUGINS_DIR, marketplaceName);
52
- const pluginPath = path.join(marketplacePath, pluginSource.replace(/^\.\//, ''));
53
- const mcpConfigPath = path.join(pluginPath, 'mcp-servers', 'mcp-config.json');
54
+ const pluginPath = path.join(marketplacePath, pluginSource.replace(/^\.\//, ""));
55
+ const mcpConfigPath = path.join(pluginPath, "mcp-servers", "mcp-config.json");
54
56
  return mcpConfigPath;
55
57
  }
56
58
  /**
@@ -69,7 +71,7 @@ export async function readPluginMcpConfig(marketplaceName, pluginSource) {
69
71
  // Filter out comment fields (keys starting with _)
70
72
  const filtered = {};
71
73
  for (const [key, value] of Object.entries(content)) {
72
- if (!key.startsWith('_') && value && typeof value === 'object') {
74
+ if (!key.startsWith("_") && value && typeof value === "object") {
73
75
  filtered[key] = value;
74
76
  }
75
77
  }
@@ -88,9 +90,9 @@ export async function readPluginMcpConfig(marketplaceName, pluginSource) {
88
90
  */
89
91
  function generateLabel(varName) {
90
92
  return varName
91
- .split('_')
92
- .map(word => word.charAt(0) + word.slice(1).toLowerCase())
93
- .join(' ');
93
+ .split("_")
94
+ .map((word) => word.charAt(0) + word.slice(1).toLowerCase())
95
+ .join(" ");
94
96
  }
95
97
  /**
96
98
  * Get all environment variable requirements for a plugin
@@ -148,7 +150,7 @@ export async function getPluginEnvRequirements(marketplaceName, pluginSource) {
148
150
  */
149
151
  export async function getPluginSourcePath(marketplaceName, pluginName) {
150
152
  const marketplacePath = path.join(CLAUDE_PLUGINS_DIR, marketplaceName);
151
- const manifestPath = path.join(marketplacePath, '.claude-plugin', 'marketplace.json');
153
+ const manifestPath = path.join(marketplacePath, ".claude-plugin", "marketplace.json");
152
154
  try {
153
155
  if (await fs.pathExists(manifestPath)) {
154
156
  const manifest = await fs.readJson(manifestPath);
@@ -173,4 +175,3 @@ export async function getPluginMcpServerNames(marketplaceName, pluginSource) {
173
175
  const mcpConfig = await readPluginMcpConfig(marketplaceName, pluginSource);
174
176
  return Object.keys(mcpConfig);
175
177
  }
176
- //# sourceMappingURL=plugin-mcp-config.js.map
@@ -0,0 +1,242 @@
1
+ import fs from "fs-extra";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+
5
+ const CLAUDE_PLUGINS_DIR = path.join(
6
+ os.homedir(),
7
+ ".claude",
8
+ "plugins",
9
+ "marketplaces",
10
+ );
11
+
12
+ /**
13
+ * Represents a required environment variable for a plugin's MCP server
14
+ */
15
+ export interface PluginEnvRequirement {
16
+ /** The environment variable name (e.g., "FIGMA_ACCESS_TOKEN") */
17
+ name: string;
18
+ /** User-friendly label (defaults to name if not provided) */
19
+ label: string;
20
+ /** The MCP server name this env var is for */
21
+ serverName: string;
22
+ /** Whether this env var is required (all detected vars are considered required) */
23
+ required: boolean;
24
+ }
25
+
26
+ /**
27
+ * Extract ${VAR_NAME} patterns from a value
28
+ * @param value - The value to search for env var references
29
+ * @returns Array of env var names found
30
+ */
31
+ function extractEnvVarReferences(value: unknown): string[] {
32
+ if (typeof value !== "string") return [];
33
+
34
+ const matches = value.match(/\$\{([A-Z_][A-Z0-9_]*)\}/g);
35
+ if (!matches) return [];
36
+
37
+ return matches
38
+ .map((match) => {
39
+ // Extract VAR_NAME from ${VAR_NAME}
40
+ const innerMatch = match.match(/\$\{([A-Z_][A-Z0-9_]*)\}/);
41
+ return innerMatch ? innerMatch[1] : "";
42
+ })
43
+ .filter(Boolean);
44
+ }
45
+
46
+ /**
47
+ * Recursively extract all env var references from an object
48
+ */
49
+ function extractAllEnvVarReferences(obj: unknown): string[] {
50
+ const vars: string[] = [];
51
+
52
+ if (typeof obj === "string") {
53
+ vars.push(...extractEnvVarReferences(obj));
54
+ } else if (Array.isArray(obj)) {
55
+ for (const item of obj) {
56
+ vars.push(...extractAllEnvVarReferences(item));
57
+ }
58
+ } else if (obj && typeof obj === "object") {
59
+ for (const value of Object.values(obj)) {
60
+ vars.push(...extractAllEnvVarReferences(value));
61
+ }
62
+ }
63
+
64
+ return vars;
65
+ }
66
+
67
+ interface McpServerConfig {
68
+ command?: string;
69
+ args?: string[];
70
+ env?: Record<string, string>;
71
+ type?: "http";
72
+ url?: string;
73
+ }
74
+
75
+ /**
76
+ * Get the path to a plugin's mcp-config.json in the marketplace cache
77
+ * @param marketplaceName - Name of the marketplace (e.g., "mag-claude-plugins")
78
+ * @param pluginSource - Plugin source path from marketplace.json (e.g., "./plugins/frontend")
79
+ * @returns Full path to mcp-config.json or undefined if not found
80
+ */
81
+ function getPluginMcpConfigPath(
82
+ marketplaceName: string,
83
+ pluginSource?: string,
84
+ ): string | undefined {
85
+ if (!pluginSource) return undefined;
86
+
87
+ const marketplacePath = path.join(CLAUDE_PLUGINS_DIR, marketplaceName);
88
+ const pluginPath = path.join(
89
+ marketplacePath,
90
+ pluginSource.replace(/^\.\//, ""),
91
+ );
92
+ const mcpConfigPath = path.join(pluginPath, "mcp-servers", "mcp-config.json");
93
+
94
+ return mcpConfigPath;
95
+ }
96
+
97
+ /**
98
+ * Read and parse a plugin's MCP configuration
99
+ * @param marketplaceName - Name of the marketplace
100
+ * @param pluginSource - Plugin source path from marketplace.json
101
+ * @returns Parsed MCP config or empty object if not found
102
+ */
103
+ export async function readPluginMcpConfig(
104
+ marketplaceName: string,
105
+ pluginSource?: string,
106
+ ): Promise<Record<string, McpServerConfig>> {
107
+ const configPath = getPluginMcpConfigPath(marketplaceName, pluginSource);
108
+ if (!configPath) return {};
109
+
110
+ try {
111
+ if (await fs.pathExists(configPath)) {
112
+ const content = await fs.readJson(configPath);
113
+ // Filter out comment fields (keys starting with _)
114
+ const filtered: Record<string, McpServerConfig> = {};
115
+ for (const [key, value] of Object.entries(content)) {
116
+ if (!key.startsWith("_") && value && typeof value === "object") {
117
+ filtered[key] = value as McpServerConfig;
118
+ }
119
+ }
120
+ return filtered;
121
+ }
122
+ } catch (error) {
123
+ console.error(`Failed to read plugin MCP config: ${error}`);
124
+ }
125
+
126
+ return {};
127
+ }
128
+
129
+ /**
130
+ * Generate user-friendly label from env var name
131
+ * @param varName - Environment variable name (e.g., "FIGMA_ACCESS_TOKEN")
132
+ * @returns Human-readable label (e.g., "Figma Access Token")
133
+ */
134
+ function generateLabel(varName: string): string {
135
+ return varName
136
+ .split("_")
137
+ .map((word) => word.charAt(0) + word.slice(1).toLowerCase())
138
+ .join(" ");
139
+ }
140
+
141
+ /**
142
+ * Get all environment variable requirements for a plugin
143
+ * Extracts ${VAR_NAME} patterns from the plugin's mcp-config.json
144
+ *
145
+ * @param marketplaceName - Name of the marketplace (e.g., "mag-claude-plugins")
146
+ * @param pluginSource - Plugin source path from marketplace.json (e.g., "./plugins/frontend")
147
+ * @returns Array of required env vars with metadata
148
+ */
149
+ export async function getPluginEnvRequirements(
150
+ marketplaceName: string,
151
+ pluginSource?: string,
152
+ ): Promise<PluginEnvRequirement[]> {
153
+ const mcpConfig = await readPluginMcpConfig(marketplaceName, pluginSource);
154
+ const requirements: PluginEnvRequirement[] = [];
155
+ const seenVars = new Set<string>();
156
+
157
+ for (const [serverName, config] of Object.entries(mcpConfig)) {
158
+ // Extract from env object
159
+ if (config.env) {
160
+ for (const value of Object.values(config.env)) {
161
+ const vars = extractEnvVarReferences(value);
162
+ for (const varName of vars) {
163
+ if (!seenVars.has(varName)) {
164
+ seenVars.add(varName);
165
+ requirements.push({
166
+ name: varName,
167
+ label: generateLabel(varName),
168
+ serverName,
169
+ required: true,
170
+ });
171
+ }
172
+ }
173
+ }
174
+ }
175
+
176
+ // Also check args array for env var references (e.g., sqlite with ${DATABASE_PATH})
177
+ if (config.args) {
178
+ const argsVars = extractAllEnvVarReferences(config.args);
179
+ for (const varName of argsVars) {
180
+ if (!seenVars.has(varName)) {
181
+ seenVars.add(varName);
182
+ requirements.push({
183
+ name: varName,
184
+ label: generateLabel(varName),
185
+ serverName,
186
+ required: true,
187
+ });
188
+ }
189
+ }
190
+ }
191
+ }
192
+
193
+ return requirements;
194
+ }
195
+
196
+ /**
197
+ * Get plugin source path from local marketplace cache
198
+ * @param marketplaceName - Name of the marketplace
199
+ * @param pluginName - Name of the plugin
200
+ * @returns Plugin source path or undefined
201
+ */
202
+ export async function getPluginSourcePath(
203
+ marketplaceName: string,
204
+ pluginName: string,
205
+ ): Promise<string | undefined> {
206
+ const marketplacePath = path.join(CLAUDE_PLUGINS_DIR, marketplaceName);
207
+ const manifestPath = path.join(
208
+ marketplacePath,
209
+ ".claude-plugin",
210
+ "marketplace.json",
211
+ );
212
+
213
+ try {
214
+ if (await fs.pathExists(manifestPath)) {
215
+ const manifest = await fs.readJson(manifestPath);
216
+ if (manifest.plugins && Array.isArray(manifest.plugins)) {
217
+ const plugin = manifest.plugins.find(
218
+ (p: { name: string }) => p.name === pluginName,
219
+ );
220
+ return plugin?.source;
221
+ }
222
+ }
223
+ } catch {
224
+ // Return undefined if can't read
225
+ }
226
+
227
+ return undefined;
228
+ }
229
+
230
+ /**
231
+ * Get all MCP server names from a plugin's config
232
+ * @param marketplaceName - Name of the marketplace
233
+ * @param pluginSource - Plugin source path
234
+ * @returns Array of MCP server names
235
+ */
236
+ export async function getPluginMcpServerNames(
237
+ marketplaceName: string,
238
+ pluginSource?: string,
239
+ ): Promise<string[]> {
240
+ const mcpConfig = await readPluginMcpConfig(marketplaceName, pluginSource);
241
+ return Object.keys(mcpConfig);
242
+ }
@@ -1,12 +1,12 @@
1
- import { promises as fs } from 'node:fs';
2
- import path from 'node:path';
3
- import os from 'node:os';
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
4
  const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
5
5
  export class UpdateCache {
6
6
  cachePath;
7
7
  constructor() {
8
8
  // Cache at ~/.claude/claudeup-cache.json
9
- this.cachePath = path.join(os.homedir(), '.claude', 'claudeup-cache.json');
9
+ this.cachePath = path.join(os.homedir(), ".claude", "claudeup-cache.json");
10
10
  }
11
11
  async shouldCheckForUpdates() {
12
12
  const data = await this.getLastCheck();
@@ -19,7 +19,7 @@ export class UpdateCache {
19
19
  }
20
20
  async getLastCheck() {
21
21
  try {
22
- const content = await fs.readFile(this.cachePath, 'utf-8');
22
+ const content = await fs.readFile(this.cachePath, "utf-8");
23
23
  const data = JSON.parse(content);
24
24
  return data;
25
25
  }
@@ -34,11 +34,11 @@ export class UpdateCache {
34
34
  const cacheDir = path.dirname(this.cachePath);
35
35
  await fs.mkdir(cacheDir, { recursive: true });
36
36
  // Write cache file
37
- await fs.writeFile(this.cachePath, JSON.stringify(result, null, 2), 'utf-8');
37
+ await fs.writeFile(this.cachePath, JSON.stringify(result, null, 2), "utf-8");
38
38
  }
39
39
  catch (error) {
40
40
  // Non-fatal - just log and continue
41
- console.warn('Warning: Failed to save update cache:', error instanceof Error ? error.message : 'Unknown error');
41
+ console.warn("Warning: Failed to save update cache:", error instanceof Error ? error.message : "Unknown error");
42
42
  }
43
43
  }
44
44
  async clear() {
@@ -50,4 +50,3 @@ export class UpdateCache {
50
50
  }
51
51
  }
52
52
  }
53
- //# sourceMappingURL=update-cache.js.map
@@ -0,0 +1,78 @@
1
+ import { promises as fs } from "node:fs";
2
+ import path from "node:path";
3
+ import os from "node:os";
4
+
5
+ const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
6
+
7
+ export interface UpdateCacheData {
8
+ lastUpdateCheck: string; // ISO timestamp
9
+ lastUpdateResult: {
10
+ updated: string[]; // ["frontend@mag-claude-plugins v3.13.0", ...]
11
+ failed: string[]; // Marketplaces that failed
12
+ autoUpdated?: Array<{
13
+ pluginId: string;
14
+ oldVersion: string;
15
+ newVersion: string;
16
+ }>; // Plugins that were auto-updated
17
+ };
18
+ }
19
+
20
+ export class UpdateCache {
21
+ private cachePath: string;
22
+
23
+ constructor() {
24
+ // Cache at ~/.claude/claudeup-cache.json
25
+ this.cachePath = path.join(os.homedir(), ".claude", "claudeup-cache.json");
26
+ }
27
+
28
+ async shouldCheckForUpdates(): Promise<boolean> {
29
+ const data = await this.getLastCheck();
30
+ if (!data) return true; // No cache
31
+
32
+ const lastCheck = new Date(data.lastUpdateCheck);
33
+ const now = new Date();
34
+ const elapsed = now.getTime() - lastCheck.getTime();
35
+
36
+ return elapsed >= CACHE_TTL_MS;
37
+ }
38
+
39
+ async getLastCheck(): Promise<UpdateCacheData | null> {
40
+ try {
41
+ const content = await fs.readFile(this.cachePath, "utf-8");
42
+ const data = JSON.parse(content) as UpdateCacheData;
43
+ return data;
44
+ } catch (error) {
45
+ // Cache doesn't exist or is corrupted
46
+ return null;
47
+ }
48
+ }
49
+
50
+ async saveCheck(result: UpdateCacheData): Promise<void> {
51
+ try {
52
+ // Ensure .claude directory exists
53
+ const cacheDir = path.dirname(this.cachePath);
54
+ await fs.mkdir(cacheDir, { recursive: true });
55
+
56
+ // Write cache file
57
+ await fs.writeFile(
58
+ this.cachePath,
59
+ JSON.stringify(result, null, 2),
60
+ "utf-8",
61
+ );
62
+ } catch (error) {
63
+ // Non-fatal - just log and continue
64
+ console.warn(
65
+ "Warning: Failed to save update cache:",
66
+ error instanceof Error ? error.message : "Unknown error",
67
+ );
68
+ }
69
+ }
70
+
71
+ async clear(): Promise<void> {
72
+ try {
73
+ await fs.unlink(this.cachePath);
74
+ } catch (error) {
75
+ // Ignore errors (file might not exist)
76
+ }
77
+ }
78
+ }
@@ -1,5 +1,5 @@
1
- import { createRequire } from 'node:module';
2
- import semver from 'semver';
1
+ import { createRequire } from "node:module";
2
+ import semver from "semver";
3
3
  const require = createRequire(import.meta.url);
4
4
  // Cache the result for the session
5
5
  let cachedResult = null;
@@ -8,11 +8,11 @@ let cachedResult = null;
8
8
  */
9
9
  export function getCurrentVersion() {
10
10
  try {
11
- const pkg = require('../../package.json');
11
+ const pkg = require("../../package.json");
12
12
  return pkg.version;
13
13
  }
14
14
  catch {
15
- return '0.0.0';
15
+ return "0.0.0";
16
16
  }
17
17
  }
18
18
  /**
@@ -23,17 +23,17 @@ async function fetchLatestVersion() {
23
23
  try {
24
24
  const controller = new AbortController();
25
25
  const timeout = setTimeout(() => controller.abort(), 3000); // 3s timeout
26
- const response = await fetch('https://registry.npmjs.org/claudeup/latest', {
26
+ const response = await fetch("https://registry.npmjs.org/claudeup/latest", {
27
27
  signal: controller.signal,
28
28
  headers: {
29
- 'Accept': 'application/json',
29
+ Accept: "application/json",
30
30
  },
31
31
  });
32
32
  clearTimeout(timeout);
33
33
  if (!response.ok) {
34
34
  return null;
35
35
  }
36
- const data = await response.json();
36
+ const data = (await response.json());
37
37
  return data.version || null;
38
38
  }
39
39
  catch {
@@ -50,11 +50,11 @@ function getUpdateType(current, latest) {
50
50
  if (!currentParsed || !latestParsed)
51
51
  return undefined;
52
52
  if (latestParsed.major > currentParsed.major)
53
- return 'major';
53
+ return "major";
54
54
  if (latestParsed.minor > currentParsed.minor)
55
- return 'minor';
55
+ return "minor";
56
56
  if (latestParsed.patch > currentParsed.patch)
57
- return 'patch';
57
+ return "patch";
58
58
  return undefined;
59
59
  }
60
60
  /**
@@ -82,7 +82,9 @@ export async function checkForUpdates() {
82
82
  currentVersion,
83
83
  latestVersion,
84
84
  updateAvailable,
85
- updateType: updateAvailable ? getUpdateType(currentVersion, latestVersion) : undefined,
85
+ updateType: updateAvailable
86
+ ? getUpdateType(currentVersion, latestVersion)
87
+ : undefined,
86
88
  };
87
89
  return cachedResult;
88
90
  }
@@ -91,8 +93,7 @@ export async function checkForUpdates() {
91
93
  */
92
94
  export function formatUpdateMessage(result) {
93
95
  if (!result.updateAvailable)
94
- return '';
95
- const typeLabel = result.updateType ? ` (${result.updateType})` : '';
96
+ return "";
97
+ const typeLabel = result.updateType ? ` (${result.updateType})` : "";
96
98
  return `Update available: v${result.currentVersion} → v${result.latestVersion}${typeLabel}. Run: npm i -g claudeup`;
97
99
  }
98
- //# sourceMappingURL=version-check.js.map
@@ -0,0 +1,122 @@
1
+ import { createRequire } from "node:module";
2
+ import semver from "semver";
3
+
4
+ const require = createRequire(import.meta.url);
5
+
6
+ // Cache the result for the session
7
+ let cachedResult: VersionCheckResult | null = null;
8
+
9
+ export interface VersionCheckResult {
10
+ currentVersion: string;
11
+ latestVersion: string;
12
+ updateAvailable: boolean;
13
+ updateType?: "major" | "minor" | "patch";
14
+ }
15
+
16
+ /**
17
+ * Get the current version from package.json
18
+ */
19
+ export function getCurrentVersion(): string {
20
+ try {
21
+ const pkg = require("../../package.json");
22
+ return pkg.version;
23
+ } catch {
24
+ return "0.0.0";
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Fetch the latest version from npm registry
30
+ * Uses a short timeout to avoid blocking startup
31
+ */
32
+ async function fetchLatestVersion(): Promise<string | null> {
33
+ try {
34
+ const controller = new AbortController();
35
+ const timeout = setTimeout(() => controller.abort(), 3000); // 3s timeout
36
+
37
+ const response = await fetch("https://registry.npmjs.org/claudeup/latest", {
38
+ signal: controller.signal,
39
+ headers: {
40
+ Accept: "application/json",
41
+ },
42
+ });
43
+
44
+ clearTimeout(timeout);
45
+
46
+ if (!response.ok) {
47
+ return null;
48
+ }
49
+
50
+ const data = (await response.json()) as { version?: string };
51
+ return data.version || null;
52
+ } catch {
53
+ // Network error, timeout, or parse error - silently fail
54
+ return null;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Determine the type of update (major, minor, patch)
60
+ */
61
+ function getUpdateType(
62
+ current: string,
63
+ latest: string,
64
+ ): "major" | "minor" | "patch" | undefined {
65
+ const currentParsed = semver.parse(current);
66
+ const latestParsed = semver.parse(latest);
67
+
68
+ if (!currentParsed || !latestParsed) return undefined;
69
+
70
+ if (latestParsed.major > currentParsed.major) return "major";
71
+ if (latestParsed.minor > currentParsed.minor) return "minor";
72
+ if (latestParsed.patch > currentParsed.patch) return "patch";
73
+
74
+ return undefined;
75
+ }
76
+
77
+ /**
78
+ * Check if a new version is available
79
+ * Returns cached result if already checked this session
80
+ */
81
+ export async function checkForUpdates(): Promise<VersionCheckResult> {
82
+ // Return cached result if available
83
+ if (cachedResult) {
84
+ return cachedResult;
85
+ }
86
+
87
+ const currentVersion = getCurrentVersion();
88
+ const latestVersion = await fetchLatestVersion();
89
+
90
+ if (!latestVersion) {
91
+ // Couldn't fetch, assume no update
92
+ cachedResult = {
93
+ currentVersion,
94
+ latestVersion: currentVersion,
95
+ updateAvailable: false,
96
+ };
97
+ return cachedResult;
98
+ }
99
+
100
+ const updateAvailable = semver.gt(latestVersion, currentVersion);
101
+
102
+ cachedResult = {
103
+ currentVersion,
104
+ latestVersion,
105
+ updateAvailable,
106
+ updateType: updateAvailable
107
+ ? getUpdateType(currentVersion, latestVersion)
108
+ : undefined,
109
+ };
110
+
111
+ return cachedResult;
112
+ }
113
+
114
+ /**
115
+ * Format update message for display
116
+ */
117
+ export function formatUpdateMessage(result: VersionCheckResult): string {
118
+ if (!result.updateAvailable) return "";
119
+
120
+ const typeLabel = result.updateType ? ` (${result.updateType})` : "";
121
+ return `Update available: v${result.currentVersion} → v${result.latestVersion}${typeLabel}. Run: npm i -g claudeup`;
122
+ }
@@ -0,0 +1 @@
1
+ export {};