@brimveyn/aimux-config 0.2.4 → 0.2.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brimveyn/aimux-config",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "TypeScript configuration API for aimux — keymaps, themes, and backends with a fluent builder.",
5
5
  "keywords": [
6
6
  "aimux",
package/src/actions.ts CHANGED
@@ -237,6 +237,16 @@ export const saveSnippetEditor: KeyResult = r(
237
237
  'navigation'
238
238
  )
239
239
 
240
+ // ---------------------------------------------------------------------------
241
+ // Update-available modal
242
+ // ---------------------------------------------------------------------------
243
+
244
+ export const confirmUpdateSelection: KeyResult = r(
245
+ [{ type: 'close-modal' }],
246
+ [{ type: 'confirm-update-selection' }],
247
+ 'navigation'
248
+ )
249
+
240
250
  // Layout-specific
241
251
  export const exitLayoutToInput: KeyResult = r(
242
252
  [{ focusMode: 'terminal-input', type: 'set-focus-mode' }],
package/src/defaults.ts CHANGED
@@ -12,262 +12,273 @@ export function getDefaultKeymapConfig(): ResolvedKeymapConfig {
12
12
  .timeout(300)
13
13
 
14
14
  // -----------------------------------------------------------------------
15
- // Navigation mode (src/input/modes/handlers/navigation.ts)
15
+ // Navigation mode
16
16
  // -----------------------------------------------------------------------
17
17
  .mode('navigation', (m) =>
18
18
  m
19
- .map('<C-c>', actions.quit)
20
- .map('<C-n>', actions.newTab)
21
- .map('<C-g>', actions.sessionPicker)
22
- .map('<C-z>', actions.ctrlZSidebar)
23
- .map('dd', actions.closeTab)
24
- .map('<C-b>', actions.toggleSidebar)
25
- .map('<C-r>', actions.restartTab)
26
- .map('<C-s>', actions.snippetPicker)
27
- .map('<C-t>', actions.themePicker)
28
- .map('<C-h>', actions.resizeSidebar(-2))
29
- .map('<C-l>', actions.resizeSidebar(2))
30
- .map('G', actions.toggleGitPanel)
31
- .map('<C-d>', actions.enterGitMode)
32
- .map('<C-j>', actions.resizeGitPanel(-0.05))
33
- .map('<C-k>', actions.resizeGitPanel(0.05))
34
- .map('J', actions.reorderTab(1))
35
- .map('j', actions.nextTab)
36
- .map('K', actions.reorderTab(-1))
37
- .map('k', actions.prevTab)
38
- .map('r', actions.renameTab)
39
- .map('i', actions.enterInsert)
40
- .map('?', actions.helpModal)
19
+ .map('<C-c>', actions.quit, 'Quit')
20
+ .map('<C-n>', actions.newTab, 'New tab')
21
+ .map('<C-g>', actions.sessionPicker, 'Session picker')
22
+ .map('<C-z>', actions.ctrlZSidebar, 'Focus sidebar')
23
+ .map('dd', actions.closeTab, 'Close tab')
24
+ .map('<C-b>', actions.toggleSidebar, 'Toggle sidebar')
25
+ .map('<C-r>', actions.restartTab, 'Restart tab')
26
+ .map('<C-s>', actions.snippetPicker, 'Snippet picker')
27
+ .map('<C-t>', actions.themePicker, 'Theme picker')
28
+ .map('<C-h>', actions.resizeSidebar(-2), 'Sidebar narrower')
29
+ .map('<C-l>', actions.resizeSidebar(2), 'Sidebar wider')
30
+ .map('G', actions.toggleGitPanel, 'Toggle git panel')
31
+ .map('<C-d>', actions.enterGitMode, 'Enter git mode')
32
+ .map('<C-j>', actions.resizeGitPanel(-0.05), 'Git panel smaller')
33
+ .map('<C-k>', actions.resizeGitPanel(0.05), 'Git panel larger')
34
+ .map('J', actions.reorderTab(1), 'Move tab right')
35
+ .map('j', actions.nextTab, 'Next tab')
36
+ .map('K', actions.reorderTab(-1), 'Move tab left')
37
+ .map('k', actions.prevTab, 'Prev tab')
38
+ .map('r', actions.renameTab, 'Rename tab')
39
+ .map('i', actions.enterInsert, 'Focus terminal')
40
+ .map('?', actions.helpModal, 'Help')
41
41
  )
42
42
 
43
43
  // -----------------------------------------------------------------------
44
44
  // Terminal-input mode
45
- // Bindings here are processed by raw-input-handler.ts before bytes reach
46
- // the PTY. Only single-chord <C-*> sequences are supported (no multi-key).
47
45
  // -----------------------------------------------------------------------
48
46
  .mode('terminal-input', (m) =>
49
47
  m
50
- .map('<C-z>', actions.leaveTerminalInput)
51
- .map('<Leader>', actions.enterLayoutMode)
52
- .map('<C-b>', actions.toggleSidebarFromInput)
48
+ .map('<C-z>', actions.leaveTerminalInput, 'Leave insert')
49
+ .map('<Leader>', actions.enterLayoutMode, 'Layout mode')
50
+ .map('<C-b>', actions.toggleSidebarFromInput, 'Toggle sidebar')
53
51
  )
54
52
 
55
53
  // -----------------------------------------------------------------------
56
- // Layout mode (src/input/modes/handlers/layout.ts)
54
+ // Layout mode
57
55
  // -----------------------------------------------------------------------
58
56
  .mode('layout', (m) =>
59
57
  m
60
- .map('<Esc>', actions.exitLayoutToInput)
61
- .map('<Leader>', actions.exitLayoutToInput)
62
- .map('<C-z>', actions.exitLayoutToNavigation)
63
- .map('H', actions.resizePane(-1, 'vertical'))
64
- .map('L', actions.resizePane(1, 'vertical'))
65
- .map('K', actions.resizePane(-1, 'horizontal'))
66
- .map('J', actions.resizePane(1, 'horizontal'))
67
- .map('h', actions.focusPane('left'))
68
- .map('j', actions.focusPane('down'))
69
- .map('k', actions.focusPane('up'))
70
- .map('l', actions.focusPane('right'))
71
- .map('|', actions.splitVertical)
72
- .map('-', actions.splitHorizontal)
73
- .map('q', actions.closePane)
58
+ .map('<Esc>', actions.exitLayoutToInput, 'Back to insert')
59
+ .map('<Leader>', actions.exitLayoutToInput, 'Back to insert')
60
+ .map('<C-z>', actions.exitLayoutToNavigation, 'Back to nav')
61
+ .map('H', actions.resizePane(-1, 'vertical'), 'Shrink ←')
62
+ .map('L', actions.resizePane(1, 'vertical'), 'Grow →')
63
+ .map('K', actions.resizePane(-1, 'horizontal'), 'Shrink ↑')
64
+ .map('J', actions.resizePane(1, 'horizontal'), 'Grow ↓')
65
+ .map('h', actions.focusPane('left'), 'Focus left')
66
+ .map('j', actions.focusPane('down'), 'Focus down')
67
+ .map('k', actions.focusPane('up'), 'Focus up')
68
+ .map('l', actions.focusPane('right'), 'Focus right')
69
+ .map('|', actions.splitVertical, 'Split vertical')
70
+ .map('-', actions.splitHorizontal, 'Split horizontal')
71
+ .map('q', actions.closePane, 'Close pane')
74
72
  )
75
73
 
76
74
  // -----------------------------------------------------------------------
77
- // Git mode (src/input/modes/handlers/git-mode.ts)
75
+ // Git mode
78
76
  // -----------------------------------------------------------------------
79
77
  .mode('git-mode', (m) =>
80
78
  m
81
- .map('<Esc>', actions.exitGitMode)
82
- .map('j', actions.selectGitFile(1))
83
- .map('k', actions.selectGitFile(-1))
84
- .map('<C-d>', actions.scrollGitDiff(20))
85
- .map('<C-u>', actions.scrollGitDiff(-20))
86
- .map('<Down>', actions.scrollGitDiff(1))
87
- .map('<Up>', actions.scrollGitDiff(-1))
88
- .map('a', actions.gitStageSelected)
89
- .map('d', actions.gitDestructiveSelected)
90
- .map('c', actions.gitCommitOpen)
91
- .map('p', actions.gitPush)
79
+ .map('<Esc>', actions.exitGitMode, 'Exit git')
80
+ .map('j', actions.selectGitFile(1), 'Next file')
81
+ .map('k', actions.selectGitFile(-1), 'Prev file')
82
+ .map('<C-d>', actions.scrollGitDiff(20), 'Page down')
83
+ .map('<C-u>', actions.scrollGitDiff(-20), 'Page up')
84
+ .map('<Down>', actions.scrollGitDiff(1), 'Scroll down')
85
+ .map('<Up>', actions.scrollGitDiff(-1), 'Scroll up')
86
+ .map('a', actions.gitStageSelected, 'Stage')
87
+ .map('d', actions.gitDestructiveSelected, 'Unstage/delete')
88
+ .map('c', actions.gitCommitOpen, 'Commit')
89
+ .map('p', actions.gitPush, 'Push')
92
90
  )
93
91
 
94
92
  // -----------------------------------------------------------------------
95
- // Modal: help (src/input/modes/handlers/modal-help.ts)
93
+ // Modal: help
96
94
  // -----------------------------------------------------------------------
97
- .mode('modal.help', (m) => m.map('<Esc>', actions.closeModal))
95
+ .mode('modal.help', (m) => m.map('<Esc>', actions.closeModal, 'Close'))
98
96
 
99
97
  // -----------------------------------------------------------------------
100
- // Modal: theme-picker (src/input/modes/handlers/modal-theme-picker.ts)
98
+ // Modal: theme-picker
101
99
  // -----------------------------------------------------------------------
102
100
  .mode('modal.theme-picker', (m) =>
103
101
  m
104
- .map('<Esc>', actions.restoreTheme)
105
- .map('j', actions.previewTheme(1))
106
- .map('k', actions.previewTheme(-1))
102
+ .map('<Esc>', actions.restoreTheme, 'Cancel')
103
+ .map('j', actions.previewTheme(1), 'Next')
104
+ .map('k', actions.previewTheme(-1), 'Prev')
107
105
  .map('<Down>', actions.previewTheme(1))
108
106
  .map('<Up>', actions.previewTheme(-1))
109
- .map('<CR>', actions.confirmTheme)
107
+ .map('<CR>', actions.confirmTheme, 'Confirm')
110
108
  )
111
109
 
112
110
  // -----------------------------------------------------------------------
113
- // Modal: rename-tab (src/input/modes/handlers/modal-rename-tab.ts)
111
+ // Modal: update-available
112
+ // -----------------------------------------------------------------------
113
+ .mode('modal.update-available', (m) =>
114
+ m
115
+ .map('<Esc>', actions.closeModal, 'Cancel')
116
+ .map('l', actions.moveModalSelection(1), 'Next')
117
+ .map('h', actions.moveModalSelection(-1), 'Prev')
118
+ .map('j', actions.moveModalSelection(1))
119
+ .map('k', actions.moveModalSelection(-1))
120
+ .map('<Right>', actions.moveModalSelection(1))
121
+ .map('<Left>', actions.moveModalSelection(-1))
122
+ .map('<Down>', actions.moveModalSelection(1))
123
+ .map('<Up>', actions.moveModalSelection(-1))
124
+ .map('<CR>', actions.confirmUpdateSelection, 'Confirm')
125
+ )
126
+
127
+ // -----------------------------------------------------------------------
128
+ // Modal: rename-tab
114
129
  // -----------------------------------------------------------------------
115
130
  .mode('modal.rename-tab', (m) =>
116
- m.map('<Esc>', actions.closeModal).map('<CR>', actions.confirmRenameTab).passthrough()
131
+ m
132
+ .map('<Esc>', actions.closeModal, 'Cancel')
133
+ .map('<CR>', actions.confirmRenameTab, 'Confirm')
134
+ .passthrough()
117
135
  )
118
136
 
119
137
  // -----------------------------------------------------------------------
120
- // Modal: new-tab (src/input/modes/handlers/modal-new-tab.ts)
138
+ // Modal: new-tab
121
139
  // -----------------------------------------------------------------------
122
140
  .mode('modal.new-tab', (m) =>
123
141
  m
124
- .map('<Esc>', actions.closeModal)
125
- .map('j', actions.moveModalSelection(1))
126
- .map('k', actions.moveModalSelection(-1))
142
+ .map('<Esc>', actions.closeModal, 'Cancel')
143
+ .map('j', actions.moveModalSelection(1), 'Next')
144
+ .map('k', actions.moveModalSelection(-1), 'Prev')
127
145
  .map('<Down>', actions.moveModalSelection(1))
128
146
  .map('<Up>', actions.moveModalSelection(-1))
129
- .map('<CR>', actions.launchSelectedAssistant)
130
- .map('e', actions.beginCommandEdit)
147
+ .map('<CR>', actions.launchSelectedAssistant, 'Launch')
148
+ .map('e', actions.beginCommandEdit, 'Edit command')
131
149
  )
132
150
 
133
151
  // -----------------------------------------------------------------------
134
152
  // Modal: new-tab command-edit
135
- // (src/input/modes/handlers/modal-new-tab-command-edit.ts)
136
153
  // -----------------------------------------------------------------------
137
154
  .mode('modal.new-tab.command-edit', (m) =>
138
155
  m
139
- .map('<Esc>', actions.cancelCommandEdit('modal.new-tab'))
140
- .map('<CR>', actions.commitCommandEdit)
141
- .map('<C-n>', actions.moveModalSelection(1))
142
- .map('<C-p>', actions.moveModalSelection(-1))
156
+ .map('<Esc>', actions.cancelCommandEdit('modal.new-tab'), 'Cancel')
157
+ .map('<CR>', actions.commitCommandEdit, 'Save')
158
+ .map('<C-n>', actions.moveModalSelection(1), 'Next')
159
+ .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
143
160
  .passthrough()
144
161
  )
145
162
 
146
163
  // -----------------------------------------------------------------------
147
- // Modal: session-picker (src/input/modes/handlers/modal-session-picker.ts)
164
+ // Modal: session-picker
148
165
  // -----------------------------------------------------------------------
149
166
  .mode('modal.session-picker', (m) =>
150
167
  m
151
- .map('<Esc>', actions.sessionPickerEscape)
152
- .map('j', actions.moveModalSelection(1))
153
- .map('k', actions.moveModalSelection(-1))
168
+ .map('<Esc>', actions.sessionPickerEscape, 'Cancel')
169
+ .map('j', actions.moveModalSelection(1), 'Next')
170
+ .map('k', actions.moveModalSelection(-1), 'Prev')
154
171
  .map('<Down>', actions.moveModalSelection(1))
155
172
  .map('<Up>', actions.moveModalSelection(-1))
156
- .map('<CR>', actions.confirmSelectedSession)
157
- .map('n', actions.openCreateSessionModal)
158
- .map('r', actions.openRenameSelectedSession)
159
- .map('d', actions.deleteSelectedSession)
160
- .map('/', actions.beginSessionFilter)
173
+ .map('<CR>', actions.confirmSelectedSession, 'Open')
174
+ .map('n', actions.openCreateSessionModal, 'New')
175
+ .map('r', actions.openRenameSelectedSession, 'Rename')
176
+ .map('d', actions.deleteSelectedSession, 'Delete')
177
+ .map('/', actions.beginSessionFilter, 'Filter')
161
178
  )
162
179
 
163
180
  // -----------------------------------------------------------------------
164
181
  // Modal: session-picker filtering
165
- // (src/input/modes/handlers/modal-session-picker-filter.ts)
166
182
  // -----------------------------------------------------------------------
167
183
  .mode('modal.session-picker.filtering', (m) =>
168
184
  m
169
- .map('<Esc>', actions.cancelCommandEdit('modal.session-picker'))
170
- .map('<CR>', actions.confirmSelectedSession)
171
- .map('<C-n>', actions.moveModalSelection(1))
172
- .map('<C-p>', actions.moveModalSelection(-1))
185
+ .map('<Esc>', actions.cancelCommandEdit('modal.session-picker'), 'Cancel')
186
+ .map('<CR>', actions.confirmSelectedSession, 'Open')
187
+ .map('<C-n>', actions.moveModalSelection(1), 'Next')
188
+ .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
173
189
  .passthrough()
174
190
  )
175
191
 
176
192
  // -----------------------------------------------------------------------
177
- // Modal: session-name (src/input/modes/handlers/modal-session-name.ts)
193
+ // Modal: session-name
178
194
  // -----------------------------------------------------------------------
179
195
  .mode('modal.session-name', (m) =>
180
196
  m
181
- .map('<Esc>', actions.backToSessionPicker)
182
- .map('<CR>', actions.confirmSessionRename)
197
+ .map('<Esc>', actions.backToSessionPicker, 'Cancel')
198
+ .map('<CR>', actions.confirmSessionRename, 'Confirm')
183
199
  .passthrough()
184
200
  )
185
201
 
186
202
  // -----------------------------------------------------------------------
187
203
  // Modal: create-session
188
- // (src/input/modes/handlers/modal-create-session.ts)
189
204
  // -----------------------------------------------------------------------
190
205
  .mode('modal.create-session', (m) =>
191
206
  m
192
- .map('<Esc>', actions.backToSessionPicker)
193
- .map('<Tab>', actions.switchField)
194
- .map('<CR>', actions.confirmCreateSession)
195
- .map('<C-n>', actions.moveModalSelection(1))
196
- .map('<C-p>', actions.moveModalSelection(-1))
207
+ .map('<Esc>', actions.backToSessionPicker, 'Cancel')
208
+ .map('<Tab>', actions.switchField, 'Next field')
209
+ .map('<CR>', actions.confirmCreateSession, 'Confirm')
210
+ .map('<C-n>', actions.moveModalSelection(1), 'Next')
211
+ .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
197
212
  .passthrough()
198
213
  )
199
214
 
200
215
  // -----------------------------------------------------------------------
201
216
  // Modal: snippet-picker
202
- // (src/input/modes/handlers/modal-snippet-picker.ts)
203
217
  // -----------------------------------------------------------------------
204
218
  .mode('modal.snippet-picker', (m) =>
205
219
  m
206
- .map('<Esc>', actions.closeModal)
207
- .map('j', actions.moveModalSelection(1))
208
- .map('k', actions.moveModalSelection(-1))
220
+ .map('<Esc>', actions.closeModal, 'Cancel')
221
+ .map('j', actions.moveModalSelection(1), 'Next')
222
+ .map('k', actions.moveModalSelection(-1), 'Prev')
209
223
  .map('<Down>', actions.moveModalSelection(1))
210
224
  .map('<Up>', actions.moveModalSelection(-1))
211
- .map('<CR>', actions.pasteSelectedSnippet)
212
- .map('a', actions.pasteSnippetToGroup)
213
- .map('n', actions.openSnippetEditor)
214
- .map('r', actions.editSelectedSnippet)
225
+ .map('<CR>', actions.pasteSelectedSnippet, 'Send')
226
+ .map('a', actions.pasteSnippetToGroup, 'Send to group')
227
+ .map('n', actions.openSnippetEditor, 'New')
228
+ .map('r', actions.editSelectedSnippet, 'Edit')
215
229
  .map('e', actions.editSelectedSnippet)
216
- .map('d', actions.deleteSelectedSnippet)
217
- .map('/', actions.beginSnippetFilter)
230
+ .map('d', actions.deleteSelectedSnippet, 'Delete')
231
+ .map('/', actions.beginSnippetFilter, 'Filter')
218
232
  )
219
233
 
220
234
  // -----------------------------------------------------------------------
221
235
  // Modal: snippet-picker filtering
222
- // (src/input/modes/handlers/modal-snippet-picker-filter.ts)
223
236
  // -----------------------------------------------------------------------
224
237
  .mode('modal.snippet-picker.filtering', (m) =>
225
238
  m
226
- .map('<Esc>', actions.cancelCommandEdit('modal.snippet-picker'))
227
- .map('<CR>', actions.snippetFilterPaste)
228
- .map('<C-a>', actions.snippetFilterPasteToGroup)
229
- .map('<C-n>', actions.moveModalSelection(1))
230
- .map('<C-p>', actions.moveModalSelection(-1))
239
+ .map('<Esc>', actions.cancelCommandEdit('modal.snippet-picker'), 'Cancel')
240
+ .map('<CR>', actions.snippetFilterPaste, 'Send')
241
+ .map('<C-a>', actions.snippetFilterPasteToGroup, 'Send to group')
242
+ .map('<C-n>', actions.moveModalSelection(1), 'Next')
243
+ .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
231
244
  .passthrough()
232
245
  )
233
246
 
234
247
  // -----------------------------------------------------------------------
235
248
  // Modal: snippet-editor
236
- // (src/input/modes/handlers/modal-snippet-editor.ts)
237
249
  // -----------------------------------------------------------------------
238
250
  .mode('modal.snippet-editor', (m) =>
239
251
  m
240
- .map('<Esc>', actions.backToSnippetPicker)
241
- .map('<Tab>', actions.switchField)
242
- .map('<CR>', actions.saveSnippetEditor)
243
- .map('<C-n>', actions.moveModalSelection(1))
244
- .map('<C-p>', actions.moveModalSelection(-1))
252
+ .map('<Esc>', actions.backToSnippetPicker, 'Cancel')
253
+ .map('<Tab>', actions.switchField, 'Next field')
254
+ .map('<CR>', actions.saveSnippetEditor, 'Save')
255
+ .map('<C-n>', actions.moveModalSelection(1), 'Next')
256
+ .map('<C-p>', actions.moveModalSelection(-1), 'Prev')
245
257
  .passthrough()
246
258
  )
247
259
 
248
260
  // -----------------------------------------------------------------------
249
261
  // Modal: split-picker
250
- // (src/input/modes/handlers/modal-split-picker.ts)
251
262
  // -----------------------------------------------------------------------
252
263
  .mode('modal.split-picker', (m) =>
253
264
  m
254
- .map('<Esc>', actions.closeModal)
255
- .map('j', actions.moveModalSelection(1))
256
- .map('k', actions.moveModalSelection(-1))
265
+ .map('<Esc>', actions.closeModal, 'Cancel')
266
+ .map('j', actions.moveModalSelection(1), 'Next')
267
+ .map('k', actions.moveModalSelection(-1), 'Prev')
257
268
  .map('<Down>', actions.moveModalSelection(1))
258
269
  .map('<Up>', actions.moveModalSelection(-1))
259
- .map('<CR>', actions.confirmSplit)
270
+ .map('<CR>', actions.confirmSplit, 'Confirm')
260
271
  )
261
272
 
262
273
  // -----------------------------------------------------------------------
263
- // Modal: git-commit (src/input/modes/handlers/modal-git-commit.ts)
274
+ // Modal: git-commit
264
275
  // -----------------------------------------------------------------------
265
276
  .mode('modal.git-commit', (m) =>
266
277
  m
267
- .map('<Esc>', actions.gitCommitCancel)
268
- .map('<C-CR>', actions.gitCommitSubmit)
269
- .map('<Tab>', actions.switchField)
270
- .map('<CR>', actions.gitCommitReturnKey)
278
+ .map('<Esc>', actions.gitCommitCancel, 'Cancel')
279
+ .map('<C-CR>', actions.gitCommitSubmit, 'Commit')
280
+ .map('<Tab>', actions.switchField, 'Next field')
281
+ .map('<CR>', actions.gitCommitReturnKey, 'Newline / confirm')
271
282
  .passthrough()
272
283
  )
273
284
 
@@ -21,8 +21,13 @@ export class GroupBuilder implements GroupBuilderApi {
21
21
  private readonly groupName: string
22
22
  ) {}
23
23
 
24
- map(keys: string, action: Action): this {
25
- this.bindings.push({ group: this.groupName, keys: `${this.prefix}${keys}`, result: action })
24
+ map(keys: string, action: Action, description?: string): this {
25
+ this.bindings.push({
26
+ description,
27
+ group: this.groupName,
28
+ keys: `${this.prefix}${keys}`,
29
+ result: action,
30
+ })
26
31
  return this
27
32
  }
28
33
 
@@ -43,8 +48,8 @@ export class ModeBindingBuilder implements ModeBindingBuilderApi {
43
48
  private readonly removals: string[] = []
44
49
  private _passthrough = false
45
50
 
46
- map(keys: string, action: Action): this {
47
- this.bindings.push({ keys, result: action })
51
+ map(keys: string, action: Action, description?: string): this {
52
+ this.bindings.push({ description, keys, result: action })
48
53
  return this
49
54
  }
50
55
 
package/src/types.ts CHANGED
@@ -27,6 +27,7 @@ export type ModeId =
27
27
  | 'modal.help'
28
28
  | 'modal.split-picker'
29
29
  | 'modal.git-commit'
30
+ | 'modal.update-available'
30
31
 
31
32
  // ─── Primitive app types ──────────────────────────────────────────────────────
32
33
 
@@ -263,6 +264,12 @@ export interface ModalSnippetEditor extends ModalBase {
263
264
  contentBuffer: string
264
265
  }
265
266
 
267
+ export interface ModalUpdateAvailable extends ModalBase {
268
+ type: 'update-available'
269
+ currentVersion: string
270
+ latestVersion: string
271
+ }
272
+
266
273
  export type ModalState =
267
274
  | ModalClosed
268
275
  | ModalNewTab
@@ -276,6 +283,7 @@ export type ModalState =
276
283
  | ModalCreateSession
277
284
  | ModalSnippetEditor
278
285
  | ModalGitCommit
286
+ | ModalUpdateAvailable
279
287
 
280
288
  export interface LayoutState {
281
289
  terminalCols: number
@@ -324,6 +332,7 @@ export type ModalAction =
324
332
  | { type: 'open-snippet-editor'; snippetId?: string }
325
333
  | { type: 'begin-snippet-filter' }
326
334
  | { type: 'open-theme-picker' }
335
+ | { type: 'open-update-available-modal'; currentVersion: string; latestVersion: string }
327
336
 
328
337
  export type SessionAction =
329
338
  | { type: 'load-session'; sessionId: string; workspaceSnapshot?: WorkspaceSnapshotV1 }
@@ -467,6 +476,7 @@ export type SideEffect =
467
476
  | { type: 'git-rm'; path: string }
468
477
  | { type: 'git-commit'; title: string; body: string }
469
478
  | { type: 'git-push' }
479
+ | { type: 'confirm-update-selection' }
470
480
 
471
481
  // ─── Key input / KeyResult / ModeContext ──────────────────────────────────────
472
482
 
@@ -563,7 +573,7 @@ export type Action = KeyResult | ActionFn
563
573
  // ─── Keymap builder API types ─────────────────────────────────────────────────
564
574
 
565
575
  export interface GroupBuilderApi {
566
- map(keys: string, action: Action): GroupBuilderApi
576
+ map(keys: string, action: Action, description?: string): GroupBuilderApi
567
577
  group(
568
578
  prefix: string,
569
579
  name: string,
@@ -572,7 +582,7 @@ export interface GroupBuilderApi {
572
582
  }
573
583
 
574
584
  export interface ModeBindingBuilderApi {
575
- map(keys: string, action: Action): ModeBindingBuilderApi
585
+ map(keys: string, action: Action, description?: string): ModeBindingBuilderApi
576
586
  unmap(keys: string): ModeBindingBuilderApi
577
587
  group(
578
588
  prefix: string,
@@ -605,6 +615,7 @@ export interface BindingDef {
605
615
  keys: string
606
616
  result: Action
607
617
  group?: string
618
+ description?: string
608
619
  }
609
620
 
610
621
  export interface ModeKeymapDef {