hausfold

pounce

Config reference

Every key in ~/.config/pounce/config.json, what it defaults to, the three blocks that need a restart, and where every file lives.

Config file

Pounce reads ~/.config/pounce/config.json, re-read on every open. No restart is needed, except for the three things the daemon sets up at startup: windows, autoQuit, and the items hotkeys. Those are captured when armed and need a restart to change:

launchctl kickstart -k "gui/$(id -u)/com.hausfold.pounce"

Inside haus, a rebuild does that bounce for you when one of those keys moves.

pounce config init      # writes ~/.config/pounce/config.json
pounce config print     # …or just look at it, touching nothing

init writes every setting at its default, one commented-out line each with a sentence above it. Nothing changes until you uncomment a line, and you make the file minimal by deleting the lines you never touched. It never overwrites an existing config (it writes config.json.new beside it instead; --force replaces).

Inside haus, `config init` refuses

Your config.json is generated from haus.pounce.*, and the next rebuild would put the generated one straight back. Change it in your host file instead; see the Launcher room.

Comments and trailing commas are fine (JSON5); unknown keys are ignored, so an older Pounce never chokes on a config written by a newer one.

{
  "theme": "nebelung",       // "nebelung" (default), "mocha", or a themes/ file
  "themeLight": "nebelung-latte",  // used in macOS Light Mode
  "themeDark": "nebelung",         // used in macOS Dark Mode
  "windowMode": "default",   // "default" (720px) or "compact" (600px, tighter)
  "scale": 1.0,              // 0.8-2.0: how big the whole UI is drawn
  "hotkey": {
    "enabled": true,
    "key": "space",          // "space", "return", "tab", "escape", "a"–"z", "0"–"9"
    "modifiers": ["cmd"]     // any of "cmd", "shift", "opt", "ctrl"
  },
  "clipboard": {
    "enabled": true,
    "maxEntries": 200,
    "blacklistBundleIds": ["com.apple.Passwords"],
    "autoPaste": false       // synthesize ⌘V into the prior app (needs Accessibility)
  },
  "quickAnswers": { "currency": true },   // ECB rates, so "100 usd in eur" answers inline
  "updates": { "check": true },           // nudge (never install) when a release is out
  "fileSearch": {
    "enabled": true,
    "homeOnly": true,        // scope to ~ instead of the whole Spotlight index
    "maxResults": 60
  },
  "apps": {
    "demoteBundleIds": [],   // sink these below everything else; REPLACES a built-in list of Apple utilities (Feedback Assistant, Audio MIDI Setup, …)
    "hideBundleIds": []      // drop these from the list entirely
  },
  "windows": {
    "enabled": false,        // the MRU window switcher (needs Accessibility)
    "key": "tab",
    "modifiers": ["cmd"]
  },
  "autoQuit": {
    "enabled": false,
    "delay": 2,
    "exclude": ["com.apple.finder"]  // REPLACES the default, doesn't extend it
  },
  "items": {                 // per-item enable / alias / hotkey, see below
    "cmd:emoji": { "alias": "emo", "hotkey": "opt+space e" }
  }
}

quickAnswers.currency and updates.check are the only two settings that touch the network; set both false for a fully offline Pounce. autoQuit.enabled and windows.enabled turn on the two opt-in behaviours; both blocks are startup-only, so any edit inside them needs the daemon restart above, not just flipping enabled.

windowMode and scale are independent knobs (proportions vs. size) and they compose: a compact launcher at 1.4 is still the compact layout, just bigger. Values outside 0.8–2.0 clamp rather than reject. On haus, scale is written for you from haus.ui.scale.

Themes

themeLight / themeDark are resolved per open, so flipping macOS appearance shows on the next summon; either falls back to theme, and theme alone pins one palette for both modes.

Any theme value that isn't built-in resolves to ~/.config/pounce/themes/<name>.json: a flat catppuccin-style name → "#hex" map (nebelung's palette/*.hex.json files verbatim), which is how a desktop's theme.flavor / theme.contrast reach Pounce without a rebuild:

mkdir -p ~/.config/pounce/themes
curl -fsSLo ~/.config/pounce/themes/nebelung-latte.json \
  https://raw.githubusercontent.com/hausfold/nebelung/main/palette/nebelung-latte.hex.json
# config.json:  "theme": "nebelung-latte"

Per-item settings (items)

One map for what you'd otherwise want three keys: hide a row, give it a search shorthand, give it a global key. Each entry is keyed by an item key:

Item keyAddresses
cmd:<id>a command script, by filename without .sh
app:/Applications/Foo.appan application, by path
mode:<name>a built-in window: launcher, clipboard, emoji, screenshots, camera, filesearch
{
  "items": {
    "cmd:emoji":                     { "alias": "emo", "hotkey": "opt+e" },
    "cmd:brew-services":             { "enabled": false },
    "app:/Applications/Ghostty.app": { "alias": "term", "hotkey": "opt+t" },
    "mode:clipboard":                { "hotkey": "cmd+shift+v" }
  }
}

enabled: false drops the row without disarming a hotkey bound to it; keeping an item off the list but on a key is a legitimate setup. alias is a search shorthand that wins over whatever app fuzzy-matches the same letters. hotkey runs the item directly, skipping the palette: the last segment is the key, the rest modifiers, and the object form {"key": …, "modifiers": …} works too.

The laptop Fn/Globe key is a one-step special case ("mode:emoji": { "hotkey": "fn" }), using a keyboard event tap that needs Accessibility, firing only on a lone tap so Fn combinations keep working. "globe" / "function" are accepted aliases; haus binds emoji to it by default, and haus.pounce.items."mode:emoji".hotkey = null leaves Globe native.

Leader sequences

Add a space for a two-step key: "opt+space e" is ⌥Space then E, the Emacs/VS Code notation. Sequences sharing a leader share it (⌥Space registers once), and can run longer than two steps.

The payoff on a tiling setup: a leader can't collide with the ⌥/⌘ chords a window manager already owns, and it needs no Accessibility grant: pressing it grabs the next-step keys as ordinary global hotkeys for ~2s and releases them the instant one fires. Escape cancels; hesitate ~0.45s and a which-key overlay lists the next keys. pounce doctor reports every binding it actually armed.

Driving Pounce from another binder

AeroSpace modes, skhd, Shortcuts:

pounce run cmd:emoji
pounce run mode:clipboard

Same target grammar as items, through the same path a native binding takes; a malformed target exits non-zero with a reason.

File paths

PathWhat
~/.config/pounce/config.jsonConfiguration
~/.config/pounce/commands/Your commands (highest precedence)
~/.config/pounce/themes/Extra palettes, by name
~/.config/pounce/cheatsheet.jsonOptional cheatsheet content
~/.local/share/pounce/frecency.jsonUsage history for ranking
~/.local/share/pounce/pounce.sockDaemon control socket
~/.local/state/pounce/drafts/Saved drafts, per --draft key

Environment variables

Set by packagers (haus), rarely by hand: POUNCE_BUILTIN_DIR, POUNCE_EXTRA_COMMAND_DIRS (colon-separated Nix layers), POUNCE_COMMAND_PATH (colon-separated ad-hoc dirs).

On this page