This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
While package.json version is below 0.1.0, there are NO deprecation or migration concerns. The existing codebase is small and experimental. Old APIs, patterns, or ideas can be completely removed without backwards compatibility shims, migration paths, or deprecation warnings. Just delete and replace.
pnpm build # Build library for npm publishing
pnpm dev # Build library in watch mode
pnpm dev:docs # Start docs/demo dev server on http://localhost:3000
pnpm build:docs # Build docs/demo for production
pnpm test # Run tests
pnpm test:watch # Run tests in watch mode
pnpm test:coverage # Run tests with coverage
pnpm lint # Check linting with Biome
pnpm lint:fix # Fix lint issues
pnpm format # Format code with Biome
pnpm storybook # Start Storybook on http://localhost:6006This repo uses release-please for automated releases. When you push commits to main, release-please opens a PR titled "chore: release keymash". To trigger an npm publish, you must merge this release-please PR. Simply pushing to main does not publish - the release PR merge is what triggers the publish workflow.
KeyMash is a keyboard binding library that uses bitwise operations for O(1) chord lookup. The docs app showcases this library with an interactive keyboard visualization.
src/ # Library source code
index.ts # Main entry point (keymash)
react.ts # React hooks (keymash/react)
keymash.ts # Full keymash implementation
types.ts # Type definitions
*.test.ts # Unit tests
docs/ # Demo/documentation app (standalone)
src/ # React demo app
.storybook/ # Storybook config
The library maps each key to a unique bit in a 512-bit bigint space:
- Bits 0-255: Hold state (modifier keys currently pressed)
- Bits 256-511: Press state (the key that triggered the event)
Key concepts:
holdandpressare pre-populated Record<string, bigint> objects for all common keys- Use
+to combine keys naturally:hold.ctrl + press.t - Use
|for OR logic (alternatives):hold.ctrl + (press.a | press.b) - OR'd combinations are "exploded" into separate lookup entries at registration time
The Keymash class manages:
- Event listener lifecycle (keydown/keyup/blur)
- Binding explosion for OR'd combos
- WeakMap-based target registry for tracking instances per DOM element
- Change notification via subscriber pattern
- Real-time key state updates via
onUpdatecallback for UI visualizers
App.tsx: Marketing/demo page layout with feature sectionscomponents/KeyMashDemo.tsx: Interactive keyboard with visual key state feedback and event loggingcomponents/CodeBlock.tsx: Responsive code display using Prettier in a Web Worker (lib/prettier-worker.ts)
KeyCombo: Type alias for bigintHandlerContext: Object passed to handlers with{ event, instance }for extensibilityKeyComboHandler: Function type(context: HandlerContext) => void- handlers receive context object, not positional argsBinding: Config object withcombo,handler, optionallabel,delay,repeatFullBinding: Extended binding with resolved properties and human-readablecomboTextIKeymash: Public interface for instances
- Biome: Linting and formatting (replaces ESLint + Prettier)
- Vitest: Unit testing with jsdom environment
- Storybook: Component documentation and visual testing
- Lefthook: Git hooks for pre-commit linting and commit message validation
- Commitlint: Enforces conventional commit format
- Release Please: Automated changelog and npm releases via GitHub Actions
Commits must follow Conventional Commits format:
feat:new featuresfix:bug fixesdocs:documentation changeschore:maintenance tasks
Pre-commit hooks automatically lint and format staged files.
This project has specialized agents in .claude/agents/. Proactively invoke these agents based on the code being modified:
Invoke after ANY changes to keyboard handling code:
src/keymash.ts- Any code touching
event.key,event.code, or keyboard events - Key normalization or mapping logic
- Modifier key handling (ctrl, shift, alt, meta)
This agent reviews for cross-browser compatibility, international keyboard support (AZERTY, QWERTZ, etc.), and performance.
Invoke after changes to public API surface:
- Adding new exports, types, or public methods
- Modifying
types.ts - Updating README.md documentation
- Adding JSDoc comments
- Before creating any PR for new features
This agent ensures all APIs are documented, examples are accurate, and edge cases are covered.
Invoke after changes to developer-facing APIs:
- New React hooks or components
- API design decisions (method signatures, return types)
- Documentation examples
- README code samples
This agent reviews from a frontend developer's perspective for ergonomics and usability.
Before creating a PR, verify these agents were invoked as needed:
- Modified keyboard handling? →
keyboard-compat-advocate - Added public API surface? →
api-docs-completionist - Wrote React hooks or examples? →
frontend-api-reviewer
Use /review to invoke all relevant agents based on current changes.