Command menus 101: why every modern app has one

From Spotlight to Linear's K-bar. What makes a good command menu, and how to ship one without rebuilding it from scratch.

Hit ⌘K in almost any product shipped in the last three years and a small floating panel appears. Type a few letters, hit enter, and you've navigated, run a command, or invoked an action. Linear made it table stakes. Raycast made it a product. Now it's the default interaction model for any app dense enough to need one.

It's also a deceptively hard pattern. Most teams ship it, immediately regret the implementation, and rebuild it 18 months later. Here's what makes the good ones work.

Why command menus won

Three reasons. First, density. Once an app has more than ~25 features, a sidebar can't show them all and a settings menu buries them. The command menu is the flat index. Second, speed. Power users would rather type four letters than move a mouse, and power users determine whether your product feels fast. Third, discoverability. A good command menu is also a self-documenting list of every capability the product has, which beats a docs site for the 80% case.

The anatomy of a good one

The input

Auto-focused on open. Placeholder is a directive ("Type a command or search") not a label. No icon on the left larger than 16px, the input should feel like a terminal, not a search bar. ESC closes; ⌘K toggles.

The list

  • Grouped by intent, not by alphabet. Navigate at the top, Create in the middle, Settings near the bottom. The groups themselves are small mono labels.
  • Each row is one line, with an icon on the left, the action name, an optional dim subtext, and the keyboard shortcut right-aligned in mono.
  • Selected row is high-contrast, not just a subtle background tint. The cursor needs to be unambiguous when keyboard-navigating fast.
  • Results refresh on every keystroke with no debounce. Anything slower than ~30ms feels broken at this UI density.

The matching

Use fuzzy matching, not prefix matching. "lndr" should find "Linear". The two libraries to know are cmdk (the React command menu Vercel maintains) and fuse.js for the matching algorithm. Don't write your own fuzzy matcher unless you have a strong reason, it's a deeper problem than it looks.

Context-aware results

The best command menus show different commands depending on where you are in the app. On an invoice page, "Mark as paid" appears at the top. On the dashboard, it doesn't. This is what separates a true command menu from a glorified search box, the menu knows about your current scope.

The patterns to copy

Subpages and back-navigation

Pressing enter on a command sometimes runs the command, sometimes navigates into a subpanel ("Change theme" opens a list of themes). Backspace at an empty input returns to the parent. This nested navigation is what lets a command menu replace 80% of a settings UI.

Recents and pinned

First-open should show recent commands at the top, pinned commands above those. Empty state for a brand-new user should be the most useful 8–10 actions, not a blank slate. The empty state is a tutorial.

Inline previews

Raycast popularized previews, hover a result and a panel on the right shows what you'd see if you ran it. Borrow this when your commands have nontrivial output (search results, file contents, calendar events). Skip it when commands are atomic actions.

The mistakes

  1. 01Building the UI but not the keyboard model. A command menu you can only operate with arrow keys + enter is a command menu, adding mouse interaction is fine, but a mouse-first command menu is a search bar with bad UX.
  2. 02Showing too many results. If the menu has 200 commands, the user types two characters and sees 47 results. Hard-cap at ~8 visible, paginate the rest.
  3. 03Forgetting the close-on-execute behavior. Most commands should close the menu after executing. The few that shouldn't (running multiple actions in a row) need explicit affordance.
  4. 04Confusing it with global search. A command menu can include search results, but its primary job is actions. If 80% of your menu is search hits with no commands, you built a search bar.

Ship one

The interaction entry in the directory ships a tuned prompt that produces a Linear-style command menu, cmdk under the hood, fuzzy matching, grouped results, keyboard shortcuts on the right, ⌘K to toggle. Drop it in and customize the action list. Two hours of work for a feature your users will use a hundred times a week.

Keep reading