feat(desktop): list Files changed's keys in a ? sheet and on the Keyboard shortcuts page
Merged
DA
19h ago+478+478+012345678901234567890123456789-59-59-01234567890123456789
What was asked
Files changed (the Pull request tab's diff view) already answers stage-cli's keys, but nothing listed them. This adds stage-cli's ? sheet, and lists the same keys on Settings › Keyboard shortcuts. Both read the one table the handler matches against, so the lists can't drift from the real bindings.
What changed
- One declarative table.
@luke/settings/shortcutsnow holdsFILES_CHANGED_KEY,FILES_CHANGED_SHORTCUTS(a label and a chord per key) andFILES_CHANGED_SHORTCUT_GROUPS, using stage-cli's groups: General, Navigation, Review.filesChangedKeyFor(event)matches a press against that table through the existingshortcutMatches. - Handler reads the table.
changes-list.tsxdrops its hand-writtenFILE_KEY/fileKeyOfletter checks. What each key does is a record that must cover every key in the table (satisfies Record<FilesChangedKey, …>), so a key added to the table won't build until it's handled.FOLD_CHORD(the fold buttons' hints) now reads from the table too. ;and/are read by where they sit on the keyboard. A newplacedflag onSHORTCUT_KEY.SEMICOLONandSLASHmakes a plain chord (no ⌘) matchevent.code, because Shift turns;into:and/into?. This keeps the old by-position reading of;and⇧;. ⌘/ (Keyboard shortcuts) still matches by character, as the menu bar does. Also addsSHORTCUT_KEY.V.?(⇧/) sheet.files-changed-keys.tsxis a@luke/uiDialogat wide size. Each group is aSettingsSectionwithSettingsRows at list density, and each chord is drawn by the app'sShortcut, exactly as the Keyboard shortcuts page draws them. Escape, Done, a click on the dimmed window, or?again closes it, and focus goes back into the view.- Where
?works. Like the other plain keys, only while focus is inside Files changed and you're not typing in a field. No app command uses plain?. - Settings page. A "Files changed" group is added below the window's groups, and settings search finds its rows.
- Fewer edge-case differences: Escape with ⇧ held no longer clears the file focus, since the table's Escape is the bare key.
Coordination
- I (show or hide minimized comments) is in #3789, which isn't merged, so it isn't in this table yet. Whichever PR lands second adds it as a
FILES_CHANGED_KEYrow in the Review group, plus a line in the record inchanges-list.tsx. - The same goes for ⇧F (file tree) from the tree work. It would go in a new group, like stage-cli's "Panels".
Tests
agent-changes-tab.test.ts:- every row of the table is pressed by its own chord inside the view, and each one is answered;
?opens a sheet listing each group, label and drawn chord, and Escape or?again closes it;?does nothing outside the view (with the window keymap mounted) or when typed into the tree's search.
desktop-settings.test.ts: Keyboard shortcuts lists the Files changed group with its chords, and search finds a row of it.shortcuts.test.ts: every Files changed key appears in exactly one group of the sheet.
Checks
The per-package fallback, because pnpm check:affected ran out of memory in this sandbox (on desktop tsc and service vitest):
- per-package tsc for settings, panel and desktop: passed
- vitest for panel tasks, settings, settings search, desktop settings and the command palette: 1075 passed
./scripts/oxlint.sh, biome,pnpm knip,pnpm discarded-effect,./scripts/repository-checks.sh: passedapps/desktopnode scripts/build.mjs: bundle budget passed
This is desktop/panel only, so no Preview run.
Screenshots
Rendered from this branch's built styles.css (Linux fonts).
| Light | Dark | |
|---|---|---|
? sheet | ![]() | ![]() |
| Settings › Keyboard shortcuts | ![]() | ![]() |
Made with Luke



