# Shortkeys: a browser extension for custom keyboard shortcuts across Chrome, Firefox, Edge and Opera

> Shortkeys is a WebExtension that adds user-defined keyboard shortcuts to the browser itself, with 125 built-in actions, a command palette, macro chaining, site filtering and shortcut packs for Vim and Emacs users. It is a consumer tool built on WXT and Vue 3, not a library.

**crittermike/shortkeys** — A browser extension for custom keyboard shortcuts 

- Repository: https://github.com/crittermike/shortkeys
- Website: https://www.shortkeys.app/
- Stars: 1,257 · Forks: 182
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/crittermike-shortkeys

## A browser extension, not a keyboard remapper

Shortkeys is a cross-browser extension for custom keyboard shortcuts, built with WXT and Vue 3 and written in TypeScript. The README describes it as a shortcut layer for the browser itself, with 200,000+ Chrome users claimed for the published listing.

The scope distinction matters and is easy to misread. Shortkeys does not remap your operating system's keyboard. It installs a browser extension, and the shortcuts it registers are active inside the browser's pages, in the way that the extension APIs allow. Anything outside the browser window, including other applications, is untouched. If the problem you have is that your laptop's keyboard has the wrong layout, or that you want a system-wide layer like a modal editor, this is the wrong category of tool.

What it does instead is quite broad inside its boundary. There are 125+ built-in actions across 11 categories, namely scrolling, tabs, navigation, video controls, search, bookmarks, windows, zooming, page tools and page scripts. There is a command palette you can open by clicking the icon or binding a shortcut to, which searches and triggers any action. There is a shortcut recorder that supports multi-key sequences such as g i or g h, which is the piece that makes the Vim and Emacs packs usable rather than decorative.

The audience is therefore a keyboard-driven browser user who wants a small amount of control, or a larger amount, without giving up the mouse. The packs named in the README, Vim, Emacs, YouTube, Productivity, Developer, Reading, Tab Manager, Keyboard Power and Media Control, describe the taste of the user this is for.

The repository is a full application project rather than a package. The top level holds src/, tests/, e2e/, site/, marketing/, packs/, public/, scripts/, wxt.config.ts, vitest.config.js, playwright.config.ts, netlify.toml, package.json, package-lock.json, an AGENTS.md and a LICENSE.md.

## How the extension is put together: background, content, options, palette

The project structure section of the README describes a standard WebExtension split, and it is worth reading because the placement of the key handling explains most of the extension's behaviour.

There is an entrypoints/ directory with four parts. background.ts is the service worker, described as handling messaging, action dispatch and storage sync. content.ts is the content script, handling Mousetrap key bindings, the cheat sheet and dark mode. options/ is the options page, a Vue 3 single page application. popup/ is the command palette popup.

The rest of src/ follows from that. actions/ holds the action handlers and helpers, components/ holds the Vue components including CodeEditor, SearchSelect and ShortcutRecorder, composables/ holds the Vue composables including useShortcuts, packs/ holds the 9 curated shortcut pack collections, and utils/ handles storage, URL matching, conflict detection and JS snippets.

Mousetrap does the key binding work, which is a library for detecting keyboard shortcuts inside a page, and the content script is where it runs. That is the architectural constraint to understand: the shortcuts are active on web pages, not in the browser chrome, and a page that swallows key events can interfere with them. The cheat sheet feature lives in the same content script, which is how the extension can show its own list of available shortcuts on a page.

The service worker holds the state and dispatches. The content script captures the key press and asks the background to act, and the background writes to storage and syncs. The option to use a custom JavaScript editor and the ability to import userscripts from Greasyfork and OpenUserJS both feed into that dispatch path, which is where the extension's power and its risk sit.

The site/ directory is a separate Astro static site deployed to Netlify that serves shortkeys.app, and marketing/ holds the store listing copy, screenshot plans and promo assets.

## Building from source, running the tests, and packaging per browser

The README gives both an install route and a source route. For most people the install route is the point: the extension is published on the Chrome Web Store, Firefox Add-ons, the Microsoft Edge add-ons site and Opera's add-ons site, and the README has a table linking each. You install it from the store, you do not build it.

For anyone working on it, the build is three commands:

```bash
npm install
npm run build          # Chrome → .output/chrome-mv3/
npm run build:firefox  # Firefox → .output/firefox-mv2/
```

The output paths in those comments are the detail to notice. The Chrome build is Manifest V3 and the Firefox build is Manifest V2, which is the real constraint of a cross-browser extension today, and the two are not the same target. The package.json adds zip variants for each store, `wxt zip -b edge` and `wxt zip -b opera` alongside the Firefox and default ones, because each store wants a packaged artifact.

Development uses the same tool with a different target:

```bash
npm run dev            # Chrome dev mode with hot reload
npm run dev:firefox    # Firefox dev mode
npm test               # Run all tests (722 tests across 25 files)
npm run test:watch     # Watch mode
npm run test:coverage  # With coverage report
```

The test count is the notable number. The README states 722 tests across 25 files, and package.json runs them with vitest run, with watch and coverage variants. There is also a separate end-to-end script, `npx playwright test`, with a playwright.config.ts at the top level and an e2e/ directory, and a visual-review script that runs scripts/visual-review.ts through tsx.

The site has its own pipeline. build:site runs a catalog script with tsx, copies the public images into the site directory, and then runs an Astro build inside site/, and dev:site starts the Astro dev server. The postinstall hook runs wxt prepare, with the `|| true` suffix, so a failure there does not break installation.

## Groups, macros, site filtering and the shortcut recorder

The features that go beyond a plain key-to-action map are the ones that make this more than a shortcut list, and they are worth understanding individually.

Groups organise shortcuts into collapsible, renamable sections with bulk enable and disable. That is a small feature on paper and a significant one in practice, because a user with a hundred shortcuts needs some structure, and a bulk toggle is how you turn a set of bindings off temporarily without deleting them.

Macro chaining lets you chain multiple actions into a single shortcut. This is what turns a static binding list into something programmable without writing code: a single key can run a sequence, and the actions/ directory is where those sequences are implemented.

Site filtering decides where a shortcut applies, with three modes: all sites, a blocklist, or an allowlist per shortcut. A per-shortcut allowlist is the feature that makes the extension safe to use across a work and personal browsing split, since you can confine a destructive navigation shortcut to one domain.

The shortcut recorder with multi-key sequence support is what makes the Vim and Emacs packs work, since a chord like g i has to be captured as a sequence and not as two separate presses. The conflict detection gives platform-aware warnings for clashes with browser defaults, which is a real service: the browser's own shortcuts differ between Chrome, Firefox, Edge and Opera, and a binding that works in one can silently eat a browser command in another.

Live reload means shortcuts update in all tabs instantly, with no page refresh. Shareable links generate a URL to share shortcuts or groups with anyone, which is how a team distributes a set of bindings, and the settings page offers undo and redo so an experimental change can be walked back.

## Custom JavaScript, userscript import, and where the risk lives

This is the part of Shortkeys to read carefully before installing it, and it is the reason the extension offers more than a key rebinder would.

The extension includes a custom JavaScript editor, with CodeMirror 6 for editing and syntax highlighting and a CodeEditor component, and page scripts are one of the eleven action categories. The action set includes page scripts and page tools, which means a shortcut can run code in the page you are looking at. That is a feature, and it is also the mechanism by which a shortcut can do anything a script can do on a page.

On top of that, the extension can import userscripts from Greasyfork and OpenUserJS. Userscripts are arbitrary code published by third parties. Once imported, they run in your browser with the extension's privileges, and a shortcut is the thing that triggers them. The README lists a userscript import feature without any statement about what the imported code is permitted to do, so the reviewer of a shared shortcut link or an imported script is the person responsible for it.

The same applies to shareable links. A URL that shares shortcuts or groups is convenient and is a channel through which someone else's configuration arrives in your browser, macros and page scripts included. If a link arrives from a colleague, the convenient thing is to open it. The careful thing is to read what it contains first.

None of this makes the extension malicious. It is an open source project whose source is in the repository, distributed through the standard store review processes, and the licence file and the code are both public. But it is a browser extension that can execute code in your pages, and the honest way to evaluate it is as a privilege rather than as a key rebinder. Restricting the extension to the sites you want it on, and reviewing anything you import, is the cost of the features that make it worth installing.

## Maintenance, releases, and the licence

The project is moving. The repository is not archived and the last push was on 2026-10-17. The release list shows v5.0.0 on 2026-03-13, v5.0.1-beta.1 on 2026-03-16, and v5.0.1 on 2026-03-16, and package.json carries the version 5.0.1. The major version bump to 5 alongside a large feature set, 9 packs, the command palette and the macro system, suggests a substantial rewrite of the extension's internals rather than an incremental change, which is what a store extension occasionally needs when the platform moves.

The licence needs a note. The repository's licence field is listed as a custom licence that GitHub cannot classify, and there is a LICENSE.md file at the root. The README, however, states the project is licensed under the MIT License and links to LICENSE.md. For anyone who wants to redistribute, fork, or vendor the code, the file itself is the thing to read rather than either of these descriptions, since the two do not match on their face.

The homepage is shortkeys.app, which is an Astro static site in the site/ directory deployed to Netlify, and it carries the action catalog, since build:site runs a catalog script before the Astro build. There is also a GitHub issue tracker, and an AGENTS.md at the repository root for automation instructions.

The contribution flow is stated plainly: pull requests are welcome, all tests must pass with npm test before submitting, and bugs and feature requests go to GitHub issues. With 722 unit tests across 25 files plus a Playwright end-to-end suite, the review bar for a change is checkable rather than a matter of taste.

## Conclusion

Adopt Shortkeys if you want keyboard control over Chrome, Firefox, Edge or Opera without living in a Vim-style modal workflow, and if you are comfortable reviewing what a shortcut pack or an imported userscript will do in your browser. Do not adopt it if your browser is already driven by an extension such as Vimium that owns the same key space, or if you need shortcuts that reach into the operating system rather than the browser. Verify first that the action you need exists among the 125 built-in actions, that a conflicting extension or browser default does not claim the same combination, which the conflict detection warns about, and that the licence file in the repository matches the MIT terms the README states before you redistribute anything.

## FAQ

### Which browsers does the Shortkeys extension support?

The README lists Chrome, Firefox, Edge and Opera, with store links for the Chrome Web Store, Firefox Add-ons, the Microsoft Edge add-ons site and Opera's add-ons site. The build scripts produce a Manifest V3 build for Chrome at .output/chrome-mv3/ and a Manifest V2 build for Firefox at .output/firefox-mv2/.

### How do I build Shortkeys from source?

Run `npm install` and then `npm run build` for Chrome or `npm run build:firefox` for Firefox. The development loop is `npm run dev` for Chrome or `npm run dev:firefox` for Firefox, and the test suite runs with `npm test`.

### What can Shortkeys do that a plain key rebinder cannot?

The feature list includes a command palette, macro chaining, groups with bulk enable and disable, per-shortcut site filtering, shareable links and a shortcut recorder that supports multi-key sequences such as g i. It also includes page scripts and a custom JavaScript editor, plus import of userscripts from Greasyfork and OpenUserJS.

### Does Shortkeys remap keys system wide?

No. It is a browser extension, and the key bindings are handled by Mousetrap inside a content script, so they apply to pages in the browser rather than to your operating system or other applications.

## Sources

- [crittermike/shortkeys on GitHub](https://github.com/crittermike/shortkeys)
- [Issues](https://github.com/crittermike/shortkeys/issues)
- [Project website](https://www.shortkeys.app/)
- [README](https://github.com/crittermike/shortkeys/blob/master/README.md)
- [Releases](https://github.com/crittermike/shortkeys/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/crittermike-shortkeys
