claude-think 0.5.2 → 0.5.3

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/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.3] - 2026-02-09
9
+
10
+ ### Added
11
+ - **Inline profile creation in TUI** — create new profiles with role-based defaults without leaving the TUI
12
+ - Select a role (Senior Dev, Mid-level, Junior, Founder, Student, Hobbyist) and profile files are auto-generated
13
+ - No longer exits to `think setup` CLI wizard when creating empty profiles
14
+ - **`P profiles` visible in status bar** — profile switching shortcut is now discoverable
15
+
16
+ ### Changed
17
+ - Extracted profile generation logic into shared `profile-generator.ts` module (used by both CLI setup and TUI)
18
+
8
19
  ## [0.5.2] - 2026-02-08
9
20
 
10
21
  ### Fixed
package/README.md CHANGED
@@ -79,7 +79,7 @@ Switch between different configurations for work, personal projects, or clients:
79
79
  think switch work # Switch profile (auto-syncs)
80
80
  ```
81
81
 
82
- Press `P` in the TUI to manage profiles interactively (create, delete, switch).
82
+ Press `P` in the TUI to manage profiles interactively (create, delete, switch). New profiles can be created with role-based defaults without leaving the TUI.
83
83
 
84
84
  ## TUI
85
85
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-think",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Personal context manager for Claude - manage your preferences, patterns, and memory",
5
5
  "author": "Amit Feldman",
6
6
  "license": "MIT",
@@ -7,179 +7,19 @@ import { ensureProfilesStructure } from "../../core/profiles.ts";
7
7
  import { generatePlugin } from "../../core/generator.ts";
8
8
  import { detectProject } from "../../core/project-detect.ts";
9
9
  import type { ProjectInfo } from "../../core/project-detect.ts";
10
-
11
- // ── Description maps ──────────────────────────────────────────────
12
-
13
- const styleDescriptions: Record<string, string[]> = {
14
- direct: [
15
- "Be direct and minimal - no fluff, just answers and code",
16
- "Skip lengthy reasoning unless asked",
17
- "Don't explain obvious things",
18
- ],
19
- conversational: [
20
- "Be friendly but efficient",
21
- "Brief explanations when helpful",
22
- "Keep a conversational tone",
23
- ],
24
- detailed: [
25
- "Provide thorough explanations",
26
- "Include context and reasoning",
27
- "Explain trade-offs and alternatives",
28
- ],
29
- };
30
-
31
- const roleDescriptions: Record<string, string> = {
32
- "senior-dev": "Senior developer - experienced and autonomous, prefers concise guidance",
33
- "mid-dev": "Mid-level developer - competent but appreciates context on complex topics",
34
- "junior-dev": "Junior developer - learning, benefits from more explanation and examples",
35
- founder: "Founder/Tech Lead - focused on shipping, pragmatic decisions over perfect code",
36
- student: "Student - learning fundamentals, explain concepts when relevant",
37
- hobbyist: "Hobbyist - exploring for fun, balance learning with getting things done",
38
- };
39
-
40
- const personalityDescriptions: Record<string, string[]> = {
41
- "pair-programmer": [
42
- "Act as a pair programmer - think out loud, collaborate on solutions",
43
- "Discuss trade-offs and alternatives when relevant",
44
- "Catch potential issues early, suggest improvements as we go",
45
- ],
46
- "senior-dev": [
47
- "Act as a senior developer - give direction, review approaches",
48
- "Point out potential issues and better patterns",
49
- "Be opinionated when it matters, flexible when it doesn't",
50
- ],
51
- assistant: [
52
- "Act as an efficient assistant - execute tasks with minimal chatter",
53
- "Ask clarifying questions only when truly needed",
54
- "Focus on delivering what was asked",
55
- ],
56
- mentor: [
57
- "Act as a mentor - teach concepts, explain the 'why'",
58
- "Use opportunities to share knowledge",
59
- "Suggest learning resources when helpful",
60
- ],
61
- "rubber-duck": [
62
- "Act as a rubber duck - help me think through problems",
63
- "Ask probing questions rather than giving immediate answers",
64
- "Help me discover solutions myself",
65
- ],
66
- };
67
-
68
- const planningDescriptions: Record<string, string> = {
69
- "plan-first": "Discuss architecture and approach before writing code",
70
- iterate: "Start with a rough plan, refine as we go",
71
- "dive-in": "Start coding quickly, figure out structure as needed",
72
- };
73
-
74
- const testingDescriptions: Record<string, string> = {
75
- tdd: "Write tests first (TDD), then implement",
76
- "test-after": "Write tests after implementation",
77
- "critical-paths": "Test critical paths and edge cases",
78
- minimal: "Minimal testing - add tests when necessary",
79
- };
80
-
81
- const reviewDescriptions: Record<string, string> = {
82
- "review-before-commit": "Review changes before committing - catch issues early",
83
- "review-on-request": "Review code when explicitly asked",
84
- "self-review": "I review my own code, no automatic reviews needed",
85
- };
86
-
87
- const gitDescriptions: Record<string, string> = {
88
- "small-commits": "Small, atomic commits - easy to review and revert",
89
- "feature-branches": "Feature branches with squash merges",
90
- "trunk-based": "Trunk-based development with feature flags",
91
- flexible: "Flexible git workflow based on project needs",
92
- };
93
-
94
- const docDescriptions: Record<string, string> = {
95
- inline: "Document with inline comments as code is written",
96
- "readme-driven": "README-driven development - docs first",
97
- minimal: "Minimal documentation - code should be self-documenting",
98
- "on-request": "Add documentation when requested",
99
- };
100
-
101
- const debugDescriptions: Record<string, string> = {
102
- systematic: "Debug systematically - isolate, reproduce, trace",
103
- hypothesis: "Hypothesis-driven debugging - test likely causes first",
104
- printf: "Printf debugging - add logs and observe",
105
- "whatever-works": "Whatever works to fix the issue quickly",
106
- };
107
-
108
- const refactorDescriptions: Record<string, string> = {
109
- proactive: "Proactively suggest refactoring opportunities",
110
- "on-request": "Refactor only when asked",
111
- "boy-scout": "Boy scout rule - leave code better than you found it",
112
- "if-broken": "Don't refactor working code unless necessary",
113
- };
114
-
115
- // ── Role-based workflow defaults ──────────────────────────────────
116
-
117
- interface WorkflowDefaults {
118
- planning: string;
119
- testing: string;
120
- review: string;
121
- git: string;
122
- docs: string;
123
- debug: string;
124
- refactor: string;
125
- }
126
-
127
- const roleWorkflowDefaults: Record<string, WorkflowDefaults> = {
128
- "senior-dev": {
129
- planning: "plan-first",
130
- testing: "tdd",
131
- review: "review-before-commit",
132
- git: "small-commits",
133
- docs: "minimal",
134
- debug: "systematic",
135
- refactor: "boy-scout",
136
- },
137
- "mid-dev": {
138
- planning: "iterate",
139
- testing: "test-after",
140
- review: "review-before-commit",
141
- git: "feature-branches",
142
- docs: "inline",
143
- debug: "hypothesis",
144
- refactor: "on-request",
145
- },
146
- "junior-dev": {
147
- planning: "plan-first",
148
- testing: "test-after",
149
- review: "review-before-commit",
150
- git: "feature-branches",
151
- docs: "inline",
152
- debug: "systematic",
153
- refactor: "proactive",
154
- },
155
- founder: {
156
- planning: "dive-in",
157
- testing: "critical-paths",
158
- review: "self-review",
159
- git: "trunk-based",
160
- docs: "minimal",
161
- debug: "whatever-works",
162
- refactor: "if-broken",
163
- },
164
- student: {
165
- planning: "plan-first",
166
- testing: "test-after",
167
- review: "review-on-request",
168
- git: "feature-branches",
169
- docs: "inline",
170
- debug: "systematic",
171
- refactor: "proactive",
172
- },
173
- hobbyist: {
174
- planning: "iterate",
175
- testing: "minimal",
176
- review: "self-review",
177
- git: "flexible",
178
- docs: "on-request",
179
- debug: "printf",
180
- refactor: "if-broken",
181
- },
182
- };
10
+ import {
11
+ styleDescriptions,
12
+ roleDescriptions,
13
+ personalityDescriptions,
14
+ planningDescriptions,
15
+ testingDescriptions,
16
+ reviewDescriptions,
17
+ gitDescriptions,
18
+ docDescriptions,
19
+ debugDescriptions,
20
+ refactorDescriptions,
21
+ roleWorkflowDefaults,
22
+ } from "../../core/profile-generator.ts";
183
23
 
184
24
  // ── Helpers ───────────────────────────────────────────────────────
185
25
 
@@ -0,0 +1,290 @@
1
+ import { writeFile } from "fs/promises";
2
+ import { join } from "path";
3
+ import { CONFIG } from "./config.ts";
4
+
5
+ // ── Description maps ──────────────────────────────────────────────
6
+
7
+ export const styleDescriptions: Record<string, string[]> = {
8
+ direct: [
9
+ "Be direct and minimal - no fluff, just answers and code",
10
+ "Skip lengthy reasoning unless asked",
11
+ "Don't explain obvious things",
12
+ ],
13
+ conversational: [
14
+ "Be friendly but efficient",
15
+ "Brief explanations when helpful",
16
+ "Keep a conversational tone",
17
+ ],
18
+ detailed: [
19
+ "Provide thorough explanations",
20
+ "Include context and reasoning",
21
+ "Explain trade-offs and alternatives",
22
+ ],
23
+ };
24
+
25
+ export const roleDescriptions: Record<string, string> = {
26
+ "senior-dev": "Senior developer - experienced and autonomous, prefers concise guidance",
27
+ "mid-dev": "Mid-level developer - competent but appreciates context on complex topics",
28
+ "junior-dev": "Junior developer - learning, benefits from more explanation and examples",
29
+ founder: "Founder/Tech Lead - focused on shipping, pragmatic decisions over perfect code",
30
+ student: "Student - learning fundamentals, explain concepts when relevant",
31
+ hobbyist: "Hobbyist - exploring for fun, balance learning with getting things done",
32
+ };
33
+
34
+ export const personalityDescriptions: Record<string, string[]> = {
35
+ "pair-programmer": [
36
+ "Act as a pair programmer - think out loud, collaborate on solutions",
37
+ "Discuss trade-offs and alternatives when relevant",
38
+ "Catch potential issues early, suggest improvements as we go",
39
+ ],
40
+ "senior-dev": [
41
+ "Act as a senior developer - give direction, review approaches",
42
+ "Point out potential issues and better patterns",
43
+ "Be opinionated when it matters, flexible when it doesn't",
44
+ ],
45
+ assistant: [
46
+ "Act as an efficient assistant - execute tasks with minimal chatter",
47
+ "Ask clarifying questions only when truly needed",
48
+ "Focus on delivering what was asked",
49
+ ],
50
+ mentor: [
51
+ "Act as a mentor - teach concepts, explain the 'why'",
52
+ "Use opportunities to share knowledge",
53
+ "Suggest learning resources when helpful",
54
+ ],
55
+ "rubber-duck": [
56
+ "Act as a rubber duck - help me think through problems",
57
+ "Ask probing questions rather than giving immediate answers",
58
+ "Help me discover solutions myself",
59
+ ],
60
+ };
61
+
62
+ export const planningDescriptions: Record<string, string> = {
63
+ "plan-first": "Discuss architecture and approach before writing code",
64
+ iterate: "Start with a rough plan, refine as we go",
65
+ "dive-in": "Start coding quickly, figure out structure as needed",
66
+ };
67
+
68
+ export const testingDescriptions: Record<string, string> = {
69
+ tdd: "Write tests first (TDD), then implement",
70
+ "test-after": "Write tests after implementation",
71
+ "critical-paths": "Test critical paths and edge cases",
72
+ minimal: "Minimal testing - add tests when necessary",
73
+ };
74
+
75
+ export const reviewDescriptions: Record<string, string> = {
76
+ "review-before-commit": "Review changes before committing - catch issues early",
77
+ "review-on-request": "Review code when explicitly asked",
78
+ "self-review": "I review my own code, no automatic reviews needed",
79
+ };
80
+
81
+ export const gitDescriptions: Record<string, string> = {
82
+ "small-commits": "Small, atomic commits - easy to review and revert",
83
+ "feature-branches": "Feature branches with squash merges",
84
+ "trunk-based": "Trunk-based development with feature flags",
85
+ flexible: "Flexible git workflow based on project needs",
86
+ };
87
+
88
+ export const docDescriptions: Record<string, string> = {
89
+ inline: "Document with inline comments as code is written",
90
+ "readme-driven": "README-driven development - docs first",
91
+ minimal: "Minimal documentation - code should be self-documenting",
92
+ "on-request": "Add documentation when requested",
93
+ };
94
+
95
+ export const debugDescriptions: Record<string, string> = {
96
+ systematic: "Debug systematically - isolate, reproduce, trace",
97
+ hypothesis: "Hypothesis-driven debugging - test likely causes first",
98
+ printf: "Printf debugging - add logs and observe",
99
+ "whatever-works": "Whatever works to fix the issue quickly",
100
+ };
101
+
102
+ export const refactorDescriptions: Record<string, string> = {
103
+ proactive: "Proactively suggest refactoring opportunities",
104
+ "on-request": "Refactor only when asked",
105
+ "boy-scout": "Boy scout rule - leave code better than you found it",
106
+ "if-broken": "Don't refactor working code unless necessary",
107
+ };
108
+
109
+ // ── Role-based workflow defaults ──────────────────────────────────
110
+
111
+ export interface WorkflowDefaults {
112
+ planning: string;
113
+ testing: string;
114
+ review: string;
115
+ git: string;
116
+ docs: string;
117
+ debug: string;
118
+ refactor: string;
119
+ }
120
+
121
+ export const roleWorkflowDefaults: Record<string, WorkflowDefaults> = {
122
+ "senior-dev": {
123
+ planning: "plan-first",
124
+ testing: "tdd",
125
+ review: "review-before-commit",
126
+ git: "small-commits",
127
+ docs: "minimal",
128
+ debug: "systematic",
129
+ refactor: "boy-scout",
130
+ },
131
+ "mid-dev": {
132
+ planning: "iterate",
133
+ testing: "test-after",
134
+ review: "review-before-commit",
135
+ git: "feature-branches",
136
+ docs: "inline",
137
+ debug: "hypothesis",
138
+ refactor: "on-request",
139
+ },
140
+ "junior-dev": {
141
+ planning: "plan-first",
142
+ testing: "test-after",
143
+ review: "review-before-commit",
144
+ git: "feature-branches",
145
+ docs: "inline",
146
+ debug: "systematic",
147
+ refactor: "proactive",
148
+ },
149
+ founder: {
150
+ planning: "dive-in",
151
+ testing: "critical-paths",
152
+ review: "self-review",
153
+ git: "trunk-based",
154
+ docs: "minimal",
155
+ debug: "whatever-works",
156
+ refactor: "if-broken",
157
+ },
158
+ student: {
159
+ planning: "plan-first",
160
+ testing: "test-after",
161
+ review: "review-on-request",
162
+ git: "feature-branches",
163
+ docs: "inline",
164
+ debug: "systematic",
165
+ refactor: "proactive",
166
+ },
167
+ hobbyist: {
168
+ planning: "iterate",
169
+ testing: "minimal",
170
+ review: "self-review",
171
+ git: "flexible",
172
+ docs: "on-request",
173
+ debug: "printf",
174
+ refactor: "if-broken",
175
+ },
176
+ };
177
+
178
+ // ── Role-based personality/style defaults ─────────────────────────
179
+
180
+ const rolePersonalityDefaults: Record<string, string> = {
181
+ "senior-dev": "assistant",
182
+ "mid-dev": "pair-programmer",
183
+ "junior-dev": "mentor",
184
+ founder: "assistant",
185
+ student: "mentor",
186
+ hobbyist: "pair-programmer",
187
+ };
188
+
189
+ const roleStyleDefaults: Record<string, string> = {
190
+ "senior-dev": "direct",
191
+ "mid-dev": "conversational",
192
+ "junior-dev": "detailed",
193
+ founder: "direct",
194
+ student: "detailed",
195
+ hobbyist: "conversational",
196
+ };
197
+
198
+ // ── Profile generation ────────────────────────────────────────────
199
+
200
+ export interface ProfileGenerationOptions {
201
+ name?: string;
202
+ role: string;
203
+ style?: string;
204
+ personality?: string;
205
+ }
206
+
207
+ /**
208
+ * Generate profile files with role-based defaults.
209
+ * Creates profile.md and preferences/anti-patterns.md in the given profile directory.
210
+ */
211
+ export async function generateProfileFiles(
212
+ profileDir: string,
213
+ options: ProfileGenerationOptions,
214
+ ): Promise<void> {
215
+ const { role } = options;
216
+ const name = options.name ?? "";
217
+ const style = options.style ?? roleStyleDefaults[role] ?? "direct";
218
+ const personality = options.personality ?? rolePersonalityDefaults[role] ?? "assistant";
219
+ const defaults = roleWorkflowDefaults[role] ?? roleWorkflowDefaults["senior-dev"]!;
220
+
221
+ // ── Write profile.md ────────────────────────────────────────────
222
+ const profileContent = `---
223
+ name: ${name}
224
+ role: ${role}
225
+ style: ${style}
226
+ personality: ${personality}
227
+ ---
228
+
229
+ # Who I Am
230
+
231
+ ${roleDescriptions[role] ?? role}
232
+
233
+ # How Claude Should Behave
234
+
235
+ ${(personalityDescriptions[personality] ?? []).map((line) => `- ${line}`).join("\n")}
236
+
237
+ # Communication Style
238
+
239
+ ${(styleDescriptions[style] ?? []).map((line) => `- ${line}`).join("\n")}
240
+ - No emojis unless explicitly requested
241
+ - Show code when it's clearer than explanation
242
+
243
+ # Development Workflow
244
+
245
+ ## Planning
246
+ - ${planningDescriptions[defaults.planning] ?? defaults.planning}
247
+
248
+ ## Testing
249
+ - ${testingDescriptions[defaults.testing] ?? defaults.testing}
250
+
251
+ ## Code Review
252
+ - ${reviewDescriptions[defaults.review] ?? defaults.review}
253
+
254
+ ## Git Workflow
255
+ - ${gitDescriptions[defaults.git] ?? defaults.git}
256
+
257
+ ## Documentation
258
+ - ${docDescriptions[defaults.docs] ?? defaults.docs}
259
+
260
+ ## Debugging
261
+ - ${debugDescriptions[defaults.debug] ?? defaults.debug}
262
+
263
+ ## Refactoring
264
+ - ${refactorDescriptions[defaults.refactor] ?? defaults.refactor}
265
+ `;
266
+
267
+ await writeFile(join(profileDir, CONFIG.files.profile), profileContent);
268
+
269
+ // ── Write anti-patterns.md (moderate defaults) ──────────────────
270
+ const antiContent = `# Anti-Patterns to Avoid
271
+
272
+ ## Code Style
273
+ - Don't add comments for obvious code
274
+ - Don't add type annotations that can be inferred
275
+ - Don't create abstractions for one-time use
276
+
277
+ ## Architecture
278
+ - Don't over-engineer solutions
279
+ - Don't add features that weren't requested
280
+ - Don't create unnecessary indirection
281
+ - Don't add "future-proofing" complexity
282
+
283
+ ## Communication
284
+ - Don't explain obvious things
285
+ - Don't repeat back what was just said
286
+ - Don't pad responses with unnecessary context
287
+ `;
288
+
289
+ await writeFile(join(profileDir, CONFIG.files.antiPatterns), antiContent);
290
+ }
package/src/tui/App.tsx CHANGED
@@ -16,7 +16,6 @@ import { ProfileSwitcher } from "./components/ProfileSwitcher.tsx";
16
16
  import { FullScreen, useTerminalSize } from "./components/FullScreen.tsx";
17
17
  import { existsSync, readdirSync } from "fs";
18
18
  import { readFile } from "fs/promises";
19
- import { spawn } from "child_process";
20
19
  import { CONFIG, getActiveProfile, estimateTokens, formatTokens } from "../core/config.ts";
21
20
  import { switchProfile } from "../core/profiles.ts";
22
21
  import { generatePlugin } from "../core/generator.ts";
@@ -151,16 +150,6 @@ export function App() {
151
150
  setModal("none");
152
151
  }
153
152
 
154
- function handleSetup() {
155
- isExitingRef.current = true;
156
- exit();
157
- setTimeout(() => {
158
- spawn("think", ["setup"], {
159
- stdio: "inherit",
160
- });
161
- }, 100);
162
- }
163
-
164
153
  // Don't render while exiting
165
154
  if (isExitingRef.current) {
166
155
  return null;
@@ -224,7 +213,6 @@ export function App() {
224
213
  <ProfileSwitcher
225
214
  onClose={() => setModal("none")}
226
215
  onSwitch={handleProfileSwitch}
227
- onSetup={handleSetup}
228
216
  />
229
217
  </Box>
230
218
  </FullScreen>
@@ -3,22 +3,34 @@ import { Box, Text, useInput } from "ink";
3
3
  import TextInput from "ink-text-input";
4
4
  import type { ProfileInfo } from "../../core/profiles.ts";
5
5
  import { listProfiles, createProfile, deleteProfile } from "../../core/profiles.ts";
6
+ import { profilePath } from "../../core/config.ts";
7
+ import { roleDescriptions, generateProfileFiles } from "../../core/profile-generator.ts";
6
8
 
7
9
  interface ProfileSwitcherProps {
8
10
  onClose: () => void;
9
11
  onSwitch: (name: string) => void;
10
- onSetup?: () => void;
11
12
  }
12
13
 
13
- type Mode = "list" | "create" | "confirmCopy" | "confirmDelete";
14
+ type Mode = "list" | "create" | "confirmCopy" | "confirmDelete" | "selectRole";
14
15
 
15
- export function ProfileSwitcher({ onClose, onSwitch, onSetup }: ProfileSwitcherProps) {
16
+ const roles = [
17
+ { value: "senior-dev", label: "Senior Developer", hint: "experienced, autonomous" },
18
+ { value: "mid-dev", label: "Mid-level Developer", hint: "some guidance helpful" },
19
+ { value: "junior-dev", label: "Junior Developer", hint: "more explanation needed" },
20
+ { value: "founder", label: "Founder / Tech Lead", hint: "shipping matters" },
21
+ { value: "student", label: "Student", hint: "learning fundamentals" },
22
+ { value: "hobbyist", label: "Hobbyist", hint: "exploring for fun" },
23
+ ];
24
+
25
+ export function ProfileSwitcher({ onClose, onSwitch }: ProfileSwitcherProps) {
16
26
  const [profiles, setProfiles] = useState<ProfileInfo[]>([]);
17
27
  const [selected, setSelected] = useState(0);
18
28
  const [loading, setLoading] = useState(true);
19
29
  const [mode, setMode] = useState<Mode>("list");
20
30
  const [newName, setNewName] = useState("");
21
31
  const [error, setError] = useState<string | null>(null);
32
+ const [roleIndex, setRoleIndex] = useState(0);
33
+ const [generating, setGenerating] = useState(false);
22
34
 
23
35
  function loadProfiles() {
24
36
  const loaded = listProfiles();
@@ -47,8 +59,11 @@ export function ProfileSwitcher({ onClose, onSwitch, onSetup }: ProfileSwitcherP
47
59
  try {
48
60
  createProfile(name, copyFrom);
49
61
 
50
- if (!copyFrom && onSetup) {
51
- onSetup();
62
+ if (!copyFrom) {
63
+ // No source to copy from — go to role selection
64
+ setMode("selectRole");
65
+ setRoleIndex(0);
66
+ setError(null);
52
67
  return;
53
68
  }
54
69
 
@@ -62,6 +77,25 @@ export function ProfileSwitcher({ onClose, onSwitch, onSetup }: ProfileSwitcherP
62
77
  }
63
78
  }
64
79
 
80
+ async function handleRoleSelect() {
81
+ const name = newName.trim();
82
+ const role = roles[roleIndex]!;
83
+ setGenerating(true);
84
+ try {
85
+ const dir = profilePath(name);
86
+ await generateProfileFiles(dir, { role: role.value });
87
+ setNewName("");
88
+ setMode("list");
89
+ setError(null);
90
+ setGenerating(false);
91
+ loadProfiles();
92
+ onSwitch(name);
93
+ } catch {
94
+ setError("Failed to generate profile");
95
+ setGenerating(false);
96
+ }
97
+ }
98
+
65
99
  function handleDelete() {
66
100
  const profile = profiles[selected];
67
101
  if (!profile) return;
@@ -111,6 +145,26 @@ export function ProfileSwitcher({ onClose, onSwitch, onSetup }: ProfileSwitcherP
111
145
  return;
112
146
  }
113
147
 
148
+ // Select role mode
149
+ if (mode === "selectRole") {
150
+ if (generating) return;
151
+ if (key.escape) {
152
+ setMode("list");
153
+ setNewName("");
154
+ setError(null);
155
+ }
156
+ if (key.upArrow || input === "k") {
157
+ setRoleIndex((i) => (i - 1 + roles.length) % roles.length);
158
+ }
159
+ if (key.downArrow || input === "j") {
160
+ setRoleIndex((i) => (i + 1) % roles.length);
161
+ }
162
+ if (key.return) {
163
+ handleRoleSelect();
164
+ }
165
+ return;
166
+ }
167
+
114
168
  // Confirm delete mode
115
169
  if (mode === "confirmDelete") {
116
170
  if (input === "y" || input === "Y") {
@@ -217,6 +271,43 @@ export function ProfileSwitcher({ onClose, onSwitch, onSetup }: ProfileSwitcherP
217
271
  );
218
272
  }
219
273
 
274
+ // Select role mode
275
+ if (mode === "selectRole") {
276
+ return (
277
+ <Box flexDirection="column" padding={1}>
278
+ <Text bold color="cyan">Select Role for "{newName}"</Text>
279
+
280
+ <Box flexDirection="column" marginTop={1}>
281
+ {roles.map((role, i) => (
282
+ <Box key={role.value}>
283
+ <Text color={i === roleIndex ? "cyan" : undefined} dimColor={i !== roleIndex}>
284
+ {i === roleIndex ? " \u25b8 " : " "}
285
+ </Text>
286
+ <Text bold={i === roleIndex} color={i === roleIndex ? "white" : undefined} dimColor={i !== roleIndex}>
287
+ {role.label}
288
+ </Text>
289
+ <Text dimColor> {role.hint}</Text>
290
+ </Box>
291
+ ))}
292
+ </Box>
293
+
294
+ {generating && (
295
+ <Box marginTop={1}>
296
+ <Text color="yellow"> Generating profile...</Text>
297
+ </Box>
298
+ )}
299
+ {error && (
300
+ <Box marginTop={1}>
301
+ <Text color="red"> {error}</Text>
302
+ </Box>
303
+ )}
304
+ <Box marginTop={1}>
305
+ <Text dimColor> {"\u2191\u2193"}: select | Enter: create | Esc: cancel</Text>
306
+ </Box>
307
+ </Box>
308
+ );
309
+ }
310
+
220
311
  // Confirm delete mode
221
312
  if (mode === "confirmDelete") {
222
313
  const profile = profiles[selected];
@@ -49,7 +49,7 @@ export function StatusBar({ message, section }: StatusBarProps) {
49
49
  return (
50
50
  <Box>
51
51
  <Text dimColor>
52
- {"↑↓ nav · "}{sectionHints}{" · / search · ? help · q quit"}
52
+ {"↑↓ nav · "}{sectionHints}{" · P profiles · / search · ? help · q quit"}
53
53
  </Text>
54
54
  </Box>
55
55
  );
@@ -58,7 +58,7 @@ export function StatusBar({ message, section }: StatusBarProps) {
58
58
  return (
59
59
  <Box>
60
60
  <Text dimColor>
61
- {"↑↓ navigate · "}{sectionHints}{" · s sync · p preview · / search · ? help · q quit"}
61
+ {"↑↓ navigate · "}{sectionHints}{" · s sync · p preview · P profiles · / search · ? help · q quit"}
62
62
  </Text>
63
63
  </Box>
64
64
  );