npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

keybuddy

v0.8.5

Published

[![npm version](https://badge.fury.io/js/keybuddy.svg)](https://badge.fury.io/js/keybuddy) [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)

Readme

keybuddy ⌨️

npm version TypeScript

Define and dispatch keyboard shortcuts with keybuddy.

keybuddy provides a simple and consistent toolset for defining and dispatching keyboard shortcuts in a browser environment.

Usage

pnpm add keybuddy
import { bindKey } from 'keybuddy';

bindKey('a', handleKeyPress);
bindKey('shift+r', handleKeyPress);
bindKey('command+shift+r', handleKeyPress);
// sequences
bindKey('cmd+e k', handleKeyPress);
bindKey('g i', handleKeyPress);

Initially based on keymaster

Differences:

  1. Written modern JS using TypeScript
  2. Custom scope not conflicting with default one
  3. Unbind requires an action (unsafeUnbindKey for backward compatibility)
  4. Creator instance to replace document with any other DOM element
  5. More explicit API
  6. Provides new fixes and maintaining
  7. Added sequence support
  8. Removed support for multiple shortcuts in a single string

Migrating from keymaster

Key differences:

  • Unbinding requires the handler function: unbindKey('ctrl+s', handler) instead of key.unbind('ctrl+s')
  • Use unsafeUnbindKey('ctrl+s') if you need the old behavior (removes all handlers)
  • Import what you need: import { bindKey, setScope } from 'keybuddy'
  • Modern browsers only (no IE11)
  • Split multiple key bindings into separate calls 'cmd+r, ctrl+r' into cmd+r, ctrl+r

Supported keys

Keybuddy understands the following modifiers:

shift, alt, option, ctrl, control, command, cmd

Symbol variants: , , ,

The following special keys can be used for shortcuts:

backspace, tab, clear, enter, return, esc, escape, space, left, up, right, down, del, delete, home, end, pageup, pagedown, comma, ., /, `, -, =, ;, ', [, ], \

Sequences

Keybuddy supports sequence shortcuts - multiple key combinations pressed in order:

// Press 'g', release, then press 'i'
bindKey('g i', () => goToInbox());

// Press Cmd+K, release, then press Cmd+C
bindKey('cmd+k cmd+c', () => copyCode());

// Press Cmd+Z, release, then press 'y'
bindKey('cmd+z y', () => confirmUndo());

Syntax:

  • 'cmd+z+y' = chord (all keys held simultaneously)
  • 'cmd+z y' = sequence (press Cmd+Z, release, then press Y)

Sequences timeout after 1 second.

API

bindKey(keysStr, scopeOrMethod, actionOrNothing?, options?)

Bind a keyboard shortcut to a handler.

import { bindKey, DEFAULT_SCOPE } from 'keybuddy';

bindKey('option+e', action);
bindKey('option+e', 'myScope', action);
bindKey('option+e', DEFAULT_SCOPE, action, { skipOther: true });

Options:

  • skipOther: boolean - If true, this handler takes priority and other handlers for the same shortcut won't fire

unbindKey(keysStr, scopeOrMethod, actionOrNothing?)

Unbind a keyboard shortcut. Action is required.

import { unbindKey } from 'keybuddy';

unbindKey('option+e', action);
unbindKey('option+e', 'myScope', action);

unsafeUnbindKey(keysStr, scope?)

Remove all handlers for a key (use with caution).

import { unsafeUnbindKey } from 'keybuddy';

unsafeUnbindKey('option+e');
unsafeUnbindKey('option+e', 'myScope');

isBound(keysStr, options?)

Check if a shortcut is bound.

import { bindKey, isBound } from 'keybuddy';

bindKey('ctrl+s', saveHandler);
isBound('ctrl+s'); // true
isBound('ctrl+s', { scope: 'editor' }); // false

getBoundKeys(options?)

Get all bound shortcuts in current or specified scope.

import { bindKey, getBoundKeys } from 'keybuddy';

bindKey('ctrl+s', saveHandler);
bindKey('ctrl+z', undoHandler);
getBoundKeys(); // ['ctrl+s', 'ctrl+z']
getBoundKeys({ scope: 'editor' }); // []

getHandlers(keysStr, options?)

Get all handlers for a specific shortcut.

import { bindKey, getHandlers } from 'keybuddy';

const save = () => console.log('save');
bindKey('ctrl+s', save);
getHandlers('ctrl+s'); // [save]

getScope()

Returns current scope.

setScope(scope)

Change the active scope.

unbindScope(scope)

Remove all actions in a scope.

unbindAll()

Remove all actions.

destroy()

Remove all actions and event listeners.

Custom Document / Iframe

Use createKeybuddy to bind shortcuts to a different document or element.

import { createKeybuddy } from 'keybuddy';

const iframe = document.getElementById('iframe').contentWindow;
const myKeybuddy = createKeybuddy(iframe.document);

myKeybuddy.bind('alt+b', action);

The default filter skips editable areas (contenteditable, input, select, textarea). You can provide a custom filter:

const myKeybuddy = createKeybuddy(document, (e) => {
  return true; // Handle all events
});

For iframe usage examples, see cypress/component/iframe-bindings.spec.ts.