From 3779678eef77c8b66fa9a64d6cbf199c2c58b033 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 4 Jul 2026 13:39:52 +0000 Subject: [PATCH 1/2] =?UTF-8?q?Add=20a=20keyboard=20shortcut=20(=E2=8C=98?= =?UTF-8?q?=E2=87=A7E)=20to=20open=20the=20composer's=20thinking=20menu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The composer's thinking-level (reasoning effort) picker could only be opened with the mouse. Add a chat.openThinkingMenu action bound to mod+shift+e that opens it from the keyboard, matching Claude Code Desktop's effort-menu shortcut. The action registry lives at the app shell while the dropdown's open state lives in FreeFormInput, so the shortcut is bridged with a scoped craft:open-composer-menu event, mirroring the existing craft:focus-input pattern (shouldHandleScopedInputEvent) so multi-panel layouts target the focused composer. The action auto-appears in the Command Palette and the Keyboard Shortcuts reference. One new i18n key across all locales. Closes #54 --- .../src/renderer/actions/action-i18n.ts | 1 + .../src/renderer/actions/definitions.ts | 7 ++ .../components/app-shell/AppShell.tsx | 7 ++ .../app-shell/input/FreeFormInput.tsx | 31 +++++++ .../app-shell/input/composer-menu-events.ts | 32 +++++++ docs/loop/feature-ledger.md | 8 +- .../thinking-menu-shortcut.assert.ts | 93 +++++++++++++++++++ packages/shared/src/i18n/locales/de.json | 1 + packages/shared/src/i18n/locales/en.json | 1 + packages/shared/src/i18n/locales/es.json | 1 + packages/shared/src/i18n/locales/hu.json | 1 + packages/shared/src/i18n/locales/ja.json | 1 + packages/shared/src/i18n/locales/pl.json | 1 + packages/shared/src/i18n/locales/zh-Hans.json | 1 + 14 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 apps/electron/src/renderer/components/app-shell/input/composer-menu-events.ts create mode 100644 e2e/assertions/thinking-menu-shortcut.assert.ts diff --git a/apps/electron/src/renderer/actions/action-i18n.ts b/apps/electron/src/renderer/actions/action-i18n.ts index 7edfd681b..8f69ea005 100644 --- a/apps/electron/src/renderer/actions/action-i18n.ts +++ b/apps/electron/src/renderer/actions/action-i18n.ts @@ -36,6 +36,7 @@ export const ACTION_LABEL_KEYS: Partial> = { 'panel.focusPrev': 'shortcuts.action.focusPrevPanel', 'chat.stopProcessing': 'shortcuts.action.stopProcessing', 'chat.cyclePermissionMode': 'shortcuts.action.cyclePermissionMode', + 'chat.openThinkingMenu': 'shortcuts.action.openThinkingMenu', 'chat.nextSearchMatch': 'shortcuts.action.nextSearchMatch', 'chat.prevSearchMatch': 'shortcuts.action.prevSearchMatch', } diff --git a/apps/electron/src/renderer/actions/definitions.ts b/apps/electron/src/renderer/actions/definitions.ts index 82ecf3521..f0fd6b792 100644 --- a/apps/electron/src/renderer/actions/definitions.ts +++ b/apps/electron/src/renderer/actions/definitions.ts @@ -202,6 +202,13 @@ export const actions = { category: 'Chat', when: '!inputFocus && !menuOpen', }, + 'chat.openThinkingMenu': { + id: 'chat.openThinkingMenu', + label: 'Open Thinking Menu', + description: 'Open the thinking (reasoning effort) menu in the chat composer', + defaultHotkey: 'mod+shift+e', + category: 'Chat', + }, 'chat.nextSearchMatch': { id: 'chat.nextSearchMatch', label: 'Next Search Match', diff --git a/apps/electron/src/renderer/components/app-shell/AppShell.tsx b/apps/electron/src/renderer/components/app-shell/AppShell.tsx index f76515b6d..dc174dae4 100644 --- a/apps/electron/src/renderer/components/app-shell/AppShell.tsx +++ b/apps/electron/src/renderer/components/app-shell/AppShell.tsx @@ -222,6 +222,7 @@ import { hasOpenOverlay } from '@/lib/overlay-detection' import { getNextPermissionMode } from '@/lib/permission-mode-cycle' import { clearSourceIconCaches } from '@/lib/icon-cache' import { dispatchFocusInputEvent } from './input/focus-input-events' +import { dispatchOpenComposerMenuEvent } from './input/composer-menu-events' import { resolveEffectiveConnectionSlug } from '@config/llm-connections' import { getWorkspaceDisplayName } from '@/utils/workspace' @@ -1820,6 +1821,12 @@ function AppShellContent({ useAction('nav.goBackAlt', goBack) useAction('nav.goForwardAlt', goForward) + // Open the composer's thinking (reasoning effort) menu (CMD+SHIFT+E). + // Targets the focused panel's composer via the scoped composer-menu event. + useAction('chat.openThinkingMenu', () => + dispatchOpenComposerMenuEvent({ menu: 'thinking' }), + ) + // Search match navigation (CMD+G next, CMD+SHIFT+G prev) useAction( 'chat.nextSearchMatch', diff --git a/apps/electron/src/renderer/components/app-shell/input/FreeFormInput.tsx b/apps/electron/src/renderer/components/app-shell/input/FreeFormInput.tsx index bb596ed1d..7c5ec1ddc 100644 --- a/apps/electron/src/renderer/components/app-shell/input/FreeFormInput.tsx +++ b/apps/electron/src/renderer/components/app-shell/input/FreeFormInput.tsx @@ -96,6 +96,10 @@ import { clearPendingFocusForSession, consumePendingFocusForSession, } from './focus-input-events'; +import { + COMPOSER_MENU_EVENT, + type ComposerMenuEventDetail, +} from './composer-menu-events'; import { getRecentWorkingDirs, addRecentWorkingDir, @@ -1212,6 +1216,33 @@ export function FreeFormInput({ window.removeEventListener('craft:focus-input', handleFocusInput); }, [sessionId, isFocusedPanel, richInputRef]); + // Listen for craft:open-composer-menu events (open a toolbar menu from a + // global keyboard shortcut). Scoped like focus-input so the focused panel's + // composer responds. + React.useEffect(() => { + const handleOpenMenu = (e: Event) => { + const detail = (e as CustomEvent).detail; + if ( + !shouldHandleScopedInputEvent({ + sessionId, + isFocusedPanel, + targetSessionId: detail?.sessionId, + }) + ) + return; + + if (detail?.menu === 'thinking') { + // The thinking picker only renders in the full (non-compact) toolbar. + if (compactMode || !onThinkingLevelChange) return; + setThinkingDropdownOpen(true); + } + }; + + window.addEventListener(COMPOSER_MENU_EVENT, handleOpenMenu); + return () => + window.removeEventListener(COMPOSER_MENU_EVENT, handleOpenMenu); + }, [sessionId, isFocusedPanel, compactMode, onThinkingLevelChange]); + // Recover queued focus requests after session switch/mount races. React.useEffect(() => { if (!consumePendingFocusForSession(sessionId)) return; diff --git a/apps/electron/src/renderer/components/app-shell/input/composer-menu-events.ts b/apps/electron/src/renderer/components/app-shell/input/composer-menu-events.ts new file mode 100644 index 000000000..d03c0e1ef --- /dev/null +++ b/apps/electron/src/renderer/components/app-shell/input/composer-menu-events.ts @@ -0,0 +1,32 @@ +/** + * Cross-component bridge for opening a composer toolbar menu from a global + * keyboard shortcut. + * + * The action registry lives at the app shell (it owns the global hotkey + * listener), while the composer's toolbar dropdowns (thinking / model) own + * their controlled `open` state inside `FreeFormInput`. This event lets the + * shell ask the focused composer to open one of its menus, mirroring the + * scoping model of `focus-input-events.ts` so multi-panel layouts target the + * right composer. + */ + +/** Composer toolbar menus that can be opened via a shortcut. */ +export type ComposerMenu = 'thinking' + +export interface ComposerMenuEventDetail { + /** Restrict to a specific session's composer; omit to target the focused panel. */ + sessionId?: string + menu: ComposerMenu +} + +export const COMPOSER_MENU_EVENT = 'craft:open-composer-menu' + +/** + * Ask a composer to open one of its toolbar menus. With no `sessionId`, the + * focused panel's composer handles it (see `shouldHandleScopedInputEvent`). + */ +export function dispatchOpenComposerMenuEvent(detail: ComposerMenuEventDetail): void { + window.dispatchEvent( + new CustomEvent(COMPOSER_MENU_EVENT, { detail }), + ) +} diff --git a/docs/loop/feature-ledger.md b/docs/loop/feature-ledger.md index d992798ab..54a5ec16f 100644 --- a/docs/loop/feature-ledger.md +++ b/docs/loop/feature-ledger.md @@ -32,6 +32,12 @@ log, not the system of record. | slug | title | source | feasibility | status | issue | pr | branch | updated | notes | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| thinking-level-picker | Thinking-level (reasoning effort) picker in the chat composer | Claude Code Desktop effort menu (⌘⇧E) + OpenWork's own model picker | frontend-only | pr-open | [#44](https://github.com/modelstudioai/openwork/issues/44) | [#45](https://github.com/modelstudioai/openwork/pull/45) | loop/thinking-level-picker | 2026-07-02 | `thinkingLevel`/`onThinkingLevelChange` already plumbed to `FreeFormInput`; only the UI trigger was missing. Reuses `thinking.*` + `settings.ai.thinking` i18n keys (zero new keys). typecheck/`bun test` zero-delta vs main (3578 pass/56 fail on both); renderer build ✅. **CDP could not run locally**: this sandbox's egress policy 403s the Electron binary download and the `libsignal` GitHub dep (WhatsApp worker), so the app can't be built/launched here — assertion included for CI/reviewer. | +| thinking-menu-shortcut | Keyboard shortcut (⌘⇧E) to open the composer's thinking (effort) menu | Claude Code Desktop effort-menu shortcut (⌘⇧E); explicit follow-up flagged in #44 | frontend-only | in-progress | [#54](https://github.com/modelstudioai/openwork/issues/54) | — | loop/thinking-menu-shortcut | 2026-07-04 | New `chat.openThinkingMenu` action (`mod+shift+e`) → scoped `craft:open-composer-menu` event → `FreeFormInput` opens its already-controlled `thinkingDropdownOpen`. Mirrors `craft:focus-input`/`shouldHandleScopedInputEvent` for multi-panel safety. Auto-appears in Command Palette + Shortcuts reference. 1 new i18n key across 7 locales. Avoids ⌘⇧I (reserved for DevTools) / ⌘⇧M (permission mode already has Shift+Tab). typecheck zero-delta (11 pre-existing); `bun test` zero-delta (56 identical failures, diffed vs main); i18n parity OK; renderer build ✅; assertion transpiles ✅. **CDP blocked locally** (same egress limit: `libsignal` GitHub dep + Electron binary 403). | +| command-palette-search-bug (#43) | `Cmd+F` / `app.search` doesn't activate session search from its shortcut | Bug report | frontend-only | proposed | [#43](https://github.com/modelstudioai/openwork/issues/43) | — | — | 2026-07-04 | Open bug (no PR yet). Needs a seeded-session repro to diff the button path vs registry-`execute` path. Not selected this round. | +| composer-prompt-history | Recall previously-sent prompts in the composer with Up/Down arrows | Claude Code CLI / Codex desktop composer history recall | frontend-only | pr-open | [#52](https://github.com/modelstudioai/openwork/issues/52) | [#53](https://github.com/modelstudioai/openwork/pull/53) | loop/composer-prompt-history | 2026-07-04 | Reconciled from GitHub. Awaiting review. | +| reduce-motion | "Reduce motion" accessibility setting in Appearance | Claude desktop / macOS / Windows reduce-motion; `prefers-reduced-motion` | frontend-only | pr-open | [#50](https://github.com/modelstudioai/openwork/issues/50) | [#51](https://github.com/modelstudioai/openwork/pull/51) | loop/reduce-motion | 2026-07-04 | Reconciled from GitHub. Awaiting review. | +| composer-expand | Expand / collapse (maximize) toggle for the chat composer | Claude / ChatGPT / Codex desktop composer maximize | frontend-only | pr-open | [#48](https://github.com/modelstudioai/openwork/issues/48) | [#49](https://github.com/modelstudioai/openwork/pull/49) | loop/composer-expand | 2026-07-04 | Reconciled from GitHub. Awaiting review. | +| scroll-to-bottom | "Jump to latest" (scroll-to-bottom) button in the chat transcript | Claude Code Desktop / ChatGPT / Codex desktop jump-to-latest | frontend-only | pr-open | [#46](https://github.com/modelstudioai/openwork/issues/46) | [#47](https://github.com/modelstudioai/openwork/pull/47) | loop/scroll-to-bottom | 2026-07-04 | Reconciled from GitHub. Added a reusable `seed(profileDirs)` harness hook. Awaiting review. | +| thinking-level-picker | Thinking-level (reasoning effort) picker in the chat composer | Claude Code Desktop effort menu (⌘⇧E) + OpenWork's own model picker | frontend-only | merged | [#44](https://github.com/modelstudioai/openwork/issues/44) | [#45](https://github.com/modelstudioai/openwork/pull/45) | loop/thinking-level-picker | 2026-07-04 | **Merged** into `main` (commit `26f609c`). `thinkingLevel`/`onThinkingLevelChange` already plumbed to `FreeFormInput`; only the UI trigger was missing. Reuses `thinking.*` + `settings.ai.thinking` i18n keys (zero new keys). | | command-palette | Global command palette (⌘K/Ctrl+K) to search & run any action | Claude Code Desktop ⌘K / VS Code & Codex ⌘⇧P / Linear ⌘K | frontend-only | merged | [#41](https://github.com/modelstudioai/openwork/issues/41) | [#42](https://github.com/modelstudioai/openwork/pull/42) | loop/command-palette | 2026-07-02 | Merged into `main`. Reuses action registry `execute()` + cmdk primitives; zero new i18n keys. CDP e2e 2/2 pass. typecheck/test +0 vs main. | | settings-search | Searchable/filterable settings navigation | Claude Code Desktop / VS Code / Codex desktop settings search | frontend-only | merged | [#39](https://github.com/modelstudioai/openwork/issues/39) | [#40](https://github.com/modelstudioai/openwork/pull/40) | loop/settings-search | 2026-07-01 | Merged into `main`. Filters `SettingsNavigator` by title+description; reuses `common.search`/`common.noResultsFound` (no new locale keys). Also hardened `e2e/app.ts` teardown (per-launch profile dir + setsid process-group kill) so multiple CDP assertions run under headless xvfb. | diff --git a/e2e/assertions/thinking-menu-shortcut.assert.ts b/e2e/assertions/thinking-menu-shortcut.assert.ts new file mode 100644 index 000000000..98f2e7e58 --- /dev/null +++ b/e2e/assertions/thinking-menu-shortcut.assert.ts @@ -0,0 +1,93 @@ +/** + * Feature assertion: the keyboard shortcut that opens the composer's thinking + * (reasoning effort) menu. + * + * Mirrors Claude Code Desktop's effort-menu shortcut (⌘⇧E). Drives the real + * built app over CDP: + * composer renders a thinking-level trigger with its menu CLOSED → dispatch + * the Cmd/Ctrl+Shift+E keydown at the window level → the thinking menu OPENS + * (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. + */ + +import type { Assertion } from '../runner'; + +const TRIGGER = '[data-testid="thinking-level-trigger"]'; +const ITEM = '[data-testid="thinking-level-item"]'; + +/** The six thinking levels are the single source of truth for the count. */ +const EXPECTED_LEVEL_COUNT = 6; + +/** Menu items that are actually visible (Radix renders them in a portal). */ +const VISIBLE_ITEMS_EXPR = `[...document.querySelectorAll(${JSON.stringify( + ITEM, +)})].filter((el) => el.offsetParent !== null)`; + +/** + * Dispatch the effort-menu shortcut at the window level, where the action + * registry's capture-phase keydown listener lives. `mod` resolves to Cmd on + * macOS and Ctrl elsewhere; set both `metaKey` and `ctrlKey` so the same event + * matches on either platform (the registry only checks the platform's mod key). + */ +const PRESS_SHORTCUT_EXPR = `(() => { + window.dispatchEvent(new KeyboardEvent('keydown', { + key: 'e', + code: 'KeyE', + ctrlKey: true, + metaKey: true, + shiftKey: true, + bubbles: true, + cancelable: true, + })); + return true; +})()`; + +const assertion: Assertion = { + name: 'Cmd/Ctrl+Shift+E opens the composer thinking-level menu', + async run(app) { + const { session } = app; + + // App fully mounted. + await session.waitForFunction( + '!document.getElementById("_loader") && (document.getElementById("root")?.childElementCount ?? 0) > 0', + { timeoutMs: 30000, message: 'React UI did not mount' }, + ); + + // Reach the ready AppShell (not onboarding / workspace picker) — the same + // stable, non-localized anchor the other composer assertions wait on. + await session.waitForSelector('[aria-label="Craft menu"]', { + timeoutMs: 30000, + message: 'app did not reach the ready AppShell state', + }); + + // The composer renders a thinking-level trigger. + await session.waitForSelector(TRIGGER, { + timeoutMs: 20000, + message: 'thinking-level picker trigger did not render in the composer', + }); + + // Precondition: the menu is closed (no visible items). + if ((await session.evaluate(`${VISIBLE_ITEMS_EXPR}.length`)) !== 0) { + throw new Error('thinking-level menu was already open before pressing the shortcut'); + } + + // Press the shortcut at the window level. + if (!(await session.evaluate(PRESS_SHORTCUT_EXPR))) { + throw new Error('failed to dispatch the Cmd/Ctrl+Shift+E keydown'); + } + + // The menu opens and lists all six thinking levels — proving the shortcut + // opened it. + await session.waitForFunction( + `${VISIBLE_ITEMS_EXPR}.length === ${EXPECTED_LEVEL_COUNT}`, + { + timeoutMs: 8000, + message: `thinking-level menu did not open (expected ${EXPECTED_LEVEL_COUNT} levels) after pressing Cmd/Ctrl+Shift+E`, + }, + ); + }, +}; + +export default assertion; diff --git a/packages/shared/src/i18n/locales/de.json b/packages/shared/src/i18n/locales/de.json index ad23be300..11f75dfe4 100644 --- a/packages/shared/src/i18n/locales/de.json +++ b/packages/shared/src/i18n/locales/de.json @@ -1162,6 +1162,7 @@ "shortcuts.action.newChatInPanel": "Neuer Chat im Panel", "shortcuts.action.newWindow": "Neues Fenster", "shortcuts.action.nextSearchMatch": "Nächster Treffer", + "shortcuts.action.openThinkingMenu": "Denk-Menü öffnen", "shortcuts.action.prevSearchMatch": "Vorheriger Treffer", "shortcuts.action.quit": "Beenden", "shortcuts.action.search": "Suchen", diff --git a/packages/shared/src/i18n/locales/en.json b/packages/shared/src/i18n/locales/en.json index 515571e0a..f90981ec3 100644 --- a/packages/shared/src/i18n/locales/en.json +++ b/packages/shared/src/i18n/locales/en.json @@ -1162,6 +1162,7 @@ "shortcuts.action.newChatInPanel": "New Chat in Panel", "shortcuts.action.newWindow": "New Window", "shortcuts.action.nextSearchMatch": "Next Search Match", + "shortcuts.action.openThinkingMenu": "Open Thinking Menu", "shortcuts.action.prevSearchMatch": "Previous Search Match", "shortcuts.action.quit": "Quit", "shortcuts.action.search": "Search", diff --git a/packages/shared/src/i18n/locales/es.json b/packages/shared/src/i18n/locales/es.json index 0ae1c140c..bb458d369 100644 --- a/packages/shared/src/i18n/locales/es.json +++ b/packages/shared/src/i18n/locales/es.json @@ -1162,6 +1162,7 @@ "shortcuts.action.newChatInPanel": "Nuevo chat en panel", "shortcuts.action.newWindow": "Nueva ventana", "shortcuts.action.nextSearchMatch": "Siguiente coincidencia", + "shortcuts.action.openThinkingMenu": "Abrir menú de razonamiento", "shortcuts.action.prevSearchMatch": "Coincidencia anterior", "shortcuts.action.quit": "Salir", "shortcuts.action.search": "Buscar", diff --git a/packages/shared/src/i18n/locales/hu.json b/packages/shared/src/i18n/locales/hu.json index 9f613dd4f..2972c3bca 100644 --- a/packages/shared/src/i18n/locales/hu.json +++ b/packages/shared/src/i18n/locales/hu.json @@ -1162,6 +1162,7 @@ "shortcuts.action.newChatInPanel": "Új chat a panelben", "shortcuts.action.newWindow": "Új ablak", "shortcuts.action.nextSearchMatch": "Következő találat", + "shortcuts.action.openThinkingMenu": "Gondolkodás menü megnyitása", "shortcuts.action.prevSearchMatch": "Előző találat", "shortcuts.action.quit": "Kilépés", "shortcuts.action.search": "Keresés", diff --git a/packages/shared/src/i18n/locales/ja.json b/packages/shared/src/i18n/locales/ja.json index 6c09b71d4..1b42f891f 100644 --- a/packages/shared/src/i18n/locales/ja.json +++ b/packages/shared/src/i18n/locales/ja.json @@ -1162,6 +1162,7 @@ "shortcuts.action.newChatInPanel": "パネルで新規チャット", "shortcuts.action.newWindow": "新規ウィンドウ", "shortcuts.action.nextSearchMatch": "次の検索結果", + "shortcuts.action.openThinkingMenu": "思考メニューを開く", "shortcuts.action.prevSearchMatch": "前の検索結果", "shortcuts.action.quit": "終了", "shortcuts.action.search": "検索", diff --git a/packages/shared/src/i18n/locales/pl.json b/packages/shared/src/i18n/locales/pl.json index 049c922ce..28893fa36 100644 --- a/packages/shared/src/i18n/locales/pl.json +++ b/packages/shared/src/i18n/locales/pl.json @@ -1162,6 +1162,7 @@ "shortcuts.action.newChatInPanel": "Nowy czat w panelu", "shortcuts.action.newWindow": "Nowe okno", "shortcuts.action.nextSearchMatch": "Następny wynik wyszukiwania", + "shortcuts.action.openThinkingMenu": "Otwórz menu myślenia", "shortcuts.action.prevSearchMatch": "Poprzedni wynik wyszukiwania", "shortcuts.action.quit": "Zakończ", "shortcuts.action.search": "Szukaj", diff --git a/packages/shared/src/i18n/locales/zh-Hans.json b/packages/shared/src/i18n/locales/zh-Hans.json index 1879d2df7..85b77a4e6 100644 --- a/packages/shared/src/i18n/locales/zh-Hans.json +++ b/packages/shared/src/i18n/locales/zh-Hans.json @@ -1162,6 +1162,7 @@ "shortcuts.action.newChatInPanel": "在面板中新建聊天", "shortcuts.action.newWindow": "新建窗口", "shortcuts.action.nextSearchMatch": "下一个搜索匹配", + "shortcuts.action.openThinkingMenu": "打开思考菜单", "shortcuts.action.prevSearchMatch": "上一个搜索匹配", "shortcuts.action.quit": "退出", "shortcuts.action.search": "搜索", From 15ed3011831249b8eadda555ab469a88649bc2b4 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 4 Jul 2026 13:40:48 +0000 Subject: [PATCH 2/2] docs(loop): mark thinking-menu-shortcut pr-open (#55) --- docs/loop/feature-ledger.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/loop/feature-ledger.md b/docs/loop/feature-ledger.md index 54a5ec16f..83edeb039 100644 --- a/docs/loop/feature-ledger.md +++ b/docs/loop/feature-ledger.md @@ -32,7 +32,7 @@ log, not the system of record. | slug | title | source | feasibility | status | issue | pr | branch | updated | notes | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | -| thinking-menu-shortcut | Keyboard shortcut (⌘⇧E) to open the composer's thinking (effort) menu | Claude Code Desktop effort-menu shortcut (⌘⇧E); explicit follow-up flagged in #44 | frontend-only | in-progress | [#54](https://github.com/modelstudioai/openwork/issues/54) | — | loop/thinking-menu-shortcut | 2026-07-04 | New `chat.openThinkingMenu` action (`mod+shift+e`) → scoped `craft:open-composer-menu` event → `FreeFormInput` opens its already-controlled `thinkingDropdownOpen`. Mirrors `craft:focus-input`/`shouldHandleScopedInputEvent` for multi-panel safety. Auto-appears in Command Palette + Shortcuts reference. 1 new i18n key across 7 locales. Avoids ⌘⇧I (reserved for DevTools) / ⌘⇧M (permission mode already has Shift+Tab). typecheck zero-delta (11 pre-existing); `bun test` zero-delta (56 identical failures, diffed vs main); i18n parity OK; renderer build ✅; assertion transpiles ✅. **CDP blocked locally** (same egress limit: `libsignal` GitHub dep + Electron binary 403). | +| thinking-menu-shortcut | Keyboard shortcut (⌘⇧E) to open the composer's thinking (effort) menu | Claude Code Desktop effort-menu shortcut (⌘⇧E); explicit follow-up flagged in #44 | frontend-only | pr-open | [#54](https://github.com/modelstudioai/openwork/issues/54) | [#55](https://github.com/modelstudioai/openwork/pull/55) | loop/thinking-menu-shortcut | 2026-07-04 | New `chat.openThinkingMenu` action (`mod+shift+e`) → scoped `craft:open-composer-menu` event → `FreeFormInput` opens its already-controlled `thinkingDropdownOpen`. Mirrors `craft:focus-input`/`shouldHandleScopedInputEvent` for multi-panel safety. Auto-appears in Command Palette + Shortcuts reference. 1 new i18n key across 7 locales. Avoids ⌘⇧I (reserved for DevTools) / ⌘⇧M (permission mode already has Shift+Tab). typecheck zero-delta (11 pre-existing); `bun test` zero-delta (56 identical failures, diffed vs main); i18n parity OK; renderer build ✅; assertion transpiles ✅. **CDP blocked locally** (same egress limit: `libsignal` GitHub dep + Electron binary 403). | | command-palette-search-bug (#43) | `Cmd+F` / `app.search` doesn't activate session search from its shortcut | Bug report | frontend-only | proposed | [#43](https://github.com/modelstudioai/openwork/issues/43) | — | — | 2026-07-04 | Open bug (no PR yet). Needs a seeded-session repro to diff the button path vs registry-`execute` path. Not selected this round. | | composer-prompt-history | Recall previously-sent prompts in the composer with Up/Down arrows | Claude Code CLI / Codex desktop composer history recall | frontend-only | pr-open | [#52](https://github.com/modelstudioai/openwork/issues/52) | [#53](https://github.com/modelstudioai/openwork/pull/53) | loop/composer-prompt-history | 2026-07-04 | Reconciled from GitHub. Awaiting review. | | reduce-motion | "Reduce motion" accessibility setting in Appearance | Claude desktop / macOS / Windows reduce-motion; `prefers-reduced-motion` | frontend-only | pr-open | [#50](https://github.com/modelstudioai/openwork/issues/50) | [#51](https://github.com/modelstudioai/openwork/pull/51) | loop/reduce-motion | 2026-07-04 | Reconciled from GitHub. Awaiting review. |