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
@@ -0,0 +1,141 @@
1
+ export interface McpServer {
2
+ name: string;
3
+ description: string;
4
+ // Command-based MCP server
5
+ command?: string;
6
+ args?: string[];
7
+ env?: Record<string, string>;
8
+ // HTTP-based MCP server
9
+ type?: "http";
10
+ url?: string;
11
+ // Common fields
12
+ category:
13
+ | "browser"
14
+ | "ai"
15
+ | "design"
16
+ | "dev-tools"
17
+ | "cloud"
18
+ | "database"
19
+ | "productivity"
20
+ | "seo";
21
+ requiresConfig?: boolean;
22
+ configFields?: ConfigField[];
23
+ }
24
+
25
+ export interface ConfigField {
26
+ name: string;
27
+ label: string;
28
+ type: "string" | "path" | "url" | "boolean";
29
+ required: boolean;
30
+ default?: string;
31
+ envVar?: string;
32
+ }
33
+
34
+ export interface Marketplace {
35
+ name: string;
36
+ displayName: string;
37
+ source: {
38
+ source: "github";
39
+ repo: string;
40
+ };
41
+ description: string;
42
+ official?: boolean;
43
+ featured?: boolean; // Featured marketplaces have plugins fetched by default (like official)
44
+ }
45
+
46
+ export interface DiscoveredMarketplace {
47
+ name: string;
48
+ source: "default" | "configured" | "inferred";
49
+ config?: MarketplaceSource;
50
+ }
51
+
52
+ export interface Plugin {
53
+ name: string;
54
+ version: string;
55
+ description: string;
56
+ marketplace: string;
57
+ installed: boolean;
58
+ availableVersion?: string;
59
+ hasUpdate?: boolean;
60
+ }
61
+
62
+ export interface StatusLineConfig {
63
+ name: string;
64
+ description: string;
65
+ template: string;
66
+ }
67
+
68
+ export interface MarketplaceSource {
69
+ source: {
70
+ source: "github";
71
+ repo: string;
72
+ };
73
+ autoUpdate?: boolean; // Enable auto-update for this marketplace (default: true for new marketplaces)
74
+ }
75
+
76
+ export interface ClaudeSettings {
77
+ enabledMcpServers?: Record<string, boolean>;
78
+ mcpServers?: Record<string, McpServerConfig>;
79
+ enabledPlugins?: Record<string, boolean>;
80
+ extraKnownMarketplaces?: Record<string, MarketplaceSource>;
81
+ installedPluginVersions?: Record<string, string>;
82
+ statusLine?: string;
83
+ }
84
+
85
+ export interface McpServerConfig {
86
+ // Command-based
87
+ command?: string;
88
+ args?: string[];
89
+ env?: Record<string, string>;
90
+ // HTTP-based
91
+ type?: "http";
92
+ url?: string;
93
+ }
94
+
95
+ export interface ClaudeLocalSettings extends ClaudeSettings {
96
+ allowMcp?: boolean;
97
+ enabledMcpjsonServers?: string[];
98
+ enableAllProjectMcpServers?: boolean;
99
+ env?: Record<string, string>;
100
+ }
101
+
102
+ export type Screen =
103
+ | "main"
104
+ | "mcp"
105
+ | "mcp-registry"
106
+ | "plugins"
107
+ | "statusline"
108
+ | "cli-tools"
109
+ | "env-vars";
110
+
111
+ // MCP Registry Types (registry.modelcontextprotocol.io)
112
+ export interface McpRegistryServer {
113
+ name: string;
114
+ url: string;
115
+ short_description: string;
116
+ version?: string;
117
+ source_code_url?: string;
118
+ package_registry?: string;
119
+ published_at?: string;
120
+ }
121
+
122
+ export interface McpRegistryResponse {
123
+ servers: McpRegistryServer[];
124
+ next_cursor?: string;
125
+ }
126
+
127
+ // installed_plugins.json registry types
128
+ export interface InstalledPluginEntry {
129
+ scope: "user" | "project" | "local";
130
+ projectPath?: string;
131
+ installPath: string;
132
+ version: string;
133
+ installedAt: string;
134
+ lastUpdated: string;
135
+ gitCommitSha?: string;
136
+ }
137
+
138
+ export interface InstalledPluginsRegistry {
139
+ version: number;
140
+ plugins: Record<string, InstalledPluginEntry[]>;
141
+ }
package/src/ui/App.js ADDED
@@ -0,0 +1,213 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { useRenderer } from "@opentui/react";
4
+ import fs from "node:fs";
5
+ import { AppProvider, useApp, useNavigation, useModal, } from "./state/AppContext.js";
6
+ import { DimensionsProvider, useDimensions, } from "./state/DimensionsContext.js";
7
+ import { ModalContainer } from "./components/modals/index.js";
8
+ import { PluginsScreen, McpScreen, McpRegistryScreen, StatusLineScreen, EnvVarsScreen, CliToolsScreen, ModelSelectorScreen, } from "./screens/index.js";
9
+ import { repairAllMarketplaces } from "../services/local-marketplace.js";
10
+ import { checkForUpdates, getCurrentVersion, } from "../services/version-check.js";
11
+ import { useKeyboardHandler } from "./hooks/useKeyboardHandler.js";
12
+ import { ProgressBar } from "./components/layout/ProgressBar.js";
13
+ export const VERSION = getCurrentVersion();
14
+ /**
15
+ * Router Component
16
+ * Renders the current screen based on route
17
+ */
18
+ function Router() {
19
+ const { state } = useApp();
20
+ const { currentRoute } = state;
21
+ switch (currentRoute.screen) {
22
+ case "plugins":
23
+ return _jsx(PluginsScreen, {});
24
+ case "mcp":
25
+ return _jsx(McpScreen, {});
26
+ case "mcp-registry":
27
+ return _jsx(McpRegistryScreen, {});
28
+ case "statusline":
29
+ return _jsx(StatusLineScreen, {});
30
+ case "env-vars":
31
+ return _jsx(EnvVarsScreen, {});
32
+ case "cli-tools":
33
+ return _jsx(CliToolsScreen, {});
34
+ case "model-selector":
35
+ return _jsx(ModelSelectorScreen, {});
36
+ default:
37
+ return _jsx(PluginsScreen, {});
38
+ }
39
+ }
40
+ /**
41
+ * GlobalKeyHandler Component
42
+ * Handles global keyboard shortcuts (1-5, Tab, Escape, q, ?, Shift+D)
43
+ * Does not render anything (returns null)
44
+ */
45
+ function GlobalKeyHandler({ onDebugToggle, onExit, }) {
46
+ const { state } = useApp();
47
+ const { navigateToScreen } = useNavigation();
48
+ const modal = useModal();
49
+ const renderer = useRenderer();
50
+ useKeyboardHandler((input, key) => {
51
+ // Debug key (Shift+D) - always available
52
+ if (input === "D" && key.shift) {
53
+ onDebugToggle();
54
+ // Write debug info to file
55
+ const debugInfo = {
56
+ timestamp: new Date().toISOString(),
57
+ terminal: { rows: renderer.height, columns: renderer.width },
58
+ state: {
59
+ currentRoute: state.currentRoute,
60
+ isSearching: state.isSearching,
61
+ modal: state.modal ? { type: state.modal.type } : null,
62
+ plugins: {
63
+ scope: state.plugins.scope,
64
+ selectedIndex: state.plugins.selectedIndex,
65
+ searchQuery: state.plugins.searchQuery,
66
+ marketplacesStatus: state.plugins.marketplaces.status,
67
+ pluginsStatus: state.plugins.plugins.status,
68
+ },
69
+ },
70
+ };
71
+ fs.writeFileSync("/tmp/claudeup-debug.json", JSON.stringify(debugInfo, null, 2));
72
+ return;
73
+ }
74
+ // Don't handle keys when modal is open or searching
75
+ if (state.modal || state.isSearching)
76
+ return;
77
+ // Global navigation shortcuts (1-5) - include mcp-registry as it's a sub-screen of mcp
78
+ const isTopLevel = [
79
+ "plugins",
80
+ "mcp",
81
+ "mcp-registry",
82
+ "statusline",
83
+ "env-vars",
84
+ "cli-tools",
85
+ "model-selector",
86
+ ].includes(state.currentRoute.screen);
87
+ if (isTopLevel) {
88
+ if (input === "1")
89
+ navigateToScreen("plugins");
90
+ else if (input === "2")
91
+ navigateToScreen("mcp");
92
+ else if (input === "3")
93
+ navigateToScreen("statusline");
94
+ else if (input === "4")
95
+ navigateToScreen("env-vars");
96
+ else if (input === "5")
97
+ navigateToScreen("cli-tools");
98
+ // Tab navigation cycling
99
+ if (key.tab) {
100
+ const screens = [
101
+ "plugins",
102
+ "mcp",
103
+ "statusline",
104
+ "env-vars",
105
+ "cli-tools",
106
+ ];
107
+ const currentIndex = screens.indexOf(state.currentRoute.screen);
108
+ if (currentIndex !== -1) {
109
+ const nextIndex = key.shift
110
+ ? (currentIndex - 1 + screens.length) % screens.length
111
+ : (currentIndex + 1) % screens.length;
112
+ navigateToScreen(screens[nextIndex]);
113
+ }
114
+ }
115
+ }
116
+ // Escape/q to go back or exit
117
+ if (key.escape || input === "q") {
118
+ if (state.currentRoute.screen === "plugins") {
119
+ // On home screen, exit immediately
120
+ onExit();
121
+ }
122
+ else if (state.currentRoute.screen === "mcp-registry") {
123
+ // Go back to MCP from registry
124
+ navigateToScreen("mcp");
125
+ }
126
+ else {
127
+ // Go back to plugins (home)
128
+ navigateToScreen("plugins");
129
+ }
130
+ }
131
+ // ? for help
132
+ if (input === "?") {
133
+ modal.message("claudeup Help", `Navigation
134
+ ↑/↓ or j/k Move selection
135
+ Enter Select / Toggle
136
+ Escape or q Back / Quit
137
+ ? This help
138
+
139
+ Quick Navigation
140
+ 1 Plugins 4 Env Vars
141
+ 2 MCP Servers 5 CLI Tools
142
+ 3 Status Line
143
+
144
+ Plugin Actions
145
+ u Update d Uninstall
146
+ a Update All r Refresh
147
+
148
+ MCP Servers
149
+ / Search local + remote
150
+ r Browse MCP registry`, "info");
151
+ }
152
+ });
153
+ return null;
154
+ }
155
+ /**
156
+ * UpdateBanner Component
157
+ * Shows version update notification
158
+ */
159
+ function UpdateBanner({ result, }) {
160
+ if (!result.updateAvailable)
161
+ return null;
162
+ return (_jsxs("box", { paddingLeft: 1, paddingRight: 1, children: [_jsx("text", { bg: "yellow", fg: "black", children: _jsx("strong", { children: " UPDATE " }) }), _jsxs("text", { fg: "yellow", children: [" ", "v", result.currentVersion, " \u2192 v", result.latestVersion] }), _jsx("text", { fg: "gray", children: " Run: " }), _jsx("text", { fg: "cyan", children: "npm i -g claudeup" })] }));
163
+ }
164
+ /**
165
+ * ProgressIndicator Component
166
+ * Shows progress bar when operations are running
167
+ */
168
+ function ProgressIndicator({ message, current, total, }) {
169
+ return (_jsx("box", { paddingLeft: 1, paddingRight: 1, children: _jsx(ProgressBar, { message: message, current: current, total: total }) }));
170
+ }
171
+ function AppContentInner({ showDebug, onDebugToggle, updateInfo, onExit, }) {
172
+ const { state, dispatch } = useApp();
173
+ const { progress } = state;
174
+ const dimensions = useDimensions();
175
+ // Auto-refresh marketplaces on startup
176
+ useEffect(() => {
177
+ const noRefresh = process.argv.includes("--no-refresh");
178
+ if (noRefresh)
179
+ return;
180
+ dispatch({
181
+ type: "SHOW_PROGRESS",
182
+ state: { message: "Scanning marketplaces..." },
183
+ });
184
+ // Note: Marketplace updates should be done via Claude Code's /plugin marketplace update
185
+ // Just repair plugin.json files
186
+ repairAllMarketplaces()
187
+ .then(async () => {
188
+ dispatch({ type: "HIDE_PROGRESS" });
189
+ dispatch({ type: "DATA_REFRESH_COMPLETE" });
190
+ })
191
+ .catch(() => {
192
+ dispatch({ type: "HIDE_PROGRESS" });
193
+ });
194
+ }, [dispatch]);
195
+ return (_jsxs("box", { flexDirection: "column", height: dimensions.terminalHeight, children: [updateInfo?.updateAvailable && _jsx(UpdateBanner, { result: updateInfo }), showDebug && (_jsx("box", { paddingLeft: 1, paddingRight: 1, children: _jsxs("text", { fg: "#888888", children: ["DEBUG: ", dimensions.terminalWidth, "x", dimensions.terminalHeight, " | content=", dimensions.contentHeight, " | screen=", state.currentRoute.screen] }) })), progress && _jsx(ProgressIndicator, { ...progress }), _jsx("box", { flexDirection: "column", height: dimensions.contentHeight, paddingLeft: 1, paddingRight: 1, children: _jsx(Router, {}) }), _jsx(GlobalKeyHandler, { onDebugToggle: onDebugToggle, onExit: onExit }), _jsx(ModalContainer, {})] }));
196
+ }
197
+ function AppContent({ onExit }) {
198
+ const { state } = useApp();
199
+ const { progress } = state;
200
+ const [showDebug, setShowDebug] = useState(false);
201
+ const [updateInfo, setUpdateInfo] = useState(null);
202
+ // Check for updates on startup (non-blocking)
203
+ useEffect(() => {
204
+ checkForUpdates()
205
+ .then(setUpdateInfo)
206
+ .catch(() => { });
207
+ }, []);
208
+ return (_jsx(DimensionsProvider, { showProgress: !!progress, showDebug: showDebug, showUpdateBanner: !!updateInfo?.updateAvailable, children: _jsx(AppContentInner, { showDebug: showDebug, onDebugToggle: () => setShowDebug((s) => !s), updateInfo: updateInfo, onExit: onExit }) }));
209
+ }
210
+ export function App({ onExit }) {
211
+ return (_jsx(AppProvider, { children: _jsx(AppContent, { onExit: onExit }) }));
212
+ }
213
+ export default App;
package/src/ui/App.tsx ADDED
@@ -0,0 +1,359 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { useRenderer } from "@opentui/react";
3
+ import fs from "node:fs";
4
+ import {
5
+ AppProvider,
6
+ useApp,
7
+ useNavigation,
8
+ useModal,
9
+ } from "./state/AppContext.js";
10
+ import {
11
+ DimensionsProvider,
12
+ useDimensions,
13
+ } from "./state/DimensionsContext.js";
14
+ import { ModalContainer } from "./components/modals/index.js";
15
+ import {
16
+ PluginsScreen,
17
+ McpScreen,
18
+ McpRegistryScreen,
19
+ StatusLineScreen,
20
+ EnvVarsScreen,
21
+ CliToolsScreen,
22
+ ModelSelectorScreen,
23
+ } from "./screens/index.js";
24
+ import type { Screen } from "./state/types.js";
25
+ import { repairAllMarketplaces } from "../services/local-marketplace.js";
26
+ import {
27
+ checkForUpdates,
28
+ getCurrentVersion,
29
+ type VersionCheckResult,
30
+ } from "../services/version-check.js";
31
+ import { useKeyboardHandler } from "./hooks/useKeyboardHandler.js";
32
+ import { ProgressBar } from "./components/layout/ProgressBar.js";
33
+
34
+ export const VERSION = getCurrentVersion();
35
+
36
+ /**
37
+ * Router Component
38
+ * Renders the current screen based on route
39
+ */
40
+ function Router() {
41
+ const { state } = useApp();
42
+ const { currentRoute } = state;
43
+
44
+ switch (currentRoute.screen) {
45
+ case "plugins":
46
+ return <PluginsScreen />;
47
+ case "mcp":
48
+ return <McpScreen />;
49
+ case "mcp-registry":
50
+ return <McpRegistryScreen />;
51
+ case "statusline":
52
+ return <StatusLineScreen />;
53
+ case "env-vars":
54
+ return <EnvVarsScreen />;
55
+ case "cli-tools":
56
+ return <CliToolsScreen />;
57
+ case "model-selector":
58
+ return <ModelSelectorScreen />;
59
+ default:
60
+ return <PluginsScreen />;
61
+ }
62
+ }
63
+
64
+ /**
65
+ * GlobalKeyHandler Component
66
+ * Handles global keyboard shortcuts (1-5, Tab, Escape, q, ?, Shift+D)
67
+ * Does not render anything (returns null)
68
+ */
69
+ function GlobalKeyHandler({
70
+ onDebugToggle,
71
+ onExit,
72
+ }: { onDebugToggle: () => void; onExit: () => void }): null {
73
+ const { state } = useApp();
74
+ const { navigateToScreen } = useNavigation();
75
+ const modal = useModal();
76
+ const renderer = useRenderer();
77
+
78
+ useKeyboardHandler((input, key) => {
79
+ // Debug key (Shift+D) - always available
80
+ if (input === "D" && key.shift) {
81
+ onDebugToggle();
82
+ // Write debug info to file
83
+ const debugInfo = {
84
+ timestamp: new Date().toISOString(),
85
+ terminal: { rows: renderer.height, columns: renderer.width },
86
+ state: {
87
+ currentRoute: state.currentRoute,
88
+ isSearching: state.isSearching,
89
+ modal: state.modal ? { type: state.modal.type } : null,
90
+ plugins: {
91
+ scope: state.plugins.scope,
92
+ selectedIndex: state.plugins.selectedIndex,
93
+ searchQuery: state.plugins.searchQuery,
94
+ marketplacesStatus: state.plugins.marketplaces.status,
95
+ pluginsStatus: state.plugins.plugins.status,
96
+ },
97
+ },
98
+ };
99
+ fs.writeFileSync(
100
+ "/tmp/claudeup-debug.json",
101
+ JSON.stringify(debugInfo, null, 2),
102
+ );
103
+ return;
104
+ }
105
+
106
+ // Don't handle keys when modal is open or searching
107
+ if (state.modal || state.isSearching) return;
108
+
109
+ // Global navigation shortcuts (1-5) - include mcp-registry as it's a sub-screen of mcp
110
+ const isTopLevel = [
111
+ "plugins",
112
+ "mcp",
113
+ "mcp-registry",
114
+ "statusline",
115
+ "env-vars",
116
+ "cli-tools",
117
+ "model-selector",
118
+ ].includes(state.currentRoute.screen);
119
+
120
+ if (isTopLevel) {
121
+ if (input === "1") navigateToScreen("plugins");
122
+ else if (input === "2") navigateToScreen("mcp");
123
+ else if (input === "3") navigateToScreen("statusline");
124
+ else if (input === "4") navigateToScreen("env-vars");
125
+ else if (input === "5") navigateToScreen("cli-tools");
126
+
127
+ // Tab navigation cycling
128
+ if (key.tab) {
129
+ const screens: Screen[] = [
130
+ "plugins",
131
+ "mcp",
132
+ "statusline",
133
+ "env-vars",
134
+ "cli-tools",
135
+ ];
136
+ const currentIndex = screens.indexOf(
137
+ state.currentRoute.screen as Screen,
138
+ );
139
+ if (currentIndex !== -1) {
140
+ const nextIndex = key.shift
141
+ ? (currentIndex - 1 + screens.length) % screens.length
142
+ : (currentIndex + 1) % screens.length;
143
+ navigateToScreen(screens[nextIndex]);
144
+ }
145
+ }
146
+ }
147
+
148
+ // Escape/q to go back or exit
149
+ if (key.escape || input === "q") {
150
+ if (state.currentRoute.screen === "plugins") {
151
+ // On home screen, exit immediately
152
+ onExit();
153
+ } else if (state.currentRoute.screen === "mcp-registry") {
154
+ // Go back to MCP from registry
155
+ navigateToScreen("mcp");
156
+ } else {
157
+ // Go back to plugins (home)
158
+ navigateToScreen("plugins");
159
+ }
160
+ }
161
+
162
+ // ? for help
163
+ if (input === "?") {
164
+ modal.message(
165
+ "claudeup Help",
166
+ `Navigation
167
+ ↑/↓ or j/k Move selection
168
+ Enter Select / Toggle
169
+ Escape or q Back / Quit
170
+ ? This help
171
+
172
+ Quick Navigation
173
+ 1 Plugins 4 Env Vars
174
+ 2 MCP Servers 5 CLI Tools
175
+ 3 Status Line
176
+
177
+ Plugin Actions
178
+ u Update d Uninstall
179
+ a Update All r Refresh
180
+
181
+ MCP Servers
182
+ / Search local + remote
183
+ r Browse MCP registry`,
184
+ "info",
185
+ );
186
+ }
187
+ });
188
+
189
+ return null;
190
+ }
191
+
192
+ /**
193
+ * UpdateBanner Component
194
+ * Shows version update notification
195
+ */
196
+ function UpdateBanner({
197
+ result,
198
+ }: { result: VersionCheckResult }) {
199
+ if (!result.updateAvailable) return null;
200
+
201
+ return (
202
+ <box paddingLeft={1} paddingRight={1} >
203
+ <text bg="yellow" fg="black">
204
+ <strong> UPDATE </strong>
205
+ </text>
206
+ <text fg="yellow">
207
+ {" "}
208
+ v{result.currentVersion} → v{result.latestVersion}
209
+ </text>
210
+ <text fg="gray"> Run: </text>
211
+ <text fg="cyan">npm i -g claudeup</text>
212
+ </box>
213
+ );
214
+ }
215
+
216
+ /**
217
+ * ProgressIndicator Component
218
+ * Shows progress bar when operations are running
219
+ */
220
+ function ProgressIndicator({
221
+ message,
222
+ current,
223
+ total,
224
+ }: {
225
+ message: string;
226
+ current?: number;
227
+ total?: number;
228
+ }) {
229
+ return (
230
+ <box paddingLeft={1} paddingRight={1}>
231
+ <ProgressBar message={message} current={current} total={total} />
232
+ </box>
233
+ );
234
+ }
235
+
236
+ /**
237
+ * AppContentInner Component
238
+ * Main app layout with all UI elements
239
+ */
240
+ interface AppContentInnerProps {
241
+ showDebug: boolean;
242
+ onDebugToggle: () => void;
243
+ updateInfo: VersionCheckResult | null;
244
+ onExit: () => void;
245
+ }
246
+
247
+ function AppContentInner({
248
+ showDebug,
249
+ onDebugToggle,
250
+ updateInfo,
251
+ onExit,
252
+ }: AppContentInnerProps) {
253
+ const { state, dispatch } = useApp();
254
+ const { progress } = state;
255
+ const dimensions = useDimensions();
256
+
257
+ // Auto-refresh marketplaces on startup
258
+ useEffect(() => {
259
+ const noRefresh = process.argv.includes("--no-refresh");
260
+ if (noRefresh) return;
261
+
262
+ dispatch({
263
+ type: "SHOW_PROGRESS",
264
+ state: { message: "Scanning marketplaces..." },
265
+ });
266
+
267
+ // Note: Marketplace updates should be done via Claude Code's /plugin marketplace update
268
+ // Just repair plugin.json files
269
+ repairAllMarketplaces()
270
+ .then(async () => {
271
+ dispatch({ type: "HIDE_PROGRESS" });
272
+ dispatch({ type: "DATA_REFRESH_COMPLETE" });
273
+ })
274
+ .catch(() => {
275
+ dispatch({ type: "HIDE_PROGRESS" });
276
+ });
277
+ }, [dispatch]);
278
+
279
+ return (
280
+ <box flexDirection="column" height={dimensions.terminalHeight}>
281
+ {updateInfo?.updateAvailable && <UpdateBanner result={updateInfo} />}
282
+ {showDebug && (
283
+ <box paddingLeft={1} paddingRight={1}>
284
+ <text fg="#888888">
285
+ DEBUG: {dimensions.terminalWidth}x{dimensions.terminalHeight} |
286
+ content={dimensions.contentHeight} | screen=
287
+ {state.currentRoute.screen}
288
+ </text>
289
+ </box>
290
+ )}
291
+ {progress && <ProgressIndicator {...progress} />}
292
+ <box
293
+ flexDirection="column"
294
+ height={dimensions.contentHeight}
295
+ paddingLeft={1} paddingRight={1}
296
+ >
297
+ <Router />
298
+ </box>
299
+ <GlobalKeyHandler onDebugToggle={onDebugToggle} onExit={onExit} />
300
+ <ModalContainer />
301
+ </box>
302
+ );
303
+ }
304
+
305
+ /**
306
+ * AppContent Component
307
+ * Wraps app with DimensionsProvider and manages state for debug/updates
308
+ */
309
+ interface AppContentProps {
310
+ onExit: () => void;
311
+ }
312
+
313
+ function AppContent({ onExit }: AppContentProps) {
314
+ const { state } = useApp();
315
+ const { progress } = state;
316
+ const [showDebug, setShowDebug] = useState(false);
317
+ const [updateInfo, setUpdateInfo] = useState<VersionCheckResult | null>(null);
318
+
319
+ // Check for updates on startup (non-blocking)
320
+ useEffect(() => {
321
+ checkForUpdates()
322
+ .then(setUpdateInfo)
323
+ .catch(() => {});
324
+ }, []);
325
+
326
+ return (
327
+ <DimensionsProvider
328
+ showProgress={!!progress}
329
+ showDebug={showDebug}
330
+ showUpdateBanner={!!updateInfo?.updateAvailable}
331
+ >
332
+ <AppContentInner
333
+ showDebug={showDebug}
334
+ onDebugToggle={() => setShowDebug((s) => !s)}
335
+ updateInfo={updateInfo}
336
+ onExit={onExit}
337
+ />
338
+ </DimensionsProvider>
339
+ );
340
+ }
341
+
342
+ /**
343
+ * App Component (Root)
344
+ * Entry point for the OpenTUI application
345
+ * Wraps everything with AppProvider
346
+ */
347
+ interface AppProps {
348
+ onExit: () => void;
349
+ }
350
+
351
+ export function App({ onExit }: AppProps) {
352
+ return (
353
+ <AppProvider>
354
+ <AppContent onExit={onExit} />
355
+ </AppProvider>
356
+ );
357
+ }
358
+
359
+ export default App;