Skip to content

Pounce — the launcher

Pounce is a free, open-source, native command palette for macOS — a fast, dmenu-style picker you summon with a hotkey. Hit ⌘Space, fuzzy-type, hit Return. It launches apps, runs commands, answers quick questions inline, and hosts a handful of built-in modes (clipboard, emoji, screenshots, and more).

Its whole personality is one idea: every command is a file. Drop a shell script in a folder and it’s in the palette — no plugin API, no extension store, no account.

It’s MIT licensed and free — every feature on this page, no paid tier.

  • ⌘Space — the default hotkey. Registered in-process by the daemon, so it opens instantly. (nebelhaus disables Spotlight’s ⌘Space so Pounce can own it.)
  • Change it in config: the hotkey object takes a key and modifiers.

Launch apps

Type a few letters — saf → Safari. Freshly-installed apps get boosted so they’re easy to find right after install.

Run commands

Your scripts and the built-ins appear alongside apps, ranked by how often you use them.

Clipboard history

Browse and restore recent copies in a two-pane view; optionally auto-paste into the app you came from.

Find Files

Search files and folders by name as you type, over Spotlight’s index. ⏎ opens, ⌘⏎ reveals in Finder, ⌥⏎ copies the path.

Quick answers

Math, unit, time-zone, and currency queries answer inline as a pinned first row — copies the result.

Emoji, screenshots, more

Built-in modes for an emoji grid, a screenshot browser, a camera peek, and a searchable cheatsheet.

KeyAction
TypeFuzzy-search in real time
/ Move the selection
ReturnRun the default action
⇧ReturnInsert a newline — the query field is multi-line
⌘ReturnThe modifier action (often “Reveal in Finder” for apps)
⌥Return / ⌃ReturnAlternate actions, when shown
TabCycle sections (or emoji categories)
EscDismiss

The action bar at the bottom always shows which modifiers do what for the selected row, so you don’t have to memorize them.

Results are ordered by a blend of three signals, so the thing you want is usually already on top:

  1. Fuzzy match quality — consecutive runs, matches at word boundaries, and how much of the name your query covers all score higher. Titles count double subtitles.
  2. Frecency — frequency × recency, with a 72-hour half-life. The apps and commands you actually use float up.
  3. Freshly-installed boost — apps installed in the last week get a temporary bump (halving every two days) so new installs are easy to find.

Some queries are answered in the palette instead of being fuzzy-matched against apps and commands. The answer pins to the top as its own row, and Return copies it:

TypeGet
2*847, 2^10, sqrt(9), round(2pi)Arithmetic, with the interpretation shown beside it
100 + 10%, 20% of 150Percentages
72 f in c, 1 pound in kg, 10 km in mi, 1 gib in mibUnit conversion
100 usd in eur, $100 in eur, 50 euros in yenCurrency conversion
14:00 utc in pst, 2pm utc in tokyo, 9pm pst in utcTime-zone conversion

There’s no trigger prefix — a query that no engine can parse just falls through to the normal results, and anything without a digit skips the engines entirely (so safari and 1password stay searches). Output follows your locale, so 1/4 copies 0,25 on a German Mac.

Currency uses the European Central Bank’s daily reference rates (fetched from api.frankfurter.app, refreshed at most every 12 hours, cached to ~/.local/share/pounce/currency-rates.json so it keeps answering offline). It’s the only network request Pounce makes; set quickAnswers.currency to false in config to switch it off entirely. Nothing about your usage is ever sent anywhere.

A window switcher, not an app switcher (opt-in)

Section titled “A window switcher, not an app switcher (opt-in)”

Pounce ships an MRU window switcher: tap the chord to bounce to your last window, hold it and keep tapping to walk older ones, or type while holding to fuzzy-filter. It moves by window, not by app, so two Ghostty windows are two rows.

It’s off by default because it needs the Accessibility grant to install an event tap. Turn it on with the windows block in config (or nebelhaus.pounce.windowSwitcher in the rice, where it defaults on). If you run AeroSpace, rows carry the window’s workspace and focusing goes through aerospace focus --window-id so a window parked elsewhere surfaces properly; without it, everything degrades to plain focus.

Some commands open a second picker instead of acting immediately — “Brew Services” lists services, “Force Quit” lists processes. Pounce swaps the list in place with no window flicker. Any command you write can do this by declaring # pounce: submenu = true. See Writing pounce commands.

Out of the box you get: Activity Monitor, Brew Services, Camera, Capitalize, Clipboard History, Emoji, Find Files, Force Quit, Lock Screen, Lowercase, Ports, Report Issue, Screenshots, System Settings, and (Homebrew installs) Update Pounce. Each is just a script you can read, copy, or replace.

Capitalize and Lowercase rewrite the text you have selected in any app — they copy the selection, run it through a one-line shell filter, and paste it back via pounce --transform. Swap tr for anything and you have your own text action.

Update Pounce self-updates in place, and what it does follows how you installed Pounce: a Homebrew build runs brew upgrade pounce and restarts the service; a copy dragged to /Applications downloads the new release and swaps itself out; a Nix or rice install is pointed at the flake (haus update) rather than overwritten, since the next rebuild would revert it. It runs in the background and reports via notifications — see the Pounce reference for the full per-install breakdown.

Every System Settings pane is its own command too, so typing “Displays” or “Accessibility” jumps straight there instead of dropping you at the front door.

Report Issue opens a pre-filled GitHub issue with your pounce and macOS versions already in the body — the rice ships a matching one for nebelhaus itself.

Beyond the built-ins there’s a shelf of optional plugins, off by default because each one assumes a specific tool, service, or app on your machine:

PluginWhat it doesNeeds
Audio DevicesSwitch sound output & input from the palettebrew install switchaudio-osx
BluetoothConnect & disconnect paired devices (AirPods, keyboards, …)brew install blueutil
CaffeinateKeep the Mac awake — indefinitely or on a 30m/1h/2h timernothing (system caffeinate)
DockerStart, stop, restart & tail logs of containers; offers to start the engineany engine that answers docker ps (Docker Desktop, OrbStack, colima)
GitHubJump to your PRs, review requests, issues & repos in the browsergh CLI, authenticated
SpotifyPlayback controls: play/pause, next, shuffle, now-playingSpotify.app (drives it over AppleScript)
SSH HostsPick a host from ~/.ssh/config (Includes too); ⏎ connects, ⌘⏎ copies the commandhosts in ~/.ssh/config
TailscaleConnect/disconnect, copy your tailnet IP or any peer’stailscale CLI (ships inside Tailscale.app)

On Nix, enable them by id when consuming the pounce-commands package:

pounce-commands.override { plugins = [ "docker" "ssh" "tailscale" ]; }

An enabled plugin behaves exactly like a built-in — same palette discovery, same pounce-<id> bin for hotkey bindings, still shadowable from your user dir. Not on Nix? Every plugin is still just one script: copy it from pkgs/pounce-commands/optional/ into ~/.config/pounce/commands/ and it’s live on the next ⌘Space.

Terminal window
brew tap nebelhaus/tap
brew install pounce
brew services start pounce # start the daemon
pounce --request-accessibility # one-time, for paste-back features

The formula installs a prebuilt Pounce.app signed with our Apple Developer ID and notarized by Apple — it opens straight away, no Gatekeeper prompt and no compile step. Requires macOS 14 Sonoma or later on Apple Silicon; the release is arm64 only.

Because that signing identity is stable, the Accessibility grant survives brew upgrade — you approve it once, not once per release.

Or with Nix: nix run github:nebelhaus/pounce -- --help.

Clipboard auto-paste and emoji paste synthesize a ⌘V into your previous app, which macOS gates behind Accessibility:

Terminal window
pounce --request-accessibility # approve the dialog
pounce --check-accessibility # prints true when granted

Full configuration, CLI flags, and file paths are on the Pounce config & CLI reference. To extend it, head to Writing pounce commands.