Skip to content

Keyboard shortcut to open the composer's thinking (reasoning effort) menu (⌘⇧E) #54

Description

@DragonnZhang

Problem or Motivation

OpenWork's composer toolbar has three picker controls — the model picker, the
thinking-level (reasoning effort) picker (added in #45), and the
permission-mode selector. Two of those already have keyboard access: the
permission mode cycles with Shift+Tab (chat.cyclePermissionMode). But the
thinking-level menu can only be opened with the mouse — there is no keyboard
shortcut to open it.

Claude Code Desktop documents a dedicated effort menu shortcut (⌘⇧E) in its
composer, right next to the model menu (⌘⇧I) and permission-mode menu (⌘⇧M).
When the thinking-level picker itself landed here (#44), the issue explicitly
flagged this as a natural follow-up:

A keyboard-only shortcut (à la ⌘⇧E) could open a menu … A shortcut can be
layered on later.

This issue layers it on: press ⌘⇧E (macOS) / Ctrl+Shift+E (Windows/Linux) to
open the composer's thinking-effort menu from anywhere, without reaching for the
mouse — matching Claude Code Desktop's effort-menu shortcut exactly.

Proposed Solution

Add a chat.openThinkingMenu action (default hotkey mod+shift+e, category
Chat) to the renderer action registry. When triggered it opens the composer's
existing thinking-level dropdown (FreeFormInput's already-controlled
thinkingDropdownOpen state).

Because the action registry lives at the app shell while the dropdown's open
state lives inside the composer, the shortcut is bridged with a small scoped
custom event (craft:open-composer-menu), mirroring the existing
craft:focus-input pattern (shouldHandleScopedInputEvent) so that in
multi-panel layouts only the focused panel's composer responds.

This is a frontend-only change:

  • No backend / qwen-code change. It reuses the composer's existing controlled
    dropdown state and the existing action-registry + hotkey infrastructure.
  • Because it registers in the action registry, the shortcut automatically
    appears in the Command Palette (Add a global command palette (⌘K / Ctrl+K) #42) and the Keyboard Shortcuts reference —
    no extra wiring.
  • One new i18n key (shortcuts.action.openThinkingMenu) added to all locales
    for the action label; the shortcut itself has no new visible chrome.

Alternatives Considered

  • Model menu (⌘⇧I) / permission-mode menu (⌘⇧M) shortcuts too: Claude
    binds all three. ⌘⇧I / Ctrl+Shift+I is already reserved for Developer
    Tools
    in OpenWork's menus, so reusing it would conflict; and permission mode
    already has a keyboard affordance (Shift+Tab). The thinking menu is the one
    composer picker with no keyboard access and no binding conflict, so this
    scopes to ⌘⇧E — the cleanest, conflict-free gap.
  • A visible extra affordance: unnecessary; the value here is precisely the
    no-mouse path to the existing picker.

Additional Context

Feasibility: frontend-only / doable. Verified against apps/electron — the
thinking dropdown already owns a controlled thinkingDropdownOpen state and
carries data-testid="thinking-level-trigger" / thinking-level-item hooks
(from #45), so opening it programmatically needs no structural change.

Acceptance criteria (CDP e2e assertion)

A new e2e/assertions/thinking-menu-shortcut.assert.ts drives the real built app
over CDP entirely in the draft (no-session) state — no seeded conversation and no
backend:

  1. The composer renders the thinking-level trigger with its menu closed (zero
    visible menu items).
  2. Dispatch the Cmd/Ctrl+Shift+E keydown at the window level (where the action
    registry's capture-phase listener lives).
  3. The thinking menu opens and lists all six levels.

Asserting the menu is closed before the keypress and open after it proves the
shortcut actually opens the menu, not merely that the menu can render.

Part of the autonomous desktop-feature loop (loop-bot).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions