wiggum-cli 0.11.2 → 0.11.5

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.
@@ -1,1142 +0,0 @@
1
- # Wiggum CLI - TUI Architecture Specification
2
-
3
- > Comprehensive documentation of the Terminal User Interface layer for UX review and improvement.
4
-
5
- ---
6
-
7
- ## Table of Contents
8
-
9
- 1. [Overview](#1-overview)
10
- 2. [Entry Points & Initialization](#2-entry-points--initialization)
11
- 3. [Screen Architecture](#3-screen-architecture)
12
- 4. [Component Library](#4-component-library)
13
- 5. [State Management](#5-state-management)
14
- 6. [Navigation Patterns](#6-navigation-patterns)
15
- 7. [Input Handling](#7-input-handling)
16
- 8. [Theme & Visual System](#8-theme--visual-system)
17
- 9. [User Flows](#9-user-flows)
18
- 10. [Current Issues & Pain Points](#10-current-issues--pain-points)
19
- 11. [Out of Scope](#11-out-of-scope)
20
-
21
- ---
22
-
23
- ## 1. Overview
24
-
25
- ### Technology Stack
26
-
27
- | Layer | Technology | Purpose |
28
- |-------|------------|---------|
29
- | Runtime | Node.js ≥18 | JavaScript execution |
30
- | UI Framework | Ink 5.x | React for CLI rendering |
31
- | React | 18.x | Component model |
32
- | Input | ink-text-input | Text input handling |
33
- | Entry | Commander.js | CLI argument parsing |
34
-
35
- ### Architecture Pattern
36
-
37
- ```
38
- ┌─────────────────────────────────────────────────────────────┐
39
- │ User Terminal │
40
- └─────────────────────────────────────────────────────────────┘
41
-
42
-
43
- ┌─────────────────────────────────────────────────────────────┐
44
- │ Entry Point (index.ts) │
45
- │ • Mode detection (TUI vs CLI) │
46
- │ • Session state initialization │
47
- │ • Provider/config loading │
48
- └─────────────────────────────────────────────────────────────┘
49
-
50
-
51
- ┌─────────────────────────────────────────────────────────────┐
52
- │ App.tsx (Router) │
53
- │ • Screen navigation state │
54
- │ • SessionState propagation │
55
- │ • Completion/exit callbacks │
56
- └─────────────────────────────────────────────────────────────┘
57
-
58
- ┌───────────────────┼───────────────────┐
59
- ▼ ▼ ▼
60
- ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
61
- │ WelcomeScreen │ │ MainShell │ │ InitScreen │
62
- │ │ │ │ │ │
63
- │ • ASCII banner │ │ • REPL loop │ │ • Multi-phase │
64
- │ • Press Enter │ │ • Commands │ │ • Provider │
65
- └─────────────────┘ │ • Navigation │ │ • AI analysis │
66
- └─────────────────┘ └─────────────────┘
67
-
68
-
69
- ┌─────────────────┐
70
- │ InterviewScreen │
71
- │ │
72
- │ • Spec gen │
73
- │ • Q&A flow │
74
- │ • Streaming │
75
- └─────────────────┘
76
- ```
77
-
78
- ---
79
-
80
- ## 2. Entry Points & Initialization
81
-
82
- ### File: `src/index.ts`
83
-
84
- ### Startup Function
85
-
86
- ```typescript
87
- startInkTui(initialScreen: AppScreen = 'welcome', interviewFeature?: string)
88
- ```
89
-
90
- ### Initialization Sequence
91
-
92
- ```
93
- 1. Detect project root (cwd)
94
-
95
-
96
- 2. Check config exists? ──────────────────┐
97
- hasConfig(projectRoot) │
98
- │ │
99
- ┌────┴────┐ │
100
- │ YES │ NO │
101
- ▼ ▼ │
102
- 3a. Load 3b. Set │
103
- config initialized=false │
104
- │ │
105
- ▼ │
106
- 4. Detect available provider ◄────────────┘
107
- getAvailableProvider()
108
- (checks env vars: ANTHROPIC_API_KEY,
109
- OPENAI_API_KEY, OPENROUTER_API_KEY)
110
-
111
-
112
- 5. Create SessionState
113
- {
114
- projectRoot,
115
- provider,
116
- model (defaults based on provider),
117
- config,
118
- initialized
119
- }
120
-
121
-
122
- 6. Render App with sessionState
123
- render(<App sessionState={...} />)
124
- ```
125
-
126
- ### SessionState Interface
127
-
128
- ```typescript
129
- interface SessionState {
130
- projectRoot: string;
131
- provider: AIProvider | null; // 'anthropic' | 'openai' | 'openrouter'
132
- model: string;
133
- config: RalphConfig | null;
134
- initialized: boolean;
135
- scanResult?: ScanResult; // Cached from /init
136
- }
137
- ```
138
-
139
- ### Model Defaults by Provider
140
-
141
- | Provider | Default Model |
142
- |----------|---------------|
143
- | anthropic | claude-sonnet-4-20250514 |
144
- | openai | gpt-4.1 |
145
- | openrouter | anthropic/claude-sonnet-4 |
146
-
147
- ---
148
-
149
- ## 3. Screen Architecture
150
-
151
- ### File: `src/tui/screens/`
152
-
153
- ### Screen Registry
154
-
155
- | Screen | File | Purpose | Entry Condition |
156
- |--------|------|---------|-----------------|
157
- | WelcomeScreen | `WelcomeScreen.tsx` | First-run welcome | App startup |
158
- | MainShell | `MainShell.tsx` | Interactive REPL | After welcome / navigation |
159
- | InitScreen | `InitScreen.tsx` | Project initialization | `/init` command |
160
- | InterviewScreen | `InterviewScreen.tsx` | Spec generation | `/new <feature>` command |
161
-
162
- ---
163
-
164
- ### 3.1 WelcomeScreen
165
-
166
- **Purpose**: Branded entry point with status display
167
-
168
- **Visual Layout**:
169
- ```
170
- ┌────────────────────────────────────────────────────┐
171
- │ │
172
- │ ██╗ ██╗██╗ ██████╗ ██████╗ ██╗ ██╗███╗ ███╗│
173
- │ ██║ ██║██║██╔════╝ ██╔════╝ ██║ ██║████╗ ████║│
174
- │ ██║ █╗ ██║██║██║ ███╗██║ ███╗██║ ██║██╔████╔██║│
175
- │ ██║███╗██║██║██║ ██║██║ ██║██║ ██║██║╚██╔╝██║│
176
- │ ╚███╔███╔╝██║╚██████╔╝╚██████╔╝╚██████╔╝██║ ╚═╝ ██║│
177
- │ ╚══╝╚══╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝│
178
- │ │
179
- │ v0.10.9 │
180
- │ anthropic/claude-sonnet-4 │ Ready │
181
- │ │
182
- │ Press Enter to continue... (blinking) │
183
- │ │
184
- │ Tips: /init, /new <feature>, /help │
185
- │ │
186
- └────────────────────────────────────────────────────┘
187
- ```
188
-
189
- **Props**:
190
- ```typescript
191
- interface WelcomeScreenProps {
192
- provider: AIProvider | null;
193
- model: string;
194
- version: string;
195
- isInitialized: boolean;
196
- onContinue: () => void;
197
- }
198
- ```
199
-
200
- **Behavior**:
201
- - Blinking "Press Enter..." text (800ms interval)
202
- - Status shows green "Ready" or orange "Not initialized"
203
- - Enter key → navigates to MainShell
204
-
205
- ---
206
-
207
- ### 3.2 MainShell
208
-
209
- **Purpose**: Primary interactive interface (REPL replacement)
210
-
211
- **Visual Layout**:
212
- ```
213
- ┌────────────────────────────────────────────────────┐
214
- │ Wiggum Interactive Mode │ Ready │
215
- │ openai/gpt-5.1 │ Type /help for commands │
216
- ├────────────────────────────────────────────────────┤
217
- │ │
218
- │ (message history appears here) │
219
- │ │
220
- │ › Feature name required. Usage: /new <feature> │
221
- │ │
222
- ├────────────────────────────────────────────────────┤
223
- │ › /new my-feature█ │
224
- │ ┌──────────────────────────────┐ │
225
- │ │ /init Initialize project │ │
226
- │ │ /new Create spec │ ← dropdown │
227
- │ │ /run Run spec with AI │ │
228
- │ │ /help Show commands │ │
229
- │ └──────────────────────────────┘ │
230
- └────────────────────────────────────────────────────┘
231
- ```
232
-
233
- **Props**:
234
- ```typescript
235
- interface MainShellProps {
236
- sessionState: SessionState;
237
- onNavigate: (target: NavigationTarget, props?: NavigationProps) => void;
238
- onSessionStateChange?: (state: SessionState) => void;
239
- }
240
- ```
241
-
242
- **Available Commands**:
243
-
244
- | Command | Aliases | Description | Requires Init |
245
- |---------|---------|-------------|---------------|
246
- | `/init` | `/i` | Initialize project | No |
247
- | `/new <name>` | `/n` | Create feature spec | Yes |
248
- | `/run <name>` | `/r` | Run feature loop | Yes |
249
- | `/monitor <name>` | `/m` | Monitor running loop | No |
250
- | `/config` | `/cfg` | Manage settings | No |
251
- | `/help` | `/h`, `/?` | Show help | No |
252
- | `/exit` | `/quit`, `/q` | Exit application | No |
253
-
254
- **Message Types**:
255
- - User messages: `› content` (blue prefix)
256
- - Assistant messages: `● content` (yellow prefix)
257
- - System messages: dimmed text (no prefix)
258
-
259
- ---
260
-
261
- ### 3.3 InitScreen
262
-
263
- **Purpose**: Multi-phase project initialization wizard
264
-
265
- **Phases**:
266
-
267
- | # | Phase | Display Name | User Action |
268
- |---|-------|--------------|-------------|
269
- | 1 | scanning | Analyzing project | (automatic) |
270
- | 2 | provider-select | Select AI provider | Select from list |
271
- | 2 | key-input | Enter API key | Type masked input |
272
- | 2 | key-save | Save to .env.local | Yes/No confirm |
273
- | 3 | model-select | Select AI model | Select from list |
274
- | 4 | ai-analysis | AI codebase analysis | (automatic, shows tools) |
275
- | 5 | confirm | Confirm generation | Yes/No confirm |
276
- | 5 | generating | Creating files | (automatic) |
277
- | 6 | complete | Done | Press Enter |
278
- | - | error | Error occurred | Press Escape |
279
-
280
- **Visual Layout** (ai-analysis phase):
281
- ```
282
- ┌────────────────────────────────────────────────────┐
283
- │ ━━━ Phase 4 of 5: AI-powered codebase analysis ━━━ │
284
- ├────────────────────────────────────────────────────┤
285
- │ │
286
- │ ● Search Code (pattern: "export.*component") │
287
- │ → 12 matches found │
288
- │ │
289
- │ ● Read File (src/index.ts) │
290
- │ → 156 lines │
291
- │ │
292
- │ ◐ List Directory (src/components) │
293
- │ Running... │
294
- │ │
295
- │ ⠋ Analyzing codebase structure... │
296
- │ │
297
- └────────────────────────────────────────────────────┘
298
- ```
299
-
300
- **Props**:
301
- ```typescript
302
- interface InitScreenProps {
303
- projectRoot: string;
304
- sessionState: SessionState;
305
- onComplete: (newState: SessionState) => void;
306
- onCancel: () => void;
307
- }
308
- ```
309
-
310
- **State Hook**: `useInit` (manages all phase transitions)
311
-
312
- ---
313
-
314
- ### 3.4 InterviewScreen
315
-
316
- **Purpose**: Interactive spec generation through AI conversation
317
-
318
- **Phases**:
319
-
320
- | # | Phase | Display Name | User Action |
321
- |---|-------|--------------|-------------|
322
- | 1 | context | Share references | Enter URLs/files or skip |
323
- | 2 | goals | Describe feature | Type description |
324
- | 3 | interview | Clarify requirements | Answer 2-10 questions |
325
- | 4 | generation | Generating spec | (automatic, streaming) |
326
- | 5 | complete | Spec ready | Press Enter |
327
-
328
- **Visual Layout** (interview phase):
329
- ```
330
- ┌────────────────────────────────────────────────────┐
331
- │ ━━━ Phase 3 of 4: Answer clarifying questions ━━━ │
332
- ├────────────────────────────────────────────────────┤
333
- │ │
334
- │ › I want to build a user authentication system │
335
- │ │
336
- │ ● Reading codebase to understand structure... │
337
- │ ◐ search_codebase → 8 matches │
338
- │ ● read_file (src/app.tsx) → 234 lines │
339
- │ │
340
- │ ● What authentication method do you prefer? │
341
- │ - JWT tokens │
342
- │ - Session-based │
343
- │ - OAuth providers │
344
- │ │
345
- │ › JWT with refresh tokens█ │
346
- │ │
347
- │ (Type "done" or "skip" to generate early) │
348
- └────────────────────────────────────────────────────┘
349
- ```
350
-
351
- **Props**:
352
- ```typescript
353
- interface InterviewScreenProps {
354
- featureName: string;
355
- projectRoot: string;
356
- provider: AIProvider;
357
- model: string;
358
- scanResult?: ScanResult;
359
- onComplete: (spec: string) => void;
360
- onCancel: () => void;
361
- }
362
- ```
363
-
364
- **State Hook**: `useSpecGenerator`
365
- **Orchestrator**: `InterviewOrchestrator` (bridges TUI ↔ AI)
366
-
367
- ---
368
-
369
- ## 4. Component Library
370
-
371
- ### File: `src/tui/components/`
372
-
373
- ### Component Hierarchy
374
-
375
- ```
376
- App
377
- ├── WelcomeScreen
378
- │ └── WiggumBanner
379
- ├── MainShell
380
- │ ├── MessageList
381
- │ │ ├── UserMessage
382
- │ │ ├── AssistantMessage
383
- │ │ │ ├── ToolCallCard
384
- │ │ │ └── StreamingText
385
- │ │ └── SystemMessage
386
- │ └── ChatInput
387
- │ └── CommandDropdown
388
- ├── InitScreen
389
- │ ├── PhaseHeader
390
- │ ├── Select
391
- │ ├── PasswordInput
392
- │ ├── Confirm
393
- │ ├── ActionList
394
- │ │ └── ActionOutput
395
- │ └── WorkingIndicator
396
- └── InterviewScreen
397
- ├── PhaseHeader
398
- ├── MessageList
399
- ├── WorkingIndicator
400
- └── ChatInput
401
- ```
402
-
403
- ---
404
-
405
- ### 4.1 Input Components
406
-
407
- #### ChatInput
408
-
409
- **Purpose**: Primary text input with command dropdown support
410
-
411
- **Visual**:
412
- ```
413
- › Type your message...█
414
- ```
415
-
416
- **Props**:
417
- ```typescript
418
- interface ChatInputProps {
419
- onSubmit: (value: string) => void;
420
- placeholder?: string;
421
- disabled?: boolean;
422
- allowEmpty?: boolean;
423
- commands?: Command[];
424
- onCommand?: (command: string) => void;
425
- }
426
- ```
427
-
428
- **Behavior**:
429
- - Shows `›` blue prompt prefix
430
- - Typing `/` triggers CommandDropdown
431
- - Space after command hides dropdown
432
- - Disabled state shows `› [waiting for AI...]`
433
-
434
- ---
435
-
436
- #### CommandDropdown
437
-
438
- **Purpose**: Autocomplete for slash commands
439
-
440
- **Visual**:
441
- ```
442
- /init Initialize project with CLAUDE.md
443
- /new Create a new feature specification
444
- ► /run Run a spec file with AI
445
- /help Show available commands
446
- ```
447
-
448
- **Props**:
449
- ```typescript
450
- interface CommandDropdownProps {
451
- commands: Command[];
452
- filter: string;
453
- onSelect: (command: string) => void;
454
- onCancel: () => void;
455
- }
456
- ```
457
-
458
- ---
459
-
460
- #### Select
461
-
462
- **Purpose**: Arrow-navigable option list
463
-
464
- **Visual**:
465
- ```
466
- Select AI provider:
467
- ○ Anthropic (Claude)
468
- ► ● OpenAI (GPT-4)
469
- ○ OpenRouter
470
- ```
471
-
472
- **Props**:
473
- ```typescript
474
- interface SelectProps<T> {
475
- message: string;
476
- options: SelectOption<T>[];
477
- onSelect: (value: T) => void;
478
- onCancel?: () => void;
479
- initialIndex?: number;
480
- }
481
- ```
482
-
483
- **Controls**: ↑/↓, j/k, Enter, Escape
484
-
485
- ---
486
-
487
- #### PasswordInput
488
-
489
- **Purpose**: Masked text input for secrets
490
-
491
- **Visual**:
492
- ```
493
- Enter your API key:
494
- › ************************************█
495
- (Enter to submit, Esc to cancel)
496
- ```
497
-
498
- **Props**:
499
- ```typescript
500
- interface PasswordInputProps {
501
- message: string;
502
- onSubmit: (value: string) => void;
503
- onCancel?: () => void;
504
- mask?: string;
505
- placeholder?: string;
506
- }
507
- ```
508
-
509
- ---
510
-
511
- #### Confirm
512
-
513
- **Purpose**: Yes/No binary choice
514
-
515
- **Visual**:
516
- ```
517
- Save API key to .env.local?
518
- [Yes] No
519
- ```
520
-
521
- **Props**:
522
- ```typescript
523
- interface ConfirmProps {
524
- message: string;
525
- onConfirm: (value: boolean) => void;
526
- onCancel?: () => void;
527
- initialValue?: boolean;
528
- }
529
- ```
530
-
531
- **Controls**: ←/→, y/n, Enter, Escape
532
-
533
- ---
534
-
535
- ### 4.2 Display Components
536
-
537
- #### PhaseHeader
538
-
539
- **Purpose**: Progress indicator for multi-step flows
540
-
541
- **Visual**:
542
- ```
543
- ━━━ Phase 3 of 5: AI-powered codebase analysis ━━━
544
- ```
545
-
546
- **Props**:
547
- ```typescript
548
- interface PhaseHeaderProps {
549
- currentPhase: number;
550
- totalPhases: number;
551
- phaseName: string;
552
- }
553
- ```
554
-
555
- ---
556
-
557
- #### MessageList
558
-
559
- **Purpose**: Conversation history display
560
-
561
- **Visual**:
562
- ```
563
- › What should I build? (user - blue)
564
-
565
- ● Let me explore the codebase... (assistant - yellow)
566
- ● search_codebase → 5 matches
567
- ● read_file → 120 lines
568
-
569
- Project not initialized. (system - dimmed)
570
- ```
571
-
572
- **Props**:
573
- ```typescript
574
- interface MessageListProps {
575
- messages: Message[];
576
- maxHeight?: number;
577
- }
578
-
579
- interface Message {
580
- id: string;
581
- role: 'user' | 'assistant' | 'system';
582
- content: string;
583
- toolCalls?: ToolCall[];
584
- isStreaming?: boolean;
585
- }
586
- ```
587
-
588
- ---
589
-
590
- #### ToolCallCard
591
-
592
- **Purpose**: Tool execution status display
593
-
594
- **Visual States**:
595
- ```
596
- ○ Search Code (pattern) (pending - brown)
597
- ◐ Read File (path) (running - yellow)
598
- ● List Directory (path) → 5 items (complete - green)
599
- ● Search Code (pattern) → Error (error - pink)
600
- ```
601
-
602
- **Props**:
603
- ```typescript
604
- interface ToolCallCardProps {
605
- toolName: string;
606
- status: ToolCallStatus; // 'pending' | 'running' | 'complete' | 'error'
607
- input: string;
608
- output?: string;
609
- error?: string;
610
- }
611
- ```
612
-
613
- ---
614
-
615
- #### WorkingIndicator
616
-
617
- **Purpose**: Loading state with spinner
618
-
619
- **Visual**:
620
- ```
621
- ⠋ Analyzing codebase structure... (Press Esc to cancel)
622
- ```
623
-
624
- **Props**:
625
- ```typescript
626
- interface WorkingIndicatorProps {
627
- state: {
628
- isWorking: boolean;
629
- status: string;
630
- hint?: string;
631
- };
632
- }
633
- ```
634
-
635
- ---
636
-
637
- #### StreamingText
638
-
639
- **Purpose**: Real-time text display with cursor
640
-
641
- **Visual**:
642
- ```
643
- The authentication system should use JWT tokens for...█
644
- ```
645
-
646
- **Props**:
647
- ```typescript
648
- interface StreamingTextProps {
649
- text: string;
650
- isStreaming: boolean;
651
- color?: string;
652
- showCursor?: boolean;
653
- }
654
- ```
655
-
656
- ---
657
-
658
- ### 4.3 Branding Components
659
-
660
- #### WiggumBanner
661
-
662
- **Purpose**: ASCII art logo
663
-
664
- **Visual**:
665
- ```
666
- ██╗ ██╗██╗ ██████╗ ██████╗ ██╗ ██╗███╗ ███╗
667
- ██║ ██║██║██╔════╝ ██╔════╝ ██║ ██║████╗ ████║
668
- ██║ █╗ ██║██║██║ ███╗██║ ███╗██║ ██║██╔████╔██║
669
- ██║███╗██║██║██║ ██║██║ ██║██║ ██║██║╚██╔╝██║
670
- ╚███╔███╔╝██║╚██████╔╝╚██████╔╝╚██████╔╝██║ ╚═╝ ██║
671
- ╚══╝╚══╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝
672
- ```
673
-
674
- ---
675
-
676
- ## 5. State Management
677
-
678
- ### Patterns
679
-
680
- | Level | Scope | Mechanism | Persistence |
681
- |-------|-------|-----------|-------------|
682
- | Session | Cross-screen | SessionState object | Yes (config files) |
683
- | Screen | Single screen | useState/hooks | No |
684
- | Component | Single component | useState | No |
685
-
686
- ### State Hooks
687
-
688
- #### useInit (`src/tui/hooks/useInit.ts`)
689
-
690
- **Manages**: InitScreen phases and data
691
-
692
- **Key State**:
693
- ```typescript
694
- interface InitState {
695
- phase: InitPhase;
696
- projectRoot: string;
697
- scanResult: ScanResult | null;
698
- enhancedResult: EnhancedScanResult | null;
699
- provider: AIProvider | null;
700
- model: string | null;
701
- hasApiKey: boolean;
702
- apiKeyEnteredThisSession: boolean;
703
- saveKeyToEnv: boolean;
704
- isWorking: boolean;
705
- workingStatus: string;
706
- error: string | null;
707
- generatedFiles: string[];
708
- toolCalls: ToolCallDisplay[];
709
- }
710
- ```
711
-
712
- **Actions**: `initialize`, `setScanResult`, `selectProvider`, `setApiKey`, `selectModel`, `setEnhancedResult`, `setGenerationComplete`, etc.
713
-
714
- ---
715
-
716
- #### useSpecGenerator (`src/tui/hooks/useSpecGenerator.ts`)
717
-
718
- **Manages**: InterviewScreen phases and conversation
719
-
720
- **Key State**:
721
- ```typescript
722
- interface SpecGeneratorState {
723
- phase: 'context' | 'goals' | 'interview' | 'generation' | 'complete';
724
- messages: Message[];
725
- isWorking: boolean;
726
- workingStatus: string;
727
- currentQuestion: string;
728
- awaitingInput: boolean;
729
- generatedSpec: string | null;
730
- error: string | null;
731
- questionCount: number;
732
- references: Array<{ source: string; content: string }>;
733
- }
734
- ```
735
-
736
- **Actions**: `initialize`, `addMessage`, `setPhase`, `startToolCall`, `completeToolCall`, `updateStreamingMessage`, etc.
737
-
738
- ---
739
-
740
- ### Orchestrator Pattern
741
-
742
- **File**: `src/tui/orchestration/interview-orchestrator.ts`
743
-
744
- **Purpose**: Bridge between TUI state and AI services
745
-
746
- ```
747
- ┌─────────────────────────────────────────────────────────────┐
748
- │ InterviewOrchestrator │
749
- ├─────────────────────────────────────────────────────────────┤
750
- │ │
751
- │ TUI Callbacks AI Services │
752
- │ ───────────────── ─────────────── │
753
- │ onMessage() ◄─────► ConversationManager │
754
- │ onStreamChunk() ◄─────► InterviewTools │
755
- │ onToolStart() ◄─────► TavilySearchTool │
756
- │ onToolEnd() ◄─────► Context7Tools │
757
- │ onPhaseChange() │
758
- │ onComplete() │
759
- │ onError() │
760
- │ onWorkingChange() │
761
- │ onReady() │
762
- │ │
763
- └─────────────────────────────────────────────────────────────┘
764
- ```
765
-
766
- ---
767
-
768
- ## 6. Navigation Patterns
769
-
770
- ### Navigation Targets
771
-
772
- ```typescript
773
- type NavigationTarget = 'welcome' | 'shell' | 'interview' | 'init';
774
- ```
775
-
776
- ### Navigation Flow Diagram
777
-
778
- ```
779
- ┌──────────────────┐
780
- │ App Startup │
781
- └────────┬─────────┘
782
-
783
-
784
- ┌──────────────────┐
785
- ┌────────│ WelcomeScreen │
786
- │ └────────┬─────────┘
787
- │ │ [Enter]
788
- │ ▼
789
- │ ┌──────────────────┐
790
- │ ┌────│ MainShell │◄─────────────────┐
791
- │ │ └────────┬─────────┘ │
792
- │ │ │ │
793
- │ │ ┌────────┼────────┐ │
794
- │ │ │ │ │ │
795
- │ │ [/init] [/new] [/exit] │
796
- │ │ │ │ │ │
797
- │ │ ▼ │ ▼ │
798
- │ │ ┌──────┐ │ ┌────────┐ │
799
- │ │ │ Init │────┼───►│ Exit() │ │
800
- │ │ │Screen│ │ └────────┘ │
801
- │ │ └──┬───┘ │ │
802
- │ │ │ │ │
803
- │ │ [complete] │ │
804
- │ │ │ ▼ │
805
- │ │ │ ┌──────────┐ │
806
- │ │ │ │Interview │ │
807
- │ │ │ │ Screen │─────────────────────┤
808
- │ │ │ └──────────┘ [complete] │
809
- │ │ │ │
810
- │ └────┴────────────────────────────────────┘
811
- │ [Escape]
812
-
813
- [Deep link: wiggum --new feature]
814
- ```
815
-
816
- ### Navigation Triggers
817
-
818
- | Trigger | From | To | Condition |
819
- |---------|------|-----|-----------|
820
- | Enter | Welcome | Shell | Always |
821
- | `/init` | Shell | Init | Always |
822
- | `/new <name>` | Shell | Interview | `initialized=true` |
823
- | `/exit` | Shell | (exit) | Always |
824
- | Escape | Init/Interview | Shell | Always |
825
- | Complete | Init | Shell | Success |
826
- | Complete | Interview | Shell | Spec saved |
827
-
828
- ---
829
-
830
- ## 7. Input Handling
831
-
832
- ### Input Pipeline
833
-
834
- ```
835
- ┌─────────────────────────────────────────────────────────────┐
836
- │ Raw Stdin │
837
- │ (managed by Ink internally) │
838
- └─────────────────────────────────────────────────────────────┘
839
-
840
-
841
- ┌─────────────────────────────────────────────────────────────┐
842
- │ useInput Hook │
843
- │ (keyboard events: chars, arrows, special keys) │
844
- └─────────────────────────────────────────────────────────────┘
845
-
846
- ┌───────────────────┼───────────────────┐
847
- ▼ ▼ ▼
848
- ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
849
- │ TextInput │ │ Select │ │ PasswordInput │
850
- │ (typing) │ │ (navigation) │ │ (masked) │
851
- └─────────────────┘ └─────────────────┘ └─────────────────┘
852
-
853
-
854
- ┌─────────────────────────────────────────────────────────────┐
855
- │ Component Handler │
856
- │ (ChatInput.handleSubmit, Select.handleSelect, etc.) │
857
- └─────────────────────────────────────────────────────────────┘
858
-
859
-
860
- ┌─────────────────────────────────────────────────────────────┐
861
- │ Screen Handler │
862
- │ (MainShell.handleSubmit → parseInput → executeCommand) │
863
- └─────────────────────────────────────────────────────────────┘
864
-
865
-
866
- ┌─────────────────────────────────────────────────────────────┐
867
- │ Business Logic │
868
- │ (Orchestrator, AI services, file operations) │
869
- └─────────────────────────────────────────────────────────────┘
870
- ```
871
-
872
- ### Key Bindings
873
-
874
- | Key | Context | Action |
875
- |-----|---------|--------|
876
- | Enter | TextInput | Submit |
877
- | Enter | Select | Confirm selection |
878
- | Enter | Welcome | Continue |
879
- | Escape | Any screen | Cancel/back |
880
- | Ctrl+C | MainShell | Show "use /exit" hint |
881
- | ↑/↓ | Select/Dropdown | Navigate options |
882
- | j/k | Select | Vim navigation |
883
- | ←/→ | Confirm | Toggle Yes/No |
884
- | y/n | Confirm | Quick select |
885
- | Backspace | TextInput | Delete char |
886
-
887
- ### Command Parsing
888
-
889
- **File**: `src/repl/command-parser.ts`
890
-
891
- ```typescript
892
- parseInput(value: string): ParsedInput
893
-
894
- // Returns one of:
895
- { type: 'empty' }
896
- { type: 'slash-command', command: { name, args, raw } }
897
- { type: 'natural-language', text }
898
- ```
899
-
900
- ---
901
-
902
- ## 8. Theme & Visual System
903
-
904
- ### File: `src/tui/theme.ts`
905
-
906
- ### Color Palette (Simpson Theme)
907
-
908
- | Name | Hex | Usage |
909
- |------|-----|-------|
910
- | blue | #2f64d6 | Input prompts (›), user messages |
911
- | yellow | #f8db27 | Primary accent, headers, assistant messages |
912
- | brown | #9c5b01 | Secondary, hints, pending states |
913
- | white | #ffffff | Content text |
914
- | pink | #ff81c1 | Errors, warnings |
915
- | green | #4ade80 | Success states |
916
- | orange | #fb923c | Caution, not initialized |
917
-
918
- ### Status Indicators
919
-
920
- | Symbol | Name | Usage |
921
- |--------|------|-------|
922
- | `○` | pending | Tool not started |
923
- | `◐` | active | Tool running |
924
- | `●` | complete | Tool done / bullet |
925
- | `✓` | success | Phase complete |
926
- | `✗` | error | Phase failed |
927
- | `›` | prompt | User input prefix |
928
- | `█` | cursor | Streaming text cursor |
929
-
930
- ### Box Drawing
931
-
932
- ```typescript
933
- const box = {
934
- topLeft: '┌', topRight: '┐',
935
- bottomLeft: '└', bottomRight: '┘',
936
- horizontal: '─', vertical: '│',
937
- }
938
- ```
939
-
940
- ### Phase Header Style
941
-
942
- ```
943
- ━━━ Phase 3 of 5: Phase Name ━━━
944
- ```
945
- (Uses U+2501 heavy horizontal line)
946
-
947
- ---
948
-
949
- ## 9. User Flows
950
-
951
- ### Flow 1: First-Time Setup
952
-
953
- ```
954
- 1. User runs `wiggum`
955
-
956
-
957
- 2. WelcomeScreen displays
958
- - ASCII banner
959
- - "Not initialized" status (orange)
960
- - Tips shown
961
-
962
- ▼ [Enter]
963
- 3. MainShell displays
964
- - Status bar shows provider/model
965
-
966
- ▼ [/init]
967
- 4. InitScreen starts
968
-
969
- ├─► Phase 1: Scanning (automatic)
970
-
971
- ├─► Phase 2: Provider selection
972
- │ └─► API key entry (if needed)
973
- │ └─► Save to .env.local confirmation
974
-
975
- ├─► Phase 3: Model selection
976
-
977
- ├─► Phase 4: AI analysis
978
- │ └─► Tool calls displayed
979
-
980
- ├─► Phase 5: Confirm & generate
981
- │ └─► Files created
982
-
983
- └─► Complete: Return to MainShell
984
-
985
-
986
- 5. MainShell with "Ready" status
987
- ```
988
-
989
- ### Flow 2: Create Feature Spec
990
-
991
- ```
992
- 1. User in MainShell
993
-
994
- ▼ [/new my-feature]
995
- 2. InterviewScreen starts
996
-
997
- ├─► Phase 1: Context (optional)
998
- │ └─► User enters URLs/files or skips
999
-
1000
- ├─► Phase 2: Goals
1001
- │ └─► User describes feature
1002
-
1003
- ├─► Phase 3: Interview (2-10 questions)
1004
- │ └─► AI asks questions
1005
- │ └─► User answers
1006
- │ └─► Tool calls shown
1007
-
1008
- ├─► Phase 4: Generation (streaming)
1009
- │ └─► Spec text appears incrementally
1010
-
1011
- └─► Phase 5: Complete
1012
- └─► Spec saved to .ralph/specs/my-feature.md
1013
-
1014
-
1015
- 3. Return to MainShell
1016
- ```
1017
-
1018
- ### Flow 3: Quick Commands
1019
-
1020
- ```
1021
- MainShell
1022
-
1023
- ├─► [/help] → Shows command list (inline)
1024
-
1025
- ├─► [/config] → "Not implemented" message
1026
-
1027
- ├─► [/run feature] → "Not implemented" message
1028
-
1029
- └─► [/exit] → "Goodbye!" → Process exits
1030
- ```
1031
-
1032
- ---
1033
-
1034
- ## 10. Current Issues & Pain Points
1035
-
1036
- ### Known UX Issues
1037
-
1038
- | Issue | Severity | Location | Description |
1039
- |-------|----------|----------|-------------|
1040
- | Stdin conflicts | High | index.ts | Ink/readline mode switching |
1041
- | Buffered input | Medium | repl-prompts.ts | 100ms delay workaround |
1042
- | No scroll | Medium | MessageList | Long conversations overflow |
1043
- | No persistence | Low | MainShell | Messages lost on navigation |
1044
- | Limited feedback | Medium | Various | No progress bars |
1045
-
1046
- ### Visual Inconsistencies
1047
-
1048
- | Issue | Location | Description |
1049
- |-------|----------|-------------|
1050
- | Mixed prefixes | Various | Sometimes `>`, sometimes `›` |
1051
- | Color usage | Various | Inconsistent success/error colors |
1052
- | Spacing | Various | Inconsistent padding/margins |
1053
-
1054
- ### Missing Features
1055
-
1056
- | Feature | Priority | Notes |
1057
- |---------|----------|-------|
1058
- | History | High | Command history (up arrow) |
1059
- | Autocomplete | Medium | Tab completion for paths |
1060
- | Resize handling | Medium | Terminal resize events |
1061
- | Copy/paste | Low | Full clipboard support |
1062
- | Mouse support | Low | Click to select |
1063
-
1064
- ---
1065
-
1066
- ## 11. Out of Scope
1067
-
1068
- The following are **not** part of this TUI review:
1069
-
1070
- ### Ralph Loop Layer (AI/Generation)
1071
- - `src/ai/` - AI providers, prompts, tools
1072
- - `src/generator/` - File generation, templates
1073
- - `src/scanner/` - Tech stack detection
1074
-
1075
- ### Configuration Files
1076
- - `.ralph/claude.md` content/format
1077
- - `.ralph/specs/*.md` content/format
1078
- - Template files in `src/templates/`
1079
-
1080
- ### CLI Mode
1081
- - `src/cli.ts` - Commander.js CLI
1082
- - Direct command execution (non-TUI)
1083
-
1084
- ---
1085
-
1086
- ## Appendix: File Reference
1087
-
1088
- ### Core TUI Files
1089
-
1090
- | Path | Purpose |
1091
- |------|---------|
1092
- | `src/index.ts` | Entry point, TUI initialization |
1093
- | `src/tui/app.tsx` | Root component, screen router |
1094
- | `src/tui/theme.ts` | Colors, symbols, box drawing |
1095
-
1096
- ### Screens
1097
-
1098
- | Path | Screen |
1099
- |------|--------|
1100
- | `src/tui/screens/WelcomeScreen.tsx` | Welcome |
1101
- | `src/tui/screens/MainShell.tsx` | Shell/REPL |
1102
- | `src/tui/screens/InitScreen.tsx` | Initialization |
1103
- | `src/tui/screens/InterviewScreen.tsx` | Spec generation |
1104
-
1105
- ### Components
1106
-
1107
- | Path | Component |
1108
- |------|-----------|
1109
- | `src/tui/components/ChatInput.tsx` | Text input |
1110
- | `src/tui/components/CommandDropdown.tsx` | Command autocomplete |
1111
- | `src/tui/components/MessageList.tsx` | Conversation display |
1112
- | `src/tui/components/ToolCallCard.tsx` | Tool status |
1113
- | `src/tui/components/PhaseHeader.tsx` | Progress header |
1114
- | `src/tui/components/WorkingIndicator.tsx` | Loading spinner |
1115
- | `src/tui/components/Select.tsx` | Option list |
1116
- | `src/tui/components/PasswordInput.tsx` | Masked input |
1117
- | `src/tui/components/Confirm.tsx` | Yes/No prompt |
1118
- | `src/tui/components/WiggumBanner.tsx` | ASCII logo |
1119
-
1120
- ### Hooks
1121
-
1122
- | Path | Hook |
1123
- |------|------|
1124
- | `src/tui/hooks/useInit.ts` | Init state |
1125
- | `src/tui/hooks/useSpecGenerator.ts` | Interview state |
1126
-
1127
- ### Orchestration
1128
-
1129
- | Path | Class |
1130
- |------|-------|
1131
- | `src/tui/orchestration/interview-orchestrator.ts` | TUI↔AI bridge |
1132
-
1133
- ### Support
1134
-
1135
- | Path | Purpose |
1136
- |------|---------|
1137
- | `src/repl/command-parser.ts` | Command parsing |
1138
- | `src/repl/session-state.ts` | Session state types |
1139
-
1140
- ---
1141
-
1142
- *Document generated for UX/TUI review. Last updated: 2026-01-27*