magus-cli 7.3.1 → 7.4.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/package.json +4 -4
- package/src/__tests__/blind/c1-npm-package.test.ts +206 -0
- package/src/__tests__/blind/c10-colour-roles.test.ts +265 -0
- package/src/__tests__/blind/c11-cli-parse-refusal.test.ts +454 -0
- package/src/__tests__/blind/c12-skill-frontmatter.test.ts +323 -0
- package/src/__tests__/blind/c13-wrong-shape.test.ts +603 -0
- package/src/__tests__/blind/c14-cli-row-label.test.ts +259 -0
- package/src/__tests__/blind/c15-probe-ownership.test.ts +533 -0
- package/src/__tests__/blind/c16-nested-wrong-shape.test.ts +297 -0
- package/src/__tests__/blind/c17-enter-label.test.ts +625 -0
- package/src/__tests__/blind/c18-hook-shape.test.ts +354 -0
- package/src/__tests__/blind/c2-settings-parse.test.ts +350 -0
- package/src/__tests__/blind/c4-key-dispatch.test.ts +397 -0
- package/src/__tests__/blind/c5-keymap.test.ts +461 -0
- package/src/__tests__/blind/c6-request-gate.test.ts +133 -0
- package/src/__tests__/blind/c7-tab-tiers.test.ts +320 -0
- package/src/__tests__/blind/c8-text-width.test.ts +137 -0
- package/src/__tests__/blind/c9-cli-tool-version.test.ts +239 -0
- package/src/__tests__/blind/child-run.ts +114 -0
- package/src/__tests__/cli-tools-adapter.test.ts +5 -2
- package/src/__tests__/component-badge.test.ts +20 -36
- package/src/__tests__/footer-hints.test.ts +1 -1
- package/src/__tests__/manifest.test.ts +25 -17
- package/src/__tests__/marketplace-badge.test.ts +4 -4
- package/src/__tests__/models-screen-state.test.ts +36 -13
- package/src/__tests__/scope-squares.test.tsx +28 -114
- package/src/__tests__/shutdown.test.ts +578 -0
- package/src/__tests__/styles-manager.test.ts +4 -4
- package/src/__tests__/styles-screen-state.test.ts +26 -12
- package/src/__tests__/tabbar-layout.test.ts +44 -32
- package/src/__tests__/theme-adaptive-colors.test.ts +6 -59
- package/src/__tests__/tool-probe.test.ts +47 -22
- package/src/__tests__/uppercase-keybindings.test.ts +25 -12
- package/src/cli/ansi.ts +2 -2
- package/src/cli/bootstrap.ts +33 -2
- package/src/cli/doctor.ts +105 -14
- package/src/cli/install.ts +8 -2
- package/src/cli/profile.ts +18 -1
- package/src/cli/router.ts +31 -18
- package/src/cli/update-view.ts +1 -1
- package/src/data/cli-tools.ts +9 -1
- package/src/services/claude-settings.ts +151 -73
- package/src/services/cli-tool-commands.ts +15 -5
- package/src/services/cli-tool-version.ts +101 -0
- package/src/services/hook-registration.ts +23 -6
- package/src/services/manifest.ts +117 -52
- package/src/services/plugin-manager.ts +19 -5
- package/src/services/profile-adopt.ts +7 -2
- package/src/services/profile-startup.ts +87 -7
- package/src/services/profiles.ts +36 -23
- package/src/services/settings-file.ts +158 -4
- package/src/services/settings-manager.ts +19 -5
- package/src/services/skills-manager.ts +46 -0
- package/src/services/tool-probe.ts +272 -45
- package/src/services/toolchain.ts +39 -0
- package/src/services/update-engine.ts +5 -0
- package/src/services/update-plan.ts +9 -0
- package/src/tui.tsx +48 -21
- package/src/ui/App.tsx +58 -197
- package/src/ui/adapters/cliToolsAdapter.ts +141 -12
- package/src/ui/adapters/pluginsAdapter.ts +10 -7
- package/src/ui/adapters/settingsAdapter.ts +0 -21
- package/src/ui/adapters/skillsAdapter.ts +27 -8
- package/src/ui/adapters/stylesAdapter.ts +15 -11
- package/src/ui/components/CategoryHeader.tsx +7 -1
- package/src/ui/components/EmptyFilterState.tsx +2 -2
- package/src/ui/components/FlagDetailEditor.tsx +0 -0
- package/src/ui/components/ScreenErrorBoundary.tsx +105 -0
- package/src/ui/components/TabBar.tsx +93 -21
- package/src/ui/components/layout/FooterHints.tsx +6 -27
- package/src/ui/components/layout/ScreenLayout.tsx +68 -42
- package/src/ui/components/layout/index.ts +1 -5
- package/src/ui/components/modals/ConfirmModal.tsx +2 -19
- package/src/ui/components/modals/HelpOverlay.tsx +186 -0
- package/src/ui/components/modals/MessageModal.tsx +3 -15
- package/src/ui/components/modals/ModalContainer.tsx +99 -60
- package/src/ui/components/primitives/ErrorNotice.tsx +38 -0
- package/src/ui/components/primitives/ListCategoryRow.tsx +18 -7
- package/src/ui/components/primitives/MetaText.tsx +1 -1
- package/src/ui/components/primitives/ScopeDetail.tsx +31 -26
- package/src/ui/components/primitives/ScopeSquares.tsx +23 -28
- package/src/ui/components/primitives/SelectableRow.tsx +24 -1
- package/src/ui/components/primitives/index.ts +4 -3
- package/src/ui/hooks/useProfileStartupModal.ts +15 -3
- package/src/ui/input/KeyRouter.tsx +180 -0
- package/src/ui/input/key-dispatch.ts +149 -0
- package/src/ui/keymap.ts +898 -0
- package/src/ui/renderers/cliToolRenderers.tsx +128 -66
- package/src/ui/renderers/gitignoreRenderers.tsx +41 -43
- package/src/ui/renderers/markdownRenderer.tsx +2 -2
- package/src/ui/renderers/mcpRenderers.tsx +28 -14
- package/src/ui/renderers/modelRenderers.tsx +12 -13
- package/src/ui/renderers/modelVisuals.tsx +0 -2
- package/src/ui/renderers/pluginRenderers.tsx +47 -54
- package/src/ui/renderers/profileRenderers.tsx +32 -37
- package/src/ui/renderers/settingsRenderers.tsx +84 -55
- package/src/ui/renderers/skillRenderers.tsx +237 -190
- package/src/ui/renderers/styleRenderers.tsx +13 -2
- package/src/ui/runtime/shutdown.ts +268 -0
- package/src/ui/screens/AliasScreen.tsx +118 -100
- package/src/ui/screens/CliToolsScreen.tsx +98 -87
- package/src/ui/screens/EnvVarsScreen.tsx +44 -42
- package/src/ui/screens/GitignoreScreen.tsx +50 -55
- package/src/ui/screens/McpRegistryScreen.tsx +52 -86
- package/src/ui/screens/McpScreen.tsx +47 -33
- package/src/ui/screens/ModelsScreen.tsx +59 -104
- package/src/ui/screens/PluginsScreen.tsx +123 -127
- package/src/ui/screens/ProfilesScreen.tsx +49 -46
- package/src/ui/screens/SkillsScreen.tsx +184 -204
- package/src/ui/screens/StylesScreen.tsx +104 -157
- package/src/ui/state/AppContext.tsx +6 -0
- package/src/ui/state/DimensionsContext.tsx +1 -10
- package/src/ui/state/reducer.ts +5 -8
- package/src/ui/state/types.ts +11 -9
- package/src/ui/text-width.ts +341 -0
- package/src/ui/theme-mode.ts +34 -71
- package/src/ui/theme.ts +50 -28
- package/src/utils/request-gate.ts +37 -0
- package/src/ui/components/ScopeIndicator.tsx +0 -63
- package/src/ui/components/SearchInput.tsx +0 -57
- package/src/ui/hooks/index.ts +0 -2
- package/src/ui/hooks/useKeyboard.ts +0 -24
- package/src/ui/hooks/useKeyboardHandler.ts +0 -63
|
@@ -27,14 +27,17 @@ import {
|
|
|
27
27
|
DetailSection,
|
|
28
28
|
KeyValueLine,
|
|
29
29
|
MetaText,
|
|
30
|
+
ScopeDot,
|
|
31
|
+
ScopeKeyChip,
|
|
30
32
|
ScopeSquares,
|
|
31
33
|
SelectableRow,
|
|
34
|
+
rowLead,
|
|
32
35
|
} from "../components/primitives/index.js";
|
|
33
36
|
import type {
|
|
34
37
|
PluginContentsEntry,
|
|
35
38
|
PluginSkillDetailEntry,
|
|
36
39
|
} from "../state/types.js";
|
|
37
|
-
import {
|
|
40
|
+
import { componentChip } from "../theme-mode.js";
|
|
38
41
|
import { type UiColor, theme } from "../theme.js";
|
|
39
42
|
import { renderMarkdown } from "./markdownRenderer.js";
|
|
40
43
|
import { type PluginRowSegment, pluginRowText } from "./pluginRowText.js";
|
|
@@ -58,7 +61,7 @@ function categoryRow(
|
|
|
58
61
|
return (
|
|
59
62
|
<SelectableRow selected={true}>
|
|
60
63
|
<strong>
|
|
61
|
-
{
|
|
64
|
+
{rowLead(true)}
|
|
62
65
|
{arrow} {mp.displayName}
|
|
63
66
|
{versionLabel}
|
|
64
67
|
{count}{" "}
|
|
@@ -67,14 +70,13 @@ function categoryRow(
|
|
|
67
70
|
);
|
|
68
71
|
}
|
|
69
72
|
|
|
70
|
-
//
|
|
73
|
+
// The adapter names a role; the badge after the title wears its ink.
|
|
71
74
|
const statusColorMap: Record<PluginCategoryItem["tone"], UiColor> = {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
teal: theme.colors.info,
|
|
75
|
+
neutral: theme.colors.muted,
|
|
76
|
+
info: theme.colors.info,
|
|
77
|
+
success: theme.colors.success,
|
|
78
|
+
warning: theme.colors.warning,
|
|
79
|
+
danger: theme.colors.danger,
|
|
78
80
|
byline: theme.colors.byline,
|
|
79
81
|
};
|
|
80
82
|
|
|
@@ -122,7 +124,7 @@ function categoryDetail(
|
|
|
122
124
|
<text fg={isEnabled ? theme.colors.success : theme.colors.muted}>
|
|
123
125
|
{isEnabled ? "● Added" : "○ Not added"}
|
|
124
126
|
</text>
|
|
125
|
-
<text fg={theme.colors.
|
|
127
|
+
<text fg={theme.colors.info}>github.com/{mp.source.repo}</text>
|
|
126
128
|
<text fg={theme.colors.text}>Plugins: {item.pluginCount}</text>
|
|
127
129
|
<ActionHints
|
|
128
130
|
hints={[
|
|
@@ -185,6 +187,9 @@ function RowSegments({
|
|
|
185
187
|
);
|
|
186
188
|
}
|
|
187
189
|
|
|
190
|
+
/** Drawn in the scope column of a plugin no marketplace we read lists. */
|
|
191
|
+
const ORPHAN_MARK = "✗";
|
|
192
|
+
|
|
188
193
|
function pluginRow(
|
|
189
194
|
item: PluginPluginItem,
|
|
190
195
|
isSelected: boolean,
|
|
@@ -210,7 +215,7 @@ function pluginRow(
|
|
|
210
215
|
if (isSelected) {
|
|
211
216
|
return (
|
|
212
217
|
<text bg={theme.selection.bg} fg={theme.selection.fg}>
|
|
213
|
-
{
|
|
218
|
+
{rowLead(true)}
|
|
214
219
|
<ScopeSquares
|
|
215
220
|
user={hasUser}
|
|
216
221
|
project={hasProject}
|
|
@@ -233,12 +238,16 @@ function pluginRow(
|
|
|
233
238
|
: plugin.name;
|
|
234
239
|
|
|
235
240
|
if (plugin.isOrphaned) {
|
|
236
|
-
//
|
|
237
|
-
// we read"
|
|
238
|
-
//
|
|
241
|
+
// ✗ in the scope column is the presence marker for "published by no
|
|
242
|
+
// marketplace we read" — not three squares, which would claim it is
|
|
243
|
+
// installed at every scope. WHAT is known about it — moved, withdrawn, or
|
|
244
|
+
// its marketplace was never read — is the status suffix, the same words
|
|
245
|
+
// the CLI prints.
|
|
239
246
|
return (
|
|
240
247
|
<text fg={theme.colors.text}>
|
|
241
|
-
<span
|
|
248
|
+
<span
|
|
249
|
+
fg={theme.colors.danger}
|
|
250
|
+
>{`${rowLead(false)} ${ORPHAN_MARK} `}</span>
|
|
242
251
|
{/* An orphan is never expandable, but it keeps the arrow cell so its
|
|
243
252
|
name lands in the same column as every other plugin's. */}
|
|
244
253
|
<span>{" "}</span>
|
|
@@ -447,7 +456,7 @@ function pluginDetail(
|
|
|
447
456
|
isInstalled
|
|
448
457
|
? theme.colors.success
|
|
449
458
|
: brokenInstall
|
|
450
|
-
? theme.colors.
|
|
459
|
+
? theme.colors.danger
|
|
451
460
|
: theme.colors.muted
|
|
452
461
|
}
|
|
453
462
|
>
|
|
@@ -505,7 +514,7 @@ function pluginDetail(
|
|
|
505
514
|
label="Version"
|
|
506
515
|
value={
|
|
507
516
|
<span>
|
|
508
|
-
<span fg={theme.colors.
|
|
517
|
+
<span fg={theme.colors.info}>v{plugin.version}</span>
|
|
509
518
|
{showInstalledVersion ? (
|
|
510
519
|
<span> (v{plugin.installedVersion} installed)</span>
|
|
511
520
|
) : null}
|
|
@@ -541,7 +550,7 @@ function pluginDetail(
|
|
|
541
550
|
{plugin.category ? (
|
|
542
551
|
<KeyValueLine
|
|
543
552
|
label="Category"
|
|
544
|
-
value={<span fg={theme.colors.
|
|
553
|
+
value={<span fg={theme.colors.info}>{plugin.category}</span>}
|
|
545
554
|
/>
|
|
546
555
|
) : null}
|
|
547
556
|
{plugin.author ? (
|
|
@@ -553,9 +562,7 @@ function pluginDetail(
|
|
|
553
562
|
{components.length > 0 ? (
|
|
554
563
|
<KeyValueLine
|
|
555
564
|
label="Contains"
|
|
556
|
-
value={
|
|
557
|
-
<span fg={theme.colors.warning}>{components.join(" · ")}</span>
|
|
558
|
-
}
|
|
565
|
+
value={<span fg={theme.colors.info}>{components.join(" · ")}</span>}
|
|
559
566
|
/>
|
|
560
567
|
) : null}
|
|
561
568
|
{item.isExpandable ? (
|
|
@@ -577,21 +584,18 @@ function pluginDetail(
|
|
|
577
584
|
keyHint="u"
|
|
578
585
|
name="User"
|
|
579
586
|
qualifier="global"
|
|
580
|
-
color={theme.scopes.user}
|
|
581
587
|
scope={plugin.userScope}
|
|
582
588
|
/>
|
|
583
589
|
<ScopeLine
|
|
584
590
|
keyHint="p"
|
|
585
591
|
name="Project"
|
|
586
592
|
qualifier="team"
|
|
587
|
-
color={theme.scopes.project}
|
|
588
593
|
scope={plugin.projectScope}
|
|
589
594
|
/>
|
|
590
595
|
<ScopeLine
|
|
591
596
|
keyHint="l"
|
|
592
597
|
name="Local"
|
|
593
598
|
qualifier="private"
|
|
594
|
-
color={theme.scopes.local}
|
|
595
599
|
scope={plugin.localScope}
|
|
596
600
|
/>
|
|
597
601
|
</box>
|
|
@@ -636,30 +640,25 @@ function ScopeLine({
|
|
|
636
640
|
keyHint,
|
|
637
641
|
name,
|
|
638
642
|
qualifier,
|
|
639
|
-
color,
|
|
640
643
|
scope,
|
|
641
644
|
}: {
|
|
642
645
|
keyHint: string;
|
|
643
646
|
name: string;
|
|
644
647
|
qualifier: string;
|
|
645
|
-
color: UiColor;
|
|
646
648
|
scope?: ScopeStatus;
|
|
647
649
|
}): React.ReactNode {
|
|
648
650
|
const installed = isInstalledInScope(scope);
|
|
649
651
|
return (
|
|
650
652
|
<text fg={theme.colors.text}>
|
|
651
|
-
<
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
</span>
|
|
655
|
-
|
|
656
|
-
{
|
|
657
|
-
|
|
658
|
-
<span fg={color}>{name}</span>
|
|
659
|
-
<span> {qualifier}</span>
|
|
660
|
-
{scope?.version ? <span fg={color}> v{scope.version}</span> : null}
|
|
653
|
+
<ScopeKeyChip scopeKey={keyHint} />
|
|
654
|
+
<ScopeDot installed={installed} />
|
|
655
|
+
<span>{name}</span>
|
|
656
|
+
<span fg={theme.colors.muted}> {qualifier}</span>
|
|
657
|
+
{scope?.version ? (
|
|
658
|
+
<span fg={theme.colors.info}> v{scope.version}</span>
|
|
659
|
+
) : null}
|
|
661
660
|
{!installed && scope?.enabled ? (
|
|
662
|
-
<span fg={theme.colors.
|
|
661
|
+
<span fg={theme.colors.danger}> enabled, not installed</span>
|
|
663
662
|
) : null}
|
|
664
663
|
</text>
|
|
665
664
|
);
|
|
@@ -702,7 +701,7 @@ function ReleaseHistory({
|
|
|
702
701
|
? theme.colors.warning
|
|
703
702
|
: isInstalled
|
|
704
703
|
? theme.colors.success
|
|
705
|
-
: theme.colors.
|
|
704
|
+
: theme.colors.info;
|
|
706
705
|
|
|
707
706
|
return (
|
|
708
707
|
<box key={release.version} flexDirection="column" marginBottom={1}>
|
|
@@ -795,13 +794,6 @@ export const COMPONENT_ICON: Record<PluginComponentKind, string> = {
|
|
|
795
794
|
mcp: "⬢",
|
|
796
795
|
};
|
|
797
796
|
|
|
798
|
-
const COMPONENT_COLOR: Record<PluginComponentKind, UiColor> = {
|
|
799
|
-
skill: theme.colors.accent,
|
|
800
|
-
command: theme.colors.info,
|
|
801
|
-
agent: theme.colors.link,
|
|
802
|
-
mcp: theme.colors.warning,
|
|
803
|
-
};
|
|
804
|
-
|
|
805
797
|
const COMPONENT_NOUN: Record<PluginComponentKind, string> = {
|
|
806
798
|
skill: "Skill",
|
|
807
799
|
command: "Command",
|
|
@@ -829,7 +821,7 @@ function componentBadge(
|
|
|
829
821
|
const icon = COMPONENT_ICON[kind];
|
|
830
822
|
if (isSelected) return ` ${icon} `;
|
|
831
823
|
|
|
832
|
-
const chip =
|
|
824
|
+
const chip = componentChip();
|
|
833
825
|
return <span bg={chip.bg} fg={chip.fg}>{` ${icon} `}</span>;
|
|
834
826
|
}
|
|
835
827
|
|
|
@@ -845,7 +837,8 @@ function componentRow(
|
|
|
845
837
|
if (isSelected) {
|
|
846
838
|
return (
|
|
847
839
|
<text bg={theme.selection.bg} fg={theme.selection.fg}>
|
|
848
|
-
{
|
|
840
|
+
{rowLead(true)}
|
|
841
|
+
{COMPONENT_INDENT.slice(1)}
|
|
849
842
|
{componentBadge(component.kind, true)}
|
|
850
843
|
{`${" ".repeat(BADGE_GAP)}${label} `}
|
|
851
844
|
</text>
|
|
@@ -868,7 +861,7 @@ function contentsStatusRow(
|
|
|
868
861
|
if (isSelected) {
|
|
869
862
|
return (
|
|
870
863
|
<text bg={theme.selection.bg} fg={theme.selection.fg}>
|
|
871
|
-
{`${pad}${item.label} `}
|
|
864
|
+
{`${rowLead(true)}${pad.slice(1)}${item.label} `}
|
|
872
865
|
</text>
|
|
873
866
|
);
|
|
874
867
|
}
|
|
@@ -938,7 +931,7 @@ function componentDetail(
|
|
|
938
931
|
value={
|
|
939
932
|
<span>
|
|
940
933
|
{componentBadge(component.kind, false)}
|
|
941
|
-
<span fg={
|
|
934
|
+
<span fg={theme.colors.text}>
|
|
942
935
|
{` ${COMPONENT_NOUN[component.kind]}`}
|
|
943
936
|
</span>
|
|
944
937
|
</span>
|
|
@@ -946,29 +939,29 @@ function componentDetail(
|
|
|
946
939
|
/>
|
|
947
940
|
<KeyValueLine
|
|
948
941
|
label="Plugin"
|
|
949
|
-
value={<span fg={theme.colors.
|
|
942
|
+
value={<span fg={theme.colors.info}>{plugin.name}</span>}
|
|
950
943
|
/>
|
|
951
944
|
{component.group ? (
|
|
952
945
|
<KeyValueLine
|
|
953
946
|
label="Group"
|
|
954
|
-
value={<span fg={theme.colors.
|
|
947
|
+
value={<span fg={theme.colors.info}>{component.group}</span>}
|
|
955
948
|
/>
|
|
956
949
|
) : null}
|
|
957
950
|
{component.mcpCommand ? (
|
|
958
951
|
<KeyValueLine
|
|
959
952
|
label="Runs"
|
|
960
|
-
value={<span fg={theme.colors.
|
|
953
|
+
value={<span fg={theme.colors.info}>{component.mcpCommand}</span>}
|
|
961
954
|
/>
|
|
962
955
|
) : null}
|
|
963
956
|
<KeyValueLine
|
|
964
957
|
label="Path"
|
|
965
|
-
value={<span fg={theme.colors.
|
|
958
|
+
value={<span fg={theme.colors.info}>{component.repoPath}</span>}
|
|
966
959
|
/>
|
|
967
960
|
{rest.map((field) => (
|
|
968
961
|
<KeyValueLine
|
|
969
962
|
key={field.key}
|
|
970
963
|
label={field.key}
|
|
971
|
-
value={<span fg={theme.colors.
|
|
964
|
+
value={<span fg={theme.colors.text}>{field.value}</span>}
|
|
972
965
|
/>
|
|
973
966
|
))}
|
|
974
967
|
</box>
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type React from "react";
|
|
2
2
|
import type { PredefinedProfile } from "../../data/predefined-profiles.js";
|
|
3
3
|
import type { ProfileEntry } from "../../types/index.js";
|
|
4
|
+
import { ListCategoryRow, rowLead } from "../components/primitives/index.js";
|
|
4
5
|
import type { ItemRenderer } from "../registry.js";
|
|
5
|
-
import {
|
|
6
|
+
import { theme } from "../theme.js";
|
|
6
7
|
|
|
7
8
|
// ─── List item types ───────────────────────────────────────────────────────────
|
|
8
9
|
|
|
9
10
|
export type ProfileListItem =
|
|
10
|
-
| { kind: "header"; label: string;
|
|
11
|
+
| { kind: "header"; label: string; count: number }
|
|
11
12
|
| { kind: "predefined"; profile: PredefinedProfile }
|
|
12
13
|
| { kind: "saved"; entry: ProfileEntry };
|
|
13
14
|
|
|
@@ -92,19 +93,20 @@ export function formatDate(iso: string | undefined): string {
|
|
|
92
93
|
|
|
93
94
|
// ─── Header renderer ───────────────────────────────────────────────────────────
|
|
94
95
|
|
|
96
|
+
/** A section label. Neutral: both sections are just groups, and the cursor
|
|
97
|
+
* steps over them, so a header wearing the accent would read as the cursor. */
|
|
95
98
|
const headerRenderer: ItemRenderer<{
|
|
96
99
|
kind: "header";
|
|
97
100
|
label: string;
|
|
98
|
-
color: UiColor;
|
|
99
101
|
count: number;
|
|
100
102
|
}> = {
|
|
101
|
-
renderRow: ({ item }) => (
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
renderRow: ({ item, isSelected }) => (
|
|
104
|
+
<ListCategoryRow
|
|
105
|
+
selected={isSelected}
|
|
106
|
+
title={item.label}
|
|
107
|
+
count={item.count}
|
|
108
|
+
expandable={false}
|
|
109
|
+
/>
|
|
108
110
|
),
|
|
109
111
|
renderDetail: () => (
|
|
110
112
|
<text fg={theme.colors.muted}>Select a profile to see details</text>
|
|
@@ -129,8 +131,7 @@ const predefinedRenderer: ItemRenderer<{
|
|
|
129
131
|
if (isSelected) {
|
|
130
132
|
return (
|
|
131
133
|
<text bg={theme.selection.bg} fg={theme.selection.fg}>
|
|
132
|
-
{"
|
|
133
|
-
{profile.name} {countStr}{" "}
|
|
134
|
+
{rowLead(true)} {profile.name} {countStr}{" "}
|
|
134
135
|
</text>
|
|
135
136
|
);
|
|
136
137
|
}
|
|
@@ -174,8 +175,8 @@ const predefinedRenderer: ItemRenderer<{
|
|
|
174
175
|
>{`\nMagus (${profile.magusPlugins.length})`}</text>
|
|
175
176
|
</box>
|
|
176
177
|
<box>
|
|
177
|
-
<text fg={theme.colors.
|
|
178
|
-
{profile.magusPlugins.map((p) => `
|
|
178
|
+
<text fg={theme.colors.text}>
|
|
179
|
+
{profile.magusPlugins.map((p) => ` • ${p}`).join("\n")}
|
|
179
180
|
</text>
|
|
180
181
|
</box>
|
|
181
182
|
|
|
@@ -186,8 +187,8 @@ const predefinedRenderer: ItemRenderer<{
|
|
|
186
187
|
>{`\nAnthropic (${profile.anthropicPlugins.length})`}</text>
|
|
187
188
|
</box>
|
|
188
189
|
<box>
|
|
189
|
-
<text fg={theme.colors.
|
|
190
|
-
{profile.anthropicPlugins.map((p) => `
|
|
190
|
+
<text fg={theme.colors.text}>
|
|
191
|
+
{profile.anthropicPlugins.map((p) => ` • ${p}`).join("\n")}
|
|
191
192
|
</text>
|
|
192
193
|
</box>
|
|
193
194
|
|
|
@@ -200,8 +201,8 @@ const predefinedRenderer: ItemRenderer<{
|
|
|
200
201
|
>{`\nSkills (${profile.skills.length})`}</text>
|
|
201
202
|
</box>
|
|
202
203
|
<box>
|
|
203
|
-
<text fg={theme.colors.
|
|
204
|
-
{profile.skills.map((s) => `
|
|
204
|
+
<text fg={theme.colors.text}>
|
|
205
|
+
{profile.skills.map((s) => ` • ${s}`).join("\n")}
|
|
205
206
|
</text>
|
|
206
207
|
</box>
|
|
207
208
|
</>
|
|
@@ -256,22 +257,22 @@ const savedRenderer: ItemRenderer<{ kind: "saved"; entry: ProfileEntry }> = {
|
|
|
256
257
|
if (isSelected) {
|
|
257
258
|
return (
|
|
258
259
|
<text bg={theme.selection.bg} fg={theme.selection.fg}>
|
|
259
|
-
{
|
|
260
|
+
{rowLead(true)}
|
|
260
261
|
{marker} {label}{" "}
|
|
261
262
|
</text>
|
|
262
263
|
);
|
|
263
264
|
}
|
|
264
265
|
|
|
265
|
-
|
|
266
|
-
entry.scope === "user" ? theme.scopes.user : theme.scopes.project;
|
|
266
|
+
// The words say the scope; it needs no hue of its own.
|
|
267
267
|
const scopeLabel = entry.scope === "user" ? "[user]" : "[proj]";
|
|
268
268
|
|
|
269
269
|
return (
|
|
270
270
|
<text fg={theme.colors.text}>
|
|
271
271
|
<span fg={entry.active ? theme.colors.success : theme.colors.text}>
|
|
272
|
+
{rowLead(false)}
|
|
272
273
|
{marker}{" "}
|
|
273
274
|
</span>
|
|
274
|
-
<span fg={
|
|
275
|
+
<span fg={theme.colors.muted}>{scopeLabel} </span>
|
|
275
276
|
<span fg={theme.colors.text}>{label}</span>
|
|
276
277
|
</text>
|
|
277
278
|
);
|
|
@@ -281,10 +282,6 @@ const savedRenderer: ItemRenderer<{ kind: "saved"; entry: ProfileEntry }> = {
|
|
|
281
282
|
const { entry: selectedProfile } = item;
|
|
282
283
|
const plugins = Object.keys(selectedProfile.plugins ?? {});
|
|
283
284
|
const cleanPlugins = plugins.map(stripSuffix);
|
|
284
|
-
const scopeColor =
|
|
285
|
-
selectedProfile.scope === "user"
|
|
286
|
-
? theme.scopes.user
|
|
287
|
-
: theme.scopes.project;
|
|
288
285
|
const scopeLabel =
|
|
289
286
|
selectedProfile.scope === "user"
|
|
290
287
|
? "User (~/.claude/profiles.json)"
|
|
@@ -295,9 +292,9 @@ const savedRenderer: ItemRenderer<{ kind: "saved"; entry: ProfileEntry }> = {
|
|
|
295
292
|
<text fg={theme.colors.info}>
|
|
296
293
|
<strong>{selectedProfile.name}</strong>
|
|
297
294
|
</text>
|
|
298
|
-
<box marginTop={1}>
|
|
295
|
+
<box flexDirection="row" marginTop={1}>
|
|
299
296
|
<text fg={theme.colors.muted}>Scope: </text>
|
|
300
|
-
<text fg={
|
|
297
|
+
<text fg={theme.colors.text}>{scopeLabel}</text>
|
|
301
298
|
{/* Stated in words as well as the row glyph: the detail pane is
|
|
302
299
|
where someone looks to check, and "●" alone is not an answer
|
|
303
300
|
to "is this the one that is running?". */}
|
|
@@ -330,36 +327,36 @@ const savedRenderer: ItemRenderer<{ kind: "saved"; entry: ProfileEntry }> = {
|
|
|
330
327
|
)}
|
|
331
328
|
</box>
|
|
332
329
|
<box marginTop={2} flexDirection="column">
|
|
333
|
-
<box>
|
|
330
|
+
<box flexDirection="row">
|
|
334
331
|
<text bg={theme.selection.bg} fg={theme.selection.fg}>
|
|
335
332
|
{" "}
|
|
336
333
|
Enter/a{" "}
|
|
337
334
|
</text>
|
|
338
335
|
<text fg={theme.colors.muted}> Apply profile</text>
|
|
339
336
|
</box>
|
|
340
|
-
<box marginTop={1}>
|
|
337
|
+
<box flexDirection="row" marginTop={1}>
|
|
341
338
|
<text bg={theme.colors.dim} fg={theme.hints.fg}>
|
|
342
339
|
{" "}
|
|
343
340
|
r{" "}
|
|
344
341
|
</text>
|
|
345
342
|
<text fg={theme.colors.muted}> Rename</text>
|
|
346
343
|
</box>
|
|
347
|
-
<box marginTop={1}>
|
|
344
|
+
<box flexDirection="row" marginTop={1}>
|
|
348
345
|
<text bg={theme.colors.danger} fg={theme.hints.fg}>
|
|
349
346
|
{" "}
|
|
350
347
|
d{" "}
|
|
351
348
|
</text>
|
|
352
349
|
<text fg={theme.colors.muted}> Delete</text>
|
|
353
350
|
</box>
|
|
354
|
-
<box marginTop={1}>
|
|
355
|
-
<text bg={theme.colors.
|
|
351
|
+
<box flexDirection="row" marginTop={1}>
|
|
352
|
+
<text bg={theme.colors.dim} fg={theme.hints.fg}>
|
|
356
353
|
{" "}
|
|
357
354
|
c{" "}
|
|
358
355
|
</text>
|
|
359
356
|
<text fg={theme.colors.muted}> Copy JSON to clipboard</text>
|
|
360
357
|
</box>
|
|
361
|
-
<box marginTop={1}>
|
|
362
|
-
<text bg={theme.colors.
|
|
358
|
+
<box flexDirection="row" marginTop={1}>
|
|
359
|
+
<text bg={theme.colors.dim} fg={theme.hints.fg}>
|
|
363
360
|
{" "}
|
|
364
361
|
i{" "}
|
|
365
362
|
</text>
|
|
@@ -410,7 +407,6 @@ export function buildProfileListItems(
|
|
|
410
407
|
items.push({
|
|
411
408
|
kind: "header",
|
|
412
409
|
label: "Presets",
|
|
413
|
-
color: theme.colors.accent,
|
|
414
410
|
count: PREDEFINED_PROFILES.length,
|
|
415
411
|
});
|
|
416
412
|
for (const p of PREDEFINED_PROFILES) {
|
|
@@ -419,7 +415,6 @@ export function buildProfileListItems(
|
|
|
419
415
|
items.push({
|
|
420
416
|
kind: "header",
|
|
421
417
|
label: "Your Profiles",
|
|
422
|
-
color: theme.colors.info,
|
|
423
418
|
count: profileList.length,
|
|
424
419
|
});
|
|
425
420
|
for (const e of profileList) {
|