claudeup 4.18.0 → 4.22.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 (191) hide show
  1. package/bin/claudeup.js +43 -19
  2. package/package.json +14 -19
  3. package/scripts/build-binaries.ts +77 -0
  4. package/scripts/check-optional-deps.ts +49 -0
  5. package/scripts/test-isolated.ts +43 -0
  6. package/src/__tests__/alias-adopt.test.ts +364 -0
  7. package/src/__tests__/alias-parser.test.ts +92 -0
  8. package/src/__tests__/alias-shell-writer.test.ts +7 -0
  9. package/src/__tests__/alias-store.test.ts +77 -0
  10. package/src/__tests__/cli-router.test.ts +65 -0
  11. package/src/__tests__/conventions-integration.test.ts +745 -0
  12. package/src/__tests__/conventions-manager.test.ts +1172 -0
  13. package/src/__tests__/doctor-bins.test.ts +35 -0
  14. package/src/__tests__/doctor.test.ts +450 -0
  15. package/src/__tests__/dual-write-prevention.test.ts +14 -4
  16. package/src/__tests__/file-locking.test.ts +208 -0
  17. package/src/__tests__/gitignore-prerun.test.ts +1 -0
  18. package/src/__tests__/install-command.test.ts +81 -0
  19. package/src/__tests__/install-plan.test.ts +98 -0
  20. package/src/__tests__/manifest.test.ts +136 -0
  21. package/src/__tests__/marketplace-refresh.test.ts +267 -0
  22. package/src/__tests__/plugin-requires.test.ts +133 -0
  23. package/src/__tests__/plugin-setup.test.ts +118 -0
  24. package/src/__tests__/profile-command.test.ts +116 -0
  25. package/src/__tests__/profile-materializer.test.ts +82 -0
  26. package/src/__tests__/profile-sync.test.ts +136 -0
  27. package/src/__tests__/registry-version-resolution.test.ts +74 -0
  28. package/src/__tests__/resolve-executable.test.ts +42 -0
  29. package/src/__tests__/resolver.test.ts +218 -0
  30. package/src/__tests__/symlink-manager.test.ts +99 -0
  31. package/src/__tests__/toolchain.test.ts +56 -0
  32. package/src/cli/claude.ts +21 -0
  33. package/src/cli/doctor.ts +132 -0
  34. package/src/cli/install.ts +360 -0
  35. package/src/cli/profile.ts +166 -0
  36. package/src/cli/router.ts +107 -0
  37. package/src/cli/update.ts +85 -0
  38. package/src/data/alias-flags.ts +11 -1
  39. package/src/data/cli-tools.ts +7 -7
  40. package/src/data/gitignore-defaults.ts +4 -0
  41. package/src/data/marketplaces.ts +12 -0
  42. package/src/data/predefined-profiles.ts +3 -4
  43. package/src/main.tsx +11 -154
  44. package/src/prerunner/index.ts +62 -27
  45. package/src/services/alias-shell-writer.ts +382 -8
  46. package/src/services/alias-store.ts +60 -0
  47. package/src/services/claude-cli.ts +19 -22
  48. package/src/services/claude-settings.ts +99 -26
  49. package/src/services/conventions-manager.ts +865 -0
  50. package/src/services/doctor-bins.ts +49 -0
  51. package/src/services/doctor.ts +509 -0
  52. package/src/services/install-plan.ts +107 -0
  53. package/src/services/manifest.ts +166 -0
  54. package/src/services/marketplace-refresh.ts +173 -0
  55. package/src/services/plugin-manager.ts +7 -1
  56. package/src/services/plugin-requires.ts +215 -0
  57. package/src/services/plugin-setup.ts +61 -4
  58. package/src/services/plugin-version-check.ts +9 -4
  59. package/src/services/profile-materializer.ts +61 -0
  60. package/src/services/profile-sync.ts +150 -0
  61. package/src/services/resolver.ts +293 -0
  62. package/src/services/symlink-manager.ts +146 -0
  63. package/src/services/toolchain.ts +97 -0
  64. package/src/services/version-check.ts +10 -11
  65. package/src/types/index.ts +138 -31
  66. package/src/ui/App.tsx +16 -11
  67. package/src/ui/components/FlagDetailEditor.tsx +0 -0
  68. package/src/ui/components/modals/ConfirmModal.tsx +1 -1
  69. package/src/ui/screens/AliasScreen.tsx +491 -359
  70. package/src/ui/screens/CliToolsScreen.tsx +11 -3
  71. package/src/ui/screens/PluginsScreen.tsx +3 -1
  72. package/src/ui/screens/index.ts +0 -1
  73. package/src/ui/state/reducer.ts +6 -102
  74. package/src/ui/state/types.ts +8 -35
  75. package/src/utils/command-utils.ts +23 -0
  76. package/src/utils/file-locking.ts +144 -0
  77. package/src/data/alias-flags.js +0 -196
  78. package/src/data/cli-tools.js +0 -123
  79. package/src/data/gitignore-defaults.js +0 -24
  80. package/src/data/gitignore-reasons.js +0 -97
  81. package/src/data/gitignore-templates.js +0 -21
  82. package/src/data/marketplaces.js +0 -138
  83. package/src/data/mcp-servers.js +0 -509
  84. package/src/data/predefined-profiles.js +0 -248
  85. package/src/data/settings-catalog.js +0 -625
  86. package/src/data/skill-repos.js +0 -160
  87. package/src/data/statuslines.js +0 -159
  88. package/src/data/statuslines.ts +0 -188
  89. package/src/index.js +0 -4
  90. package/src/index.ts +0 -5
  91. package/src/main.js +0 -170
  92. package/src/prerunner/index.js +0 -252
  93. package/src/services/alias-settings.js +0 -51
  94. package/src/services/alias-shell-writer.js +0 -764
  95. package/src/services/alias-store.js +0 -77
  96. package/src/services/claude-cli.js +0 -189
  97. package/src/services/claude-runner.js +0 -28
  98. package/src/services/claude-settings.js +0 -1223
  99. package/src/services/gitignore-detector.js +0 -155
  100. package/src/services/gitignore-fixer.js +0 -231
  101. package/src/services/gitignore-prerun.js +0 -46
  102. package/src/services/gitignore-resolver.js +0 -143
  103. package/src/services/gitignore-service.js +0 -117
  104. package/src/services/local-marketplace.js +0 -339
  105. package/src/services/marketplace-fetcher.js +0 -96
  106. package/src/services/marketplace-sync.js +0 -94
  107. package/src/services/mcp-registry.js +0 -87
  108. package/src/services/plugin-manager.js +0 -473
  109. package/src/services/plugin-mcp-config.js +0 -177
  110. package/src/services/plugin-setup.js +0 -444
  111. package/src/services/plugin-version-check.js +0 -262
  112. package/src/services/profiles.js +0 -161
  113. package/src/services/settings-manager.js +0 -243
  114. package/src/services/skills-manager.js +0 -393
  115. package/src/services/skillsmp-client.js +0 -87
  116. package/src/services/update-cache.js +0 -52
  117. package/src/services/version-check.js +0 -99
  118. package/src/types/gitignore.js +0 -6
  119. package/src/types/index.js +0 -1
  120. package/src/ui/App.js +0 -346
  121. package/src/ui/adapters/pluginsAdapter.js +0 -139
  122. package/src/ui/adapters/settingsAdapter.js +0 -111
  123. package/src/ui/adapters/skillsAdapter.js +0 -154
  124. package/src/ui/components/CategoryHeader.js +0 -9
  125. package/src/ui/components/EmptyFilterState.js +0 -4
  126. package/src/ui/components/ScopeIndicator.js +0 -30
  127. package/src/ui/components/ScrollableList.js +0 -36
  128. package/src/ui/components/SearchInput.js +0 -19
  129. package/src/ui/components/StyledText.js +0 -39
  130. package/src/ui/components/TabBar.js +0 -19
  131. package/src/ui/components/layout/FooterHints.js +0 -29
  132. package/src/ui/components/layout/Panel.js +0 -6
  133. package/src/ui/components/layout/ProgressBar.js +0 -14
  134. package/src/ui/components/layout/ScopeTabs.js +0 -6
  135. package/src/ui/components/layout/ScreenLayout.js +0 -16
  136. package/src/ui/components/layout/index.js +0 -5
  137. package/src/ui/components/modals/ConfirmModal.js +0 -14
  138. package/src/ui/components/modals/InputModal.js +0 -5
  139. package/src/ui/components/modals/LoadingModal.js +0 -17
  140. package/src/ui/components/modals/MessageModal.js +0 -16
  141. package/src/ui/components/modals/ModalContainer.js +0 -137
  142. package/src/ui/components/modals/SelectModal.js +0 -18
  143. package/src/ui/components/modals/VersionMismatchModal.js +0 -36
  144. package/src/ui/components/modals/index.js +0 -6
  145. package/src/ui/components/primitives/ActionHints.js +0 -13
  146. package/src/ui/components/primitives/DetailSection.js +0 -7
  147. package/src/ui/components/primitives/KeyValueLine.js +0 -8
  148. package/src/ui/components/primitives/ListCategoryRow.js +0 -8
  149. package/src/ui/components/primitives/MetaText.js +0 -8
  150. package/src/ui/components/primitives/ScopeDetail.js +0 -32
  151. package/src/ui/components/primitives/ScopeSquares.js +0 -11
  152. package/src/ui/components/primitives/SelectableRow.js +0 -5
  153. package/src/ui/components/primitives/index.js +0 -8
  154. package/src/ui/hooks/index.js +0 -4
  155. package/src/ui/hooks/useAsyncData.js +0 -77
  156. package/src/ui/hooks/useGitignoreModal.js +0 -74
  157. package/src/ui/hooks/useKeyboard.js +0 -13
  158. package/src/ui/hooks/useKeyboardHandler.js +0 -39
  159. package/src/ui/hooks/useMismatchModal.js +0 -77
  160. package/src/ui/registry.js +0 -1
  161. package/src/ui/renderers/cliToolRenderers.js +0 -54
  162. package/src/ui/renderers/gitignoreRenderers.js +0 -46
  163. package/src/ui/renderers/mcpRenderers.js +0 -26
  164. package/src/ui/renderers/pluginRenderers.js +0 -124
  165. package/src/ui/renderers/profileRenderers.js +0 -177
  166. package/src/ui/renderers/settingsRenderers.js +0 -73
  167. package/src/ui/renderers/skillRenderers.js +0 -138
  168. package/src/ui/screens/AliasScreen.js +0 -1008
  169. package/src/ui/screens/CliToolsScreen.js +0 -338
  170. package/src/ui/screens/EnvVarsScreen.js +0 -152
  171. package/src/ui/screens/GitignoreScreen.js +0 -328
  172. package/src/ui/screens/McpRegistryScreen.js +0 -238
  173. package/src/ui/screens/McpScreen.js +0 -176
  174. package/src/ui/screens/ModelSelectorScreen.js +0 -296
  175. package/src/ui/screens/ModelSelectorScreen.tsx +0 -444
  176. package/src/ui/screens/PluginsScreen.js +0 -766
  177. package/src/ui/screens/ProfilesScreen.js +0 -298
  178. package/src/ui/screens/SkillsScreen.js +0 -549
  179. package/src/ui/screens/StatusLineScreen.js +0 -206
  180. package/src/ui/screens/StatusLineScreen.tsx +0 -416
  181. package/src/ui/screens/index.js +0 -10
  182. package/src/ui/state/AnimationContext.js +0 -34
  183. package/src/ui/state/AppContext.js +0 -162
  184. package/src/ui/state/DimensionsContext.js +0 -71
  185. package/src/ui/state/reducer.js +0 -543
  186. package/src/ui/state/types.js +0 -1
  187. package/src/ui/theme.js +0 -47
  188. package/src/utils/clipboard.js +0 -56
  189. package/src/utils/command-utils.js +0 -19
  190. package/src/utils/fuzzy-search.js +0 -101
  191. package/src/utils/string-utils.js +0 -62
@@ -1,543 +0,0 @@
1
- export const initialState = {
2
- // Navigation - start on plugins screen
3
- currentRoute: { screen: "plugins" },
4
- // Project context
5
- projectPath: process.cwd(),
6
- // Global UI state
7
- modal: null,
8
- progress: null,
9
- isSearching: false,
10
- // Refresh counter for triggering data refetch
11
- dataRefreshVersion: 0,
12
- // Screen-specific state
13
- plugins: {
14
- scope: "project",
15
- collapsedMarketplaces: new Set(),
16
- selectedIndex: 0,
17
- searchQuery: "",
18
- marketplaces: { status: "idle" },
19
- plugins: { status: "idle" },
20
- },
21
- mcp: {
22
- selectedIndex: 0,
23
- servers: { status: "idle" },
24
- installedServers: {},
25
- },
26
- mcpRegistry: {
27
- searchQuery: "",
28
- selectedIndex: 0,
29
- servers: { status: "idle" },
30
- },
31
- statusline: {
32
- scope: "project",
33
- selectedIndex: 0,
34
- presets: { status: "idle" },
35
- currentPreset: null,
36
- },
37
- settings: {
38
- selectedIndex: 0,
39
- values: { status: "idle" },
40
- },
41
- cliTools: {
42
- selectedIndex: 0,
43
- tools: { status: "idle" },
44
- },
45
- modelSelector: {
46
- selectedIndex: 0,
47
- searchQuery: "",
48
- taskSize: "large",
49
- },
50
- profiles: {
51
- selectedIndex: 0,
52
- profiles: { status: "idle" },
53
- },
54
- skills: {
55
- scope: "user",
56
- selectedIndex: 0,
57
- searchQuery: "",
58
- skills: { status: "idle" },
59
- updateStatus: null,
60
- },
61
- };
62
- export function appReducer(state, action) {
63
- switch (action.type) {
64
- // =========================================================================
65
- // Navigation
66
- // =========================================================================
67
- case "NAVIGATE":
68
- return {
69
- ...state,
70
- currentRoute: action.route,
71
- // Clear search state when navigating away
72
- isSearching: false,
73
- };
74
- // =========================================================================
75
- // Plugins Screen
76
- // =========================================================================
77
- case "PLUGINS_SET_SCOPE":
78
- return {
79
- ...state,
80
- plugins: {
81
- ...state.plugins,
82
- scope: action.scope,
83
- selectedIndex: 0, // Reset selection when scope changes
84
- marketplaces: { status: "loading" },
85
- plugins: { status: "loading" },
86
- },
87
- };
88
- case "PLUGINS_TOGGLE_SCOPE":
89
- return appReducer(state, {
90
- type: "PLUGINS_SET_SCOPE",
91
- scope: state.plugins.scope === "project" ? "global" : "project",
92
- });
93
- case "PLUGINS_TOGGLE_MARKETPLACE": {
94
- const collapsed = new Set(state.plugins.collapsedMarketplaces);
95
- if (collapsed.has(action.name)) {
96
- collapsed.delete(action.name);
97
- }
98
- else {
99
- collapsed.add(action.name);
100
- }
101
- return {
102
- ...state,
103
- plugins: {
104
- ...state.plugins,
105
- collapsedMarketplaces: collapsed,
106
- },
107
- };
108
- }
109
- case "PLUGINS_SELECT":
110
- return {
111
- ...state,
112
- plugins: {
113
- ...state.plugins,
114
- selectedIndex: action.index,
115
- },
116
- };
117
- case "PLUGINS_SET_SEARCH":
118
- return {
119
- ...state,
120
- plugins: {
121
- ...state.plugins,
122
- searchQuery: action.query,
123
- selectedIndex: 0, // Reset selection when search changes
124
- },
125
- };
126
- case "PLUGINS_DATA_LOADING":
127
- return {
128
- ...state,
129
- plugins: {
130
- ...state.plugins,
131
- marketplaces: { status: "loading" },
132
- plugins: { status: "loading" },
133
- },
134
- };
135
- case "PLUGINS_DATA_SUCCESS":
136
- return {
137
- ...state,
138
- plugins: {
139
- ...state.plugins,
140
- marketplaces: { status: "success", data: action.marketplaces },
141
- plugins: { status: "success", data: action.plugins },
142
- },
143
- };
144
- case "PLUGINS_DATA_ERROR":
145
- return {
146
- ...state,
147
- plugins: {
148
- ...state.plugins,
149
- marketplaces: { status: "error", error: action.error },
150
- plugins: { status: "error", error: action.error },
151
- },
152
- };
153
- // =========================================================================
154
- // MCP Screen
155
- // =========================================================================
156
- case "MCP_SELECT":
157
- return {
158
- ...state,
159
- mcp: {
160
- ...state.mcp,
161
- selectedIndex: action.index,
162
- },
163
- };
164
- case "MCP_DATA_LOADING":
165
- return {
166
- ...state,
167
- mcp: {
168
- ...state.mcp,
169
- servers: { status: "loading" },
170
- },
171
- };
172
- case "MCP_DATA_SUCCESS":
173
- return {
174
- ...state,
175
- mcp: {
176
- ...state.mcp,
177
- servers: { status: "success", data: action.servers },
178
- installedServers: action.installedServers,
179
- },
180
- };
181
- case "MCP_DATA_ERROR":
182
- return {
183
- ...state,
184
- mcp: {
185
- ...state.mcp,
186
- servers: { status: "error", error: action.error },
187
- },
188
- };
189
- // =========================================================================
190
- // MCP Registry Screen
191
- // =========================================================================
192
- case "MCP_REGISTRY_SET_QUERY":
193
- case "MCPREGISTRY_SEARCH":
194
- return {
195
- ...state,
196
- mcpRegistry: {
197
- ...state.mcpRegistry,
198
- searchQuery: action.query,
199
- selectedIndex: 0,
200
- },
201
- };
202
- case "MCP_REGISTRY_SELECT":
203
- case "MCPREGISTRY_SELECT":
204
- return {
205
- ...state,
206
- mcpRegistry: {
207
- ...state.mcpRegistry,
208
- selectedIndex: action.index,
209
- },
210
- };
211
- case "MCP_REGISTRY_DATA_LOADING":
212
- return {
213
- ...state,
214
- mcpRegistry: {
215
- ...state.mcpRegistry,
216
- servers: { status: "loading" },
217
- },
218
- };
219
- case "MCP_REGISTRY_DATA_SUCCESS":
220
- return {
221
- ...state,
222
- mcpRegistry: {
223
- ...state.mcpRegistry,
224
- servers: { status: "success", data: action.servers },
225
- },
226
- };
227
- case "MCP_REGISTRY_DATA_ERROR":
228
- return {
229
- ...state,
230
- mcpRegistry: {
231
- ...state.mcpRegistry,
232
- servers: { status: "error", error: action.error },
233
- },
234
- };
235
- // =========================================================================
236
- // Status Line Screen
237
- // =========================================================================
238
- case "STATUSLINE_SET_SCOPE":
239
- return {
240
- ...state,
241
- statusline: {
242
- ...state.statusline,
243
- scope: action.scope,
244
- selectedIndex: 0,
245
- presets: { status: "loading" },
246
- },
247
- };
248
- case "STATUSLINE_TOGGLE_SCOPE":
249
- return appReducer(state, {
250
- type: "STATUSLINE_SET_SCOPE",
251
- scope: state.statusline.scope === "project" ? "global" : "project",
252
- });
253
- case "STATUSLINE_SELECT":
254
- return {
255
- ...state,
256
- statusline: {
257
- ...state.statusline,
258
- selectedIndex: action.index,
259
- },
260
- };
261
- case "STATUSLINE_DATA_LOADING":
262
- return {
263
- ...state,
264
- statusline: {
265
- ...state.statusline,
266
- presets: { status: "loading" },
267
- },
268
- };
269
- case "STATUSLINE_DATA_SUCCESS":
270
- return {
271
- ...state,
272
- statusline: {
273
- ...state.statusline,
274
- presets: { status: "success", data: action.presets },
275
- currentPreset: action.currentPreset,
276
- },
277
- };
278
- case "STATUSLINE_DATA_ERROR":
279
- return {
280
- ...state,
281
- statusline: {
282
- ...state.statusline,
283
- presets: { status: "error", error: action.error },
284
- },
285
- };
286
- // =========================================================================
287
- // Settings Screen
288
- // =========================================================================
289
- case "SETTINGS_SELECT":
290
- return {
291
- ...state,
292
- settings: {
293
- ...state.settings,
294
- selectedIndex: action.index,
295
- },
296
- };
297
- case "SETTINGS_DATA_LOADING":
298
- return {
299
- ...state,
300
- settings: {
301
- ...state.settings,
302
- values: { status: "loading" },
303
- },
304
- };
305
- case "SETTINGS_DATA_SUCCESS":
306
- return {
307
- ...state,
308
- settings: {
309
- ...state.settings,
310
- values: { status: "success", data: action.values },
311
- },
312
- };
313
- case "SETTINGS_DATA_ERROR":
314
- return {
315
- ...state,
316
- settings: {
317
- ...state.settings,
318
- values: { status: "error", error: action.error },
319
- },
320
- };
321
- // =========================================================================
322
- // CLI Tools Screen
323
- // =========================================================================
324
- case "CLITOOLS_SELECT":
325
- return {
326
- ...state,
327
- cliTools: {
328
- ...state.cliTools,
329
- selectedIndex: action.index,
330
- },
331
- };
332
- case "CLITOOLS_DATA_LOADING":
333
- return {
334
- ...state,
335
- cliTools: {
336
- ...state.cliTools,
337
- tools: { status: "loading" },
338
- },
339
- };
340
- case "CLITOOLS_DATA_SUCCESS":
341
- return {
342
- ...state,
343
- cliTools: {
344
- ...state.cliTools,
345
- tools: { status: "success", data: action.tools },
346
- },
347
- };
348
- case "CLITOOLS_DATA_ERROR":
349
- return {
350
- ...state,
351
- cliTools: {
352
- ...state.cliTools,
353
- tools: { status: "error", error: action.error },
354
- },
355
- };
356
- case "CLITOOLS_UPDATE_TOOL": {
357
- if (state.cliTools.tools.status !== "success")
358
- return state;
359
- return {
360
- ...state,
361
- cliTools: {
362
- ...state.cliTools,
363
- tools: {
364
- status: "success",
365
- data: state.cliTools.tools.data.map((tool) => tool.name === action.name ? { ...tool, ...action.updates } : tool),
366
- },
367
- },
368
- };
369
- }
370
- // =========================================================================
371
- // Model Selector Screen
372
- // =========================================================================
373
- case "MODEL_SELECTOR_SELECT":
374
- return {
375
- ...state,
376
- modelSelector: {
377
- ...state.modelSelector,
378
- selectedIndex: action.index,
379
- },
380
- };
381
- case "MODEL_SELECTOR_SET_SEARCH":
382
- return {
383
- ...state,
384
- modelSelector: {
385
- ...state.modelSelector,
386
- searchQuery: action.query,
387
- selectedIndex: 0, // Reset selection when search changes
388
- },
389
- };
390
- case "MODEL_SELECTOR_SET_TASK_SIZE":
391
- return {
392
- ...state,
393
- modelSelector: {
394
- ...state.modelSelector,
395
- taskSize: action.size,
396
- },
397
- };
398
- // =========================================================================
399
- // Profiles Screen
400
- // =========================================================================
401
- case "PROFILES_SELECT":
402
- return {
403
- ...state,
404
- profiles: {
405
- ...state.profiles,
406
- selectedIndex: action.index,
407
- },
408
- };
409
- case "PROFILES_DATA_LOADING":
410
- return {
411
- ...state,
412
- profiles: {
413
- ...state.profiles,
414
- profiles: { status: "loading" },
415
- },
416
- };
417
- case "PROFILES_DATA_SUCCESS":
418
- return {
419
- ...state,
420
- profiles: {
421
- ...state.profiles,
422
- profiles: { status: "success", data: action.profiles },
423
- },
424
- };
425
- case "PROFILES_DATA_ERROR":
426
- return {
427
- ...state,
428
- profiles: {
429
- ...state.profiles,
430
- profiles: { status: "error", error: action.error },
431
- },
432
- };
433
- // =========================================================================
434
- // Skills Screen
435
- // =========================================================================
436
- case "SKILLS_SET_SCOPE":
437
- return {
438
- ...state,
439
- skills: {
440
- ...state.skills,
441
- scope: action.scope,
442
- selectedIndex: 0,
443
- skills: { status: "loading" },
444
- },
445
- };
446
- case "SKILLS_TOGGLE_SCOPE":
447
- return appReducer(state, {
448
- type: "SKILLS_SET_SCOPE",
449
- scope: state.skills.scope === "user" ? "project" : "user",
450
- });
451
- case "SKILLS_SELECT":
452
- return {
453
- ...state,
454
- skills: {
455
- ...state.skills,
456
- selectedIndex: action.index,
457
- },
458
- };
459
- case "SKILLS_SET_SEARCH":
460
- return {
461
- ...state,
462
- skills: {
463
- ...state.skills,
464
- searchQuery: action.query,
465
- selectedIndex: 0,
466
- },
467
- };
468
- case "SKILLS_DATA_LOADING":
469
- return {
470
- ...state,
471
- skills: {
472
- ...state.skills,
473
- skills: { status: "loading" },
474
- },
475
- };
476
- case "SKILLS_DATA_SUCCESS":
477
- return {
478
- ...state,
479
- skills: {
480
- ...state.skills,
481
- skills: { status: "success", data: action.skills },
482
- },
483
- };
484
- case "SKILLS_DATA_ERROR":
485
- return {
486
- ...state,
487
- skills: {
488
- ...state.skills,
489
- skills: { status: "error", error: action.error },
490
- },
491
- };
492
- case "SKILLS_UPDATE_STATUS":
493
- return {
494
- ...state,
495
- skills: {
496
- ...state.skills,
497
- updateStatus: action.updates,
498
- },
499
- };
500
- case "SKILLS_UPDATE_ITEM": {
501
- if (state.skills.skills.status !== "success")
502
- return state;
503
- return {
504
- ...state,
505
- skills: {
506
- ...state.skills,
507
- skills: {
508
- status: "success",
509
- data: state.skills.skills.data.map((s) => s.name === action.name ? { ...s, ...action.updates } : s),
510
- },
511
- },
512
- };
513
- }
514
- // =========================================================================
515
- // Modals
516
- // =========================================================================
517
- case "SHOW_MODAL":
518
- return { ...state, modal: action.modal, isSearching: true };
519
- case "HIDE_MODAL":
520
- return { ...state, modal: null, isSearching: false };
521
- // =========================================================================
522
- // Progress
523
- // =========================================================================
524
- case "SHOW_PROGRESS":
525
- return { ...state, progress: action.state };
526
- case "UPDATE_PROGRESS":
527
- return { ...state, progress: action.state };
528
- case "HIDE_PROGRESS":
529
- return { ...state, progress: null };
530
- // =========================================================================
531
- // Search State
532
- // =========================================================================
533
- case "SET_SEARCHING":
534
- return { ...state, isSearching: action.isSearching };
535
- // =========================================================================
536
- // Data Refresh
537
- // =========================================================================
538
- case "DATA_REFRESH_COMPLETE":
539
- return { ...state, dataRefreshVersion: state.dataRefreshVersion + 1 };
540
- default:
541
- return state;
542
- }
543
- }
@@ -1 +0,0 @@
1
- export {};
package/src/ui/theme.js DELETED
@@ -1,47 +0,0 @@
1
- export const theme = {
2
- colors: {
3
- text: "white",
4
- muted: "#666666",
5
- dim: "#333333",
6
- border: "#444444",
7
- link: "#5c9aff",
8
- accent: "#7e57c2",
9
- success: "green",
10
- warning: "yellow",
11
- danger: "red",
12
- info: "cyan",
13
- },
14
- selection: {
15
- bg: "magenta",
16
- fg: "white",
17
- },
18
- scopes: {
19
- user: "cyan",
20
- project: "green",
21
- local: "yellow",
22
- },
23
- category: {
24
- purple: { bg: "#7e57c2", fg: "white", badgeFg: "#d1c4e9" },
25
- green: { bg: "#2e7d32", fg: "white", badgeFg: "#c8e6c9" },
26
- teal: { bg: "#00695c", fg: "white", badgeFg: "#b2dfdb" },
27
- yellow: { bg: "#8d6e00", fg: "white", badgeFg: "#ffe082" },
28
- gray: { bg: "#455a64", fg: "white", badgeFg: "#cfd8dc" },
29
- red: { bg: "#b71c1c", fg: "white", badgeFg: "#ffcdd2" },
30
- },
31
- meta: {
32
- muted: "gray",
33
- warning: "yellow",
34
- success: "green",
35
- danger: "red",
36
- },
37
- hints: {
38
- defaultBg: "white",
39
- primaryBg: "cyan",
40
- dangerBg: "red",
41
- },
42
- spacing: {
43
- rowIndent: 1,
44
- sectionGap: 1,
45
- panelPadding: 1,
46
- },
47
- };
@@ -1,56 +0,0 @@
1
- import { execSync } from "node:child_process";
2
- /**
3
- * Write text to the system clipboard.
4
- * macOS: uses pbcopy
5
- * Linux: uses xclip
6
- * Throws ClipboardUnavailableError if no clipboard tool is available.
7
- */
8
- export async function writeClipboard(text) {
9
- if (process.platform === "darwin") {
10
- execSync("pbcopy", { input: text });
11
- }
12
- else if (process.platform === "linux") {
13
- execSync("xclip -selection clipboard", { input: text });
14
- }
15
- else {
16
- throw new ClipboardUnavailableError(`Clipboard not supported on platform: ${process.platform}`);
17
- }
18
- }
19
- /**
20
- * Read text from the system clipboard.
21
- * macOS: uses pbpaste
22
- * Linux: uses xclip
23
- * Throws ClipboardUnavailableError if no clipboard tool is available.
24
- */
25
- export async function readClipboard() {
26
- if (process.platform === "darwin") {
27
- return execSync("pbpaste").toString();
28
- }
29
- else if (process.platform === "linux") {
30
- return execSync("xclip -selection clipboard -o").toString();
31
- }
32
- else {
33
- throw new ClipboardUnavailableError(`Clipboard not supported on platform: ${process.platform}`);
34
- }
35
- }
36
- export class ClipboardUnavailableError extends Error {
37
- constructor(message) {
38
- super(message);
39
- this.name = "ClipboardUnavailableError";
40
- }
41
- }
42
- /** Check if clipboard operations are available on this platform/system */
43
- export function isClipboardAvailable() {
44
- if (process.platform === "darwin")
45
- return true;
46
- if (process.platform === "linux") {
47
- try {
48
- execSync("which xclip", { stdio: "ignore" });
49
- return true;
50
- }
51
- catch {
52
- return false;
53
- }
54
- }
55
- return false;
56
- }
@@ -1,19 +0,0 @@
1
- import { execFile } from "node:child_process";
2
- import { promisify } from "node:util";
3
- const execFileAsync = promisify(execFile);
4
- /**
5
- * Check if a command exists in PATH
6
- * Uses execFile (not exec) to avoid shell injection vulnerabilities
7
- * @param command - Command name to check
8
- * @returns Path to command if found, null otherwise
9
- */
10
- export async function which(command) {
11
- try {
12
- // Use execFile with argument array to prevent command injection
13
- const { stdout } = await execFileAsync("which", [command]);
14
- return stdout.trim() || null;
15
- }
16
- catch {
17
- return null;
18
- }
19
- }