Chrome Extension Keyboard Shortcuts (chrome.commands)
Wire keyboard shortcuts into your extension with chrome.commands — including the reserved _execute_action shortcut.

Power users judge an extension by whether they can drive it from the keyboard. The commands API adds shortcuts in a few lines of manifest JSON.
Declaring commands
"commands": { "_execute_action": { "suggested_key": { "default": "Ctrl+Shift+Y", "mac": "Command+Shift+Y" } }, "toggle-focus": { "suggested_key": { "default": "Ctrl+Shift+U" }, "description": "Toggle focus mode" } }
Rules you must follow
- _execute_action is reserved and opens your popup — it takes no listener.
- Only four suggested shortcuts are assigned automatically; extras need manual setup by the user.
- Shortcuts must include Ctrl, Alt or Command (Shift alone is not enough).
- Chrome-reserved combinations like Ctrl+T are silently ignored.
Handling custom commands
chrome.commands.onCommand.addListener((command) => ...) fires in the service worker. Branch on the command id and do the work there, or forward it to the active tab.
Let users remap
Link to chrome://extensions/shortcuts from your options page. Chrome blocks extensions from opening that URL directly, so render it as copyable text or a plain instruction.
The four-shortcut auto-assignment limit
Chrome only auto-assigns suggested_key combinations for the first four commands declared in your manifest (including _execute_action). Any commands beyond that install with no shortcut bound, and the user must open chrome://extensions/shortcuts and set one manually — plan your most important actions to be among the first four.
Reserved combinations Chrome will ignore
- Browser-level shortcuts like Ctrl+T, Ctrl+N, Ctrl+W and Ctrl+Tab can never be overridden by an extension.
- F1 through F12 combined with modifiers are frequently reserved by the OS or Chrome itself, depending on platform.
- Single-letter combos without Ctrl, Alt or Command (e.g. Shift+A alone) are rejected outright by the manifest schema.
- On ChromeOS, several combinations are reserved system-wide for window management and accessibility.
_execute_action vs a custom named command
_execute_action is special: Chrome opens the popup for you and no onCommand listener ever fires for it. If your shortcut needs to run logic (not just open a UI), give it its own name like "toggle-focus" and handle it in chrome.commands.onCommand.
Global vs extension-scoped shortcuts
"global" scope commands work even when Chrome is not the focused window, but Chrome restricts global shortcuts to Ctrl+Shift+[0-9] combinations specifically to avoid clobbering system-wide OS shortcuts. Regular commands only fire while a Chrome window has focus.
Debugging a shortcut that does nothing
- Open chrome://extensions/shortcuts and confirm the combination is actually assigned to your extension, not blank or assigned elsewhere.
- Check the service worker inspector console for errors thrown inside your onCommand listener.
- Confirm the service worker isn't asleep in a way that prevents the event from waking it — commands should wake an idle MV3 worker automatically, but a crashed worker will not.
Frequently asked questions
Can two extensions share the same keyboard shortcut?
Chrome will only bind a combination to the extension the user selects when there's a conflict; the other extension's shortcut for that action is left unassigned until the user manually changes it.
How many custom commands can I declare in total?
There is no hard cap enforced by the manifest schema on the number of named commands, but only the first four (including _execute_action) get an automatic suggested_key assignment on install.
Do keyboard shortcuts work on the New Tab page or chrome:// pages?
Commands still fire because they're handled by the extension process, not the page, but any action that tries to inject a script into a chrome:// page will fail since those pages are off-limits to extensions.