claudeup 4.35.0 → 4.36.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 (63) hide show
  1. package/package.json +4 -4
  2. package/src/__tests__/git-worktree.test.ts +108 -0
  3. package/src/__tests__/scope-squares.test.tsx +165 -0
  4. package/src/__tests__/theme-adaptive-colors.test.ts +307 -0
  5. package/src/__tests__/uppercase-keybindings.test.ts +101 -0
  6. package/src/__tests__/worktree-registry-resolution.test.ts +107 -0
  7. package/src/main.tsx +21 -5
  8. package/src/opentui.d.ts +21 -12
  9. package/src/services/claude-settings.ts +37 -7
  10. package/src/services/git-worktree.ts +129 -0
  11. package/src/services/plugin-manager.ts +10 -1
  12. package/src/ui/App.tsx +19 -12
  13. package/src/ui/adapters/pluginsAdapter.ts +174 -168
  14. package/src/ui/adapters/settingsAdapter.ts +119 -116
  15. package/src/ui/adapters/skillsAdapter.ts +203 -196
  16. package/src/ui/components/CategoryHeader.tsx +9 -8
  17. package/src/ui/components/EmptyFilterState.tsx +10 -5
  18. package/src/ui/components/FlagDetailEditor.tsx +0 -0
  19. package/src/ui/components/ScopeIndicator.tsx +10 -6
  20. package/src/ui/components/ScrollableList.tsx +3 -2
  21. package/src/ui/components/SearchInput.tsx +2 -1
  22. package/src/ui/components/StyledText.tsx +5 -4
  23. package/src/ui/components/TabBar.tsx +4 -3
  24. package/src/ui/components/layout/FooterHints.tsx +37 -30
  25. package/src/ui/components/layout/Panel.tsx +6 -5
  26. package/src/ui/components/layout/ProgressBar.tsx +7 -6
  27. package/src/ui/components/layout/ScopeTabs.tsx +6 -5
  28. package/src/ui/components/layout/ScreenLayout.tsx +27 -24
  29. package/src/ui/components/layout/index.ts +3 -3
  30. package/src/ui/components/modals/ConfirmModal.tsx +12 -11
  31. package/src/ui/components/modals/InputModal.tsx +14 -6
  32. package/src/ui/components/modals/LoadingModal.tsx +6 -5
  33. package/src/ui/components/modals/MessageModal.tsx +9 -8
  34. package/src/ui/components/modals/SelectModal.tsx +11 -7
  35. package/src/ui/components/modals/VersionMismatchModal.tsx +14 -16
  36. package/src/ui/components/primitives/ActionHints.tsx +26 -26
  37. package/src/ui/components/primitives/DetailSection.tsx +13 -12
  38. package/src/ui/components/primitives/KeyValueLine.tsx +9 -8
  39. package/src/ui/components/primitives/ListCategoryRow.tsx +25 -27
  40. package/src/ui/components/primitives/MetaText.tsx +3 -3
  41. package/src/ui/components/primitives/ScopeDetail.tsx +48 -48
  42. package/src/ui/components/primitives/ScopeSquares.tsx +47 -22
  43. package/src/ui/components/primitives/SelectableRow.tsx +22 -16
  44. package/src/ui/hooks/useGitignoreModal.ts +78 -74
  45. package/src/ui/registry.ts +11 -11
  46. package/src/ui/renderers/cliToolRenderers.tsx +260 -203
  47. package/src/ui/renderers/gitignoreRenderers.tsx +43 -42
  48. package/src/ui/renderers/mcpRenderers.tsx +121 -117
  49. package/src/ui/renderers/pluginRenderers.tsx +528 -471
  50. package/src/ui/renderers/profileRenderers.tsx +346 -300
  51. package/src/ui/renderers/settingsRenderers.tsx +183 -176
  52. package/src/ui/renderers/skillRenderers.tsx +410 -326
  53. package/src/ui/screens/AliasScreen.tsx +1336 -1309
  54. package/src/ui/screens/CliToolsScreen.tsx +92 -40
  55. package/src/ui/screens/EnvVarsScreen.tsx +19 -13
  56. package/src/ui/screens/GitignoreScreen.tsx +510 -493
  57. package/src/ui/screens/McpRegistryScreen.tsx +28 -21
  58. package/src/ui/screens/McpScreen.tsx +12 -3
  59. package/src/ui/screens/PluginsScreen.tsx +17 -7
  60. package/src/ui/screens/ProfilesScreen.tsx +39 -23
  61. package/src/ui/screens/SkillsScreen.tsx +832 -688
  62. package/src/ui/theme-mode.ts +73 -0
  63. package/src/ui/theme.ts +147 -53
@@ -1,29 +1,30 @@
1
1
  import {
2
- SETTINGS_CATALOG,
3
- type SettingCategory,
4
- type SettingDefinition,
2
+ SETTINGS_CATALOG,
3
+ type SettingCategory,
4
+ type SettingDefinition,
5
5
  } from "../../data/settings-catalog.js";
6
6
  import type { ScopedSettingValues } from "../../services/settings-manager.js";
7
+ import { theme, type UiColor } from "../theme.js";
7
8
 
8
9
  // ─── Item types ────────────────────────────────────────────────────────────────
9
10
 
10
11
  export interface SettingsCategoryItem {
11
- id: string;
12
- kind: "category";
13
- label: string;
14
- category: SettingCategory;
15
- isDefault: true;
12
+ id: string;
13
+ kind: "category";
14
+ label: string;
15
+ category: SettingCategory;
16
+ isDefault: true;
16
17
  }
17
18
 
18
19
  export interface SettingsSettingItem {
19
- id: string;
20
- kind: "setting";
21
- label: string;
22
- category: SettingCategory;
23
- setting: SettingDefinition;
24
- scopedValues: ScopedSettingValues;
25
- effectiveValue: string | undefined;
26
- isDefault: boolean;
20
+ id: string;
21
+ kind: "setting";
22
+ label: string;
23
+ category: SettingCategory;
24
+ setting: SettingDefinition;
25
+ scopedValues: ScopedSettingValues;
26
+ effectiveValue: string | undefined;
27
+ isDefault: boolean;
27
28
  }
28
29
 
29
30
  export type SettingsBrowserItem = SettingsCategoryItem | SettingsSettingItem;
@@ -31,92 +32,94 @@ export type SettingsBrowserItem = SettingsCategoryItem | SettingsSettingItem;
31
32
  // ─── Constants ─────────────────────────────────────────────────────────────────
32
33
 
33
34
  export const CATEGORY_LABELS: Record<SettingCategory, string> = {
34
- recommended: "Recommended",
35
- agents: "Agents & Teams",
36
- models: "Models & Thinking",
37
- workflow: "Workflow",
38
- terminal: "Terminal & UI",
39
- performance: "Performance",
40
- advanced: "Advanced",
35
+ recommended: "Recommended",
36
+ agents: "Agents & Teams",
37
+ models: "Models & Thinking",
38
+ workflow: "Workflow",
39
+ terminal: "Terminal & UI",
40
+ performance: "Performance",
41
+ advanced: "Advanced",
41
42
  };
42
43
 
43
44
  export const CATEGORY_ORDER: SettingCategory[] = [
44
- "recommended",
45
- "agents",
46
- "models",
47
- "workflow",
48
- "terminal",
49
- "performance",
50
- "advanced",
45
+ "recommended",
46
+ "agents",
47
+ "models",
48
+ "workflow",
49
+ "terminal",
50
+ "performance",
51
+ "advanced",
51
52
  ];
52
53
 
53
- export const CATEGORY_BG: Record<SettingCategory, string> = {
54
- recommended: "#2e7d32",
55
- agents: "#00838f",
56
- models: "#4527a0",
57
- workflow: "#1565c0",
58
- terminal: "#4e342e",
59
- performance: "#6a1b9a",
60
- advanced: "#e65100",
54
+ export const CATEGORY_BG: Record<SettingCategory, UiColor> = {
55
+ recommended: theme.colors.success,
56
+ agents: theme.colors.info,
57
+ models: theme.colors.accent,
58
+ workflow: theme.colors.link,
59
+ terminal: theme.colors.warning,
60
+ performance: theme.colors.accent,
61
+ advanced: theme.colors.warning,
61
62
  };
62
63
 
63
- export const CATEGORY_COLOR: Record<SettingCategory, string> = {
64
- recommended: "green",
65
- agents: "cyan",
66
- models: "cyan",
67
- workflow: "blue",
68
- terminal: "blue",
69
- performance: "magentaBright",
70
- advanced: "yellow",
64
+ export const CATEGORY_COLOR: Record<SettingCategory, UiColor> = {
65
+ recommended: theme.colors.success,
66
+ agents: theme.colors.info,
67
+ models: theme.colors.info,
68
+ workflow: theme.colors.link,
69
+ terminal: theme.colors.link,
70
+ performance: "magentaBright",
71
+ advanced: theme.colors.warning,
71
72
  };
72
73
 
73
74
  export const CATEGORY_DESCRIPTIONS: Record<SettingCategory, string> = {
74
- recommended: "Most impactful settings every user should know.",
75
- agents: "Agent teams, task lists, and subagent configuration.",
76
- models: "Model selection, extended thinking, and effort.",
77
- workflow: "Git, plans, permissions, output style, and languages.",
78
- terminal: "Shell, spinners, progress bars, voice, and UI behavior.",
79
- performance: "Compaction, token limits, timeouts, and caching.",
80
- advanced: "Telemetry, updates, debugging, and internal controls.",
75
+ recommended: "Most impactful settings every user should know.",
76
+ agents: "Agent teams, task lists, and subagent configuration.",
77
+ models: "Model selection, extended thinking, and effort.",
78
+ workflow: "Git, plans, permissions, output style, and languages.",
79
+ terminal: "Shell, spinners, progress bars, voice, and UI behavior.",
80
+ performance: "Compaction, token limits, timeouts, and caching.",
81
+ advanced: "Telemetry, updates, debugging, and internal controls.",
81
82
  };
82
83
 
83
84
  // ─── Helpers ───────────────────────────────────────────────────────────────────
84
85
 
85
86
  /** Get the effective value (project overrides user) */
86
87
  export function getEffectiveValue(
87
- scoped: ScopedSettingValues,
88
+ scoped: ScopedSettingValues,
88
89
  ): string | undefined {
89
- return scoped.project !== undefined ? scoped.project : scoped.user;
90
+ return scoped.project !== undefined ? scoped.project : scoped.user;
90
91
  }
91
92
 
92
93
  export function formatValue(
93
- setting: SettingDefinition,
94
- value: string | undefined,
94
+ setting: SettingDefinition,
95
+ value: string | undefined,
95
96
  ): string {
96
- if (value === undefined || value === "") {
97
- if (setting.type === "boolean" && setting.defaultValue !== undefined) {
98
- return setting.defaultValue === "true" ? "on" : "off";
99
- }
100
- if (setting.type === "select" && setting.defaultValue !== undefined) {
101
- const opt = setting.options?.find((o) => o.value === setting.defaultValue);
102
- return opt ? opt.label : setting.defaultValue;
103
- }
104
- return "—";
105
- }
106
-
107
- if (setting.type === "boolean") {
108
- return value === "true" || value === "1" ? "on" : "off";
109
- }
110
-
111
- if (setting.type === "select" && setting.options) {
112
- const opt = setting.options.find((o) => o.value === value);
113
- return opt ? opt.label : value;
114
- }
115
-
116
- if (value.length > 12) {
117
- return value.slice(0, 12) + "…";
118
- }
119
- return value;
97
+ if (value === undefined || value === "") {
98
+ if (setting.type === "boolean" && setting.defaultValue !== undefined) {
99
+ return setting.defaultValue === "true" ? "on" : "off";
100
+ }
101
+ if (setting.type === "select" && setting.defaultValue !== undefined) {
102
+ const opt = setting.options?.find(
103
+ (o) => o.value === setting.defaultValue,
104
+ );
105
+ return opt ? opt.label : setting.defaultValue;
106
+ }
107
+ return "—";
108
+ }
109
+
110
+ if (setting.type === "boolean") {
111
+ return value === "true" || value === "1" ? "on" : "off";
112
+ }
113
+
114
+ if (setting.type === "select" && setting.options) {
115
+ const opt = setting.options.find((o) => o.value === value);
116
+ return opt ? opt.label : value;
117
+ }
118
+
119
+ if (value.length > 12) {
120
+ return value.slice(0, 12) + "…";
121
+ }
122
+ return value;
120
123
  }
121
124
 
122
125
  // ─── Adapter ───────────────────────────────────────────────────────────────────
@@ -126,40 +129,40 @@ export function formatValue(
126
129
  * Extracted from SettingsScreen so it can be tested independently.
127
130
  */
128
131
  export function buildSettingsBrowserItems(
129
- values: Map<string, ScopedSettingValues>,
132
+ values: Map<string, ScopedSettingValues>,
130
133
  ): SettingsBrowserItem[] {
131
- const items: SettingsBrowserItem[] = [];
132
-
133
- for (const category of CATEGORY_ORDER) {
134
- items.push({
135
- id: `cat:${category}`,
136
- kind: "category",
137
- label: CATEGORY_LABELS[category],
138
- category,
139
- isDefault: true,
140
- });
141
-
142
- const categorySettings = SETTINGS_CATALOG.filter(
143
- (s) => s.category === category,
144
- );
145
- for (const setting of categorySettings) {
146
- const scoped = values.get(setting.id) || {
147
- user: undefined,
148
- project: undefined,
149
- };
150
- const effective = getEffectiveValue(scoped);
151
- items.push({
152
- id: `setting:${setting.id}`,
153
- kind: "setting",
154
- label: setting.name,
155
- category,
156
- setting,
157
- scopedValues: scoped,
158
- effectiveValue: effective,
159
- isDefault: effective === undefined || effective === "",
160
- });
161
- }
162
- }
163
-
164
- return items;
134
+ const items: SettingsBrowserItem[] = [];
135
+
136
+ for (const category of CATEGORY_ORDER) {
137
+ items.push({
138
+ id: `cat:${category}`,
139
+ kind: "category",
140
+ label: CATEGORY_LABELS[category],
141
+ category,
142
+ isDefault: true,
143
+ });
144
+
145
+ const categorySettings = SETTINGS_CATALOG.filter(
146
+ (s) => s.category === category,
147
+ );
148
+ for (const setting of categorySettings) {
149
+ const scoped = values.get(setting.id) || {
150
+ user: undefined,
151
+ project: undefined,
152
+ };
153
+ const effective = getEffectiveValue(scoped);
154
+ items.push({
155
+ id: `setting:${setting.id}`,
156
+ kind: "setting",
157
+ label: setting.name,
158
+ category,
159
+ setting,
160
+ scopedValues: scoped,
161
+ effectiveValue: effective,
162
+ isDefault: effective === undefined || effective === "",
163
+ });
164
+ }
165
+ }
166
+
167
+ return items;
165
168
  }