Snap Cat is the smallest useful window manager for macOS. Four shortcuts. A menu bar icon. Accessibility APIs. No drag-to-snap, no preference window, no updater, no account.
The mascot is Snapu — the little window cat who snaps panes into place.
If you want Rectangle with every tile preset — use Rectangle. If you want ⌘ arrows and nothing else — use this.
git clone https://github.com/stevederico/snapcat.git
cd snapcat
./build.sh
open -a SnapCat- Grant Accessibility when prompted (or System Settings → Privacy & Security → Accessibility → enable Snap Cat)
- Quit and reopen Snap Cat once so the grant sticks
- Press ⌘← on any window
| Shortcut | Action |
|---|---|
| ⌘← | Left half |
| ⌘→ | Right half |
| ⌘↑ | Fill screen (usable area — menu bar and Dock stay put) |
| ⌘↓ | Minimize |
Not macOS Full Screen. Fill uses the screen's visible frame so the window stays a normal windowed app.
- Left / right halves on the display under the window
- Fill to all usable space (not Stage Manager / Full Screen theater)
- Minimize via Accessibility, same as the yellow button
- Typing wins — in a real text field (non-browser apps), ⌘← / ⌘→ stay "line start / line end"
- Browsers always snap — Brave, Chrome, Safari, Arc, etc. never pass through (sites park focus in sidebars like x.com Grok)
- Terminals snap — Warp, Terminal, iTerm, and friends always get window actions (their UI is one big text view)
- Status item with Snap Left / Right / Fill / Minimize
- Keyboard Shortcuts checkmark — disable global hotkeys without quitting (persists)
- Accessibility Settings… deep link when the grant goes missing
- Menu actions still work when hotkeys are off
- One Swift file — the whole app lives in
Sources/main.swift - No preferences — hotkeys are fixed; less code, less UI, fewer bugs
- No network — no updater, analytics, or phoning home
- Menu bar only —
LSUIElement, no Dock icon
| macOS | 13 Ventura or later |
| Xcode / CLT | Swift 5.9+ (xcode-select --install) |
| Permission | Accessibility for /Applications/SnapCat.app |
./build.sh compiles a release binary, wraps it in SnapCat.app, codesigns, and copies to /Applications.
./build.sh
# → /Applications/SnapCat.appSigning (Accessibility grants stick better with a stable code signature):
# Default in this repo: your Apple Development identity (if present)
./build.sh
# Ad-hoc sign (works everywhere; may need re-grant after rebuilds)
SNAPCAT_SIGN_ID="-" ./build.sh
# Custom identity
SNAPCAT_SIGN_ID="Apple Development: Your Name (TEAMID)" ./build.shInstall somewhere else:
SNAPCAT_INSTALL="$HOME/Applications" ./build.shIf the Accessibility dialog keeps popping up: System Settings → Privacy & Security → Accessibility → remove every Snap Cat entry → enable the one from Applications → restart Snap Cat.
Menu bar icon → Quit Snap Cat, or:
pkill -x SnapCat| Technology | Purpose |
|---|---|
| Swift | App language |
| Cocoa | Menu bar status item |
| ApplicationServices (AX) | Read/write front window frames, minimize |
| CGEvent tap | Global ⌘+arrow hotkeys with pass-through |
| Carbon.HIToolbox | Virtual key codes only |
- A CGEvent tap watches key-downs for pure ⌘ + arrow (no Shift / Option / Control).
- If focus is a real text field, the key is left alone (line / document navigation).
- Otherwise Snap Cat swallows the event and resizes or minimizes the front window via Accessibility.
- Frames use
NSScreen.visibleFrameso menu bar and Dock remain visible.
Heavy Accessibility tree walks are intentionally not done on the hotkey path — they can timeout the event tap and leak keys (e.g. browser back/forward).
git clone https://github.com/stevederico/snapcat.git
cd snapcat
./build.sh
open -a SnapCatKeep it small. New tile layouts, prefs panes, and updaters are usually out of scope — open an issue first if you're unsure.
- 🐦 X: @stevederico
- 🐛 Issues: GitHub Issues
- Rectangle — the gold standard; Snap Cat is the opposite end of the spectrum
- Apple Accessibility and Quartz Event Services — the whole app is a thin shell over these
./build.sh && open -a SnapCatGrant Accessibility. Press ⌘←. Done.
MIT License — use it however you want. See LICENSE for details.
Built with ❤️ by Steve Derico
⭐ Star on GitHub — it helps!
