claudeup 1.8.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.
- package/bin/claudeup.js +20 -2
- package/package.json +10 -19
- package/src/data/cli-tools.js +123 -0
- package/src/data/cli-tools.ts +140 -0
- package/{dist → src}/data/marketplaces.js +23 -24
- package/src/data/marketplaces.ts +95 -0
- package/src/data/mcp-servers.js +509 -0
- package/src/data/mcp-servers.ts +526 -0
- package/src/data/statuslines.js +159 -0
- package/src/data/statuslines.ts +188 -0
- package/src/index.js +4 -0
- package/src/index.ts +5 -0
- package/{dist → src}/main.js +46 -47
- package/src/main.tsx +145 -0
- package/src/opentui.d.ts +191 -0
- package/{dist → src}/prerunner/index.js +31 -41
- package/src/prerunner/index.ts +124 -0
- package/{dist → src}/services/claude-runner.js +9 -10
- package/src/services/claude-runner.ts +31 -0
- package/{dist → src}/services/claude-settings.js +72 -33
- package/src/services/claude-settings.ts +934 -0
- package/src/services/local-marketplace.js +339 -0
- package/src/services/local-marketplace.ts +489 -0
- package/{dist → src}/services/mcp-registry.js +13 -14
- package/src/services/mcp-registry.ts +105 -0
- package/{dist → src}/services/plugin-manager.js +61 -13
- package/src/services/plugin-manager.ts +693 -0
- package/{dist → src}/services/plugin-mcp-config.js +19 -18
- package/src/services/plugin-mcp-config.ts +242 -0
- package/{dist → src}/services/update-cache.js +0 -1
- package/src/services/update-cache.ts +78 -0
- package/{dist → src}/services/version-check.js +15 -14
- package/src/services/version-check.ts +122 -0
- package/src/types/index.js +1 -0
- package/src/types/index.ts +141 -0
- package/src/ui/App.js +213 -0
- package/src/ui/App.tsx +359 -0
- package/src/ui/components/CategoryHeader.js +9 -0
- package/src/ui/components/CategoryHeader.tsx +41 -0
- package/{dist → src}/ui/components/ScrollableList.js +19 -6
- package/src/ui/components/ScrollableList.tsx +98 -0
- package/src/ui/components/SearchInput.js +19 -0
- package/src/ui/components/SearchInput.tsx +56 -0
- package/src/ui/components/StyledText.js +39 -0
- package/src/ui/components/StyledText.tsx +70 -0
- package/src/ui/components/TabBar.js +38 -0
- package/src/ui/components/TabBar.tsx +88 -0
- package/src/ui/components/layout/Panel.js +6 -0
- package/src/ui/components/layout/Panel.tsx +62 -0
- package/src/ui/components/layout/ProgressBar.js +14 -0
- package/src/ui/components/layout/ProgressBar.tsx +47 -0
- package/src/ui/components/layout/ScopeTabs.js +6 -0
- package/src/ui/components/layout/ScopeTabs.tsx +53 -0
- package/src/ui/components/layout/ScreenLayout.js +21 -0
- package/src/ui/components/layout/ScreenLayout.tsx +147 -0
- package/src/ui/components/layout/index.js +4 -0
- package/src/ui/components/layout/index.ts +4 -0
- package/src/ui/components/modals/ConfirmModal.js +14 -0
- package/src/ui/components/modals/ConfirmModal.tsx +59 -0
- package/src/ui/components/modals/InputModal.js +16 -0
- package/src/ui/components/modals/InputModal.tsx +68 -0
- package/src/ui/components/modals/LoadingModal.js +14 -0
- package/src/ui/components/modals/LoadingModal.tsx +40 -0
- package/src/ui/components/modals/MessageModal.js +16 -0
- package/src/ui/components/modals/MessageModal.tsx +64 -0
- package/src/ui/components/modals/ModalContainer.js +56 -0
- package/src/ui/components/modals/ModalContainer.tsx +104 -0
- package/src/ui/components/modals/SelectModal.js +26 -0
- package/src/ui/components/modals/SelectModal.tsx +82 -0
- package/src/ui/components/modals/index.js +6 -0
- package/src/ui/components/modals/index.ts +6 -0
- package/src/ui/hooks/index.js +3 -0
- package/src/ui/hooks/index.ts +3 -0
- package/{dist → src}/ui/hooks/useAsyncData.js +21 -22
- package/src/ui/hooks/useAsyncData.ts +127 -0
- package/src/ui/hooks/useKeyboard.js +13 -0
- package/src/ui/hooks/useKeyboard.ts +26 -0
- package/src/ui/hooks/useKeyboardHandler.js +39 -0
- package/src/ui/hooks/useKeyboardHandler.ts +63 -0
- package/{dist → src}/ui/screens/CliToolsScreen.js +60 -54
- package/src/ui/screens/CliToolsScreen.tsx +468 -0
- package/src/ui/screens/EnvVarsScreen.js +154 -0
- package/src/ui/screens/EnvVarsScreen.tsx +269 -0
- package/{dist → src}/ui/screens/McpRegistryScreen.js +56 -55
- package/src/ui/screens/McpRegistryScreen.tsx +331 -0
- package/{dist → src}/ui/screens/McpScreen.js +46 -47
- package/src/ui/screens/McpScreen.tsx +392 -0
- package/src/ui/screens/ModelSelectorScreen.js +292 -0
- package/src/ui/screens/ModelSelectorScreen.tsx +441 -0
- package/{dist → src}/ui/screens/PluginsScreen.js +305 -293
- package/src/ui/screens/PluginsScreen.tsx +1231 -0
- package/src/ui/screens/StatusLineScreen.js +200 -0
- package/src/ui/screens/StatusLineScreen.tsx +411 -0
- package/src/ui/screens/index.js +7 -0
- package/src/ui/screens/index.ts +7 -0
- package/src/ui/state/AnimationContext.js +34 -0
- package/src/ui/state/AnimationContext.tsx +76 -0
- package/{dist → src}/ui/state/AppContext.js +31 -32
- package/src/ui/state/AppContext.tsx +235 -0
- package/{dist → src}/ui/state/DimensionsContext.js +16 -17
- package/src/ui/state/DimensionsContext.tsx +144 -0
- package/{dist → src}/ui/state/reducer.js +89 -90
- package/src/ui/state/reducer.ts +467 -0
- package/src/ui/state/types.js +1 -0
- package/src/ui/state/types.ts +273 -0
- package/{dist → src}/utils/command-utils.js +3 -4
- package/src/utils/command-utils.ts +20 -0
- package/{dist → src}/utils/fuzzy-search.js +2 -3
- package/src/utils/fuzzy-search.ts +138 -0
- package/{dist → src}/utils/string-utils.js +6 -6
- package/src/utils/string-utils.ts +88 -0
- package/dist/data/cli-tools.d.ts +0 -13
- package/dist/data/cli-tools.d.ts.map +0 -1
- package/dist/data/cli-tools.js +0 -124
- package/dist/data/cli-tools.js.map +0 -1
- package/dist/data/marketplaces.d.ts +0 -6
- package/dist/data/marketplaces.d.ts.map +0 -1
- package/dist/data/marketplaces.js.map +0 -1
- package/dist/data/mcp-servers.d.ts +0 -8
- package/dist/data/mcp-servers.d.ts.map +0 -1
- package/dist/data/mcp-servers.js +0 -503
- package/dist/data/mcp-servers.js.map +0 -1
- package/dist/data/statuslines.d.ts +0 -10
- package/dist/data/statuslines.d.ts.map +0 -1
- package/dist/data/statuslines.js +0 -160
- package/dist/data/statuslines.js.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -90
- package/dist/index.js.map +0 -1
- package/dist/main.d.ts +0 -3
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/prerunner/index.d.ts +0 -7
- package/dist/prerunner/index.d.ts.map +0 -1
- package/dist/prerunner/index.js.map +0 -1
- package/dist/services/claude-runner.d.ts +0 -7
- package/dist/services/claude-runner.d.ts.map +0 -1
- package/dist/services/claude-runner.js.map +0 -1
- package/dist/services/claude-settings.d.ts +0 -73
- package/dist/services/claude-settings.d.ts.map +0 -1
- package/dist/services/claude-settings.js.map +0 -1
- package/dist/services/local-marketplace.d.ts +0 -111
- package/dist/services/local-marketplace.d.ts.map +0 -1
- package/dist/services/local-marketplace.js +0 -599
- package/dist/services/local-marketplace.js.map +0 -1
- package/dist/services/mcp-registry.d.ts +0 -10
- package/dist/services/mcp-registry.d.ts.map +0 -1
- package/dist/services/mcp-registry.js.map +0 -1
- package/dist/services/plugin-manager.d.ts +0 -65
- package/dist/services/plugin-manager.d.ts.map +0 -1
- package/dist/services/plugin-manager.js.map +0 -1
- package/dist/services/plugin-mcp-config.d.ts +0 -52
- package/dist/services/plugin-mcp-config.d.ts.map +0 -1
- package/dist/services/plugin-mcp-config.js.map +0 -1
- package/dist/services/update-cache.d.ts +0 -21
- package/dist/services/update-cache.d.ts.map +0 -1
- package/dist/services/update-cache.js.map +0 -1
- package/dist/services/version-check.d.ts +0 -20
- package/dist/services/version-check.d.ts.map +0 -1
- package/dist/services/version-check.js.map +0 -1
- package/dist/types/index.d.ts +0 -105
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -2
- package/dist/types/index.js.map +0 -1
- package/dist/ui/InkApp.d.ts +0 -5
- package/dist/ui/InkApp.d.ts.map +0 -1
- package/dist/ui/InkApp.js +0 -188
- package/dist/ui/InkApp.js.map +0 -1
- package/dist/ui/components/CategoryHeader.d.ts +0 -16
- package/dist/ui/components/CategoryHeader.d.ts.map +0 -1
- package/dist/ui/components/CategoryHeader.js +0 -11
- package/dist/ui/components/CategoryHeader.js.map +0 -1
- package/dist/ui/components/ScrollableList.d.ts +0 -16
- package/dist/ui/components/ScrollableList.d.ts.map +0 -1
- package/dist/ui/components/ScrollableList.js.map +0 -1
- package/dist/ui/components/SearchInput.d.ts +0 -18
- package/dist/ui/components/SearchInput.d.ts.map +0 -1
- package/dist/ui/components/SearchInput.js +0 -30
- package/dist/ui/components/SearchInput.js.map +0 -1
- package/dist/ui/components/TabBar.d.ts +0 -8
- package/dist/ui/components/TabBar.d.ts.map +0 -1
- package/dist/ui/components/TabBar.js +0 -18
- package/dist/ui/components/TabBar.js.map +0 -1
- package/dist/ui/components/layout/Footer.d.ts +0 -14
- package/dist/ui/components/layout/Footer.d.ts.map +0 -1
- package/dist/ui/components/layout/Footer.js +0 -23
- package/dist/ui/components/layout/Footer.js.map +0 -1
- package/dist/ui/components/layout/Header.d.ts +0 -4
- package/dist/ui/components/layout/Header.d.ts.map +0 -1
- package/dist/ui/components/layout/Header.js +0 -25
- package/dist/ui/components/layout/Header.js.map +0 -1
- package/dist/ui/components/layout/Panel.d.ts +0 -22
- package/dist/ui/components/layout/Panel.d.ts.map +0 -1
- package/dist/ui/components/layout/Panel.js +0 -8
- package/dist/ui/components/layout/Panel.js.map +0 -1
- package/dist/ui/components/layout/ProgressBar.d.ts +0 -12
- package/dist/ui/components/layout/ProgressBar.d.ts.map +0 -1
- package/dist/ui/components/layout/ProgressBar.js +0 -16
- package/dist/ui/components/layout/ProgressBar.js.map +0 -1
- package/dist/ui/components/layout/ScopeTabs.d.ts +0 -12
- package/dist/ui/components/layout/ScopeTabs.d.ts.map +0 -1
- package/dist/ui/components/layout/ScopeTabs.js +0 -8
- package/dist/ui/components/layout/ScopeTabs.js.map +0 -1
- package/dist/ui/components/layout/ScreenLayout.d.ts +0 -30
- package/dist/ui/components/layout/ScreenLayout.d.ts.map +0 -1
- package/dist/ui/components/layout/ScreenLayout.js +0 -23
- package/dist/ui/components/layout/ScreenLayout.js.map +0 -1
- package/dist/ui/components/layout/index.d.ts +0 -7
- package/dist/ui/components/layout/index.d.ts.map +0 -1
- package/dist/ui/components/layout/index.js +0 -7
- package/dist/ui/components/layout/index.js.map +0 -1
- package/dist/ui/components/modals/ConfirmModal.d.ts +0 -14
- package/dist/ui/components/modals/ConfirmModal.d.ts.map +0 -1
- package/dist/ui/components/modals/ConfirmModal.js +0 -15
- package/dist/ui/components/modals/ConfirmModal.js.map +0 -1
- package/dist/ui/components/modals/InputModal.d.ts +0 -16
- package/dist/ui/components/modals/InputModal.d.ts.map +0 -1
- package/dist/ui/components/modals/InputModal.js +0 -23
- package/dist/ui/components/modals/InputModal.js.map +0 -1
- package/dist/ui/components/modals/LoadingModal.d.ts +0 -8
- package/dist/ui/components/modals/LoadingModal.d.ts.map +0 -1
- package/dist/ui/components/modals/LoadingModal.js +0 -8
- package/dist/ui/components/modals/LoadingModal.js.map +0 -1
- package/dist/ui/components/modals/MessageModal.d.ts +0 -14
- package/dist/ui/components/modals/MessageModal.d.ts.map +0 -1
- package/dist/ui/components/modals/MessageModal.js +0 -17
- package/dist/ui/components/modals/MessageModal.js.map +0 -1
- package/dist/ui/components/modals/ModalContainer.d.ts +0 -7
- package/dist/ui/components/modals/ModalContainer.d.ts.map +0 -1
- package/dist/ui/components/modals/ModalContainer.js +0 -38
- package/dist/ui/components/modals/ModalContainer.js.map +0 -1
- package/dist/ui/components/modals/SelectModal.d.ts +0 -17
- package/dist/ui/components/modals/SelectModal.d.ts.map +0 -1
- package/dist/ui/components/modals/SelectModal.js +0 -33
- package/dist/ui/components/modals/SelectModal.js.map +0 -1
- package/dist/ui/components/modals/index.d.ts +0 -7
- package/dist/ui/components/modals/index.d.ts.map +0 -1
- package/dist/ui/components/modals/index.js +0 -7
- package/dist/ui/components/modals/index.js.map +0 -1
- package/dist/ui/hooks/index.d.ts +0 -3
- package/dist/ui/hooks/index.d.ts.map +0 -1
- package/dist/ui/hooks/index.js +0 -3
- package/dist/ui/hooks/index.js.map +0 -1
- package/dist/ui/hooks/useAsyncData.d.ts +0 -40
- package/dist/ui/hooks/useAsyncData.d.ts.map +0 -1
- package/dist/ui/hooks/useAsyncData.js.map +0 -1
- package/dist/ui/hooks/useKeyboardNavigation.d.ts +0 -27
- package/dist/ui/hooks/useKeyboardNavigation.d.ts.map +0 -1
- package/dist/ui/hooks/useKeyboardNavigation.js +0 -82
- package/dist/ui/hooks/useKeyboardNavigation.js.map +0 -1
- package/dist/ui/screens/CliToolsScreen.d.ts +0 -4
- package/dist/ui/screens/CliToolsScreen.d.ts.map +0 -1
- package/dist/ui/screens/CliToolsScreen.js.map +0 -1
- package/dist/ui/screens/EnvVarsScreen.d.ts +0 -4
- package/dist/ui/screens/EnvVarsScreen.d.ts.map +0 -1
- package/dist/ui/screens/EnvVarsScreen.js +0 -145
- package/dist/ui/screens/EnvVarsScreen.js.map +0 -1
- package/dist/ui/screens/McpRegistryScreen.d.ts +0 -4
- package/dist/ui/screens/McpRegistryScreen.d.ts.map +0 -1
- package/dist/ui/screens/McpRegistryScreen.js.map +0 -1
- package/dist/ui/screens/McpScreen.d.ts +0 -4
- package/dist/ui/screens/McpScreen.d.ts.map +0 -1
- package/dist/ui/screens/McpScreen.js.map +0 -1
- package/dist/ui/screens/ModelSelectorScreen.d.ts +0 -4
- package/dist/ui/screens/ModelSelectorScreen.d.ts.map +0 -1
- package/dist/ui/screens/ModelSelectorScreen.js +0 -143
- package/dist/ui/screens/ModelSelectorScreen.js.map +0 -1
- package/dist/ui/screens/PluginsScreen.d.ts +0 -4
- package/dist/ui/screens/PluginsScreen.d.ts.map +0 -1
- package/dist/ui/screens/PluginsScreen.js.map +0 -1
- package/dist/ui/screens/StatusLineScreen.d.ts +0 -4
- package/dist/ui/screens/StatusLineScreen.d.ts.map +0 -1
- package/dist/ui/screens/StatusLineScreen.js +0 -197
- package/dist/ui/screens/StatusLineScreen.js.map +0 -1
- package/dist/ui/screens/index.d.ts +0 -8
- package/dist/ui/screens/index.d.ts.map +0 -1
- package/dist/ui/screens/index.js +0 -8
- package/dist/ui/screens/index.js.map +0 -1
- package/dist/ui/state/AppContext.d.ts +0 -40
- package/dist/ui/state/AppContext.d.ts.map +0 -1
- package/dist/ui/state/AppContext.js.map +0 -1
- package/dist/ui/state/DimensionsContext.d.ts +0 -27
- package/dist/ui/state/DimensionsContext.d.ts.map +0 -1
- package/dist/ui/state/DimensionsContext.js.map +0 -1
- package/dist/ui/state/reducer.d.ts +0 -4
- package/dist/ui/state/reducer.d.ts.map +0 -1
- package/dist/ui/state/reducer.js.map +0 -1
- package/dist/ui/state/types.d.ts +0 -266
- package/dist/ui/state/types.d.ts.map +0 -1
- package/dist/ui/state/types.js +0 -2
- package/dist/ui/state/types.js.map +0 -1
- package/dist/utils/command-utils.d.ts +0 -8
- package/dist/utils/command-utils.d.ts.map +0 -1
- package/dist/utils/command-utils.js.map +0 -1
- package/dist/utils/fuzzy-search.d.ts +0 -33
- package/dist/utils/fuzzy-search.d.ts.map +0 -1
- package/dist/utils/fuzzy-search.js.map +0 -1
- package/dist/utils/string-utils.d.ts +0 -24
- package/dist/utils/string-utils.d.ts.map +0 -1
- package/dist/utils/string-utils.js.map +0 -1
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import React, { useEffect, useCallback, useState } from "react";
|
|
2
|
+
import { useApp, useModal } from "../state/AppContext.js";
|
|
3
|
+
import { useDimensions } from "../state/DimensionsContext.js";
|
|
4
|
+
import { useKeyboard } from "../hooks/useKeyboard.js";
|
|
5
|
+
import { ScreenLayout } from "../components/layout/index.js";
|
|
6
|
+
import { ScrollableList } from "../components/ScrollableList.js";
|
|
7
|
+
import {
|
|
8
|
+
getMcpEnvVars,
|
|
9
|
+
setMcpEnvVar,
|
|
10
|
+
removeMcpEnvVar,
|
|
11
|
+
} from "../../services/claude-settings.js";
|
|
12
|
+
|
|
13
|
+
interface EnvVar {
|
|
14
|
+
name: string;
|
|
15
|
+
value: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function EnvVarsScreen() {
|
|
19
|
+
const { state, dispatch } = useApp();
|
|
20
|
+
const { envVars } = state;
|
|
21
|
+
const modal = useModal();
|
|
22
|
+
const dimensions = useDimensions();
|
|
23
|
+
|
|
24
|
+
const [envVarList, setEnvVarList] = useState<EnvVar[]>([]);
|
|
25
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
26
|
+
|
|
27
|
+
// Fetch data
|
|
28
|
+
const fetchData = useCallback(async () => {
|
|
29
|
+
setIsLoading(true);
|
|
30
|
+
try {
|
|
31
|
+
const vars = await getMcpEnvVars(state.projectPath);
|
|
32
|
+
const list = Object.entries(vars).map(([name, value]) => ({
|
|
33
|
+
name,
|
|
34
|
+
value,
|
|
35
|
+
}));
|
|
36
|
+
setEnvVarList(list);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
setEnvVarList([]);
|
|
39
|
+
}
|
|
40
|
+
setIsLoading(false);
|
|
41
|
+
}, [state.projectPath]);
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
fetchData();
|
|
45
|
+
}, [fetchData]);
|
|
46
|
+
|
|
47
|
+
// Keyboard handling
|
|
48
|
+
useKeyboard((event) => {
|
|
49
|
+
if (state.isSearching || state.modal) return;
|
|
50
|
+
|
|
51
|
+
if (event.name === "up" || event.name === "k") {
|
|
52
|
+
const newIndex = Math.max(0, envVars.selectedIndex - 1);
|
|
53
|
+
dispatch({ type: "ENVVARS_SELECT", index: newIndex });
|
|
54
|
+
} else if (event.name === "down" || event.name === "j") {
|
|
55
|
+
const newIndex = Math.min(
|
|
56
|
+
Math.max(0, envVarList.length - 1),
|
|
57
|
+
envVars.selectedIndex + 1,
|
|
58
|
+
);
|
|
59
|
+
dispatch({ type: "ENVVARS_SELECT", index: newIndex });
|
|
60
|
+
} else if (event.name === "a") {
|
|
61
|
+
handleAdd();
|
|
62
|
+
} else if (event.name === "e" || event.name === "enter") {
|
|
63
|
+
handleEdit();
|
|
64
|
+
} else if (event.name === "d") {
|
|
65
|
+
handleDelete();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const handleAdd = async () => {
|
|
70
|
+
const varName = await modal.input("Add Variable", "Variable name:");
|
|
71
|
+
if (varName === null || !varName.trim()) return;
|
|
72
|
+
|
|
73
|
+
const cleanName = varName
|
|
74
|
+
.trim()
|
|
75
|
+
.toUpperCase()
|
|
76
|
+
.replace(/[^A-Z0-9_]/g, "_");
|
|
77
|
+
|
|
78
|
+
// Check if already exists
|
|
79
|
+
const existing = envVarList.find((v) => v.name === cleanName);
|
|
80
|
+
if (existing) {
|
|
81
|
+
const overwrite = await modal.confirm(
|
|
82
|
+
`${cleanName} exists`,
|
|
83
|
+
"Overwrite existing value?",
|
|
84
|
+
);
|
|
85
|
+
if (!overwrite) return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const value = await modal.input(`Set ${cleanName}`, "Value:");
|
|
89
|
+
if (value === null) return;
|
|
90
|
+
|
|
91
|
+
modal.loading(`Adding ${cleanName}...`);
|
|
92
|
+
try {
|
|
93
|
+
await setMcpEnvVar(cleanName, value, state.projectPath);
|
|
94
|
+
modal.hideModal();
|
|
95
|
+
await modal.message(
|
|
96
|
+
"Added",
|
|
97
|
+
`${cleanName} added.\nRestart Claude Code to apply.`,
|
|
98
|
+
"success",
|
|
99
|
+
);
|
|
100
|
+
fetchData();
|
|
101
|
+
} catch (error) {
|
|
102
|
+
modal.hideModal();
|
|
103
|
+
await modal.message("Error", `Failed to add: ${error}`, "error");
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const handleEdit = async () => {
|
|
108
|
+
if (envVarList.length === 0) return;
|
|
109
|
+
const envVar = envVarList[envVars.selectedIndex];
|
|
110
|
+
if (!envVar) return;
|
|
111
|
+
|
|
112
|
+
const newValue = await modal.input(
|
|
113
|
+
`Edit ${envVar.name}`,
|
|
114
|
+
"New value:",
|
|
115
|
+
envVar.value,
|
|
116
|
+
);
|
|
117
|
+
if (newValue === null) return;
|
|
118
|
+
|
|
119
|
+
modal.loading(`Updating ${envVar.name}...`);
|
|
120
|
+
try {
|
|
121
|
+
await setMcpEnvVar(envVar.name, newValue, state.projectPath);
|
|
122
|
+
modal.hideModal();
|
|
123
|
+
await modal.message(
|
|
124
|
+
"Updated",
|
|
125
|
+
`${envVar.name} updated.\nRestart Claude Code to apply.`,
|
|
126
|
+
"success",
|
|
127
|
+
);
|
|
128
|
+
fetchData();
|
|
129
|
+
} catch (error) {
|
|
130
|
+
modal.hideModal();
|
|
131
|
+
await modal.message("Error", `Failed to update: ${error}`, "error");
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const handleDelete = async () => {
|
|
136
|
+
if (envVarList.length === 0) return;
|
|
137
|
+
const envVar = envVarList[envVars.selectedIndex];
|
|
138
|
+
if (!envVar) return;
|
|
139
|
+
|
|
140
|
+
const confirmed = await modal.confirm(
|
|
141
|
+
`Delete ${envVar.name}?`,
|
|
142
|
+
"This will remove the variable from configuration.",
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (confirmed) {
|
|
146
|
+
modal.loading(`Deleting ${envVar.name}...`);
|
|
147
|
+
try {
|
|
148
|
+
await removeMcpEnvVar(envVar.name, state.projectPath);
|
|
149
|
+
modal.hideModal();
|
|
150
|
+
await modal.message("Deleted", `${envVar.name} removed.`, "success");
|
|
151
|
+
fetchData();
|
|
152
|
+
} catch (error) {
|
|
153
|
+
modal.hideModal();
|
|
154
|
+
await modal.message("Error", `Failed to delete: ${error}`, "error");
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Get selected item
|
|
160
|
+
const selectedVar = envVarList[envVars.selectedIndex];
|
|
161
|
+
|
|
162
|
+
const renderDetail = () => {
|
|
163
|
+
if (isLoading) {
|
|
164
|
+
return <text fg="gray">Loading environment variables...</text>;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (envVarList.length === 0) {
|
|
168
|
+
return (
|
|
169
|
+
<box flexDirection="column">
|
|
170
|
+
<text fg="gray">No environment variables configured.</text>
|
|
171
|
+
<box marginTop={1}>
|
|
172
|
+
<text fg="green">Press 'a' to add a new variable</text>
|
|
173
|
+
</box>
|
|
174
|
+
</box>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!selectedVar) {
|
|
179
|
+
return <text fg="gray">Select a variable to see details</text>;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<box flexDirection="column">
|
|
184
|
+
<text fg="cyan">
|
|
185
|
+
<strong>{selectedVar.name}</strong>
|
|
186
|
+
</text>
|
|
187
|
+
<box marginTop={1}>
|
|
188
|
+
<text fg="gray">Value: </text>
|
|
189
|
+
<text>
|
|
190
|
+
{selectedVar.value.length > 50
|
|
191
|
+
? selectedVar.value.slice(0, 50) + "..."
|
|
192
|
+
: selectedVar.value}
|
|
193
|
+
</text>
|
|
194
|
+
</box>
|
|
195
|
+
<box marginTop={2} flexDirection="column">
|
|
196
|
+
<box>
|
|
197
|
+
<text bg="magenta" fg="white">
|
|
198
|
+
{" "}
|
|
199
|
+
Enter{" "}
|
|
200
|
+
</text>
|
|
201
|
+
<text fg="gray"> Edit value</text>
|
|
202
|
+
</box>
|
|
203
|
+
<box marginTop={1}>
|
|
204
|
+
<text bg="red" fg="white">
|
|
205
|
+
{" "}
|
|
206
|
+
d{" "}
|
|
207
|
+
</text>
|
|
208
|
+
<text fg="gray"> Delete variable</text>
|
|
209
|
+
</box>
|
|
210
|
+
</box>
|
|
211
|
+
</box>
|
|
212
|
+
);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const renderListItem = (
|
|
216
|
+
envVar: EnvVar,
|
|
217
|
+
_idx: number,
|
|
218
|
+
isSelected: boolean,
|
|
219
|
+
) => {
|
|
220
|
+
const masked =
|
|
221
|
+
envVar.value.length > 20
|
|
222
|
+
? envVar.value.slice(0, 20) + "..."
|
|
223
|
+
: envVar.value;
|
|
224
|
+
return isSelected ? (
|
|
225
|
+
<text bg="magenta" fg="white">
|
|
226
|
+
{" "}
|
|
227
|
+
{envVar.name} = "{masked}"{" "}
|
|
228
|
+
</text>
|
|
229
|
+
) : (
|
|
230
|
+
<text>
|
|
231
|
+
<span fg="cyan">{envVar.name}</span>
|
|
232
|
+
<span fg="gray"> = "{masked}"</span>
|
|
233
|
+
</text>
|
|
234
|
+
);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const statusContent = (
|
|
238
|
+
<>
|
|
239
|
+
<text fg="gray">Variables: </text>
|
|
240
|
+
<text fg="cyan">{envVarList.length}</text>
|
|
241
|
+
<text fg="gray"> │ Location: </text>
|
|
242
|
+
<text fg="green">.claude/settings.local.json</text>
|
|
243
|
+
</>
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
<ScreenLayout
|
|
248
|
+
title="claudeup Environment Variables"
|
|
249
|
+
currentScreen="env-vars"
|
|
250
|
+
statusLine={statusContent}
|
|
251
|
+
footerHints="↑↓:nav │ Enter/e:edit │ a:add │ d:delete"
|
|
252
|
+
listPanel={
|
|
253
|
+
envVarList.length === 0 ? (
|
|
254
|
+
<text fg="gray">No environment variables configured</text>
|
|
255
|
+
) : (
|
|
256
|
+
<ScrollableList
|
|
257
|
+
items={envVarList}
|
|
258
|
+
selectedIndex={envVars.selectedIndex}
|
|
259
|
+
renderItem={renderListItem}
|
|
260
|
+
maxHeight={dimensions.listPanelHeight}
|
|
261
|
+
/>
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
detailPanel={renderDetail()}
|
|
265
|
+
/>
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export default EnvVarsScreen;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useCallback, useState, useRef } from
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { ScreenLayout } from
|
|
7
|
-
import { ScrollableList } from
|
|
8
|
-
import { searchMcpServers, formatDate } from
|
|
9
|
-
import { addMcpServer, setAllowMcp } from
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { useEffect, useCallback, useState, useRef } from "react";
|
|
3
|
+
import { useApp, useModal, useNavigation } from "../state/AppContext.js";
|
|
4
|
+
import { useDimensions } from "../state/DimensionsContext.js";
|
|
5
|
+
import { useKeyboard } from "../hooks/useKeyboard.js";
|
|
6
|
+
import { ScreenLayout } from "../components/layout/index.js";
|
|
7
|
+
import { ScrollableList } from "../components/ScrollableList.js";
|
|
8
|
+
import { searchMcpServers, formatDate } from "../../services/mcp-registry.js";
|
|
9
|
+
import { addMcpServer, setAllowMcp } from "../../services/claude-settings.js";
|
|
10
10
|
/**
|
|
11
11
|
* Deduplicate servers by name, keeping only the latest version.
|
|
12
12
|
* Uses version string comparison, falling back to published_at date.
|
|
@@ -36,8 +36,8 @@ function deduplicateServers(servers) {
|
|
|
36
36
|
function compareVersions(a, b) {
|
|
37
37
|
// Try semver comparison first
|
|
38
38
|
if (a.version && b.version) {
|
|
39
|
-
const aParts = a.version.split(
|
|
40
|
-
const bParts = b.version.split(
|
|
39
|
+
const aParts = a.version.split(".").map((n) => parseInt(n, 10) || 0);
|
|
40
|
+
const bParts = b.version.split(".").map((n) => parseInt(n, 10) || 0);
|
|
41
41
|
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
42
42
|
const aVal = aParts[i] || 0;
|
|
43
43
|
const bVal = bParts[i] || 0;
|
|
@@ -48,7 +48,7 @@ function compareVersions(a, b) {
|
|
|
48
48
|
}
|
|
49
49
|
// Fall back to published_at date
|
|
50
50
|
if (a.published_at && b.published_at) {
|
|
51
|
-
return new Date(a.published_at).getTime() - new Date(b.published_at).getTime();
|
|
51
|
+
return (new Date(a.published_at).getTime() - new Date(b.published_at).getTime());
|
|
52
52
|
}
|
|
53
53
|
// If one has a date and other doesn't, prefer the one with date
|
|
54
54
|
if (a.published_at && !b.published_at)
|
|
@@ -66,8 +66,10 @@ export function McpRegistryScreen() {
|
|
|
66
66
|
const [servers, setServers] = useState([]);
|
|
67
67
|
const [isLoading, setIsLoading] = useState(true);
|
|
68
68
|
const [error, setError] = useState(null);
|
|
69
|
-
const [searchQuery, setSearchQuery] = useState(mcpRegistry.searchQuery ||
|
|
70
|
-
const isSearchActive = state.isSearching &&
|
|
69
|
+
const [searchQuery, setSearchQuery] = useState(mcpRegistry.searchQuery || "");
|
|
70
|
+
const isSearchActive = state.isSearching &&
|
|
71
|
+
state.currentRoute.screen === "mcp-registry" &&
|
|
72
|
+
!state.modal;
|
|
71
73
|
const searchTimeoutRef = useRef(null);
|
|
72
74
|
// Load servers
|
|
73
75
|
const loadServers = useCallback(async (query) => {
|
|
@@ -76,14 +78,14 @@ export function McpRegistryScreen() {
|
|
|
76
78
|
try {
|
|
77
79
|
const response = await searchMcpServers({ query, limit: 50 });
|
|
78
80
|
if (!response || !Array.isArray(response.servers)) {
|
|
79
|
-
throw new Error(
|
|
81
|
+
throw new Error("Invalid response from MCP Registry API");
|
|
80
82
|
}
|
|
81
83
|
// Deduplicate to show only latest version of each server
|
|
82
84
|
const deduplicated = deduplicateServers(response.servers);
|
|
83
85
|
setServers(deduplicated);
|
|
84
86
|
}
|
|
85
87
|
catch (err) {
|
|
86
|
-
setError(err instanceof Error ? err.message :
|
|
88
|
+
setError(err instanceof Error ? err.message : "Failed to load servers");
|
|
87
89
|
setServers([]);
|
|
88
90
|
}
|
|
89
91
|
setIsLoading(false);
|
|
@@ -106,36 +108,36 @@ export function McpRegistryScreen() {
|
|
|
106
108
|
};
|
|
107
109
|
}, []);
|
|
108
110
|
// Keyboard handling
|
|
109
|
-
|
|
111
|
+
useKeyboard((event) => {
|
|
110
112
|
// Handle search mode
|
|
111
113
|
if (isSearchActive) {
|
|
112
|
-
if (
|
|
113
|
-
dispatch({ type:
|
|
114
|
+
if (event.name === "escape") {
|
|
115
|
+
dispatch({ type: "SET_SEARCHING", isSearching: false });
|
|
114
116
|
}
|
|
115
|
-
else if (
|
|
117
|
+
else if (event.name === "enter") {
|
|
116
118
|
// Exit search mode and stay on list for navigation
|
|
117
|
-
dispatch({ type:
|
|
119
|
+
dispatch({ type: "SET_SEARCHING", isSearching: false });
|
|
118
120
|
}
|
|
119
|
-
else if (
|
|
121
|
+
else if (event.name === "up") {
|
|
120
122
|
// Allow navigation while searching
|
|
121
123
|
const newIndex = Math.max(0, mcpRegistry.selectedIndex - 1);
|
|
122
|
-
dispatch({ type:
|
|
124
|
+
dispatch({ type: "MCPREGISTRY_SELECT", index: newIndex });
|
|
123
125
|
}
|
|
124
|
-
else if (
|
|
126
|
+
else if (event.name === "down") {
|
|
125
127
|
// Allow navigation while searching
|
|
126
128
|
const newIndex = Math.min(Math.max(0, servers.length - 1), mcpRegistry.selectedIndex + 1);
|
|
127
|
-
dispatch({ type:
|
|
129
|
+
dispatch({ type: "MCPREGISTRY_SELECT", index: newIndex });
|
|
128
130
|
}
|
|
129
|
-
else if (
|
|
131
|
+
else if (event.name === "backspace" || event.name === "delete") {
|
|
130
132
|
const newQuery = searchQuery.slice(0, -1);
|
|
131
133
|
setSearchQuery(newQuery);
|
|
132
|
-
dispatch({ type:
|
|
134
|
+
dispatch({ type: "MCPREGISTRY_SEARCH", query: newQuery });
|
|
133
135
|
debouncedSearch(newQuery);
|
|
134
136
|
}
|
|
135
|
-
else if (
|
|
136
|
-
const newQuery = searchQuery +
|
|
137
|
+
else if (event.name.length === 1 && !event.ctrl && !event.meta) {
|
|
138
|
+
const newQuery = searchQuery + event.name;
|
|
137
139
|
setSearchQuery(newQuery);
|
|
138
|
-
dispatch({ type:
|
|
140
|
+
dispatch({ type: "MCPREGISTRY_SEARCH", query: newQuery });
|
|
139
141
|
debouncedSearch(newQuery);
|
|
140
142
|
}
|
|
141
143
|
return;
|
|
@@ -143,26 +145,26 @@ export function McpRegistryScreen() {
|
|
|
143
145
|
if (state.modal)
|
|
144
146
|
return;
|
|
145
147
|
// Start search with /
|
|
146
|
-
if (
|
|
147
|
-
dispatch({ type:
|
|
148
|
+
if (event.name === "/") {
|
|
149
|
+
dispatch({ type: "SET_SEARCHING", isSearching: true });
|
|
148
150
|
return;
|
|
149
151
|
}
|
|
150
152
|
// Navigation
|
|
151
|
-
if (
|
|
153
|
+
if (event.name === "up" || event.name === "k") {
|
|
152
154
|
const newIndex = Math.max(0, mcpRegistry.selectedIndex - 1);
|
|
153
|
-
dispatch({ type:
|
|
155
|
+
dispatch({ type: "MCPREGISTRY_SELECT", index: newIndex });
|
|
154
156
|
}
|
|
155
|
-
else if (
|
|
157
|
+
else if (event.name === "down" || event.name === "j") {
|
|
156
158
|
const newIndex = Math.min(Math.max(0, servers.length - 1), mcpRegistry.selectedIndex + 1);
|
|
157
|
-
dispatch({ type:
|
|
159
|
+
dispatch({ type: "MCPREGISTRY_SELECT", index: newIndex });
|
|
158
160
|
}
|
|
159
|
-
else if (
|
|
160
|
-
navigateToScreen(
|
|
161
|
+
else if (event.name === "l") {
|
|
162
|
+
navigateToScreen("mcp");
|
|
161
163
|
}
|
|
162
|
-
else if (
|
|
164
|
+
else if (event.name === "R") {
|
|
163
165
|
loadServers(searchQuery);
|
|
164
166
|
}
|
|
165
|
-
else if (
|
|
167
|
+
else if (event.name === "enter") {
|
|
166
168
|
handleInstall();
|
|
167
169
|
}
|
|
168
170
|
});
|
|
@@ -171,7 +173,7 @@ export function McpRegistryScreen() {
|
|
|
171
173
|
if (!server)
|
|
172
174
|
return;
|
|
173
175
|
const config = {
|
|
174
|
-
type:
|
|
176
|
+
type: "http",
|
|
175
177
|
url: server.url,
|
|
176
178
|
};
|
|
177
179
|
modal.loading(`Installing ${server.name}...`);
|
|
@@ -179,48 +181,47 @@ export function McpRegistryScreen() {
|
|
|
179
181
|
await setAllowMcp(true, state.projectPath);
|
|
180
182
|
await addMcpServer(server.name, config, state.projectPath);
|
|
181
183
|
modal.hideModal();
|
|
182
|
-
await modal.message(
|
|
184
|
+
await modal.message("Installed", `${server.name} has been configured.\n\nRestart Claude Code to activate.`, "success");
|
|
183
185
|
}
|
|
184
186
|
catch (error) {
|
|
185
187
|
modal.hideModal();
|
|
186
|
-
await modal.message(
|
|
188
|
+
await modal.message("Error", `Failed to install: ${error}`, "error");
|
|
187
189
|
}
|
|
188
190
|
};
|
|
189
191
|
// Get selected server
|
|
190
192
|
const selectedServer = servers[mcpRegistry.selectedIndex];
|
|
191
193
|
const renderDetail = () => {
|
|
192
194
|
if (isLoading) {
|
|
193
|
-
return _jsx(
|
|
195
|
+
return _jsx("text", { fg: "gray", children: "Loading..." });
|
|
194
196
|
}
|
|
195
197
|
if (error) {
|
|
196
|
-
return _jsxs(
|
|
198
|
+
return _jsxs("text", { fg: "red", children: ["Error: ", error] });
|
|
197
199
|
}
|
|
198
200
|
if (!selectedServer) {
|
|
199
|
-
return _jsx(
|
|
201
|
+
return _jsx("text", { fg: "gray", children: "Select a server to see details" });
|
|
200
202
|
}
|
|
201
203
|
const dateDisplay = selectedServer.published_at
|
|
202
204
|
? formatDate(selectedServer.published_at)
|
|
203
|
-
:
|
|
205
|
+
: "unknown";
|
|
204
206
|
const versionDisplay = selectedServer.version
|
|
205
207
|
? `v${selectedServer.version}`
|
|
206
|
-
:
|
|
207
|
-
return (_jsxs(
|
|
208
|
+
: "unknown";
|
|
209
|
+
return (_jsxs("box", { flexDirection: "column", children: [_jsx("text", { fg: "magenta", children: _jsx("strong", { children: selectedServer.name }) }), _jsx("box", { marginTop: 1, children: _jsx("text", { children: selectedServer.short_description }) }), _jsxs("box", { marginTop: 1, children: [_jsx("text", { children: _jsx("strong", { children: "Version: " }) }), _jsx("text", { fg: "green", children: versionDisplay })] }), _jsxs("box", { children: [_jsx("text", { children: _jsx("strong", { children: "Published: " }) }), _jsx("text", { fg: "cyan", children: dateDisplay })] }), _jsxs("box", { marginTop: 1, flexDirection: "column", children: [_jsx("text", { children: _jsx("strong", { children: "URL:" }) }), _jsx("text", { fg: "cyan", children: selectedServer.url })] }), selectedServer.source_code_url && (_jsxs("box", { marginTop: 1, flexDirection: "column", children: [_jsx("text", { children: _jsx("strong", { children: "Source:" }) }), _jsx("text", { fg: "gray", children: selectedServer.source_code_url })] })), _jsx("box", { marginTop: 1, children: _jsx("text", { fg: "green", children: "Press Enter to install" }) })] }));
|
|
208
210
|
};
|
|
209
211
|
const renderListItem = (server, _idx, isSelected) => {
|
|
210
|
-
const version = server.version ? ` v${server.version}` :
|
|
211
|
-
return isSelected ? (_jsxs(
|
|
212
|
+
const version = server.version ? ` v${server.version}` : "";
|
|
213
|
+
return isSelected ? (_jsxs("text", { bg: "magenta", fg: "white", children: [" ", server.name, version, " "] })) : (_jsxs("text", { children: [_jsx("span", { children: _jsx("strong", { children: server.name }) }), _jsx("span", { fg: "green", children: version })] }));
|
|
212
214
|
};
|
|
213
215
|
// Footer hints
|
|
214
216
|
const footerHints = isSearchActive
|
|
215
|
-
?
|
|
216
|
-
:
|
|
217
|
+
? "Type to search │ ↑↓:nav │ Enter:done │ Esc:cancel"
|
|
218
|
+
: "↑↓:nav │ Enter:install │ /:search │ R:refresh │ l:local";
|
|
217
219
|
// Status for search placeholder
|
|
218
220
|
const searchPlaceholder = `${servers.length} servers │ / to search`;
|
|
219
221
|
return (_jsx(ScreenLayout, { title: "claudeup MCP Registry", subtitle: "Powered by MCP Registry", currentScreen: "mcp-registry", search: {
|
|
220
222
|
isActive: isSearchActive,
|
|
221
223
|
query: searchQuery,
|
|
222
224
|
placeholder: searchPlaceholder,
|
|
223
|
-
}, footerHints: footerHints, listPanel: isLoading ? (_jsx(
|
|
225
|
+
}, footerHints: footerHints, listPanel: isLoading ? (_jsx("text", { fg: "gray", children: "Loading..." })) : error ? (_jsxs("text", { fg: "red", children: ["Error: ", error] })) : servers.length === 0 ? (_jsx("text", { fg: "gray", children: "No servers found" })) : (_jsx(ScrollableList, { items: servers, selectedIndex: mcpRegistry.selectedIndex, renderItem: renderListItem, maxHeight: dimensions.listPanelHeight })), detailPanel: renderDetail() }));
|
|
224
226
|
}
|
|
225
227
|
export default McpRegistryScreen;
|
|
226
|
-
//# sourceMappingURL=McpRegistryScreen.js.map
|