Overview
dsh-keyboard-shortcut
README / EN
Package documentation
Registry summary
dsh.pub verifies the pinned bundle contract, runtime facts, and distribution semantics. The complete README remains in the source repository.
Read the full README on GitHubLIMITATIONS
Known limitations
- **Cycle, effort, status-page and task-list shortcuts are Desktop-only by default.** DSH reserves <kbd>Ctrl</kbd>+<kbd>Q</kbd> outside Desktop Windows and macOS, and browsers claim <kbd>Ctrl</kbd>+<kbd>1</kbd>…<kbd>Ctrl</kbd>+<kbd>8</kbd> for tab switching. <kbd>Alt</kbd>+<kbd>A</kbd> and <kbd>Ctrl</kbd>+<kbd>L</kbd> are not admitted by the browser allowlist at all — a single non-primary modifier is refused, and both keys are spoken for. All five commands exist on every platform and can be bound by hand; they simply ship unbound where the combination cannot work. - **The DSH Desktop shell is classified as a browser by the shortcut service.** It publishes no `html[data-platform]` marker — that marker would make the service demand a native keyboard bridge the shell does not provide, and the service throws without one — so `desktop:*` defaults never resolve and the registry refuses to store the combinations above. The plugin detects the window itself and delivers them through `observeFixedInput`, the same raw-input path the page keys use. A registry binding always wins, so one press never runs an action twice, and a combination a desktop window also reserves (<kbd>Ctrl</kbd>+<kbd>C</kbd>, <kbd>Ctrl</kbd>+<kbd>V</kbd>, …) is never taken over. See [docs/shortcuts.md](docs/shortcuts.md). - **The status-page shortcut reuses a page, not a tab.** The sidebar browser registers itself as a tab type that may appear more than once, so opening it through the sidebar's own API always mints a new tab. The plugin therefore looks for a browser tab that is *showing the status page* and reveals it, expanding the column if it is collapsed. A tab on another address is left alone and the status page opens beside it, and a tab belonging to another session is ignored, because the sidebar only reveals tabs in the session on screen. - **The task-list toggle clicks the panel header.** DSH keeps the collapsed state inside the panel component and exposes no handle, so the shortcut drives the same button a click would. A session with no task list shows nothing to toggle, which the shortcut reports instead of failing. - **Prompt navigation drives the turn rail.** DSH publishes no service for jumping to a turn, so the shortcut activates the rail's own marks. A turn is anchored at its first user message, so "previous input" means "previous turn". - **The page keys cannot be registered, so they are read raw.** <kbd>PgUp</kbd>/<kbd>PgDn</kbd> are handled through `observeFixedInput` rather than `registerFixed`, because DSH's shortcut registry validates every declared code against a closed whitelist — `Key*`, `Digit*`, `F1`–`F24`, and a fixed set of named keys that does **not** include the page keys. `registerFixed` normalizes its bindings up front and throws `Unsupported shortcut code: PageUp`, so a registration could never succeed. The keyboard layer forwards every keydown to `observeFixedInput` regardless of registration, so the keys work; they just have no catalog row, and the settings page lists them from a local table as non-rebindable rows. - **A self-delivered binding is invisible to DSH's shortcut reference.** It is held by this plugin, so only this plugin's settings page lists it. The row says so; if DSH later marks its desktop windows, every binding returns to the registry and this limitation disappears. - **The composer remap is a DOM-layer integration.** The composer's keymap is private to `dsh-client-ui-conversation`; the option rewrites an event's modifier flags rather than reimplementing the send logic. See [docs/design.md](docs/design.md) for the reasoning and the failure mode. - **The settings navigation glyph is a DOM patch.** DSH chooses navigation icons with a hardcoded switch on the section id and offers no icon field on the registration, so the glyph is applied with a CSS mask. - **Recording loses React state.** Rebinding re-registers the command and r
