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