@brimveyn/aimux-config 0.8.6 → 0.10.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.
package/src/types.ts CHANGED
@@ -14,13 +14,15 @@ export type ModeId =
14
14
  | 'git-mode'
15
15
  | 'modal.new-tab.command-edit'
16
16
  | 'modal.new-tab.editing-command'
17
- | 'modal.new-tab.worktree-delete-confirm'
18
- | 'modal.worktree-delete-confirm'
19
- | 'modal.session-picker.filtering'
20
- | 'modal.session-name'
21
- | 'modal.create-session'
17
+ | 'modal.workspace-delete-confirm'
18
+ | 'modal.project-picker.filtering'
19
+ | 'modal.project-name'
20
+ | 'modal.create-project'
21
+ | 'modal.create-workspace'
22
22
  | 'modal.rename-tab'
23
- | 'modal.rename-worktree'
23
+ | 'modal.rename-workspace'
24
+ | 'modal.setting-text'
25
+ | 'modal.settings-search.filtering'
24
26
  | 'modal.snippet-picker.filtering'
25
27
  | 'modal.snippet-editor'
26
28
  | 'modal.theme-picker.filtering'
@@ -30,10 +32,11 @@ export type ModeId =
30
32
  | 'modal.git-commit.confirm'
31
33
  | 'modal.git-commit.generating'
32
34
  | 'modal.update-available'
33
- | 'modal.worktree-move'
34
- | 'modal.worktree-move-confirm'
35
+ | 'modal.workspace-move'
36
+ | 'modal.workspace-move-confirm'
35
37
  | 'modal.ai-usage'
36
38
  | 'modal.flash-jump'
39
+ | 'settings'
37
40
 
38
41
  // ─── Primitive app types ──────────────────────────────────────────────────────
39
42
 
@@ -49,16 +52,27 @@ export type AssistantId = BuiltinAssistantId | (string & {})
49
52
  export type TabStatus = 'starting' | 'running' | 'disconnected' | 'error'
50
53
 
51
54
  /**
52
- * Status values that may appear in legacy on-disk workspace snapshots but are
55
+ * Status values that may appear in legacy on-disk project snapshots but are
53
56
  * not produced by the running app anymore.
54
57
  */
55
58
  export type LegacyPersistedTabStatus = TabStatus | 'exited'
56
59
  export type TabActivity = 'working' | 'waiting-input' | 'idle'
57
- export interface SessionStatus {
60
+ export interface ProjectStatus {
58
61
  working: boolean
59
62
  waiting: boolean
60
63
  }
61
- export type FocusMode = 'navigation' | 'terminal-input' | 'modal' | 'command-edit' | 'git'
64
+ export interface WorkspaceActivity {
65
+ working: boolean
66
+ waiting: boolean
67
+ done: boolean
68
+ }
69
+ export type FocusMode =
70
+ | 'navigation'
71
+ | 'terminal-input'
72
+ | 'modal'
73
+ | 'command-edit'
74
+ | 'git'
75
+ | 'settings'
62
76
  export type SplitDirection = 'horizontal' | 'vertical'
63
77
 
64
78
  // ─── Terminal data shapes ─────────────────────────────────────────────────────
@@ -121,11 +135,11 @@ export interface PersistedTabSnapshot {
121
135
  terminalModes: TerminalModeState
122
136
  errorMessage?: string
123
137
  exitCode?: number
124
- worktreeId?: string
138
+ workspaceId?: string
125
139
  autoRenameStatus?: 'eligible' | 'attempted'
126
140
  }
127
141
 
128
- export interface WorkspaceSnapshotV1 {
142
+ export interface ProjectSnapshotV1 {
129
143
  version: 1
130
144
  savedAt: string
131
145
  activeTabId: string | null
@@ -138,17 +152,17 @@ export interface WorkspaceSnapshotV1 {
138
152
  layoutTrees?: Record<string, LayoutNode>
139
153
  tabGroupMap?: Record<string, string>
140
154
  /**
141
- * Last viewed tab per worktree, keyed by worktree id. Optional and additive
155
+ * Last viewed tab per workspace, keyed by workspace id. Optional and additive
142
156
  * (no version bump): older builds ignore it, newer builds tolerate its
143
157
  * absence. Written now so the data accrues, but restoring it at startup is
144
- * gated off until a future change flips RESTORE_LAST_ACTIVE_TAB_BY_WORKTREE.
158
+ * gated off until a future change flips RESTORE_LAST_ACTIVE_TAB_BY_WORKSPACE.
145
159
  */
146
- lastActiveTabByWorktree?: Record<string, string>
160
+ lastActiveTabByWorkspace?: Record<string, string>
147
161
  }
148
162
 
149
- export type WorktreeSource = 'primary' | 'aimux-temp' | 'external'
163
+ export type WorkspaceSource = 'primary' | 'aimux-temp' | 'external'
150
164
 
151
- export interface WorktreeRecord {
165
+ export interface WorkspaceRecord {
152
166
  id: string
153
167
  name: string
154
168
  path: string
@@ -156,14 +170,18 @@ export interface WorktreeRecord {
156
170
  branch?: string
157
171
  baseRef?: string
158
172
  commitSha?: string
159
- source: WorktreeSource
173
+ source: WorkspaceSource
160
174
  createdByAimux: boolean
161
175
  color?: string
162
176
  createdAt: string
163
177
  updatedAt: string
178
+ /** Last setup-script run for this workspace. Display only — the auto-run gate
179
+ * is "this session has not seen this workspace id before". */
180
+ setupRanAt?: string
181
+ setupExitCode?: number
164
182
  }
165
183
 
166
- export interface SessionRecord {
184
+ export interface ProjectRecord {
167
185
  id: string
168
186
  name: string
169
187
  projectPath?: string
@@ -171,9 +189,9 @@ export interface SessionRecord {
171
189
  updatedAt: string
172
190
  lastOpenedAt: string
173
191
  order?: number
174
- workspaceSnapshot?: WorkspaceSnapshotV1
175
- worktrees?: WorktreeRecord[]
176
- activeWorktreeId?: string
192
+ projectSnapshot?: ProjectSnapshotV1
193
+ workspaces?: WorkspaceRecord[]
194
+ activeWorkspaceId?: string
177
195
  }
178
196
 
179
197
  export interface TabSession {
@@ -188,8 +206,14 @@ export interface TabSession {
188
206
  command: string
189
207
  errorMessage?: string
190
208
  exitCode?: number
191
- worktreeId?: string
209
+ workspaceId?: string
210
+ /** This tab finished a turn while you were elsewhere. See `src/state/types.ts`. */
211
+ unseen?: boolean
192
212
  autoRenameStatus?: 'eligible' | 'attempted'
213
+ /** Real PTY tab that no chrome enumerates. See `src/state/types.ts`. */
214
+ hidden?: boolean
215
+ /** Who owns this tab, independent of visibility. See `src/state/types.ts`. */
216
+ role?: 'setup'
193
217
  }
194
218
 
195
219
  export interface SnippetRecord {
@@ -200,7 +224,7 @@ export interface SnippetRecord {
200
224
  vars?: Record<string, SnippetVar>
201
225
  }
202
226
 
203
- export type DirectoryResultType = 'git-repo' | 'worktree' | 'workspace'
227
+ export type DirectoryResultType = 'git-repo' | 'workspace' | 'project'
204
228
 
205
229
  export interface DirectoryResult {
206
230
  path: string
@@ -309,48 +333,58 @@ export interface GitModeState {
309
333
  interface ModalBase {
310
334
  selectedIndex: number
311
335
  editBuffer: string | null
312
- sessionTargetId: string | null
336
+ projectTargetId: string | null
313
337
  cursorPos?: number
338
+ /**
339
+ * Where the focus goes when this modal closes, when it is not back to the
340
+ * panes. Set by whoever opened it, because that is who knows what is behind it
341
+ * — the settings screen opens five different modals, and none of them should
342
+ * have to grow a case in the reducer to find their way home.
343
+ */
344
+ returnTo?: FocusMode
314
345
  }
315
346
 
316
347
  export interface ModalClosed extends ModalBase {
317
348
  type: null
318
349
  editBuffer: null
319
- sessionTargetId: null
350
+ projectTargetId: null
320
351
  }
321
352
 
322
353
  export interface ModalNewTab extends ModalBase {
323
354
  type: 'new-tab'
324
355
  editingCommand: AssistantId | null
325
- activeField: 'assistant' | 'branch-name' | 'target-worktree' | 'worktree-name' | 'base'
326
- branchError: string | null
327
- branchName: string
328
- createWorktree: boolean
329
- selectedAssistantId: AssistantId | null
330
- step: 'assistant' | 'worktree' | 'worktree-create' | 'template'
331
- targetWorktreeIndex: number
332
- worktreeDeletePrompt: { worktreeId: string; reason: string } | null
333
- worktreeName: string
334
- /** Filter text typed into the "Base" picker on the worktree-create step. */
335
- baseQuery: string
336
- /** Resolved base ref the new worktree is forked from (branch of a worktree or a local branch). */
337
- baseRef: string
338
- /** Local branches available as base refs, loaded when the create step opens. */
339
- baseBranches: string[]
356
+ /** Set when `create-workspace` chained into this picker. */
357
+ pendingWorkspace?: PendingWorkspaceLaunch
358
+ /** A prompt for the picked assistant, without the workspace pinning/rename. */
359
+ pendingPrompt?: string
360
+ }
361
+ export interface PendingWorkspaceLaunch {
362
+ projectId: string
363
+ workspaceId: string
364
+ prompt: string
340
365
  }
341
- export interface ModalSessionPicker extends ModalBase {
342
- type: 'session-picker'
366
+ export interface ModalProjectPicker extends ModalBase {
367
+ type: 'project-picker'
343
368
  }
344
- export interface ModalSessionName extends ModalBase {
345
- type: 'session-name'
346
- returnToSessionPicker: boolean
369
+ export interface ModalProjectName extends ModalBase {
370
+ type: 'project-name'
371
+ returnToProjectPicker: boolean
347
372
  }
348
373
  export interface ModalRenameTab extends ModalBase {
349
374
  type: 'rename-tab'
350
375
  }
351
- export interface ModalRenameWorktree extends ModalBase {
352
- type: 'rename-worktree'
353
- worktreeSessionId: string
376
+ /** Fuzzy-ish search across every setting, from inside the settings screen. */
377
+ export interface ModalSettingsSearch extends ModalBase {
378
+ type: 'settings-search'
379
+ }
380
+ export interface ModalSettingText extends ModalBase {
381
+ type: 'setting-text'
382
+ settingId: string
383
+ settingLabel: string
384
+ }
385
+ export interface ModalRenameWorkspace extends ModalBase {
386
+ type: 'rename-workspace'
387
+ workspaceProjectId: string
354
388
  }
355
389
  export interface ModalSnippetPicker extends ModalBase {
356
390
  type: 'snippet-picker'
@@ -369,13 +403,23 @@ export interface ModalSplitPicker extends ModalBase {
369
403
  type: 'split-picker'
370
404
  splitDirection: SplitDirection
371
405
  }
372
- export interface ModalCreateSession extends ModalBase {
373
- type: 'create-session'
406
+ export interface ModalCreateProject extends ModalBase {
407
+ type: 'create-project'
374
408
  directoryResults: DirectoryResult[]
375
409
  pendingProjectPath: string | null
376
410
  activeField: 'directory' | 'name'
377
411
  nameBuffer: string
378
- returnToSessionPicker: boolean
412
+ returnToProjectPicker: boolean
413
+ }
414
+ export interface ModalCreateWorkspace extends ModalBase {
415
+ type: 'create-workspace'
416
+ activeField: 'prompt' | 'base'
417
+ /** "What do you want to work on?" — names the workspace and its branch. */
418
+ prompt: string
419
+ branchError: string | null
420
+ baseQuery: string
421
+ baseRef: string
422
+ baseBranches: string[]
379
423
  }
380
424
  export interface ModalGitCommit extends ModalBase {
381
425
  type: 'git-commit'
@@ -401,56 +445,56 @@ export interface ModalAIUsage extends ModalBase {
401
445
  type: 'ai-usage'
402
446
  }
403
447
 
404
- export interface ModalWorktreeMove extends ModalBase {
405
- type: 'worktree-move'
406
- /** The worktree being moved (may differ from the active one, e.g. a tab menu). */
407
- sourceWorktreeId: string
448
+ export interface ModalWorkspaceMove extends ModalBase {
449
+ type: 'workspace-move'
450
+ /** The workspace being moved (may differ from the active one, e.g. a tab menu). */
451
+ sourceWorkspaceId: string
408
452
  deleteSource: boolean
409
- /** Per-worktree dirty file counts, loaded async when the modal opens. */
453
+ /** Per-workspace dirty file counts, loaded async when the modal opens. */
410
454
  stats: { kind: 'loading' } | { kind: 'ready'; dirtyFiles: Record<string, number> }
411
455
  }
412
456
 
413
457
  /**
414
458
  * Confirmation for a recoverable move failure: the target's dirty files
415
459
  * overlap the incoming changes (stash-target) or the squash conflicts
416
- * (keep-conflicts). Both worktrees are already restored; confirming re-runs
417
- * move-worktree with the matching flag.
460
+ * (keep-conflicts). Both workspaces are already restored; confirming re-runs
461
+ * move-workspace with the matching flag.
418
462
  */
419
- export interface ModalWorktreeMoveConfirm extends ModalBase {
420
- type: 'worktree-move-confirm'
463
+ export interface ModalWorkspaceMoveConfirm extends ModalBase {
464
+ type: 'workspace-move-confirm'
421
465
  variant: 'stash-target' | 'keep-conflicts'
422
466
  files: string[]
423
- sessionId: string
424
- sourceWorktreeId: string
425
- targetWorktreeId: string
467
+ projectId: string
468
+ sourceWorkspaceId: string
469
+ targetWorkspaceId: string
426
470
  deleteSource: boolean
427
471
  sourceLabel: string
428
472
  targetLabel: string
429
473
  }
430
474
 
431
475
  /**
432
- * Standalone confirmation for a recoverable worktree delete failure triggered
433
- * outside the new-tab picker (e.g. the sidebar's "Remove worktree"). Carries the
476
+ * Standalone confirmation for a recoverable workspace delete failure triggered
477
+ * outside the new-tab picker (e.g. the sidebar's "Remove workspace"). Carries the
434
478
  * params needed to re-run the delete with force once confirmed.
435
479
  */
436
- export interface ModalWorktreeDeleteConfirm extends ModalBase {
437
- type: 'worktree-delete-confirm'
438
- sessionId: string
439
- worktreeId: string
440
- worktreeLabel: string
480
+ export interface ModalWorkspaceDeleteConfirm extends ModalBase {
481
+ type: 'workspace-delete-confirm'
482
+ projectId: string
483
+ workspaceId: string
484
+ workspaceLabel: string
441
485
  reason: string
442
486
  closeTabs: boolean
443
487
  /** Whether confirming force-deletes — true only after a recoverable failure. */
444
488
  force: boolean
445
489
  }
446
490
 
447
- export type FlashJumpTargetKind = 'workspace' | 'worktree' | 'tab'
491
+ export type FlashJumpTargetKind = 'project' | 'workspace' | 'tab'
448
492
 
449
493
  export interface FlashJumpTarget {
450
494
  kind: FlashJumpTargetKind
451
- sessionIndex: number
452
- sessionId: string
453
- worktreeId?: string
495
+ projectIndex: number
496
+ projectId: string
497
+ workspaceId?: string
454
498
  tabId?: string
455
499
  }
456
500
 
@@ -470,30 +514,33 @@ export interface ModalFlashJump extends ModalBase {
470
514
  export type ModalState =
471
515
  | ModalClosed
472
516
  | ModalNewTab
473
- | ModalSessionPicker
474
- | ModalSessionName
517
+ | ModalProjectPicker
518
+ | ModalProjectName
475
519
  | ModalRenameTab
476
- | ModalRenameWorktree
520
+ | ModalRenameWorkspace
477
521
  | ModalSnippetPicker
478
522
  | ModalThemePicker
479
523
  | ModalHelp
480
524
  | ModalSplitPicker
481
- | ModalCreateSession
525
+ | ModalCreateProject
526
+ | ModalCreateWorkspace
482
527
  | ModalSnippetEditor
483
528
  | ModalGitCommit
484
529
  | ModalUpdateAvailable
485
530
  | ModalAIUsage
486
- | ModalWorktreeMove
487
- | ModalWorktreeMoveConfirm
488
- | ModalWorktreeDeleteConfirm
531
+ | ModalWorkspaceMove
532
+ | ModalWorkspaceMoveConfirm
533
+ | ModalWorkspaceDeleteConfirm
489
534
  | ModalFlashJump
535
+ | ModalSettingText
536
+ | ModalSettingsSearch
490
537
 
491
538
  export interface LayoutState {
492
539
  terminalCols: number
493
540
  terminalRows: number
494
541
  }
495
542
 
496
- export interface SessionBarState {
543
+ export interface ProjectBarState {
497
544
  visible: boolean
498
545
  }
499
546
 
@@ -516,7 +563,7 @@ export type AutoCommitSuggestion =
516
563
  }
517
564
 
518
565
  export interface AutoCommitState {
519
- bySession: Record<string, AutoCommitSuggestion>
566
+ byProject: Record<string, AutoCommitSuggestion>
520
567
  }
521
568
 
522
569
  export interface DiscoveredRepo {
@@ -530,15 +577,22 @@ export interface MultiRepoState {
530
577
  prefixes: Record<string, string>
531
578
  }
532
579
 
580
+ /** Where the cursor is in the settings screen — the cursor only, not the values. */
581
+ export interface SettingsUIState {
582
+ sectionId: string
583
+ pane: 'nav' | 'rows'
584
+ rowIndex: number
585
+ }
586
+
533
587
  export interface AppState {
534
588
  tabs: TabSession[]
535
589
  activeTabId: string | null
536
590
  layoutTrees: Record<string, LayoutNode>
537
591
  tabGroupMap: Record<string, string>
538
- sessions: SessionRecord[]
539
- currentSessionId: string | null
540
- sessionStatuses: Record<string, SessionStatus>
541
- sessionBar: SessionBarState
592
+ projects: ProjectRecord[]
593
+ currentProjectId: string | null
594
+ projectStatuses: Record<string, ProjectStatus>
595
+ projectBar: ProjectBarState
542
596
  snippets: SnippetRecord[]
543
597
  focusMode: FocusMode
544
598
  bars: BarsState
@@ -550,79 +604,77 @@ export interface AppState {
550
604
  gitMode: GitModeState
551
605
  autoCommit: AutoCommitState
552
606
  multiRepo: MultiRepoState
553
- worktreeDivergence: Record<string, BranchDivergence>
554
- lastActiveTabByWorktree: Record<string, string>
607
+ settings: SettingsUIState
608
+ workspaceDivergence: Record<string, BranchDivergence>
609
+ workspaceActivity: Record<string, WorkspaceActivity>
610
+ lastActiveTabByWorkspace: Record<string, string>
555
611
  pendingChords: string[] | null
556
- worktreeTemplates: WorktreeTemplate[]
557
612
  }
558
613
 
559
614
  // ─── AppAction union ──────────────────────────────────────────────────────────
560
615
 
561
616
  export type ModalAction =
562
- | { type: 'open-new-tab-modal' }
563
- | { type: 'set-new-tab-branch-error'; message: string | null }
564
617
  | {
565
- type: 'set-new-tab-worktree-delete-prompt'
566
- prompt: { worktreeId: string; reason: string } | null
618
+ type: 'open-new-tab-modal'
619
+ pendingWorkspace?: PendingWorkspaceLaunch
620
+ pendingPrompt?: string
567
621
  }
568
- | { type: 'set-new-tab-base-branches'; branches: string[] }
569
- | { type: 'enter-new-tab-worktree-create' }
570
- | { type: 'enter-new-tab-template-pick' }
571
- | { type: 'enter-new-tab-template-shortcut' }
572
- | { type: 'select-new-tab-assistant'; assistantId?: AssistantId }
573
- | { type: 'toggle-new-tab-worktree'; assistantId?: AssistantId }
574
622
  | { type: 'open-help-modal'; scope?: ModeId }
575
623
  | { type: 'open-split-picker'; direction: SplitDirection }
576
- | { type: 'open-session-picker' }
624
+ | { type: 'open-project-picker' }
577
625
  | {
578
- type: 'open-session-name-modal'
579
- sessionTargetId?: string
626
+ type: 'open-project-name-modal'
627
+ projectTargetId?: string
580
628
  initialName?: string
581
- returnToSessionPicker?: boolean
629
+ returnToProjectPicker?: boolean
582
630
  }
583
631
  | { type: 'close-modal' }
584
632
  | { type: 'move-modal-selection'; delta: number }
585
633
  | { type: 'update-command-edit'; char: string }
586
634
  | { type: 'cancel-command-edit' }
587
- | { type: 'open-create-session-modal'; returnToSessionPicker: boolean }
635
+ | { type: 'open-create-project-modal'; returnToProjectPicker: boolean }
636
+ | { type: 'open-create-workspace-modal' }
637
+ | { type: 'set-create-workspace-base-branches'; branches: string[]; defaultBranch?: string }
638
+ | { type: 'set-create-workspace-branch-error'; message: string | null }
639
+ | { type: 'switch-create-workspace-field' }
588
640
  | { type: 'set-directory-results'; results: DirectoryResult[] }
589
- | { type: 'switch-create-session-field' }
641
+ | { type: 'switch-create-project-field' }
590
642
  | { type: 'select-directory' }
591
643
  | { type: 'open-rename-tab-modal' }
592
644
  | {
593
- type: 'open-rename-worktree-modal'
594
- sessionId: string
595
- worktreeId: string
645
+ type: 'open-rename-workspace-modal'
646
+ projectId: string
647
+ workspaceId: string
596
648
  initialName: string
597
649
  }
598
- | { type: 'open-snippet-picker' }
650
+ | { type: 'open-snippet-picker'; returnTo?: FocusMode }
599
651
  | { type: 'open-snippet-editor'; snippetId?: string }
600
652
  | { type: 'set-help-entry-count'; count: number }
601
653
  | { type: 'set-theme-entry-count'; count: number }
602
- | { type: 'open-theme-picker' }
654
+ | { type: 'open-theme-picker'; returnTo?: FocusMode }
603
655
  | { type: 'open-update-available-modal'; currentVersion: string; latestVersion: string }
604
656
  | { type: 'set-modal-selection-index'; index: number }
605
657
  | { type: 'open-ai-usage-modal' }
606
658
  | { type: 'open-edit-custom-command'; assistantId: AssistantId }
607
- | { type: 'open-worktree-move-modal'; sourceWorktreeId: string }
608
- | { type: 'toggle-worktree-move-delete' }
609
- | { type: 'set-worktree-move-stats'; dirtyFiles: Record<string, number> }
659
+ | { type: 'open-workspace-move-modal'; sourceWorkspaceId: string }
660
+ | { type: 'toggle-workspace-move-delete' }
661
+ | { type: 'set-workspace-move-stats'; dirtyFiles: Record<string, number> }
610
662
  | {
611
- type: 'open-worktree-move-confirm'
663
+ type: 'open-workspace-move-confirm'
612
664
  variant: 'stash-target' | 'keep-conflicts'
613
665
  files: string[]
614
- sessionId: string
615
- sourceWorktreeId: string
616
- targetWorktreeId: string
666
+ projectId: string
667
+ sourceWorkspaceId: string
668
+ targetWorkspaceId: string
617
669
  deleteSource: boolean
618
670
  sourceLabel: string
619
671
  targetLabel: string
620
672
  }
621
673
  | {
622
- type: 'open-worktree-delete-confirm'
623
- sessionId: string
624
- worktreeId: string
625
- worktreeLabel: string
674
+ type: 'open-workspace-delete-confirm'
675
+ projectId: string
676
+ workspaceId: string
677
+ workspaceLabel: string
626
678
  reason: string
627
679
  closeTabs: boolean
628
680
  force: boolean
@@ -630,28 +682,35 @@ export type ModalAction =
630
682
  | { type: 'open-flash-jump-modal' }
631
683
  | { type: 'clear-flash-jump-pending' }
632
684
 
633
- export type SessionAction =
634
- | { type: 'load-session'; sessionId: string; workspaceSnapshot?: WorkspaceSnapshotV1 }
635
- | { type: 'set-sessions'; sessions: SessionRecord[] }
636
- | { type: 'create-session-record'; session: SessionRecord }
637
- | { type: 'rename-session-record'; sessionId: string; name: string }
638
- | { type: 'delete-session-record'; sessionId: string; openSessionPicker?: boolean }
639
- | { type: 'reorder-sessions'; orderedIds: string[] }
640
- | { type: 'reorder-active-session'; delta: number }
641
- | { type: 'set-session-status'; sessionId: string; status: SessionStatus }
642
- | { type: 'add-worktree-record'; sessionId: string; worktree: WorktreeRecord; activate?: boolean }
643
- | { type: 'set-active-worktree'; sessionId: string; worktreeId: string }
685
+ export type ProjectAction =
686
+ | { type: 'load-project'; projectId: string; projectSnapshot?: ProjectSnapshotV1 }
687
+ | { type: 'set-projects'; projects: ProjectRecord[] }
688
+ | { type: 'create-project-record'; project: ProjectRecord }
689
+ | { type: 'rename-project-record'; projectId: string; name: string }
690
+ | { type: 'delete-project-record'; projectId: string; openProjectPicker?: boolean }
691
+ | { type: 'reorder-projects'; orderedIds: string[] }
692
+ | { type: 'reorder-active-project'; delta: number }
693
+ | { type: 'set-project-status'; projectId: string; status: ProjectStatus }
694
+ | { type: 'set-workspace-activity'; workspaceId: string; working: boolean; waiting: boolean }
695
+ | { type: 'mark-workspace-done'; workspaceId: string }
696
+ | {
697
+ type: 'add-workspace-record'
698
+ projectId: string
699
+ workspace: WorkspaceRecord
700
+ activate?: boolean
701
+ }
702
+ | { type: 'set-active-workspace'; projectId: string; workspaceId: string }
644
703
  | {
645
- type: 'update-worktree-record'
646
- sessionId: string
647
- worktreeId: string
648
- patch: Partial<WorktreeRecord>
704
+ type: 'update-workspace-record'
705
+ projectId: string
706
+ workspaceId: string
707
+ patch: Partial<WorkspaceRecord>
649
708
  }
650
709
 
651
710
  export type TabAction =
652
711
  | { type: 'add-tab'; tab: TabSession }
653
712
  | {
654
- type: 'hydrate-workspace'
713
+ type: 'hydrate-project'
655
714
  tabs: TabSession[]
656
715
  activeTabId: string | null
657
716
  layoutTree?: LayoutNode | null
@@ -663,7 +722,7 @@ export type TabAction =
663
722
  | { type: 'set-active-tab'; tabId: string }
664
723
  | { type: 'move-active-tab'; delta: number }
665
724
  | { type: 'reorder-active-tab'; delta: number }
666
- | { type: 'reset-tab-session'; tabId: string }
725
+ | { type: 'reset-tab-project'; tabId: string }
667
726
  | { type: 'rename-tab'; tabId: string; title: string }
668
727
  | { type: 'append-tab-buffer'; tabId: string; chunk: string }
669
728
  | {
@@ -711,7 +770,17 @@ export type UIAction =
711
770
  | { type: 'set-terminal-size'; cols: number; rows: number }
712
771
  | { type: 'resize-git-diff-pane'; delta: number }
713
772
  | { type: 'set-pending-chords'; chords: string[] | null }
714
- | { type: 'toggle-session-bar' }
773
+ | { type: 'toggle-project-bar' }
774
+
775
+ export type SettingsAction =
776
+ | { type: 'enter-settings' }
777
+ | { type: 'exit-settings' }
778
+ | { type: 'settings-focus-pane'; pane: 'nav' | 'rows' }
779
+ | { type: 'settings-move-selection'; delta: -1 | 1 }
780
+ | { type: 'settings-select-section'; sectionId: string }
781
+ | { type: 'settings-select-row'; rowIndex: number }
782
+ | { type: 'open-settings-search' }
783
+ | { type: 'open-setting-text-modal'; settingId: string; label: string; value: string }
715
784
 
716
785
  export interface GitRefreshPayload {
717
786
  branch: string | null
@@ -720,37 +789,21 @@ export interface GitRefreshPayload {
720
789
  files: GitFileEntry[]
721
790
  }
722
791
 
723
- /** Commits a worktree branch is ahead/behind the ref it forked from. */
792
+ /** Commits a workspace branch is ahead/behind the ref it forked from. */
724
793
  export interface BranchDivergence {
725
794
  ahead: number
726
795
  behind: number
727
- }
728
-
729
- export interface WorktreeTemplatePane {
730
- id: string
731
- assistant: string
732
- splitFrom?: string
733
- direction?: SplitDirection
734
- ratio?: number
735
- send?: string
736
- }
737
-
738
- export interface WorktreeTemplateTab {
739
- panes: WorktreeTemplatePane[]
740
- }
741
-
742
- export interface WorktreeTemplate {
743
- id: string
744
- name: string
745
- description?: string
746
- tabs: WorktreeTemplateTab[]
796
+ /** Lines changed since the fork point, working tree included. */
797
+ added?: number
798
+ removed?: number
747
799
  }
748
800
 
749
801
  export type GitPanelAction =
750
802
  | { type: 'git-refresh-success'; payload: GitRefreshPayload }
751
803
  | { type: 'git-refresh-error'; kind: GitPanelError }
752
804
  | { type: 'git-panel-reset' }
753
- | { type: 'set-worktree-divergence'; divergence: Record<string, BranchDivergence> }
805
+ | { type: 'set-workspace-divergence'; divergence: Record<string, BranchDivergence> }
806
+ | { type: 'set-git-pane'; patch: Partial<GitPaneState> }
754
807
 
755
808
  export type GitModeAction =
756
809
  | { type: 'enter-git-mode' }
@@ -789,10 +842,10 @@ export type GitModeAction =
789
842
  fromSection: GitFileSection
790
843
  toSection: GitFileSection | null
791
844
  }
792
- | { type: 'open-git-commit-modal'; sessionId?: string }
845
+ | { type: 'open-git-commit-modal'; projectId?: string }
793
846
  | { type: 'git-commit-enter-confirm' }
794
847
  | { type: 'git-commit-leave-confirm' }
795
- | { type: 'git-commit-enter-generating'; sessionId: string }
848
+ | { type: 'git-commit-enter-generating'; projectId: string }
796
849
  | { type: 'git-commit-leave-generating' }
797
850
 
798
851
  export type DataAction =
@@ -802,7 +855,7 @@ export type DataAction =
802
855
  export type AutoCommitAction =
803
856
  | {
804
857
  type: 'auto-commit-generation-started'
805
- sessionId: string
858
+ projectId: string
806
859
  tabId: string
807
860
  workingTreeHash: string
808
861
  abortController: AbortController
@@ -810,20 +863,21 @@ export type AutoCommitAction =
810
863
  }
811
864
  | {
812
865
  type: 'auto-commit-generation-ready'
813
- sessionId: string
866
+ projectId: string
814
867
  workingTreeHash: string
815
868
  title: string
816
869
  body: string
817
870
  generatedAt: number
818
871
  }
819
- | { type: 'auto-commit-clear'; sessionId: string }
872
+ | { type: 'auto-commit-clear'; projectId: string }
820
873
 
821
874
  export type AppAction =
822
875
  | ModalAction
823
- | SessionAction
876
+ | ProjectAction
824
877
  | TabAction
825
878
  | LayoutAction
826
879
  | UIAction
880
+ | SettingsAction
827
881
  | DataAction
828
882
  | GitPanelAction
829
883
  | GitModeAction
@@ -833,13 +887,15 @@ export type AppAction =
833
887
 
834
888
  export type SideEffect =
835
889
  | { type: 'quit'; state: AppState }
890
+ | { type: 'open-new-tab' }
836
891
  | { type: 'launch-selected-assistant' }
837
- | { type: 'load-new-tab-base-branches' }
838
892
  | { type: 'edit-selected-assistant' }
839
- | { type: 'confirm-selected-session' }
840
- | { type: 'delete-selected-session' }
841
- | { type: 'open-rename-selected-session' }
842
- | { type: 'create-session'; name: string; projectPath?: string }
893
+ | { type: 'confirm-selected-project' }
894
+ | { type: 'delete-selected-project' }
895
+ | { type: 'open-rename-selected-project' }
896
+ | { type: 'create-project'; name: string; projectPath?: string }
897
+ | { type: 'create-workspace' }
898
+ | { type: 'load-create-workspace-base-branches' }
843
899
  | { type: 'close-tab'; tabId: string }
844
900
  | { type: 'restart-tab'; tab: TabSession }
845
901
  | { type: 'paste-selected-snippet' }
@@ -852,7 +908,7 @@ export type SideEffect =
852
908
  | { type: 'apply-theme'; action: 'restore' }
853
909
  | { type: 'apply-theme'; action: 'confirm' }
854
910
  | { type: 'apply-theme'; action: 'preview'; delta: 1 | -1 }
855
- | { type: 'rename-session'; sessionId: string; name: string }
911
+ | { type: 'rename-project'; projectId: string; name: string }
856
912
  | { type: 'rename-tab'; tabId: string; title: string }
857
913
  | { type: 'split-pane'; direction: SplitDirection; sourceTabId?: string }
858
914
  | { type: 'confirm-split' }
@@ -868,40 +924,50 @@ export type SideEffect =
868
924
  | { type: 'git-rm'; path: string }
869
925
  | { type: 'git-commit'; title: string; body: string }
870
926
  | { type: 'git-commit-auto'; title: string; body: string }
871
- | { type: 'generate-auto-commit-now'; sessionId: string }
927
+ | { type: 'generate-auto-commit-now'; projectId: string }
872
928
  | { type: 'git-push' }
873
929
  | { type: 'confirm-update-selection' }
874
- | { type: 'switch-session-by-index'; index: number }
930
+ | { type: 'switch-project-by-index'; index: number }
875
931
  | { type: 'cycle-sidebar-item'; direction: 1 | -1 }
876
932
  | { type: 'switch-tab-by-index'; index: number }
877
- | { type: 'delete-session'; sessionId: string }
933
+ | { type: 'delete-project'; projectId: string }
878
934
  | {
879
- type: 'delete-worktree'
880
- sessionId: string
881
- worktreeId: string
935
+ type: 'delete-workspace'
936
+ projectId: string
937
+ workspaceId: string
882
938
  // Force the git worktree removal (discards uncommitted changes in the
883
- // worktree). Also implies closing the worktree's tabs.
939
+ // workspace). Also implies closing the workspace's tabs.
884
940
  force?: boolean
885
- // Close the worktree's tabs without forcing the git removal. Lets the
886
- // sidebar "Remove worktree" clean up tabs (avoiding orphans) while still
887
- // refusing to discard uncommitted work in a temp worktree.
941
+ // Close the workspace's tabs without forcing the git removal. Lets the
942
+ // sidebar "Remove workspace" clean up tabs (avoiding orphans) while still
943
+ // refusing to discard uncommitted work in a temp workspace.
888
944
  closeTabs?: boolean
889
945
  }
890
946
  | {
891
- type: 'move-worktree'
892
- sessionId: string
893
- sourceWorktreeId: string
894
- targetWorktreeId: string
947
+ type: 'move-workspace'
948
+ projectId: string
949
+ sourceWorkspaceId: string
950
+ targetWorkspaceId: string
895
951
  deleteSource?: boolean
896
- // Retry flags set by the worktree-move-confirm dialog.
952
+ // Retry flags set by the workspace-move-confirm dialog.
897
953
  stashTarget?: boolean
898
954
  keepConflicts?: boolean
899
955
  }
900
- | { type: 'load-worktree-move-stats' }
956
+ | { type: 'load-workspace-move-stats' }
901
957
  | { type: 'toggle-transparent' }
902
958
  | { type: 'toggle-mode' }
903
959
  | { type: 'open-file-in-editor'; path: string }
904
960
  | { type: 'open-selected-snippet-source-in-editor' }
961
+ | { type: 'run-setup' }
962
+ | { type: 'stop-setup' }
963
+ | { type: 'configure-setup-script'; projectId?: string }
964
+ | { type: 'ask-agent-for-setup-script' }
965
+ | { type: 'promote-setup-tab' }
966
+ | { type: 'activate-settings-row' }
967
+ | { type: 'adjust-settings-row'; delta: 1 | -1 }
968
+ | { type: 'reset-settings-row' }
969
+ | { type: 'confirm-settings-search' }
970
+ | { type: 'commit-setting-text'; settingId: string; value: string }
905
971
 
906
972
  // ─── Key input / KeyResult / ModeContext ──────────────────────────────────────
907
973
 
@@ -948,7 +1014,7 @@ export interface SidebarConfig {
948
1014
  // ─── Hooks config (stub) ──────────────────────────────────────────────────────
949
1015
 
950
1016
  export interface HooksConfig {
951
- onSessionCreate?: (session: { name: string; projectPath?: string }) => void | Promise<void>
1017
+ onProjectCreate?: (project: { name: string; projectPath?: string }) => void | Promise<void>
952
1018
  }
953
1019
 
954
1020
  // ─── Snippet config (stub) ────────────────────────────────────────────────────
@@ -1026,8 +1092,8 @@ export interface KeymapBuilderApi {
1026
1092
 
1027
1093
  // ─── Top-level user config ────────────────────────────────────────────────────
1028
1094
 
1029
- export interface SessionBarConfig {
1030
- /** Startup override for the session bar visibility. Reapplied on each launch. */
1095
+ export interface ProjectBarConfig {
1096
+ /** Startup override for the project bar visibility. Reapplied on each launch. */
1031
1097
  initialVisible?: boolean
1032
1098
  /** @deprecated Use `initialVisible` instead. */
1033
1099
  visible?: boolean
@@ -1136,6 +1202,14 @@ export interface AimuxThemeConfig {
1136
1202
  */
1137
1203
  beta?: {
1138
1204
  harmonizeClaudeTheme?: boolean
1205
+ /**
1206
+ * Draw each agent state (idle, working, waiting, done) as a small animated
1207
+ * sprite rather than a spinner and a set of dots. Needs a terminal that
1208
+ * speaks the Kitty graphics protocol (Kitty, Ghostty, WezTerm) and does not
1209
+ * work under tmux. Sprites are read from `<config dir>/sprites`, falling
1210
+ * back to the ones aimux ships.
1211
+ */
1212
+ experimentalActivitySprites?: boolean
1139
1213
  /**
1140
1214
  * Disable Claude Code's built-in syntax highlighting and re-color diff
1141
1215
  * lines from the aimux theme via shiki. Sets
@@ -1215,7 +1289,9 @@ export interface AimuxUserConfig {
1215
1289
  keymaps?: (k: KeymapBuilderApi) => KeymapBuilderApi
1216
1290
  backends?: Record<string, BackendConfig>
1217
1291
  sidebar?: SidebarConfig
1218
- sessionBar?: SessionBarConfig
1292
+ projectBar?: ProjectBarConfig
1293
+ /** @deprecated renamed to `projectBar`. Still read in 0.9.0. */
1294
+ sessionBar?: ProjectBarConfig
1219
1295
  gitPane?: GitPaneConfig
1220
1296
  hooks?: HooksConfig
1221
1297
  snippets?: SnippetDef[]
@@ -1232,10 +1308,14 @@ export interface AimuxUserConfig {
1232
1308
  externalEditor?: ExternalEditorConfig
1233
1309
  integrations?: AimuxIntegrationsConfig
1234
1310
  /**
1235
- * Worktree templates: layouts (multi-pane + initial commands) applied at
1236
- * worktree creation. Selected from a picker in the new-tab modal.
1311
+ * @deprecated Removed. Workspace provisioning is a per-project setup script
1312
+ * now — see `docs/guide/workspaces.md#setup`. Declared here only so the strike
1313
+ * -through shows up in your editor: an unknown key parses silently, so without
1314
+ * it the setting would just vanish with no signal at all.
1237
1315
  */
1238
- worktreeTemplates?: WorktreeTemplate[]
1316
+ workspaceTemplates?: never
1317
+ /** @deprecated Removed. See `workspaceTemplates`. */
1318
+ worktreeTemplates?: never
1239
1319
  }
1240
1320
 
1241
1321
  // ─── Resolved config (internal) ───────────────────────────────────────────────
@@ -1274,7 +1354,7 @@ export interface ResolvedConfig {
1274
1354
  keymaps: ResolvedKeymapConfig
1275
1355
  backends: Record<string, BackendConfig>
1276
1356
  sidebar: SidebarConfig
1277
- sessionBar: {
1357
+ projectBar: {
1278
1358
  initialVisible?: boolean
1279
1359
  }
1280
1360
  /**
@@ -1301,5 +1381,4 @@ export interface ResolvedConfig {
1301
1381
  integrations: {
1302
1382
  claudeHooks: boolean
1303
1383
  }
1304
- worktreeTemplates: WorktreeTemplate[]
1305
1384
  }