@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/defaults.ts CHANGED
@@ -19,10 +19,13 @@ export const DEFAULT_AUTO_COMMIT_CONFIG: AutoCommitConfig = {
19
19
 
20
20
  export const DEFAULT_AUTO_RENAME_CONFIG: AutoRenameConfig = {
21
21
  enabled: true,
22
+ maxAttempts: 3,
23
+ minPromptWords: 3,
22
24
  models: {
23
25
  claude: 'claude-haiku-4-5',
24
26
  codex: 'gpt-5-mini',
25
27
  },
28
+ settleMs: 2_500,
26
29
  timeoutMs: 15_000,
27
30
  }
28
31
 
@@ -46,7 +49,8 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
46
49
  m
47
50
  .map('<C-c>', actions.quit, 'Quit')
48
51
  .map('<C-n>', actions.newTab, 'New tab')
49
- .map('<C-g>', actions.sessionPicker, 'Session picker')
52
+ .map('<C-p>', actions.createWorkspaceModal, 'Create workspace')
53
+ .map('<C-g>', actions.projectPicker, 'Project picker')
50
54
  .map('<C-z>', actions.ctrlZSidebar, 'Focus sidebar')
51
55
  .map('dd', actions.closeTab, 'Close tab')
52
56
  .map('<C-b>', actions.toggleSidebar, 'Toggle sidebar')
@@ -59,14 +63,14 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
59
63
  .map('<C-d>', actions.enterGitMode, 'Enter git mode')
60
64
  .map('<C-j>', actions.resizeGitPane(-0.05), 'Git pane smaller')
61
65
  .map('<C-k>', actions.resizeGitPane(0.05), 'Git pane larger')
62
- .map('j', actions.nextSidebarItem, 'Next workspace/worktree')
63
- .map('k', actions.prevSidebarItem, 'Prev workspace/worktree')
66
+ .map('j', actions.nextSidebarItem, 'Next project/workspace')
67
+ .map('k', actions.prevSidebarItem, 'Prev project/workspace')
64
68
  .map('l', actions.nextTab, 'Next tab')
65
69
  .map('h', actions.prevTab, 'Prev tab')
66
70
  .map('L', actions.reorderTab(1), 'Move tab right')
67
71
  .map('H', actions.reorderTab(-1), 'Move tab left')
68
- .map('J', actions.reorderSession(1), 'Move workspace down')
69
- .map('K', actions.reorderSession(-1), 'Move workspace up')
72
+ .map('J', actions.reorderProject(1), 'Move project down')
73
+ .map('K', actions.reorderProject(-1), 'Move project up')
70
74
  .map('r', actions.renameTab, 'Rename tab')
71
75
  .map('i', actions.enterInsert, 'Focus terminal')
72
76
  .map('S', actions.openFlashJump, 'Flash jump')
@@ -94,12 +98,14 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
94
98
  )
95
99
 
96
100
  // -----------------------------------------------------------------------
97
- // Session bar: same chords from nav and while typing in the terminal
101
+ // Project bar: same chords from nav and while typing in the terminal
98
102
  // -----------------------------------------------------------------------
99
103
  .mode(['navigation', 'terminal-input'], (m) =>
100
104
  m
101
- .map('<Leader>b', actions.toggleSessionBar, 'Toggle session bar')
105
+ .map('<Leader>b', actions.toggleProjectBar, 'Toggle project bar')
106
+ .map('<Leader>B', actions.toggleBar('right'), 'Toggle right bar')
102
107
  .map('<Leader>u', actions.toggleAIUsage, 'Toggle AI usage')
108
+ .map('<Leader>,', actions.enterSettings, 'Settings')
103
109
  .map('<Leader>1', actions.switchTabByIndex(1), 'Tab 1')
104
110
  .map('<Leader>2', actions.switchTabByIndex(2), 'Tab 2')
105
111
  .map('<Leader>3', actions.switchTabByIndex(3), 'Tab 3')
@@ -123,7 +129,7 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
123
129
  .map('e', actions.gitToggleFoldAll, 'Expand/collapse all folds')
124
130
  .map('o', actions.openSelectedGitFileInEditor, 'Open in editor')
125
131
  .map('c', actions.gitCommitOpen, 'Commit')
126
- .map('m', actions.openWorktreeMove, 'Move worktree')
132
+ .map('m', actions.openWorkspaceMove, 'Move workspace')
127
133
  .map('p', actions.gitPush, 'Push')
128
134
  .map('v', actions.toggleGitDiffView, 'Toggle split/stacked')
129
135
  .map('b', actions.toggleGitReviewBase, 'Review vs base')
@@ -150,6 +156,36 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
150
156
  .map('<Up>', actions.scrollGitDiff(-1), 'Scroll up')
151
157
  )
152
158
 
159
+ // -----------------------------------------------------------------------
160
+ // Settings screen
161
+ //
162
+ // `h`/`l` always mean "change column", never "change value": a number row
163
+ // would otherwise make them ambiguous. Values move on <Space>/<CR> (toggle,
164
+ // next option) and on -/+ (step a number).
165
+ // -----------------------------------------------------------------------
166
+ .mode('settings', (m) =>
167
+ m
168
+ .map('<Esc>', actions.exitSettings, 'Close settings')
169
+ .map('<Leader>,', actions.exitSettings, 'Close settings')
170
+ .map('h', actions.focusSettingsPane('nav'), 'Sections')
171
+ .map('<Left>', actions.focusSettingsPane('nav'))
172
+ .map('l', actions.activateSettingsRow, 'Settings of the section')
173
+ .map('<Right>', actions.activateSettingsRow)
174
+ .map('<CR>', actions.activateSettingsRow, 'Change')
175
+ .map('<Space>', actions.activateSettingsRow, 'Change')
176
+ .map('j', actions.moveSettingsSelection(1), 'Next', { repeatable: true })
177
+ .map('k', actions.moveSettingsSelection(-1), 'Prev', { repeatable: true })
178
+ .map('<Down>', actions.moveSettingsSelection(1), undefined, { repeatable: true })
179
+ .map('<Up>', actions.moveSettingsSelection(-1), undefined, { repeatable: true })
180
+ .map('<C-n>', actions.moveSettingsSelection(1))
181
+ .map('<C-p>', actions.moveSettingsSelection(-1))
182
+ .map('+', actions.adjustSettingsRow(1), 'Increase', { repeatable: true })
183
+ .map('-', actions.adjustSettingsRow(-1), 'Decrease', { repeatable: true })
184
+ .map('r', actions.resetSettingsRow, 'Reset to default')
185
+ .map('/', actions.openSettingsSearch, 'Search settings')
186
+ .map('?', actions.helpModal('settings'), 'Help')
187
+ )
188
+
153
189
  // -----------------------------------------------------------------------
154
190
  // Modal: help (always in filter mode via Picker)
155
191
  // -----------------------------------------------------------------------
@@ -204,9 +240,9 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
204
240
  )
205
241
 
206
242
  // -----------------------------------------------------------------------
207
- // Modal: worktree-move
243
+ // Modal: workspace-move
208
244
  // -----------------------------------------------------------------------
209
- .mode('modal.worktree-move', (m) =>
245
+ .mode('modal.workspace-move', (m) =>
210
246
  m
211
247
  .map('<Esc>', actions.closeModal, 'Cancel')
212
248
  .map('j', actions.moveModalSelection(1), 'Next')
@@ -215,30 +251,30 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
215
251
  .map('<Up>', actions.moveModalSelection(-1))
216
252
  .map('<C-n>', actions.moveModalSelection(1))
217
253
  .map('<C-p>', actions.moveModalSelection(-1))
218
- .map('d', actions.toggleWorktreeMoveDelete, 'Toggle delete source')
219
- .map('<CR>', actions.confirmWorktreeMove, 'Move')
254
+ .map('d', actions.toggleWorkspaceMoveDelete, 'Toggle delete source')
255
+ .map('<CR>', actions.confirmWorkspaceMove, 'Move')
220
256
  )
221
257
 
222
258
  // -----------------------------------------------------------------------
223
- // Modal: worktree-move recoverable-failure confirmation (stash / conflicts)
259
+ // Modal: workspace-move recoverable-failure confirmation (stash / conflicts)
224
260
  // -----------------------------------------------------------------------
225
- .mode('modal.worktree-move-confirm', (m) =>
261
+ .mode('modal.workspace-move-confirm', (m) =>
226
262
  m
227
263
  .map('<Esc>', actions.closeModal, 'Cancel')
228
264
  .map('n', actions.closeModal, 'Cancel')
229
- .map('<CR>', actions.confirmWorktreeMoveRetry, 'Confirm')
230
- .map('y', actions.confirmWorktreeMoveRetry, 'Confirm')
265
+ .map('<CR>', actions.confirmWorkspaceMoveRetry, 'Confirm')
266
+ .map('y', actions.confirmWorkspaceMoveRetry, 'Confirm')
231
267
  )
232
268
 
233
269
  // -----------------------------------------------------------------------
234
- // Modal: standalone worktree delete confirmation (sidebar "Remove worktree")
270
+ // Modal: standalone workspace delete confirmation (sidebar "Remove workspace")
235
271
  // -----------------------------------------------------------------------
236
- .mode('modal.worktree-delete-confirm', (m) =>
272
+ .mode('modal.workspace-delete-confirm', (m) =>
237
273
  m
238
274
  .map('<Esc>', actions.closeModal, 'Cancel')
239
275
  .map('n', actions.closeModal, 'Cancel')
240
- .map('<CR>', actions.confirmWorktreeDeleteModal, 'Delete worktree')
241
- .map('y', actions.confirmWorktreeDeleteModal, 'Delete worktree')
276
+ .map('<CR>', actions.confirmWorkspaceDeleteModal, 'Delete workspace')
277
+ .map('y', actions.confirmWorkspaceDeleteModal, 'Delete workspace')
242
278
  )
243
279
 
244
280
  // -----------------------------------------------------------------------
@@ -262,12 +298,36 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
262
298
  )
263
299
 
264
300
  // -----------------------------------------------------------------------
265
- // Modal: rename-worktree
301
+ // Modal: search every setting (always filtering, like the other pickers)
266
302
  // -----------------------------------------------------------------------
267
- .mode('modal.rename-worktree', (m) =>
303
+ .mode('modal.settings-search.filtering', (m) =>
304
+ m
305
+ .map('<Esc>', actions.closeSettingsModal, 'Close')
306
+ .map('<CR>', actions.confirmSettingsSearch, 'Go to setting')
307
+ .map('<C-n>', actions.moveModalSelection(1), 'Next')
308
+ .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
309
+ .map('<Down>', actions.moveModalSelection(1))
310
+ .map('<Up>', actions.moveModalSelection(-1))
311
+ .passthrough()
312
+ )
313
+
314
+ // -----------------------------------------------------------------------
315
+ // Modal: one text field over a settings row
316
+ // -----------------------------------------------------------------------
317
+ .mode('modal.setting-text', (m) =>
318
+ m
319
+ .map('<Esc>', actions.closeSettingsModal, 'Cancel')
320
+ .map('<CR>', actions.confirmSettingText, 'Confirm')
321
+ .passthrough()
322
+ )
323
+
324
+ // -----------------------------------------------------------------------
325
+ // Modal: rename-workspace
326
+ // -----------------------------------------------------------------------
327
+ .mode('modal.rename-workspace', (m) =>
268
328
  m
269
329
  .map('<Esc>', actions.closeModal, 'Cancel')
270
- .map('<CR>', actions.confirmRenameWorktree, 'Confirm')
330
+ .map('<CR>', actions.confirmRenameWorkspace, 'Confirm')
271
331
  .passthrough()
272
332
  )
273
333
 
@@ -278,9 +338,6 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
278
338
  m
279
339
  .map('<Esc>', actions.cancelNewTabModal, 'Cancel')
280
340
  .map('<CR>', actions.launchSelectedAssistant, 'Launch')
281
- .map('<C-w>', actions.toggleNewTabWorktree, 'WT')
282
- .map('<C-d>', actions.deleteSelectedWorktree, 'Delete WT')
283
- .map('<Tab>', actions.switchField, 'Next field')
284
341
  .map('<C-n>', actions.moveModalSelection(1), 'Next')
285
342
  .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
286
343
  .map('<Down>', actions.moveModalSelection(1))
@@ -297,23 +354,12 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
297
354
  )
298
355
 
299
356
  // -----------------------------------------------------------------------
300
- // Modal: new-tab worktree delete confirmation dialog
357
+ // Modal: project-picker (always in filter mode via Picker)
301
358
  // -----------------------------------------------------------------------
302
- .mode('modal.new-tab.worktree-delete-confirm', (m) =>
359
+ .mode('modal.project-picker.filtering', (m) =>
303
360
  m
304
- .map('<Esc>', actions.cancelDeleteWorktree, 'Cancel')
305
- .map('n', actions.cancelDeleteWorktree, 'Cancel')
306
- .map('<CR>', actions.confirmDeleteWorktree, 'Delete worktree')
307
- .map('y', actions.confirmDeleteWorktree, 'Delete worktree')
308
- )
309
-
310
- // -----------------------------------------------------------------------
311
- // Modal: session-picker (always in filter mode via Picker)
312
- // -----------------------------------------------------------------------
313
- .mode('modal.session-picker.filtering', (m) =>
314
- m
315
- .map('<Esc>', actions.sessionPickerEscape, 'Cancel')
316
- .map('<CR>', actions.confirmSelectedSession, 'Open')
361
+ .map('<Esc>', actions.projectPickerEscape, 'Cancel')
362
+ .map('<CR>', actions.confirmSelectedProject, 'Open')
317
363
  .map('<C-n>', actions.moveModalSelection(1), 'Next')
318
364
  .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
319
365
  .map('<Down>', actions.moveModalSelection(1))
@@ -322,23 +368,39 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
322
368
  )
323
369
 
324
370
  // -----------------------------------------------------------------------
325
- // Modal: session-name
371
+ // Modal: project-name
326
372
  // -----------------------------------------------------------------------
327
- .mode('modal.session-name', (m) =>
373
+ .mode('modal.project-name', (m) =>
328
374
  m
329
- .map('<Esc>', actions.backToSessionPicker, 'Cancel')
330
- .map('<CR>', actions.confirmSessionRename, 'Confirm')
375
+ .map('<Esc>', actions.backToProjectPicker, 'Cancel')
376
+ .map('<CR>', actions.confirmProjectRename, 'Confirm')
331
377
  .passthrough()
332
378
  )
333
379
 
334
380
  // -----------------------------------------------------------------------
335
- // Modal: create-session
381
+ // Modal: create-project
336
382
  // -----------------------------------------------------------------------
337
- .mode('modal.create-session', (m) =>
383
+ .mode('modal.create-project', (m) =>
338
384
  m
339
- .map('<Esc>', actions.createSessionEscape, 'Cancel')
385
+ .map('<Esc>', actions.createProjectEscape, 'Cancel')
340
386
  .map('<Tab>', actions.switchField, 'Next field')
341
- .map('<CR>', actions.confirmCreateSession, 'Confirm')
387
+ .map('<CR>', actions.confirmCreateProject, 'Confirm')
388
+ .map('<C-n>', actions.moveModalSelection(1), 'Next')
389
+ .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
390
+ .map('<Down>', actions.moveModalSelection(1))
391
+ .map('<Up>', actions.moveModalSelection(-1))
392
+ .passthrough()
393
+ )
394
+
395
+ // -----------------------------------------------------------------------
396
+ // Modal: create-workspace (a project inside the current project)
397
+ // -----------------------------------------------------------------------
398
+ .mode('modal.create-workspace', (m) =>
399
+ m
400
+ .map('<Esc>', actions.createWorkspaceEscape, 'Back/Cancel')
401
+ .map('<Tab>', actions.switchCreateWorkspaceField, 'Next field')
402
+ .map('<CR>', actions.confirmCreateWorkspace, 'Create')
403
+ .map('<C-CR>', actions.createWorkspaceNewline, 'Newline')
342
404
  .map('<C-n>', actions.moveModalSelection(1), 'Next')
343
405
  .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
344
406
  .map('<Down>', actions.moveModalSelection(1))
package/src/index.ts CHANGED
@@ -38,7 +38,7 @@ export {
38
38
  } from './external-editor-runtime'
39
39
  export { DEFAULT_MULTI_REPO_CONFIG } from './defaults'
40
40
 
41
- // User-facing config types (keymap/backends/sessions/etc.).
41
+ // User-facing config types (keymap/backends/projects/etc.).
42
42
  export type {
43
43
  Action,
44
44
  ActionFn,
@@ -75,9 +75,9 @@ export type {
75
75
  ModeKeymapDef,
76
76
  MultiRepoConfig,
77
77
  MultiRepoState,
78
+ ProjectRecord,
78
79
  ResolvedConfig,
79
80
  ResolvedKeymapConfig,
80
- SessionRecord,
81
81
  SidebarConfig,
82
82
  SideEffect,
83
83
  SnippetDef,
@@ -88,7 +88,4 @@ export type {
88
88
  StatusBarConfig,
89
89
  StatusBarSeparator,
90
90
  TabSession,
91
- WorktreeTemplate,
92
- WorktreeTemplatePane,
93
- WorktreeTemplateTab,
94
91
  } from './types'
package/src/resolver.ts CHANGED
@@ -32,7 +32,16 @@ export function resolveConfig(userConfig: AimuxUserConfig): ResolvedConfig {
32
32
 
33
33
  const autoRename: AutoRenameConfig = {
34
34
  enabled: userConfig.autoRename?.enabled ?? DEFAULT_AUTO_RENAME_CONFIG.enabled,
35
+ maxAttempts: Math.max(
36
+ 1,
37
+ userConfig.autoRename?.maxAttempts ?? DEFAULT_AUTO_RENAME_CONFIG.maxAttempts
38
+ ),
39
+ minPromptWords: Math.max(
40
+ 1,
41
+ userConfig.autoRename?.minPromptWords ?? DEFAULT_AUTO_RENAME_CONFIG.minPromptWords
42
+ ),
35
43
  models: { ...DEFAULT_AUTO_RENAME_CONFIG.models, ...userConfig.autoRename?.models },
44
+ settleMs: Math.max(0, userConfig.autoRename?.settleMs ?? DEFAULT_AUTO_RENAME_CONFIG.settleMs),
36
45
  timeoutMs: userConfig.autoRename?.timeoutMs ?? DEFAULT_AUTO_RENAME_CONFIG.timeoutMs,
37
46
  }
38
47
 
@@ -51,13 +60,14 @@ export function resolveConfig(userConfig: AimuxUserConfig): ResolvedConfig {
51
60
  integrations: resolveIntegrations(userConfig.integrations),
52
61
  keymaps,
53
62
  multiRepo,
54
- sessionBar: resolveSessionBar(userConfig.sessionBar),
63
+ // ponytail: `sessionBar` is the pre-rename key. Unknown keys parse
64
+ // silently, so without the fallback the setting just vanishes.
65
+ projectBar: resolveProjectBar(userConfig.projectBar ?? userConfig.sessionBar),
55
66
  sidebar: userConfig.sidebar ?? {},
56
67
  snippets: userConfig.snippets ?? [],
57
68
  snippetTriggerChar: resolveSnippetTriggerChar(userConfig.snippetTriggerChar),
58
69
  statusBar: userConfig.statusBar ?? {},
59
70
  theme: resolveTheme(userConfig.theme),
60
- worktreeTemplates: userConfig.worktreeTemplates ?? [],
61
71
  }
62
72
  }
63
73
 
@@ -87,69 +97,26 @@ function resolveTheme(userConfig: AimuxUserConfig['theme']): ResolvedConfig['the
87
97
  }
88
98
  }
89
99
 
90
- function resolveSessionBar(
91
- userConfig: AimuxUserConfig['sessionBar']
92
- ): ResolvedConfig['sessionBar'] {
100
+ function resolveProjectBar(
101
+ userConfig: AimuxUserConfig['projectBar']
102
+ ): ResolvedConfig['projectBar'] {
93
103
  if (!userConfig) return {}
94
104
  return {
95
105
  initialVisible: userConfig.initialVisible ?? userConfig.visible,
96
106
  }
97
107
  }
98
108
 
99
- function resolvePaneInitialPosition(
100
- userConfig: NonNullable<AimuxUserConfig['gitPane']>
101
- ): 'left' | 'right' | undefined {
102
- if (userConfig.initialPosition === 'left' || userConfig.initialPosition === 'right') {
103
- return userConfig.initialPosition
104
- }
105
- if (userConfig.position === 'left' || userConfig.position === 'right') {
106
- return userConfig.position
107
- }
108
- return undefined
109
- }
110
-
111
- function resolveEmbeddedInitialPosition(
112
- userConfig: NonNullable<AimuxUserConfig['gitPane']>
113
- ): 'top' | 'bottom' | undefined {
114
- if (userConfig.initialPosition === 'top' || userConfig.initialPosition === 'bottom') {
115
- return userConfig.initialPosition
116
- }
117
- if (userConfig.position === 'top' || userConfig.position === 'bottom') {
118
- return userConfig.position
119
- }
120
- return undefined
121
- }
122
-
109
+ /** Placement fields are accepted for backwards compatibility but dropped here. */
123
110
  function resolveGitPane(userConfig: AimuxUserConfig['gitPane']): ResolvedConfig['gitPane'] {
124
111
  if (!userConfig) return {}
125
-
126
- const initialMode = userConfig.initialMode ?? userConfig.mode
127
- const paneInitialPosition = resolvePaneInitialPosition(userConfig)
128
- const embeddedInitialPosition = resolveEmbeddedInitialPosition(userConfig)
129
- const shared = {
112
+ return {
130
113
  diffCount: userConfig.diffCount,
131
114
  initialDiffModeRatio: userConfig.initialDiffModeRatio ?? userConfig.diffModeRatio,
132
115
  initialFileListMode: userConfig.initialFileListMode ?? userConfig.fileListMode,
133
- initialRatio: userConfig.initialRatio ?? userConfig.ratio,
134
116
  initialTreeCompaction: userConfig.initialTreeCompaction ?? userConfig.treeCompaction,
135
- initialVisible: userConfig.initialVisible ?? userConfig.visible,
136
117
  path: userConfig.path,
137
118
  prefetchRadius: userConfig.prefetchRadius,
138
119
  }
139
-
140
- if (initialMode === 'pane') {
141
- return {
142
- ...shared,
143
- initialMode: 'pane',
144
- initialPosition: paneInitialPosition,
145
- }
146
- }
147
-
148
- return {
149
- ...shared,
150
- ...(initialMode === 'embedded' ? { initialMode: 'embedded' as const } : {}),
151
- initialPosition: embeddedInitialPosition,
152
- }
153
120
  }
154
121
 
155
122
  function resolveKeymaps(userConfig: AimuxUserConfig): ResolvedKeymapConfig {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Module-level singleton mirroring `statusBar.separator` from the resolved
3
3
  * config. The status bar component reads this each render; the app sets it
4
- * once at startup so the value is stable for the session.
4
+ * once at startup so the value is stable for the project.
5
5
  *
6
6
  * Same pattern as `auto-commit-runtime` / `external-editor-runtime` — avoids
7
7
  * threading config through React props or contexts.