claudedesk 4.4.1 → 4.6.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 (82) hide show
  1. package/CHANGELOG.md +82 -3
  2. package/CLAUDE.md +11 -4
  3. package/dist/main/built-in-playbooks.js +231 -0
  4. package/dist/main/cli-manager.js +21 -9
  5. package/dist/main/git-manager.js +272 -0
  6. package/dist/main/index.js +34 -2
  7. package/dist/main/ipc-handlers.js +298 -2
  8. package/dist/main/playbook-executor.js +321 -0
  9. package/dist/main/playbook-manager.js +271 -0
  10. package/dist/main/quota-service.js +6 -4
  11. package/dist/main/session-manager.js +92 -2
  12. package/dist/main/session-pool.js +19 -0
  13. package/dist/main/settings-persistence.js +76 -0
  14. package/dist/main/tunnel-manager.js +546 -0
  15. package/dist/renderer/assets/index-BtxPa5XT.js +21032 -0
  16. package/dist/renderer/assets/{index-DTGEErZK.css → index-Df3cuu7-.css} +1 -1
  17. package/dist/renderer/index.html +2 -2
  18. package/dist/shared/ipc-contract.js +92 -1
  19. package/dist/shared/types/playbook-types.js +3 -0
  20. package/dist/shared/types/tunnel-types.js +2 -0
  21. package/docs/agent-teams.png +0 -0
  22. package/docs/repo-index.md +50 -11
  23. package/docs/tunnel-implementation-plan.md +255 -0
  24. package/docs/tunnel-ui-spec.md +1117 -0
  25. package/package.json +1 -1
  26. package/src/main/built-in-playbooks.ts +232 -0
  27. package/src/main/cli-manager.ts +23 -9
  28. package/src/main/git-manager.ts +288 -0
  29. package/src/main/index.ts +40 -2
  30. package/src/main/ipc-handlers.test.ts +126 -0
  31. package/src/main/ipc-handlers.ts +214 -3
  32. package/src/main/playbook-executor.ts +385 -0
  33. package/src/main/playbook-manager.ts +264 -0
  34. package/src/main/quota-service.ts +6 -4
  35. package/src/main/session-manager.ts +104 -2
  36. package/src/main/session-pool.ts +20 -0
  37. package/src/main/settings-persistence.ts +85 -0
  38. package/src/main/tunnel-manager.ts +622 -0
  39. package/src/renderer/App.tsx +163 -17
  40. package/src/renderer/components/DiffContentArea.tsx +128 -0
  41. package/src/renderer/components/DiffFileNav.tsx +109 -0
  42. package/src/renderer/components/DiffViewer.tsx +478 -0
  43. package/src/renderer/components/DiffViewerHeader.tsx +76 -0
  44. package/src/renderer/components/GitPanel.tsx +51 -166
  45. package/src/renderer/components/PaneHeader.tsx +27 -0
  46. package/src/renderer/components/PlaybookEditor.tsx +749 -0
  47. package/src/renderer/components/PlaybookPanel.tsx +442 -0
  48. package/src/renderer/components/PlaybookParameterDialog.tsx +497 -0
  49. package/src/renderer/components/PlaybookPicker.tsx +319 -0
  50. package/src/renderer/components/PlaybookProgressPanel.tsx +271 -0
  51. package/src/renderer/components/TeamPanel.tsx +1 -1
  52. package/src/renderer/components/TunnelCreateDialog.tsx +669 -0
  53. package/src/renderer/components/TunnelPanel.tsx +2005 -0
  54. package/src/renderer/components/TunnelRequestLogs.tsx +568 -0
  55. package/src/renderer/components/WorktreeCleanupDialog.tsx +312 -0
  56. package/src/renderer/components/WorktreePanel.tsx +519 -0
  57. package/src/renderer/components/ui/BudgetPanel.tsx +17 -0
  58. package/src/renderer/components/ui/CommitDialog.tsx +7 -1
  59. package/src/renderer/components/ui/ContextMenu.tsx +1 -0
  60. package/src/renderer/components/ui/FuelStatusIndicator.tsx +28 -0
  61. package/src/renderer/components/ui/FuelTooltip.tsx +21 -2
  62. package/src/renderer/components/ui/NewSessionDialog.tsx +417 -2
  63. package/src/renderer/components/ui/SettingsDialog.tsx +25 -1
  64. package/src/renderer/components/ui/ShortcutsPanel.tsx +1 -0
  65. package/src/renderer/components/ui/Tab.tsx +31 -0
  66. package/src/renderer/components/ui/TabBar.tsx +17 -2
  67. package/src/renderer/components/ui/ToolsDropdown.tsx +60 -0
  68. package/src/renderer/hooks/useAgentTeams.ts +23 -5
  69. package/src/renderer/hooks/useDiffViewer.ts +145 -0
  70. package/src/renderer/hooks/useGit.ts +105 -1
  71. package/src/renderer/hooks/usePlaybooks.ts +267 -0
  72. package/src/renderer/hooks/useSessionManager.ts +5 -2
  73. package/src/renderer/hooks/useTunnel.ts +266 -0
  74. package/src/renderer/utils/diff-parser.ts +125 -0
  75. package/src/shared/ipc-contract.ts +181 -1
  76. package/src/shared/ipc-types.ts +27 -0
  77. package/src/shared/types/git-types.ts +50 -0
  78. package/src/shared/types/playbook-types.ts +149 -0
  79. package/src/shared/types/tunnel-types.ts +80 -0
  80. package/PHASE_1_IMPLEMENTATION.md +0 -313
  81. package/PHASE_2_PARTIAL_IMPLEMENTATION.md +0 -286
  82. package/dist/renderer/assets/index-B5DrEDSJ.js +0 -17189
package/CHANGELOG.md CHANGED
@@ -8,13 +8,90 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  ## [Unreleased]
9
9
 
10
10
  ### Planned
11
- - Screenshot capture for README documentation
12
- - Automated tests with Jest/Vitest
13
11
  - Homebrew/Chocolatey packaging for easier installation
14
12
  - Development dependency security updates (electron v40+, vite v7+)
15
13
 
16
14
  ---
17
15
 
16
+ ## [4.6.0] - 2026-02-19
17
+
18
+ ### Added
19
+ - **LaunchTunnel integration** — Expose local ports to the internet via LaunchTunnel (14th domain)
20
+ - `TunnelManager` with hybrid REST API + CLI (`lt preview`) process management
21
+ - API key management with validation, stored in `~/.claudedesk/tunnel-settings.json`
22
+ - Tunnel list with 30s cache, status mapping (API snake_case → camelCase)
23
+ - Account info section (email, plan badge, status)
24
+ - Request log viewer with method/path/status/duration/size columns
25
+ - TunnelPanel (4 views: setup/main/settings/logs), TunnelCreateDialog, TunnelRequestLogs
26
+ - CLI auto-detection via `where`/`which`, `shell: true` for cross-platform spawn
27
+ - Ctrl+Shift+U keyboard shortcut, ToolsDropdown entry with active count badge
28
+ - 17 IPC methods (`tunnel:*`): 13 invoke + 4 events
29
+
30
+ ### Fixed
31
+ - **Tunnel spawn ENOENT** — Use `shell: true` in spawn for cross-platform `.cmd` shim compatibility
32
+ - **Tunnel status mapping** — API returns `"active"` not `"connected"`; added to `mapApiStatus`
33
+ - **Tunnel CLI subcommand** — Fixed `lt preview --port` (was missing `preview` subcommand)
34
+ - **Tunnel URL parsing** — Match `URL:` output format from LaunchTunnel CLI (not `your url is:`)
35
+ - **API snake_case mapping** — Map `created_at`, `status_code`, `duration_ms` etc. to camelCase
36
+ - **Account response unwrapping** — API returns `{"user": {...}}` wrapper; now unwrapped correctly
37
+ - **Request logs endpoint** — Reverted from `/requests` back to correct `/logs` path
38
+
39
+ ### Changed
40
+ - **IPC contract** — Expanded from 149 to ~166 methods (added 17 tunnel methods)
41
+ - **Project scale** — ~150 source files, ~49,000 LOC, 14 domains, 14 managers
42
+
43
+ ---
44
+
45
+ ## [4.5.0] - 2026-02-17
46
+
47
+ ### Added
48
+ - **Testing infrastructure** — Vitest 4 + @testing-library/react + Playwright for Electron
49
+ - 250 tests across 20 test files, 3 workspace projects (shared/main/renderer)
50
+ - Auto-derived electronAPI mock from IPC contract
51
+ - E2E tests with Playwright for Electron (app launch, sessions, split view, keyboard shortcuts)
52
+ - CI workflow with coverage artifacts
53
+ - **Git integration** — Full Git panel with staging, commits, branches, and real-time status
54
+ - `GitManager` with `child_process.execFile` (shell injection safe), per-directory mutex, `.git` fs.watch()
55
+ - File staging/unstaging (individual + bulk), branch display, commit history log
56
+ - AI commit message generation (heuristic-based conventional commits format)
57
+ - Optional checkpoint creation on commit
58
+ - Ctrl+Shift+G keyboard shortcut, ToolsDropdown entry with staged count badge
59
+ - 30 IPC methods (`git:*`): 26 invoke + 4 events
60
+ - **Diff viewer** — Full-screen diff overlay with syntax-highlighted unified diffs
61
+ - Categorized file navigation (staged/unstaged/untracked/conflicted)
62
+ - Dual gutter line numbers, colored add/remove/context lines
63
+ - Keyboard navigation (J/K between files), stage/unstage/discard actions from diff view
64
+ - Unified diff parser (`diff-parser.ts`) with old/new line number tracking
65
+ - **Git worktrees** — Worktree management panel with create, remove, and prune operations
66
+ - `WorktreePanel` for listing and managing worktrees
67
+ - `WorktreeCleanupDialog` for cleanup prompts when closing managed worktree sessions
68
+ - **Session playbooks** — Automated multi-step prompt sequences (13th domain)
69
+ - `PlaybookManager` (CRUD + persistence), `PlaybookExecutor` (execution engine)
70
+ - 5 built-in playbooks: API endpoint, bug investigation, code review, component creation, refactor
71
+ - Silence-based step completion (3s no output = done), confirmation gates between steps
72
+ - Dynamic parameter forms (text/multiline/select/filepath), variable interpolation
73
+ - PlaybookPicker (fuzzy search), PlaybookEditor (3-tab slide-in), PlaybookProgressPanel (bottom-docked)
74
+ - Import/export playbooks as JSON, library browser for built-in + custom playbooks
75
+ - Persistence: `~/.claudedesk/playbooks.json`
76
+ - Ctrl+Shift+B keyboard shortcut, ToolsDropdown entry
77
+ - 15 IPC methods (`playbook:*`): 12 invoke + 3 events
78
+ - **Repository Atlas Engine (RAE)** — Automated CLAUDE.md + repo-index.md generation
79
+ - File enumeration via `git ls-files`, regex import analysis, 3-tier domain inference
80
+ - AtlasPanel UI with idle/scanning/preview states
81
+ - 6 IPC methods (`atlas:*`)
82
+
83
+ ### Fixed
84
+ - **Git generate button** — Action bar Generate now auto-opens CommitDialog with the generated message
85
+ - **CommitDialog generate button** — Directly sets title from return value instead of relying on fragile useEffect prop chain
86
+ - **Silent null guard in useGit** — `generateMessage()` now shows error toast when no project directory is available instead of silently returning
87
+ - **Stale generated message** — Generated commit message state is cleared after successful commit
88
+
89
+ ### Changed
90
+ - **IPC contract** — Expanded from 102 to 149 methods (118 invoke + 8 send + 23 event)
91
+ - **Project scale** — 138 source files, ~45,800 LOC, 13 domains, 13 managers
92
+
93
+ ---
94
+
18
95
  ## [4.4.1] - 2026-02-13
19
96
 
20
97
  ### Fixed
@@ -203,7 +280,9 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on suggesting changes and
203
280
 
204
281
  ---
205
282
 
206
- [Unreleased]: https://github.com/carloluisito/claudedesk/compare/v4.4.1...HEAD
283
+ [Unreleased]: https://github.com/carloluisito/claudedesk/compare/v4.6.0...HEAD
284
+ [4.6.0]: https://github.com/carloluisito/claudedesk/compare/v4.5.0...v4.6.0
285
+ [4.5.0]: https://github.com/carloluisito/claudedesk/compare/v4.4.1...v4.5.0
207
286
  [4.4.1]: https://github.com/carloluisito/claudedesk/compare/v4.3.1...v4.4.1
208
287
  [4.3.1]: https://github.com/carloluisito/claudedesk/compare/v4.3.0...v4.3.1
209
288
  [4.3.0]: https://github.com/carloluisito/claudedesk/compare/v4.1.1...v4.3.0
package/CLAUDE.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Electron desktop app wrapping Claude Code CLI with multi-session terminals, split views, and agent team visualization.
4
4
 
5
+ ## Workflow Rule
6
+
7
+ **Always run the `requirements-clarifier` agent (via the Task tool) on the user's initial prompt before planning or implementing.** This ensures requirements are analyzed, ambiguities are surfaced, and acceptance criteria are established before any work begins. Skip only for trivial tasks (typo fixes, single-line changes, or purely informational questions).
8
+
5
9
  ## Tech Stack
6
10
 
7
11
  Electron 28 | React 18 | TypeScript | xterm.js | node-pty | Tailwind CSS | reactflow
@@ -11,9 +15,9 @@ Electron 28 | React 18 | TypeScript | xterm.js | node-pty | Tailwind CSS | react
11
15
  ```
12
16
  ┌─────────────────────────────────────────────┐
13
17
  │ Main Process (Node.js) │
14
- 9 managers + IPC handlers + session pool
18
+ 14 managers + IPC handlers + session pool
15
19
  └──────────────────┬──────────────────────────┘
16
- │ IPC (102 methods)
20
+ │ IPC (~166 methods)
17
21
  ┌──────────────────┴──────────────────────────┐
18
22
  │ Preload (auto-derived context bridge) │
19
23
  └──────────────────┬──────────────────────────┘
@@ -26,7 +30,7 @@ Electron 28 | React 18 | TypeScript | xterm.js | node-pty | Tailwind CSS | react
26
30
 
27
31
  **3-layer pattern per domain:** Manager (main) → Hook (renderer) → Components (renderer)
28
32
 
29
- **IPC contract** (`src/shared/ipc-contract.ts`) is the single source of truth — 102 methods. The preload bridge and `ElectronAPI` type are auto-derived from it.
33
+ **IPC contract** (`src/shared/ipc-contract.ts`) is the single source of truth — ~166 methods. The preload bridge and `ElectronAPI` type are auto-derived from it.
30
34
 
31
35
  ## Domain Map
32
36
 
@@ -42,7 +46,9 @@ Electron 28 | React 18 | TypeScript | xterm.js | node-pty | Tailwind CSS | react
42
46
  | Drag-Drop | file-dragdrop-handler, file-utils | useDragDrop, DragDropOverlay, DragDropContextMenu, DragDropSettings | ipc-types.ts | `dragdrop:*` |
43
47
  | Workspaces | settings-persistence | SettingsDialog | ipc-types.ts | `workspace:*` |
44
48
  | Atlas | atlas-manager | useAtlas, AtlasPanel | types/atlas-types.ts | `atlas:*` |
45
- | Git | git-manager | useGit, GitPanel, CommitDialog | types/git-types.ts | `git:*` |
49
+ | Git | git-manager | useGit, useDiffViewer, GitPanel, DiffViewer, DiffFileNav, DiffViewerHeader, DiffContentArea, CommitDialog, WorktreePanel, WorktreeCleanupDialog, diff-parser | types/git-types.ts | `git:*` |
50
+ | Playbooks | playbook-manager, playbook-executor, built-in-playbooks | usePlaybooks, PlaybookPicker, PlaybookParameterDialog, PlaybookProgressPanel, PlaybookPanel, PlaybookEditor | types/playbook-types.ts | `playbook:*` |
51
+ | Tunnels | tunnel-manager | useTunnel, TunnelPanel, TunnelCreateDialog, TunnelRequestLogs | types/tunnel-types.ts | `tunnel:*` |
46
52
  | Window | index.ts | ConfirmDialog, SettingsDialog, AboutDialog, TitleBarBranding | ipc-types.ts | `window:*`, `dialog:*` |
47
53
 
48
54
  ## Adding a New IPC Method
@@ -72,6 +78,7 @@ That's it. The preload bridge and types auto-derive.
72
78
  - **Split view**: `useSplitView` manages a tree of leaf/branch nodes. Max 4 panes. State persisted in settings.
73
79
  - **Agent team detection**: `AgentTeamManager` watches `~/.claude/teams/` and `~/.claude/tasks/` via `fs.watch()`. Auto-links sessions within 30s of team creation.
74
80
  - **Git integration**: `GitManager` uses `child_process.execFile` (not `exec` — prevents shell injection). Per-directory mutex serializes operations. `.git` directory watching with 500ms debounce for real-time status. Heuristic-based AI commit message generation (conventional commits format).
81
+ - **Playbook execution**: `PlaybookExecutor` writes prompts to PTY and uses silence-based detection (3s no output = step done) for step completion. Never sends Ctrl+C on cancel (just stops sending further steps). One execution per session, confirmation gates pause between steps.
75
82
 
76
83
  ## Testing
77
84
 
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BUILT_IN_PLAYBOOKS = void 0;
4
+ const DEFAULT_EXECUTION = {
5
+ silenceThresholdMs: 3000,
6
+ interStepDelayMs: 1000,
7
+ stepTimeoutMs: 300000,
8
+ stepTimeoutPolicy: 'pause',
9
+ createCheckpointBeforeRun: false,
10
+ };
11
+ let stepCounter = 0;
12
+ function stepId() {
13
+ return `builtin-step-${++stepCounter}`;
14
+ }
15
+ exports.BUILT_IN_PLAYBOOKS = [
16
+ {
17
+ id: 'builtin-add-api-endpoint',
18
+ type: 'built-in',
19
+ name: 'Add API Endpoint',
20
+ description: 'Scaffold a new REST API endpoint with route, handler, validation, and tests.',
21
+ icon: '\u{1F310}',
22
+ category: 'Backend',
23
+ keywords: ['api', 'endpoint', 'route', 'rest', 'handler', 'scaffold'],
24
+ variables: [
25
+ { name: 'method', label: 'HTTP Method', type: 'select', required: true, options: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] },
26
+ { name: 'path', label: 'Route Path', type: 'text', required: true, placeholder: '/api/users/:id' },
27
+ { name: 'description', label: 'Endpoint Description', type: 'text', required: true, placeholder: 'Fetch user by ID' },
28
+ { name: 'auth', label: 'Authentication', type: 'select', required: true, default: 'required', options: ['required', 'optional', 'none'] },
29
+ ],
30
+ steps: [
31
+ {
32
+ id: stepId(),
33
+ name: 'Analyze existing patterns',
34
+ prompt: 'Look at the existing API routes and handlers in this project. Identify the patterns used for routing, request validation, error handling, and response formatting. Summarize the conventions you find.',
35
+ requireConfirmation: false,
36
+ },
37
+ {
38
+ id: stepId(),
39
+ name: 'Create route and handler',
40
+ prompt: 'Create a new {{method}} endpoint at {{path}} — {{description}}. Authentication: {{auth}}. Follow the existing project patterns you identified. Include request validation and proper error handling.',
41
+ requireConfirmation: true,
42
+ },
43
+ {
44
+ id: stepId(),
45
+ name: 'Add tests',
46
+ prompt: 'Write tests for the new {{method}} {{path}} endpoint. Cover: successful request, validation errors, authentication (if {{auth}} is not "none"), and edge cases. Follow the existing test patterns.',
47
+ requireConfirmation: false,
48
+ },
49
+ {
50
+ id: stepId(),
51
+ name: 'Verify and document',
52
+ prompt: 'Run the tests you just wrote. If any fail, fix them. Then add a brief description of the new endpoint to any existing API documentation files if present.',
53
+ requireConfirmation: false,
54
+ },
55
+ ],
56
+ execution: DEFAULT_EXECUTION,
57
+ createdAt: 0,
58
+ updatedAt: 0,
59
+ },
60
+ {
61
+ id: 'builtin-bug-investigation',
62
+ type: 'built-in',
63
+ name: 'Bug Investigation',
64
+ description: 'Systematic bug investigation: reproduce, find root cause, fix, and verify.',
65
+ icon: '\u{1F41B}',
66
+ category: 'Debugging',
67
+ keywords: ['bug', 'debug', 'fix', 'investigate', 'error', 'issue'],
68
+ variables: [
69
+ { name: 'bug_description', label: 'Bug Description', type: 'multiline', required: true, placeholder: 'Describe the bug behavior...' },
70
+ { name: 'expected_behavior', label: 'Expected Behavior', type: 'text', required: true, placeholder: 'What should happen instead?' },
71
+ { name: 'affected_area', label: 'Affected Area', type: 'text', required: false, placeholder: 'e.g., login page, API, database' },
72
+ ],
73
+ steps: [
74
+ {
75
+ id: stepId(),
76
+ name: 'Understand and locate',
77
+ prompt: 'I need to investigate this bug:\n\n{{bug_description}}\n\nExpected behavior: {{expected_behavior}}\nAffected area: {{affected_area}}\n\nSearch the codebase to find the relevant files and understand the current code flow. Identify where the bug likely originates.',
78
+ requireConfirmation: false,
79
+ },
80
+ {
81
+ id: stepId(),
82
+ name: 'Root cause analysis',
83
+ prompt: 'Based on what you found, identify the root cause of the bug. Explain the exact code path that leads to the incorrect behavior. Show the specific lines of code involved.',
84
+ requireConfirmation: true,
85
+ },
86
+ {
87
+ id: stepId(),
88
+ name: 'Implement fix',
89
+ prompt: 'Implement the minimal fix for this bug. Change only what is necessary to correct the behavior. Do not refactor surrounding code.',
90
+ requireConfirmation: true,
91
+ },
92
+ {
93
+ id: stepId(),
94
+ name: 'Verify fix',
95
+ prompt: 'Run any existing tests related to the fix. If tests fail, fix them. If no tests cover this area, write a targeted test that would have caught this bug.',
96
+ requireConfirmation: false,
97
+ },
98
+ ],
99
+ execution: DEFAULT_EXECUTION,
100
+ createdAt: 0,
101
+ updatedAt: 0,
102
+ },
103
+ {
104
+ id: 'builtin-code-review',
105
+ type: 'built-in',
106
+ name: 'Code Review',
107
+ description: 'Comprehensive code review: security, correctness, performance, and style.',
108
+ icon: '\u{1F50D}',
109
+ category: 'Quality',
110
+ keywords: ['review', 'audit', 'quality', 'security', 'style', 'lint'],
111
+ variables: [
112
+ { name: 'target', label: 'Files/Directories to Review', type: 'text', required: true, placeholder: 'src/api/ or specific file path' },
113
+ { name: 'focus', label: 'Review Focus', type: 'select', required: true, default: 'all', options: ['all', 'security', 'performance', 'correctness', 'style'] },
114
+ ],
115
+ steps: [
116
+ {
117
+ id: stepId(),
118
+ name: 'Read and understand',
119
+ prompt: 'Read through all the code in {{target}}. Understand its purpose, dependencies, and how it fits into the larger codebase.',
120
+ requireConfirmation: false,
121
+ },
122
+ {
123
+ id: stepId(),
124
+ name: 'Analyze issues',
125
+ prompt: 'Review the code in {{target}} with focus on: {{focus}}. Produce a structured review with categories: Critical (must fix), Important (should fix), Minor (nice to fix). For each issue, cite the exact file and line.',
126
+ requireConfirmation: true,
127
+ },
128
+ {
129
+ id: stepId(),
130
+ name: 'Fix critical issues',
131
+ prompt: 'Fix all Critical issues from your review. Make the minimal changes needed. Do not fix Important or Minor issues in this step.',
132
+ requireConfirmation: true,
133
+ },
134
+ {
135
+ id: stepId(),
136
+ name: 'Verify fixes',
137
+ prompt: 'Run tests to verify your fixes did not break anything. Summarize what was changed and what remains as Important/Minor issues for future work.',
138
+ requireConfirmation: false,
139
+ },
140
+ ],
141
+ execution: DEFAULT_EXECUTION,
142
+ createdAt: 0,
143
+ updatedAt: 0,
144
+ },
145
+ {
146
+ id: 'builtin-new-component',
147
+ type: 'built-in',
148
+ name: 'New Component',
149
+ description: 'Create a new UI component with props, styling, and tests following project patterns.',
150
+ icon: '\u{1F9E9}',
151
+ category: 'Frontend',
152
+ keywords: ['component', 'ui', 'react', 'frontend', 'widget', 'create'],
153
+ variables: [
154
+ { name: 'component_name', label: 'Component Name', type: 'text', required: true, placeholder: 'UserProfileCard' },
155
+ { name: 'purpose', label: 'Component Purpose', type: 'text', required: true, placeholder: 'Display user profile with avatar and bio' },
156
+ { name: 'location', label: 'Directory', type: 'text', required: false, default: 'src/components', placeholder: 'src/components' },
157
+ ],
158
+ steps: [
159
+ {
160
+ id: stepId(),
161
+ name: 'Analyze existing components',
162
+ prompt: 'Look at the existing components in {{location}} and nearby directories. Identify the patterns used for: component structure, props typing, styling approach, and file organization.',
163
+ requireConfirmation: false,
164
+ },
165
+ {
166
+ id: stepId(),
167
+ name: 'Create component',
168
+ prompt: 'Create a new {{component_name}} component in {{location}}. Purpose: {{purpose}}. Follow the existing component patterns. Include: TypeScript props interface, proper styling, and appropriate state management.',
169
+ requireConfirmation: true,
170
+ },
171
+ {
172
+ id: stepId(),
173
+ name: 'Add tests',
174
+ prompt: 'Write tests for the {{component_name}} component. Test: rendering with different props, user interactions, edge cases (empty data, long strings, etc.). Follow existing test patterns.',
175
+ requireConfirmation: false,
176
+ },
177
+ {
178
+ id: stepId(),
179
+ name: 'Export and integrate',
180
+ prompt: 'Add {{component_name}} to the appropriate barrel export file (index.ts) if one exists. Show an example of how to use the component.',
181
+ requireConfirmation: false,
182
+ },
183
+ ],
184
+ execution: DEFAULT_EXECUTION,
185
+ createdAt: 0,
186
+ updatedAt: 0,
187
+ },
188
+ {
189
+ id: 'builtin-refactor-pattern',
190
+ type: 'built-in',
191
+ name: 'Refactor Pattern',
192
+ description: 'Systematically refactor a code pattern across the codebase.',
193
+ icon: '\u{1F504}',
194
+ category: 'Refactoring',
195
+ keywords: ['refactor', 'rename', 'pattern', 'cleanup', 'migrate', 'modernize'],
196
+ variables: [
197
+ { name: 'current_pattern', label: 'Current Pattern', type: 'multiline', required: true, placeholder: 'Describe the pattern to replace...' },
198
+ { name: 'new_pattern', label: 'New Pattern', type: 'multiline', required: true, placeholder: 'Describe the replacement pattern...' },
199
+ { name: 'scope', label: 'Scope', type: 'text', required: false, default: '.', placeholder: 'Directory or file glob to scope the refactor' },
200
+ ],
201
+ steps: [
202
+ {
203
+ id: stepId(),
204
+ name: 'Find all occurrences',
205
+ prompt: 'Search the codebase within {{scope}} for all occurrences of this pattern:\n\n{{current_pattern}}\n\nList every file and line where this pattern appears. Count total occurrences.',
206
+ requireConfirmation: false,
207
+ },
208
+ {
209
+ id: stepId(),
210
+ name: 'Plan refactor',
211
+ prompt: 'For each occurrence found, plan the transformation to:\n\n{{new_pattern}}\n\nIdentify any edge cases where the transformation needs special handling. List the files that will be changed.',
212
+ requireConfirmation: true,
213
+ },
214
+ {
215
+ id: stepId(),
216
+ name: 'Apply refactor',
217
+ prompt: 'Apply the refactoring to all identified locations. Transform each occurrence of the current pattern to the new pattern. Handle edge cases as planned.',
218
+ requireConfirmation: true,
219
+ },
220
+ {
221
+ id: stepId(),
222
+ name: 'Verify refactor',
223
+ prompt: 'Run all tests. Search for any remaining occurrences of the old pattern to ensure nothing was missed. Fix any test failures caused by the refactor.',
224
+ requireConfirmation: false,
225
+ },
226
+ ],
227
+ execution: DEFAULT_EXECUTION,
228
+ createdAt: 0,
229
+ updatedAt: 0,
230
+ },
231
+ ];
@@ -37,6 +37,15 @@ exports.CLIManager = void 0;
37
37
  const pty = __importStar(require("node-pty"));
38
38
  const model_detector_1 = require("../shared/model-detector");
39
39
  class CLIManager {
40
+ // Safe log that ignores EPIPE errors (broken pipe when app window closes)
41
+ safeLog(...args) {
42
+ try {
43
+ console.log(...args);
44
+ }
45
+ catch {
46
+ // Ignore EPIPE / broken pipe errors on stdout
47
+ }
48
+ }
40
49
  constructor(options) {
41
50
  this.ptyProcess = null;
42
51
  this.outputCallback = null;
@@ -117,17 +126,20 @@ class CLIManager {
117
126
  cleanEnv[key] = value;
118
127
  }
119
128
  }
129
+ const ptyEnv = {
130
+ ...cleanEnv,
131
+ TERM: 'xterm-256color',
132
+ COLORTERM: 'truecolor',
133
+ };
134
+ if (this.options.enableAgentTeams !== false) {
135
+ ptyEnv.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = '1';
136
+ }
120
137
  this.ptyProcess = pty.spawn(shell, [], {
121
138
  name: 'xterm-256color',
122
139
  cols: 80,
123
140
  rows: 24,
124
141
  cwd: this.options.workingDirectory,
125
- env: {
126
- ...cleanEnv,
127
- TERM: 'xterm-256color',
128
- COLORTERM: 'truecolor',
129
- CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: '1',
130
- },
142
+ env: ptyEnv,
131
143
  });
132
144
  this._isRunning = true;
133
145
  this.ptyProcess.onData((data) => {
@@ -161,7 +173,7 @@ class CLIManager {
161
173
  this.initialDetectionBuffer += data;
162
174
  const result = (0, model_detector_1.detectModelFromOutput)(this.initialDetectionBuffer, true);
163
175
  if (result.model) {
164
- console.log('[ModelDetect] Phase 1 detected:', result.model, '(bufLen:', this.initialDetectionBuffer.length, ')');
176
+ this.safeLog('[ModelDetect] Phase 1 detected:', result.model, '(bufLen:', this.initialDetectionBuffer.length, ')');
165
177
  this.currentModel = result.model;
166
178
  if (this.modelChangeCallback) {
167
179
  this.modelChangeCallback(result.model);
@@ -170,7 +182,7 @@ class CLIManager {
170
182
  this.initialDetectionBuffer = '';
171
183
  }
172
184
  else if (this.initialDetectionBuffer.length > 8192) {
173
- console.log('[ModelDetect] Phase 1 gave up after 8KB');
185
+ this.safeLog('[ModelDetect] Phase 1 gave up after 8KB');
174
186
  this.initialDetectionDone = true;
175
187
  this.initialDetectionBuffer = '';
176
188
  }
@@ -184,7 +196,7 @@ class CLIManager {
184
196
  }
185
197
  const result = (0, model_detector_1.detectModelFromOutput)(this.switchDetectionBuffer, false);
186
198
  if (result.model && result.model !== this.currentModel) {
187
- console.log('[ModelDetect] Phase 2 detected:', result.model, '(was:', this.currentModel, ')');
199
+ this.safeLog('[ModelDetect] Phase 2 detected:', result.model, '(was:', this.currentModel, ')');
188
200
  this.currentModel = result.model;
189
201
  this.switchDetectionBuffer = ''; // Reset after successful detection
190
202
  if (this.modelChangeCallback) {