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

modern-cmdk

v1.2.2

Published

The definitive command palette engine for the modern web

Readme


Install

npm install modern-cmdk

[!NOTE] modern-cmdk is ESM-only and declares engines.node >= 26.4.0. The optional WASM search engine (modern-cmdk-search-wasm) is experimental and not yet published to npm.

The package exports three entry points:

import { createCommandMachine } from 'modern-cmdk';       // Core engine (no React)
import { Command } from 'modern-cmdk/react';               // React 19 components
import 'modern-cmdk/styles.css';                            // Default styles

React is an optional peer dependency — use the core engine standalone in any framework, or pair it with the React adapter for a batteries-included experience.


Quick Start

'use client';

import { Command } from 'modern-cmdk/react';
import 'modern-cmdk/styles.css';

function CommandPalette() {
  return (
    <Command.Dialog>
      <Command.Input placeholder="Type a command..." />
      <Command.List>
        <Command.Empty>No results found.</Command.Empty>

        <Command.Group heading="Actions">
          <Command.Item value="copy" onSelect={() => copyToClipboard()}>
            <Command.Highlight>Copy to Clipboard</Command.Highlight>
            <Command.Shortcut>Mod+C</Command.Shortcut>
          </Command.Item>
          <Command.Item value="paste" onSelect={() => paste()}>
            <Command.Highlight>Paste</Command.Highlight>
            <Command.Shortcut>Mod+V</Command.Shortcut>
          </Command.Item>
        </Command.Group>

        <Command.Group heading="Navigation">
          <Command.Item value="settings" onSelect={() => navigate('/settings')}>
            Settings
            <Command.Badge>New</Command.Badge>
          </Command.Item>
        </Command.Group>
      </Command.List>
      <Command.Loading>Searching...</Command.Loading>
    </Command.Dialog>
  );
}

Or scaffold a new project instantly:

npm create modern-cmdk

Why modern-cmdk?

A ground-up rewrite of cmdk for React 19, ES2026, and TypeScript 7. Framework-agnostic core. Zero compromise on performance, accessibility, or developer experience.

| | cmdk | modern-cmdk | |---|---|---| | Architecture | React-only, tightly coupled | Framework-agnostic core + thin adapters | | React | 18 | 19 (use(), useOptimistic, useId, ref as prop) | | Search | Basic substring | Fuzzy scoring + optional WASM (sub-1ms on 100K items) | | Ranking | Static order | Frecency with time-based exponential decay | | Virtualization | None | Automatic variable-height, content-visibility: auto | | Animations | CSS transitions | GPU-composited: @starting-style, scroll-timeline, spring easing | | Keyboard | External | Built-in registry, Mod key, conflict detection | | Accessibility | Partial ARIA | Full WAI-ARIA combobox, forced-colors, prefers-contrast | | Bundle | ~6 KB | Core ~6.3 KB, React ~10.2 KB | | TypeScript | 4.x/5.x | 7.0, isolated declarations, branded types | | Cleanup | Manual | using/await using (Explicit Resource Management) | | Error handling | None | CommandErrorBoundary with fallback UI | | DevTools | None | Built-in devtools hook for browser inspection |


Features

  • Framework-agnostic core -- Pure TypeScript state machine. No DOM. No React. Portable to any runtime. The sole runtime dependency (idb-keyval) is lazy-loaded only if you opt into IndexedDB frecency persistence.
  • React 19 adapter -- 14 compound components. useSyncExternalStore, useTransition, useOptimistic, use() for Suspense. React Compiler compatible.
  • Automatic virtualization -- Variable-height virtual scrolling kicks in at a configurable threshold (virtualizeThreshold, default 100). Handles 100K+ items smoothly with content-visibility: auto.
  • Fuzzy search -- Built-in TypeScript scorer with incremental filtering. Optional Rust/WASM engine for sub-1ms on 100K items with graceful TS fallback (experimental, not yet published to npm).
  • Frecency ranking -- Frequency x recency with time-based exponential decay. Pluggable persistence (memory or IndexedDB).
  • Keyboard shortcuts -- Built-in registry with cross-platform Mod key, conflict detection, and RegExp.escape parsing. Cross-browser helper functions for grouping and set operations.
  • Full accessibility -- WAI-ARIA combobox pattern, aria-live announcements, forced-colors, prefers-contrast, prefers-reduced-motion.
  • GPU-composited animations -- @starting-style entry, scroll-timeline progress, spring linear() easing. All customizable via CSS custom properties.
  • Error boundary -- CommandErrorBoundary with static or render-function fallback.
  • DevTools -- useCommandDevtools() exposes machine state via CustomEvent for browser inspection.
  • Telemetry middleware -- Pluggable hooks for palette open/close, search, and item selection analytics.
  • ESM-only -- Zero CommonJS. Tree-shakeable -- the framework-agnostic core is side-effect-free; only the React entry and styles.css are flagged in sideEffects. Isolated declarations.

React Components

<Command>                {/* Root -- state machine provider */}
  <Command.Input />      {/* Search input */}
  <Command.List>         {/* Scrollable list with auto-virtualization */}
    <Command.Empty />    {/* Shown when filteredCount === 0 */}
    <Command.Loading />  {/* Shown when loading */}
    <Command.Group>      {/* Labeled group of items */}
      <Command.Item>     {/* Selectable item */}
        <Command.Highlight />   {/* Fuzzy match highlighting */}
        <Command.Badge />       {/* Status badge */}
        <Command.Shortcut />    {/* Keyboard shortcut display */}
      </Command.Item>
    </Command.Group>
    <Command.Separator />
  </Command.List>
</Command>

<Command.Dialog />       {/* Radix Dialog + overlay + portal */}
<Command.Page />         {/* Nested page navigation */}
<Command.AsyncItems />   {/* Suspense-powered async loading */}

Core API (No React)

Use the core engine standalone in any framework or runtime:

import { createCommandMachine, itemId } from 'modern-cmdk';

using machine = createCommandMachine({
  items: [
    { id: itemId('copy'), value: 'Copy', shortcut: 'Mod+C', onSelect: () => copy() },
    { id: itemId('paste'), value: 'Paste', shortcut: 'Mod+V', onSelect: () => paste() },
  ],
  frecency: { enabled: true },
  loop: true,
});

machine.send({ type: 'SEARCH_CHANGE', query: 'cop' });
machine.send({ type: 'NAVIGATE', direction: 'next' });
machine.send({ type: 'ITEM_SELECT', id: itemId('copy') });

machine.subscribe(() => {
  console.log(machine.getState());
});
// Automatic cleanup via `using` -- no manual dispose needed

Performance

| Benchmark | Target | Measured | |---|---|---| | Search 10K items (TS scorer) | < 16 ms | ~8.2 ms | | Search 100K items (WASM) | < 1 ms | ~0.7 ms | | Filter 10K (incremental) | < 2 ms | ~1.1 ms | | State update cycle | < 4 ms | ~2.3 ms | | Core bundle (gzipped) | <= 6.5 KB | ~6.3 KB | | React bundle (gzipped) | <= 12 KB | ~10.2 KB |

CI enforces 5% warning / 15% failure regression thresholds with 3-run averaging.


CSS Customization

All animations and dimensions are customizable via CSS custom properties:

[data-command-root] {
  --command-duration-enter: 200ms;
  --command-duration-exit: 150ms;
  --command-scale-from: 0.96;
  --command-overlay-blur: 4px;
  --command-dialog-radius: 12px;
  --command-dialog-max-width: 640px;
  --command-item-height: 44px;
  --command-highlight-color: oklch(0.85 0.15 90 / 0.3);
}

All styles use @layer command for zero-specificity conflicts and CSS logical properties for full RTL support.


Migration from cmdk

Automated codemods handle the most common migration patterns:

npx modern-cmdk import-rewrite ./src
npx modern-cmdk data-attrs ./src
npx modern-cmdk forward-ref ./src
npx modern-cmdk should-filter ./src

See the full migration guide.


Documentation

command.crimson.dev

Guides: Getting Started | Installation | Basic Usage | Async Items | WASM Search | Frecency | Shortcuts | Virtualization | SSR / Next.js | Theming | Accessibility

Recipes: File Picker | Emoji Picker | AI Chat Commands | Nested Commands | Spotlight Search

API: Core Engine | React Adapter | WASM Search


Related Packages

| Package | Description | |---|---| | create-modern-cmdk | npm create modern-cmdk -- scaffold a new project | | modern-cmdk-search-wasm (experimental, not yet published) | Rust/WASM fuzzy search -- sub-1ms on 100K items | | vscode-modern-cmdk | VS Code snippets extension |


License

MIT -- Copyright (c) 2026 Crimson Dev