nhz-io/kbsw

Launch and switch macOS apps with global keyboard shortcuts

★ 0Forks 0RustGitHub ↗Compare

README

kbsw

A macOS menu-bar app that lets you launch and switch between applications using global keyboard shortcuts. Written in Rust. Define your shortcuts in a TOML config file and they work system-wide, regardless of which app is in front.

Each shortcut toggles its app:

  • not running: launch it
  • running but not in front: bring it forward
  • already focused: hide it

If the app has multiple windows, repeated presses cycle through them before hiding.

Install

brew tap nhz-io/tap
brew install --cask kbsw

After installing, grant Accessibility permission in System Settings > Privacy & Security > Accessibility (needed for window cycling). Then register the login agent:

kbsw install

Manual install

Download the zip from the latest release, then:

unzip kbsw-*.zip
xattr -cr kbsw.app
kbsw.app/Contents/MacOS/kbsw install

The xattr step clears the macOS Gatekeeper quarantine flag. Homebrew does this automatically.

Configuration

The config file lives at ~/.config/kbsw/config.toml and is created with sensible defaults on first run. Save the file and changes apply immediately (no restart needed). You can also pick Reload config or Edit config... from the menu-bar icon.

# Identify an app by bundle id (most reliable) ...
[[binding]]
keys = "cmd+ctrl+t"
bundle_id = "com.apple.Terminal"

# ... or by name / path.
[[binding]]
keys = "shift+alt+s"
app = "Safari"

Shortcut syntax

modifier+modifier+...+key

  • modifiers: cmd (or command/super), ctrl (or control), alt (or option), shift
  • keys: a-z, 0-9, f1-f24, space, enter, tab, escape, arrowup/arrowdown/arrowleft/arrowright, etc.

Examples: cmd+ctrl+t, shift+alt+f5, ctrl+space

Avoid ctrl+alt combos since macOS VoiceOver reserves them. If a shortcut is already taken by the system or another app, registration fails with a log message and the rest keep working.

Finding a bundle id

osascript -e 'id of app "Safari"'      # -> com.apple.Safari

Commands

kbsw                  # run the menu-bar service (default)
kbsw install          # deploy to ~/Applications + start at login
kbsw install --force  # redeploy over an existing install
kbsw uninstall        # stop and remove the agent (config is kept)
kbsw --help           # usage

install copies the app bundle to ~/Applications/kbsw.app, writes a LaunchAgent so it starts at login and restarts if it exits, and starts the agent immediately.

Installed paths:

  • ~/Applications/kbsw.app
  • ~/Library/LaunchAgents/io.nhz.kbsw.agent.plist
  • ~/Library/Logs/kbsw.log

Build from source

Requires a Rust toolchain (rustup).

# Run in the foreground (logs to the terminal):
cargo run

# Build an optimized binary:
cargo build --release

# Build a distributable zip:
cargo xtask release

cargo xtask release assembles dist/kbsw.app and zips it into dist/kbsw-<version>-macos-<arch>.zip.

Permissions

  • Launching, switching, and hiding apps works without Accessibility permission.
  • Window cycling (rotating through an app's windows on repeated presses) needs Accessibility. Without it, repeated presses just hide and restore. kbsw prompts for the grant on startup.
  • Some apps (notably Finder) don't populate the standard AXWindows attribute but still expose windows as children. kbsw handles this automatically.
  • macOS may prompt the first time the app controls another application (Automation/AppleEvents). Allow it.

Project layout

src/
  main.rs         command dispatch (run / install / uninstall / help)
  service.rs      event loop, hotkey registration, tray menu, hot-reload
  config.rs       TOML config loading + default config
  app_control.rs  launch / activate / hide / cycle via AppKit + AX
  ax.rs           Accessibility helpers (enumerate + raise windows)
  installer.rs    deploy .app bundle + LaunchAgent
assets/           templates embedded via include_str! at build time
  Info.plist          app bundle metadata
  agent.plist         LaunchAgent template
  default-config.toml default config written on first run
xtask/            build tooling (cargo xtask release)

License

GPL-3.0

Contributors

nhz-io

Issues