@brimveyn/aimux-config 0.8.5 → 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,28 +224,33 @@ 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
207
231
  type: DirectoryResultType
208
232
  }
209
233
 
210
- // ─── Sidebar / git panel / modal state (for ModeContext) ──────────────────────
234
+ // ─── Bars / git panel / modal state (for ModeContext) ─────────────────────────
235
+
236
+ export type BarSide = 'left' | 'right'
237
+
238
+ export interface BarWidget {
239
+ id: string
240
+ grow: number
241
+ visible: boolean
242
+ }
211
243
 
212
- export interface SidebarState {
244
+ export interface BarState {
213
245
  visible: boolean
214
246
  width: number
215
- minWidth: number
216
- maxWidth: number
247
+ /** Ordered top → bottom. */
248
+ widgets: BarWidget[]
217
249
  }
218
250
 
251
+ export type BarsState = Record<BarSide, BarState>
252
+
219
253
  export interface GitPaneState {
220
- visible: boolean
221
- mode: 'embedded' | 'pane'
222
- position: 'top' | 'bottom' | 'left' | 'right'
223
- paneRatio: number
224
- embeddedRatio: number
225
254
  diffModeRatio: number
226
255
  fileListMode: GitFileListMode
227
256
  treeCompaction: boolean
@@ -304,48 +333,58 @@ export interface GitModeState {
304
333
  interface ModalBase {
305
334
  selectedIndex: number
306
335
  editBuffer: string | null
307
- sessionTargetId: string | null
336
+ projectTargetId: string | null
308
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
309
345
  }
310
346
 
311
347
  export interface ModalClosed extends ModalBase {
312
348
  type: null
313
349
  editBuffer: null
314
- sessionTargetId: null
350
+ projectTargetId: null
315
351
  }
316
352
 
317
353
  export interface ModalNewTab extends ModalBase {
318
354
  type: 'new-tab'
319
355
  editingCommand: AssistantId | null
320
- activeField: 'assistant' | 'branch-name' | 'target-worktree' | 'worktree-name' | 'base'
321
- branchError: string | null
322
- branchName: string
323
- createWorktree: boolean
324
- selectedAssistantId: AssistantId | null
325
- step: 'assistant' | 'worktree' | 'worktree-create' | 'template'
326
- targetWorktreeIndex: number
327
- worktreeDeletePrompt: { worktreeId: string; reason: string } | null
328
- worktreeName: string
329
- /** Filter text typed into the "Base" picker on the worktree-create step. */
330
- baseQuery: string
331
- /** Resolved base ref the new worktree is forked from (branch of a worktree or a local branch). */
332
- baseRef: string
333
- /** Local branches available as base refs, loaded when the create step opens. */
334
- 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
335
360
  }
336
- export interface ModalSessionPicker extends ModalBase {
337
- type: 'session-picker'
361
+ export interface PendingWorkspaceLaunch {
362
+ projectId: string
363
+ workspaceId: string
364
+ prompt: string
338
365
  }
339
- export interface ModalSessionName extends ModalBase {
340
- type: 'session-name'
341
- returnToSessionPicker: boolean
366
+ export interface ModalProjectPicker extends ModalBase {
367
+ type: 'project-picker'
368
+ }
369
+ export interface ModalProjectName extends ModalBase {
370
+ type: 'project-name'
371
+ returnToProjectPicker: boolean
342
372
  }
343
373
  export interface ModalRenameTab extends ModalBase {
344
374
  type: 'rename-tab'
345
375
  }
346
- export interface ModalRenameWorktree extends ModalBase {
347
- type: 'rename-worktree'
348
- 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
349
388
  }
350
389
  export interface ModalSnippetPicker extends ModalBase {
351
390
  type: 'snippet-picker'
@@ -364,13 +403,23 @@ export interface ModalSplitPicker extends ModalBase {
364
403
  type: 'split-picker'
365
404
  splitDirection: SplitDirection
366
405
  }
367
- export interface ModalCreateSession extends ModalBase {
368
- type: 'create-session'
406
+ export interface ModalCreateProject extends ModalBase {
407
+ type: 'create-project'
369
408
  directoryResults: DirectoryResult[]
370
409
  pendingProjectPath: string | null
371
410
  activeField: 'directory' | 'name'
372
411
  nameBuffer: string
373
- 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[]
374
423
  }
375
424
  export interface ModalGitCommit extends ModalBase {
376
425
  type: 'git-commit'
@@ -396,56 +445,56 @@ export interface ModalAIUsage extends ModalBase {
396
445
  type: 'ai-usage'
397
446
  }
398
447
 
399
- export interface ModalWorktreeMove extends ModalBase {
400
- type: 'worktree-move'
401
- /** The worktree being moved (may differ from the active one, e.g. a tab menu). */
402
- 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
403
452
  deleteSource: boolean
404
- /** Per-worktree dirty file counts, loaded async when the modal opens. */
453
+ /** Per-workspace dirty file counts, loaded async when the modal opens. */
405
454
  stats: { kind: 'loading' } | { kind: 'ready'; dirtyFiles: Record<string, number> }
406
455
  }
407
456
 
408
457
  /**
409
458
  * Confirmation for a recoverable move failure: the target's dirty files
410
459
  * overlap the incoming changes (stash-target) or the squash conflicts
411
- * (keep-conflicts). Both worktrees are already restored; confirming re-runs
412
- * move-worktree with the matching flag.
460
+ * (keep-conflicts). Both workspaces are already restored; confirming re-runs
461
+ * move-workspace with the matching flag.
413
462
  */
414
- export interface ModalWorktreeMoveConfirm extends ModalBase {
415
- type: 'worktree-move-confirm'
463
+ export interface ModalWorkspaceMoveConfirm extends ModalBase {
464
+ type: 'workspace-move-confirm'
416
465
  variant: 'stash-target' | 'keep-conflicts'
417
466
  files: string[]
418
- sessionId: string
419
- sourceWorktreeId: string
420
- targetWorktreeId: string
467
+ projectId: string
468
+ sourceWorkspaceId: string
469
+ targetWorkspaceId: string
421
470
  deleteSource: boolean
422
471
  sourceLabel: string
423
472
  targetLabel: string
424
473
  }
425
474
 
426
475
  /**
427
- * Standalone confirmation for a recoverable worktree delete failure triggered
428
- * 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
429
478
  * params needed to re-run the delete with force once confirmed.
430
479
  */
431
- export interface ModalWorktreeDeleteConfirm extends ModalBase {
432
- type: 'worktree-delete-confirm'
433
- sessionId: string
434
- worktreeId: string
435
- worktreeLabel: string
480
+ export interface ModalWorkspaceDeleteConfirm extends ModalBase {
481
+ type: 'workspace-delete-confirm'
482
+ projectId: string
483
+ workspaceId: string
484
+ workspaceLabel: string
436
485
  reason: string
437
486
  closeTabs: boolean
438
487
  /** Whether confirming force-deletes — true only after a recoverable failure. */
439
488
  force: boolean
440
489
  }
441
490
 
442
- export type FlashJumpTargetKind = 'workspace' | 'worktree' | 'tab'
491
+ export type FlashJumpTargetKind = 'project' | 'workspace' | 'tab'
443
492
 
444
493
  export interface FlashJumpTarget {
445
494
  kind: FlashJumpTargetKind
446
- sessionIndex: number
447
- sessionId: string
448
- worktreeId?: string
495
+ projectIndex: number
496
+ projectId: string
497
+ workspaceId?: string
449
498
  tabId?: string
450
499
  }
451
500
 
@@ -465,30 +514,33 @@ export interface ModalFlashJump extends ModalBase {
465
514
  export type ModalState =
466
515
  | ModalClosed
467
516
  | ModalNewTab
468
- | ModalSessionPicker
469
- | ModalSessionName
517
+ | ModalProjectPicker
518
+ | ModalProjectName
470
519
  | ModalRenameTab
471
- | ModalRenameWorktree
520
+ | ModalRenameWorkspace
472
521
  | ModalSnippetPicker
473
522
  | ModalThemePicker
474
523
  | ModalHelp
475
524
  | ModalSplitPicker
476
- | ModalCreateSession
525
+ | ModalCreateProject
526
+ | ModalCreateWorkspace
477
527
  | ModalSnippetEditor
478
528
  | ModalGitCommit
479
529
  | ModalUpdateAvailable
480
530
  | ModalAIUsage
481
- | ModalWorktreeMove
482
- | ModalWorktreeMoveConfirm
483
- | ModalWorktreeDeleteConfirm
531
+ | ModalWorkspaceMove
532
+ | ModalWorkspaceMoveConfirm
533
+ | ModalWorkspaceDeleteConfirm
484
534
  | ModalFlashJump
535
+ | ModalSettingText
536
+ | ModalSettingsSearch
485
537
 
486
538
  export interface LayoutState {
487
539
  terminalCols: number
488
540
  terminalRows: number
489
541
  }
490
542
 
491
- export interface SessionBarState {
543
+ export interface ProjectBarState {
492
544
  visible: boolean
493
545
  }
494
546
 
@@ -511,7 +563,7 @@ export type AutoCommitSuggestion =
511
563
  }
512
564
 
513
565
  export interface AutoCommitState {
514
- bySession: Record<string, AutoCommitSuggestion>
566
+ byProject: Record<string, AutoCommitSuggestion>
515
567
  }
516
568
 
517
569
  export interface DiscoveredRepo {
@@ -525,18 +577,25 @@ export interface MultiRepoState {
525
577
  prefixes: Record<string, string>
526
578
  }
527
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
+
528
587
  export interface AppState {
529
588
  tabs: TabSession[]
530
589
  activeTabId: string | null
531
590
  layoutTrees: Record<string, LayoutNode>
532
591
  tabGroupMap: Record<string, string>
533
- sessions: SessionRecord[]
534
- currentSessionId: string | null
535
- sessionStatuses: Record<string, SessionStatus>
536
- sessionBar: SessionBarState
592
+ projects: ProjectRecord[]
593
+ currentProjectId: string | null
594
+ projectStatuses: Record<string, ProjectStatus>
595
+ projectBar: ProjectBarState
537
596
  snippets: SnippetRecord[]
538
597
  focusMode: FocusMode
539
- sidebar: SidebarState
598
+ bars: BarsState
540
599
  gitPane: GitPaneState
541
600
  modal: ModalState
542
601
  layout: LayoutState
@@ -545,79 +604,77 @@ export interface AppState {
545
604
  gitMode: GitModeState
546
605
  autoCommit: AutoCommitState
547
606
  multiRepo: MultiRepoState
548
- worktreeDivergence: Record<string, BranchDivergence>
549
- lastActiveTabByWorktree: Record<string, string>
607
+ settings: SettingsUIState
608
+ workspaceDivergence: Record<string, BranchDivergence>
609
+ workspaceActivity: Record<string, WorkspaceActivity>
610
+ lastActiveTabByWorkspace: Record<string, string>
550
611
  pendingChords: string[] | null
551
- worktreeTemplates: WorktreeTemplate[]
552
612
  }
553
613
 
554
614
  // ─── AppAction union ──────────────────────────────────────────────────────────
555
615
 
556
616
  export type ModalAction =
557
- | { type: 'open-new-tab-modal' }
558
- | { type: 'set-new-tab-branch-error'; message: string | null }
559
617
  | {
560
- type: 'set-new-tab-worktree-delete-prompt'
561
- prompt: { worktreeId: string; reason: string } | null
618
+ type: 'open-new-tab-modal'
619
+ pendingWorkspace?: PendingWorkspaceLaunch
620
+ pendingPrompt?: string
562
621
  }
563
- | { type: 'set-new-tab-base-branches'; branches: string[] }
564
- | { type: 'enter-new-tab-worktree-create' }
565
- | { type: 'enter-new-tab-template-pick' }
566
- | { type: 'enter-new-tab-template-shortcut' }
567
- | { type: 'select-new-tab-assistant'; assistantId?: AssistantId }
568
- | { type: 'toggle-new-tab-worktree'; assistantId?: AssistantId }
569
622
  | { type: 'open-help-modal'; scope?: ModeId }
570
623
  | { type: 'open-split-picker'; direction: SplitDirection }
571
- | { type: 'open-session-picker' }
624
+ | { type: 'open-project-picker' }
572
625
  | {
573
- type: 'open-session-name-modal'
574
- sessionTargetId?: string
626
+ type: 'open-project-name-modal'
627
+ projectTargetId?: string
575
628
  initialName?: string
576
- returnToSessionPicker?: boolean
629
+ returnToProjectPicker?: boolean
577
630
  }
578
631
  | { type: 'close-modal' }
579
632
  | { type: 'move-modal-selection'; delta: number }
580
633
  | { type: 'update-command-edit'; char: string }
581
634
  | { type: 'cancel-command-edit' }
582
- | { 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' }
583
640
  | { type: 'set-directory-results'; results: DirectoryResult[] }
584
- | { type: 'switch-create-session-field' }
641
+ | { type: 'switch-create-project-field' }
585
642
  | { type: 'select-directory' }
586
643
  | { type: 'open-rename-tab-modal' }
587
644
  | {
588
- type: 'open-rename-worktree-modal'
589
- sessionId: string
590
- worktreeId: string
645
+ type: 'open-rename-workspace-modal'
646
+ projectId: string
647
+ workspaceId: string
591
648
  initialName: string
592
649
  }
593
- | { type: 'open-snippet-picker' }
650
+ | { type: 'open-snippet-picker'; returnTo?: FocusMode }
594
651
  | { type: 'open-snippet-editor'; snippetId?: string }
595
652
  | { type: 'set-help-entry-count'; count: number }
596
653
  | { type: 'set-theme-entry-count'; count: number }
597
- | { type: 'open-theme-picker' }
654
+ | { type: 'open-theme-picker'; returnTo?: FocusMode }
598
655
  | { type: 'open-update-available-modal'; currentVersion: string; latestVersion: string }
599
656
  | { type: 'set-modal-selection-index'; index: number }
600
657
  | { type: 'open-ai-usage-modal' }
601
658
  | { type: 'open-edit-custom-command'; assistantId: AssistantId }
602
- | { type: 'open-worktree-move-modal'; sourceWorktreeId: string }
603
- | { type: 'toggle-worktree-move-delete' }
604
- | { 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> }
605
662
  | {
606
- type: 'open-worktree-move-confirm'
663
+ type: 'open-workspace-move-confirm'
607
664
  variant: 'stash-target' | 'keep-conflicts'
608
665
  files: string[]
609
- sessionId: string
610
- sourceWorktreeId: string
611
- targetWorktreeId: string
666
+ projectId: string
667
+ sourceWorkspaceId: string
668
+ targetWorkspaceId: string
612
669
  deleteSource: boolean
613
670
  sourceLabel: string
614
671
  targetLabel: string
615
672
  }
616
673
  | {
617
- type: 'open-worktree-delete-confirm'
618
- sessionId: string
619
- worktreeId: string
620
- worktreeLabel: string
674
+ type: 'open-workspace-delete-confirm'
675
+ projectId: string
676
+ workspaceId: string
677
+ workspaceLabel: string
621
678
  reason: string
622
679
  closeTabs: boolean
623
680
  force: boolean
@@ -625,28 +682,35 @@ export type ModalAction =
625
682
  | { type: 'open-flash-jump-modal' }
626
683
  | { type: 'clear-flash-jump-pending' }
627
684
 
628
- export type SessionAction =
629
- | { type: 'load-session'; sessionId: string; workspaceSnapshot?: WorkspaceSnapshotV1 }
630
- | { type: 'set-sessions'; sessions: SessionRecord[] }
631
- | { type: 'create-session-record'; session: SessionRecord }
632
- | { type: 'rename-session-record'; sessionId: string; name: string }
633
- | { type: 'delete-session-record'; sessionId: string; openSessionPicker?: boolean }
634
- | { type: 'reorder-sessions'; orderedIds: string[] }
635
- | { type: 'reorder-active-session'; delta: number }
636
- | { type: 'set-session-status'; sessionId: string; status: SessionStatus }
637
- | { type: 'add-worktree-record'; sessionId: string; worktree: WorktreeRecord; activate?: boolean }
638
- | { 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 }
639
703
  | {
640
- type: 'update-worktree-record'
641
- sessionId: string
642
- worktreeId: string
643
- patch: Partial<WorktreeRecord>
704
+ type: 'update-workspace-record'
705
+ projectId: string
706
+ workspaceId: string
707
+ patch: Partial<WorkspaceRecord>
644
708
  }
645
709
 
646
710
  export type TabAction =
647
711
  | { type: 'add-tab'; tab: TabSession }
648
712
  | {
649
- type: 'hydrate-workspace'
713
+ type: 'hydrate-project'
650
714
  tabs: TabSession[]
651
715
  activeTabId: string | null
652
716
  layoutTree?: LayoutNode | null
@@ -658,7 +722,7 @@ export type TabAction =
658
722
  | { type: 'set-active-tab'; tabId: string }
659
723
  | { type: 'move-active-tab'; delta: number }
660
724
  | { type: 'reorder-active-tab'; delta: number }
661
- | { type: 'reset-tab-session'; tabId: string }
725
+ | { type: 'reset-tab-project'; tabId: string }
662
726
  | { type: 'rename-tab'; tabId: string; title: string }
663
727
  | { type: 'append-tab-buffer'; tabId: string; chunk: string }
664
728
  | {
@@ -695,19 +759,28 @@ export type LayoutAction =
695
759
  }
696
760
 
697
761
  export type UIAction =
698
- | { type: 'toggle-sidebar' }
699
- | { type: 'resize-sidebar'; delta: number }
700
- | { type: 'set-sidebar-width'; width: number }
762
+ | { type: 'toggle-bar'; side: BarSide }
763
+ | { type: 'resize-bar'; side: BarSide; delta: number }
764
+ | { type: 'set-bar-width'; side: BarSide; width: number }
765
+ | { type: 'toggle-widget'; widgetId: string }
766
+ | { type: 'move-widget'; widgetId: string; side: BarSide; index: number }
767
+ | { type: 'set-bar-boundary'; side: BarSide; index: number; ratio: number }
768
+ | { type: 'resize-widget'; widgetId: string; delta: number }
701
769
  | { type: 'set-focus-mode'; focusMode: FocusMode }
702
770
  | { type: 'set-terminal-size'; cols: number; rows: number }
703
- | { type: 'toggle-git-pane' }
704
- | { type: 'resize-git-pane'; delta: number }
705
- | { type: 'set-git-pane-ratio'; target: 'pane' | 'embedded'; ratio: number }
706
771
  | { type: 'resize-git-diff-pane'; delta: number }
707
- | { type: 'set-git-pane-mode'; mode: 'embedded' | 'pane' }
708
- | { type: 'set-git-pane-position'; position: 'top' | 'bottom' | 'left' | 'right' }
709
772
  | { type: 'set-pending-chords'; chords: string[] | null }
710
- | { 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 }
711
784
 
712
785
  export interface GitRefreshPayload {
713
786
  branch: string | null
@@ -716,37 +789,21 @@ export interface GitRefreshPayload {
716
789
  files: GitFileEntry[]
717
790
  }
718
791
 
719
- /** 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. */
720
793
  export interface BranchDivergence {
721
794
  ahead: number
722
795
  behind: number
723
- }
724
-
725
- export interface WorktreeTemplatePane {
726
- id: string
727
- assistant: string
728
- splitFrom?: string
729
- direction?: SplitDirection
730
- ratio?: number
731
- send?: string
732
- }
733
-
734
- export interface WorktreeTemplateTab {
735
- panes: WorktreeTemplatePane[]
736
- }
737
-
738
- export interface WorktreeTemplate {
739
- id: string
740
- name: string
741
- description?: string
742
- tabs: WorktreeTemplateTab[]
796
+ /** Lines changed since the fork point, working tree included. */
797
+ added?: number
798
+ removed?: number
743
799
  }
744
800
 
745
801
  export type GitPanelAction =
746
802
  | { type: 'git-refresh-success'; payload: GitRefreshPayload }
747
803
  | { type: 'git-refresh-error'; kind: GitPanelError }
748
804
  | { type: 'git-panel-reset' }
749
- | { 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> }
750
807
 
751
808
  export type GitModeAction =
752
809
  | { type: 'enter-git-mode' }
@@ -785,10 +842,10 @@ export type GitModeAction =
785
842
  fromSection: GitFileSection
786
843
  toSection: GitFileSection | null
787
844
  }
788
- | { type: 'open-git-commit-modal'; sessionId?: string }
845
+ | { type: 'open-git-commit-modal'; projectId?: string }
789
846
  | { type: 'git-commit-enter-confirm' }
790
847
  | { type: 'git-commit-leave-confirm' }
791
- | { type: 'git-commit-enter-generating'; sessionId: string }
848
+ | { type: 'git-commit-enter-generating'; projectId: string }
792
849
  | { type: 'git-commit-leave-generating' }
793
850
 
794
851
  export type DataAction =
@@ -798,7 +855,7 @@ export type DataAction =
798
855
  export type AutoCommitAction =
799
856
  | {
800
857
  type: 'auto-commit-generation-started'
801
- sessionId: string
858
+ projectId: string
802
859
  tabId: string
803
860
  workingTreeHash: string
804
861
  abortController: AbortController
@@ -806,20 +863,21 @@ export type AutoCommitAction =
806
863
  }
807
864
  | {
808
865
  type: 'auto-commit-generation-ready'
809
- sessionId: string
866
+ projectId: string
810
867
  workingTreeHash: string
811
868
  title: string
812
869
  body: string
813
870
  generatedAt: number
814
871
  }
815
- | { type: 'auto-commit-clear'; sessionId: string }
872
+ | { type: 'auto-commit-clear'; projectId: string }
816
873
 
817
874
  export type AppAction =
818
875
  | ModalAction
819
- | SessionAction
876
+ | ProjectAction
820
877
  | TabAction
821
878
  | LayoutAction
822
879
  | UIAction
880
+ | SettingsAction
823
881
  | DataAction
824
882
  | GitPanelAction
825
883
  | GitModeAction
@@ -829,13 +887,15 @@ export type AppAction =
829
887
 
830
888
  export type SideEffect =
831
889
  | { type: 'quit'; state: AppState }
890
+ | { type: 'open-new-tab' }
832
891
  | { type: 'launch-selected-assistant' }
833
- | { type: 'load-new-tab-base-branches' }
834
892
  | { type: 'edit-selected-assistant' }
835
- | { type: 'confirm-selected-session' }
836
- | { type: 'delete-selected-session' }
837
- | { type: 'open-rename-selected-session' }
838
- | { 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' }
839
899
  | { type: 'close-tab'; tabId: string }
840
900
  | { type: 'restart-tab'; tab: TabSession }
841
901
  | { type: 'paste-selected-snippet' }
@@ -848,7 +908,7 @@ export type SideEffect =
848
908
  | { type: 'apply-theme'; action: 'restore' }
849
909
  | { type: 'apply-theme'; action: 'confirm' }
850
910
  | { type: 'apply-theme'; action: 'preview'; delta: 1 | -1 }
851
- | { type: 'rename-session'; sessionId: string; name: string }
911
+ | { type: 'rename-project'; projectId: string; name: string }
852
912
  | { type: 'rename-tab'; tabId: string; title: string }
853
913
  | { type: 'split-pane'; direction: SplitDirection; sourceTabId?: string }
854
914
  | { type: 'confirm-split' }
@@ -864,40 +924,50 @@ export type SideEffect =
864
924
  | { type: 'git-rm'; path: string }
865
925
  | { type: 'git-commit'; title: string; body: string }
866
926
  | { type: 'git-commit-auto'; title: string; body: string }
867
- | { type: 'generate-auto-commit-now'; sessionId: string }
927
+ | { type: 'generate-auto-commit-now'; projectId: string }
868
928
  | { type: 'git-push' }
869
929
  | { type: 'confirm-update-selection' }
870
- | { type: 'switch-session-by-index'; index: number }
930
+ | { type: 'switch-project-by-index'; index: number }
871
931
  | { type: 'cycle-sidebar-item'; direction: 1 | -1 }
872
932
  | { type: 'switch-tab-by-index'; index: number }
873
- | { type: 'delete-session'; sessionId: string }
933
+ | { type: 'delete-project'; projectId: string }
874
934
  | {
875
- type: 'delete-worktree'
876
- sessionId: string
877
- worktreeId: string
935
+ type: 'delete-workspace'
936
+ projectId: string
937
+ workspaceId: string
878
938
  // Force the git worktree removal (discards uncommitted changes in the
879
- // worktree). Also implies closing the worktree's tabs.
939
+ // workspace). Also implies closing the workspace's tabs.
880
940
  force?: boolean
881
- // Close the worktree's tabs without forcing the git removal. Lets the
882
- // sidebar "Remove worktree" clean up tabs (avoiding orphans) while still
883
- // 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.
884
944
  closeTabs?: boolean
885
945
  }
886
946
  | {
887
- type: 'move-worktree'
888
- sessionId: string
889
- sourceWorktreeId: string
890
- targetWorktreeId: string
947
+ type: 'move-workspace'
948
+ projectId: string
949
+ sourceWorkspaceId: string
950
+ targetWorkspaceId: string
891
951
  deleteSource?: boolean
892
- // Retry flags set by the worktree-move-confirm dialog.
952
+ // Retry flags set by the workspace-move-confirm dialog.
893
953
  stashTarget?: boolean
894
954
  keepConflicts?: boolean
895
955
  }
896
- | { type: 'load-worktree-move-stats' }
956
+ | { type: 'load-workspace-move-stats' }
897
957
  | { type: 'toggle-transparent' }
898
958
  | { type: 'toggle-mode' }
899
959
  | { type: 'open-file-in-editor'; path: string }
900
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 }
901
971
 
902
972
  // ─── Key input / KeyResult / ModeContext ──────────────────────────────────────
903
973
 
@@ -944,7 +1014,7 @@ export interface SidebarConfig {
944
1014
  // ─── Hooks config (stub) ──────────────────────────────────────────────────────
945
1015
 
946
1016
  export interface HooksConfig {
947
- onSessionCreate?: (session: { name: string; projectPath?: string }) => void | Promise<void>
1017
+ onProjectCreate?: (project: { name: string; projectPath?: string }) => void | Promise<void>
948
1018
  }
949
1019
 
950
1020
  // ─── Snippet config (stub) ────────────────────────────────────────────────────
@@ -1022,8 +1092,8 @@ export interface KeymapBuilderApi {
1022
1092
 
1023
1093
  // ─── Top-level user config ────────────────────────────────────────────────────
1024
1094
 
1025
- export interface SessionBarConfig {
1026
- /** 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. */
1027
1097
  initialVisible?: boolean
1028
1098
  /** @deprecated Use `initialVisible` instead. */
1029
1099
  visible?: boolean
@@ -1096,6 +1166,19 @@ export interface AutoRenameConfig {
1096
1166
  enabled: boolean
1097
1167
  timeoutMs: number
1098
1168
  models: Partial<Record<string, string>>
1169
+ /**
1170
+ * Quiet period after a title-worthy prompt before a title is generated.
1171
+ * Prompts submitted inside the window are appended to the same request, so a
1172
+ * "read X" / "now do Y" opening yields one title instead of two.
1173
+ */
1174
+ settleMs: number
1175
+ /** Generation attempts before falling back to a title derived locally from the prompt. */
1176
+ maxAttempts: number
1177
+ /**
1178
+ * Prompts with fewer words than this are treated as menu answers or
1179
+ * confirmations and ignored (they do not consume an attempt).
1180
+ */
1181
+ minPromptWords: number
1099
1182
  }
1100
1183
 
1101
1184
  export interface MultiRepoConfig {
@@ -1119,6 +1202,14 @@ export interface AimuxThemeConfig {
1119
1202
  */
1120
1203
  beta?: {
1121
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
1122
1213
  /**
1123
1214
  * Disable Claude Code's built-in syntax highlighting and re-color diff
1124
1215
  * lines from the aimux theme via shiki. Sets
@@ -1198,7 +1289,9 @@ export interface AimuxUserConfig {
1198
1289
  keymaps?: (k: KeymapBuilderApi) => KeymapBuilderApi
1199
1290
  backends?: Record<string, BackendConfig>
1200
1291
  sidebar?: SidebarConfig
1201
- sessionBar?: SessionBarConfig
1292
+ projectBar?: ProjectBarConfig
1293
+ /** @deprecated renamed to `projectBar`. Still read in 0.9.0. */
1294
+ sessionBar?: ProjectBarConfig
1202
1295
  gitPane?: GitPaneConfig
1203
1296
  hooks?: HooksConfig
1204
1297
  snippets?: SnippetDef[]
@@ -1215,10 +1308,14 @@ export interface AimuxUserConfig {
1215
1308
  externalEditor?: ExternalEditorConfig
1216
1309
  integrations?: AimuxIntegrationsConfig
1217
1310
  /**
1218
- * Worktree templates: layouts (multi-pane + initial commands) applied at
1219
- * 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.
1220
1315
  */
1221
- worktreeTemplates?: WorktreeTemplate[]
1316
+ workspaceTemplates?: never
1317
+ /** @deprecated Removed. See `workspaceTemplates`. */
1318
+ worktreeTemplates?: never
1222
1319
  }
1223
1320
 
1224
1321
  // ─── Resolved config (internal) ───────────────────────────────────────────────
@@ -1257,34 +1354,22 @@ export interface ResolvedConfig {
1257
1354
  keymaps: ResolvedKeymapConfig
1258
1355
  backends: Record<string, BackendConfig>
1259
1356
  sidebar: SidebarConfig
1260
- sessionBar: {
1357
+ projectBar: {
1261
1358
  initialVisible?: boolean
1262
1359
  }
1263
- gitPane:
1264
- | {
1265
- initialMode?: 'embedded'
1266
- initialPosition?: 'top' | 'bottom'
1267
- initialVisible?: boolean
1268
- initialRatio?: number
1269
- initialDiffModeRatio?: number
1270
- initialFileListMode?: GitFileListMode
1271
- initialTreeCompaction?: boolean
1272
- path?: GitPanePathConfig
1273
- diffCount?: GitPaneDiffCountConfig
1274
- prefetchRadius?: number
1275
- }
1276
- | {
1277
- initialMode: 'pane'
1278
- initialPosition?: 'left' | 'right'
1279
- initialVisible?: boolean
1280
- initialRatio?: number
1281
- initialDiffModeRatio?: number
1282
- initialFileListMode?: GitFileListMode
1283
- initialTreeCompaction?: boolean
1284
- path?: GitPanePathConfig
1285
- diffCount?: GitPaneDiffCountConfig
1286
- prefetchRadius?: number
1287
- }
1360
+ /**
1361
+ * Placement (`initialMode`/`initialPosition`/`initialRatio`/`initialVisible`)
1362
+ * moved to the bars layout in `aimux.json`; those fields are still accepted
1363
+ * in user config but ignored.
1364
+ */
1365
+ gitPane: {
1366
+ initialDiffModeRatio?: number
1367
+ initialFileListMode?: GitFileListMode
1368
+ initialTreeCompaction?: boolean
1369
+ path?: GitPanePathConfig
1370
+ diffCount?: GitPaneDiffCountConfig
1371
+ prefetchRadius?: number
1372
+ }
1288
1373
  hooks: HooksConfig
1289
1374
  snippets: SnippetDef[]
1290
1375
  snippetTriggerChar: string
@@ -1296,5 +1381,4 @@ export interface ResolvedConfig {
1296
1381
  integrations: {
1297
1382
  claudeHooks: boolean
1298
1383
  }
1299
- worktreeTemplates: WorktreeTemplate[]
1300
1384
  }