claudedesk 4.4.1 → 4.5.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 (65) hide show
  1. package/CHANGELOG.md +52 -3
  2. package/CLAUDE.md +6 -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 +25 -2
  7. package/dist/main/ipc-handlers.js +192 -2
  8. package/dist/main/playbook-executor.js +321 -0
  9. package/dist/main/playbook-manager.js +271 -0
  10. package/dist/main/session-manager.js +92 -2
  11. package/dist/main/session-pool.js +19 -0
  12. package/dist/main/settings-persistence.js +76 -0
  13. package/dist/renderer/assets/{index-B5DrEDSJ.js → index-DPk5RtXR.js} +4297 -2226
  14. package/dist/renderer/index.html +1 -1
  15. package/dist/shared/ipc-contract.js +56 -1
  16. package/dist/shared/types/playbook-types.js +3 -0
  17. package/docs/agent-teams.png +0 -0
  18. package/docs/repo-index.md +37 -11
  19. package/package.json +1 -1
  20. package/src/main/built-in-playbooks.ts +232 -0
  21. package/src/main/cli-manager.ts +23 -9
  22. package/src/main/git-manager.ts +288 -0
  23. package/src/main/index.ts +29 -2
  24. package/src/main/ipc-handlers.test.ts +126 -0
  25. package/src/main/ipc-handlers.ts +147 -3
  26. package/src/main/playbook-executor.ts +385 -0
  27. package/src/main/playbook-manager.ts +264 -0
  28. package/src/main/session-manager.ts +104 -2
  29. package/src/main/session-pool.ts +20 -0
  30. package/src/main/settings-persistence.ts +85 -0
  31. package/src/renderer/App.tsx +144 -17
  32. package/src/renderer/components/DiffContentArea.tsx +128 -0
  33. package/src/renderer/components/DiffFileNav.tsx +109 -0
  34. package/src/renderer/components/DiffViewer.tsx +478 -0
  35. package/src/renderer/components/DiffViewerHeader.tsx +76 -0
  36. package/src/renderer/components/GitPanel.tsx +51 -166
  37. package/src/renderer/components/PaneHeader.tsx +27 -0
  38. package/src/renderer/components/PlaybookEditor.tsx +749 -0
  39. package/src/renderer/components/PlaybookPanel.tsx +442 -0
  40. package/src/renderer/components/PlaybookParameterDialog.tsx +497 -0
  41. package/src/renderer/components/PlaybookPicker.tsx +319 -0
  42. package/src/renderer/components/PlaybookProgressPanel.tsx +271 -0
  43. package/src/renderer/components/TeamPanel.tsx +1 -1
  44. package/src/renderer/components/WorktreeCleanupDialog.tsx +312 -0
  45. package/src/renderer/components/WorktreePanel.tsx +519 -0
  46. package/src/renderer/components/ui/CommitDialog.tsx +7 -1
  47. package/src/renderer/components/ui/ContextMenu.tsx +1 -0
  48. package/src/renderer/components/ui/FuelStatusIndicator.tsx +28 -0
  49. package/src/renderer/components/ui/FuelTooltip.tsx +11 -0
  50. package/src/renderer/components/ui/NewSessionDialog.tsx +417 -2
  51. package/src/renderer/components/ui/SettingsDialog.tsx +25 -1
  52. package/src/renderer/components/ui/ShortcutsPanel.tsx +1 -0
  53. package/src/renderer/components/ui/Tab.tsx +31 -0
  54. package/src/renderer/components/ui/TabBar.tsx +11 -2
  55. package/src/renderer/components/ui/ToolsDropdown.tsx +39 -0
  56. package/src/renderer/hooks/useAgentTeams.ts +23 -5
  57. package/src/renderer/hooks/useDiffViewer.ts +145 -0
  58. package/src/renderer/hooks/useGit.ts +105 -1
  59. package/src/renderer/hooks/usePlaybooks.ts +267 -0
  60. package/src/renderer/hooks/useSessionManager.ts +5 -2
  61. package/src/renderer/utils/diff-parser.ts +125 -0
  62. package/src/shared/ipc-contract.ts +108 -1
  63. package/src/shared/ipc-types.ts +10 -0
  64. package/src/shared/types/git-types.ts +50 -0
  65. package/src/shared/types/playbook-types.ts +149 -0
package/CHANGELOG.md CHANGED
@@ -8,13 +8,61 @@ 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.5.0] - 2026-02-17
17
+
18
+ ### Added
19
+ - **Testing infrastructure** — Vitest 4 + @testing-library/react + Playwright for Electron
20
+ - 250 tests across 20 test files, 3 workspace projects (shared/main/renderer)
21
+ - Auto-derived electronAPI mock from IPC contract
22
+ - E2E tests with Playwright for Electron (app launch, sessions, split view, keyboard shortcuts)
23
+ - CI workflow with coverage artifacts
24
+ - **Git integration** — Full Git panel with staging, commits, branches, and real-time status
25
+ - `GitManager` with `child_process.execFile` (shell injection safe), per-directory mutex, `.git` fs.watch()
26
+ - File staging/unstaging (individual + bulk), branch display, commit history log
27
+ - AI commit message generation (heuristic-based conventional commits format)
28
+ - Optional checkpoint creation on commit
29
+ - Ctrl+Shift+G keyboard shortcut, ToolsDropdown entry with staged count badge
30
+ - 30 IPC methods (`git:*`): 26 invoke + 4 events
31
+ - **Diff viewer** — Full-screen diff overlay with syntax-highlighted unified diffs
32
+ - Categorized file navigation (staged/unstaged/untracked/conflicted)
33
+ - Dual gutter line numbers, colored add/remove/context lines
34
+ - Keyboard navigation (J/K between files), stage/unstage/discard actions from diff view
35
+ - Unified diff parser (`diff-parser.ts`) with old/new line number tracking
36
+ - **Git worktrees** — Worktree management panel with create, remove, and prune operations
37
+ - `WorktreePanel` for listing and managing worktrees
38
+ - `WorktreeCleanupDialog` for cleanup prompts when closing managed worktree sessions
39
+ - **Session playbooks** — Automated multi-step prompt sequences (13th domain)
40
+ - `PlaybookManager` (CRUD + persistence), `PlaybookExecutor` (execution engine)
41
+ - 5 built-in playbooks: API endpoint, bug investigation, code review, component creation, refactor
42
+ - Silence-based step completion (3s no output = done), confirmation gates between steps
43
+ - Dynamic parameter forms (text/multiline/select/filepath), variable interpolation
44
+ - PlaybookPicker (fuzzy search), PlaybookEditor (3-tab slide-in), PlaybookProgressPanel (bottom-docked)
45
+ - Import/export playbooks as JSON, library browser for built-in + custom playbooks
46
+ - Persistence: `~/.claudedesk/playbooks.json`
47
+ - Ctrl+Shift+B keyboard shortcut, ToolsDropdown entry
48
+ - 15 IPC methods (`playbook:*`): 12 invoke + 3 events
49
+ - **Repository Atlas Engine (RAE)** — Automated CLAUDE.md + repo-index.md generation
50
+ - File enumeration via `git ls-files`, regex import analysis, 3-tier domain inference
51
+ - AtlasPanel UI with idle/scanning/preview states
52
+ - 6 IPC methods (`atlas:*`)
53
+
54
+ ### Fixed
55
+ - **Git generate button** — Action bar Generate now auto-opens CommitDialog with the generated message
56
+ - **CommitDialog generate button** — Directly sets title from return value instead of relying on fragile useEffect prop chain
57
+ - **Silent null guard in useGit** — `generateMessage()` now shows error toast when no project directory is available instead of silently returning
58
+ - **Stale generated message** — Generated commit message state is cleared after successful commit
59
+
60
+ ### Changed
61
+ - **IPC contract** — Expanded from 102 to 149 methods (118 invoke + 8 send + 23 event)
62
+ - **Project scale** — 138 source files, ~45,800 LOC, 13 domains, 13 managers
63
+
64
+ ---
65
+
18
66
  ## [4.4.1] - 2026-02-13
19
67
 
20
68
  ### Fixed
@@ -203,7 +251,8 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on suggesting changes and
203
251
 
204
252
  ---
205
253
 
206
- [Unreleased]: https://github.com/carloluisito/claudedesk/compare/v4.4.1...HEAD
254
+ [Unreleased]: https://github.com/carloluisito/claudedesk/compare/v4.5.0...HEAD
255
+ [4.5.0]: https://github.com/carloluisito/claudedesk/compare/v4.4.1...v4.5.0
207
256
  [4.4.1]: https://github.com/carloluisito/claudedesk/compare/v4.3.1...v4.4.1
208
257
  [4.3.1]: https://github.com/carloluisito/claudedesk/compare/v4.3.0...v4.3.1
209
258
  [4.3.0]: https://github.com/carloluisito/claudedesk/compare/v4.1.1...v4.3.0
package/CLAUDE.md CHANGED
@@ -11,9 +11,9 @@ Electron 28 | React 18 | TypeScript | xterm.js | node-pty | Tailwind CSS | react
11
11
  ```
12
12
  ┌─────────────────────────────────────────────┐
13
13
  │ Main Process (Node.js) │
14
- 9 managers + IPC handlers + session pool
14
+ 13 managers + IPC handlers + session pool
15
15
  └──────────────────┬──────────────────────────┘
16
- │ IPC (102 methods)
16
+ │ IPC (149 methods)
17
17
  ┌──────────────────┴──────────────────────────┐
18
18
  │ Preload (auto-derived context bridge) │
19
19
  └──────────────────┬──────────────────────────┘
@@ -26,7 +26,7 @@ Electron 28 | React 18 | TypeScript | xterm.js | node-pty | Tailwind CSS | react
26
26
 
27
27
  **3-layer pattern per domain:** Manager (main) → Hook (renderer) → Components (renderer)
28
28
 
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.
29
+ **IPC contract** (`src/shared/ipc-contract.ts`) is the single source of truth — 149 methods. The preload bridge and `ElectronAPI` type are auto-derived from it.
30
30
 
31
31
  ## Domain Map
32
32
 
@@ -42,7 +42,8 @@ Electron 28 | React 18 | TypeScript | xterm.js | node-pty | Tailwind CSS | react
42
42
  | Drag-Drop | file-dragdrop-handler, file-utils | useDragDrop, DragDropOverlay, DragDropContextMenu, DragDropSettings | ipc-types.ts | `dragdrop:*` |
43
43
  | Workspaces | settings-persistence | SettingsDialog | ipc-types.ts | `workspace:*` |
44
44
  | Atlas | atlas-manager | useAtlas, AtlasPanel | types/atlas-types.ts | `atlas:*` |
45
- | Git | git-manager | useGit, GitPanel, CommitDialog | types/git-types.ts | `git:*` |
45
+ | Git | git-manager | useGit, useDiffViewer, GitPanel, DiffViewer, DiffFileNav, DiffViewerHeader, DiffContentArea, CommitDialog, WorktreePanel, WorktreeCleanupDialog, diff-parser | types/git-types.ts | `git:*` |
46
+ | Playbooks | playbook-manager, playbook-executor, built-in-playbooks | usePlaybooks, PlaybookPicker, PlaybookParameterDialog, PlaybookProgressPanel, PlaybookPanel, PlaybookEditor | types/playbook-types.ts | `playbook:*` |
46
47
  | Window | index.ts | ConfirmDialog, SettingsDialog, AboutDialog, TitleBarBranding | ipc-types.ts | `window:*`, `dialog:*` |
47
48
 
48
49
  ## Adding a New IPC Method
@@ -72,6 +73,7 @@ That's it. The preload bridge and types auto-derive.
72
73
  - **Split view**: `useSplitView` manages a tree of leaf/branch nodes. Max 4 panes. State persisted in settings.
73
74
  - **Agent team detection**: `AgentTeamManager` watches `~/.claude/teams/` and `~/.claude/tasks/` via `fs.watch()`. Auto-links sessions within 30s of team creation.
74
75
  - **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).
76
+ - **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
77
 
76
78
  ## Testing
77
79
 
@@ -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) {