Skip to content

Focus & DND (hush)

hush is the quiet room. One switch — the bell pill in the bar, “Toggle Hush” in the palette, or hush in a terminal — that turns macOS Do Not Disturb on or off, optionally sets your Slack status (and silences Slack on your phone), and runs any hooks you add. All three surfaces call the same engine, so they can never disagree.

Because hush drives the real macOS Focus, everything Focus already does comes along free: if Share Across Devices is on, your iPhone and iPad hush too, and the “allowed to break through” list is whatever you’ve curated in System Settings.

How the toggle works (and why it’s unusual)

Section titled “How the toggle works (and why it’s unusual)”

Apple ships no public API or CLI to set a Focus — every “focus CLI” on GitHub is secretly a Shortcuts wrapper. nebelhaus takes a different path:

  1. The binding is nix config. macOS has a hidden keyboard shortcut slot — “Turn Do Not Disturb On/Off”, symbolic hotkey 175, disabled by default and buried in Settings. Every switch binds it declaratively to ⌃⌥⇧⌘ F13, a chord nothing else uses.
  2. The engine presses it. hush synthesizes that keypress. No Shortcuts app, nothing to author by hand, and the binding heals itself on every rebuild.

State is read from the Focus database (~/Library/DoNotDisturb/DB) when the calling app has Full Disk Access, so the pill stays truthful even when you toggle Focus from Control Center or your phone; without that grant, hush falls back to remembering its own last toggle.

Synthesizing a keypress needs Accessibility, and exact state reads need Full Disk Access — both granted once, per app, in System Settings → Privacy & Security. Run hush doctor any time: it checks each piece and prints the exact fix for whatever is missing.

  • Palette toggles work out of the box — palette commands run under the pounce daemon, which already holds an Accessibility grant (that’s what pounce.signingIdentity keeps stable across rebuilds).
  • For the bar pill, add sketchybar to Accessibility.
  • For the CLI, add your terminal (Ghostty) — many setups already have it.
  • Optional but recommended: add the signed Pounce.app (or your terminal + sketchybar) to Full Disk Access so hush status reads the real Focus state instead of guessing from its own memory.

macOS Focus already silences Slack banners on your Mac. The Slack leg does what Focus can’t: tells your teammates (status + 🔕) and silences your phone (Slack’s own DND, all devices). While hushed, your previous status is stashed and restored on unhush.

It’s off by default because it needs a personal Slack token:

  1. Create a Slack app for yourself at api.slack.com/apps (“From scratch”, any name, your workspace).

  2. Under OAuth & Permissions → User Token Scopes, add users.profile:write and dnd:write, then Install to Workspace and copy the User OAuth Token (xoxp-…).

  3. Stash it in your Keychain — no secret ever touches your config or the Nix store:

    Terminal window
    security add-generic-password -s hush-slack -a "$USER" -w 'xoxp-…'
  4. Point hush at it in your host file:

    nebelhaus.hush.slack = {
    enable = true;
    tokenCommand = "security find-generic-password -s hush-slack -w";
    statusText = "heads down"; # the defaults, shown for flavor
    statusEmoji = ":no_bell:";
    snooze = true; # silence Slack push on all devices
    };

hush doctor verifies the token against Slack’s API once it’s wired.

Every hush/unhush also runs your own scripts, each called with on or off. Failures are logged, never fatal — a broken hook can’t wedge the toggle.

nebelhaus.hush.hooks = [
./onair-light.sh # turn the Elgato red while hushed
"/Users/ada/bin/pause-music" # strings run as-is, so $HOME paths work
];

Ideas: pause the music, flip an on-air light, start a Harvest timer, shove chatty apps to a parking workspace with aerospace.

  • hush flips the built-in Do Not Disturb, not named Focus modes — those have no symbolic hotkey to bind.
  • It doesn’t manage which apps or people break through; that’s your Focus allowlist, curated once in System Settings → Focus.
  • Without Full Disk Access, hush status is hush’s own memory — it can drift if you toggle Focus elsewhere. The bar pill self-corrects on the next real toggle either way.

Run hush doctor first. It checks the hotkey binding, the state-read grant, and the Slack token, and prints the fix for each.

  • Click the pill, nothing happens — sketchybar has no Accessibility grant yet; you’ll get a notification saying so. Grant it, or toggle from the palette (which needs nothing).
  • Pill shows the wrong state after toggling from Control Center — grant Full Disk Access for exact reads; otherwise the pill catches up the next time hush itself toggles.
  • The chord stopped workingdarwin-rebuild switch re-binds hotkey 175 on every activation; a rebuild heals it.