Reference · 7 min read

Chrome Extension Keyboard Shortcuts (chrome.commands)

Wire keyboard shortcuts into your extension with chrome.commands — including the reserved _execute_action shortcut.

Illustration for the ManifestGo article: Chrome Extension Keyboard Shortcuts (chrome.commands)

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

  1. Open chrome://extensions/shortcuts and confirm the combination is actually assigned to your extension, not blank or assigned elsewhere.
  2. Check the service worker inspector console for errors thrown inside your onCommand listener.
  3. 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.

Keep reading