summon-switcher 0.1.0

A tiny macOS command-line tool for opening, focusing, and cycling applications from declarative keybindings.
docs.rs failed to build summon-switcher-0.1.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

Summon is a tiny macOS command-line tool for keyboard-driven app switching.

Define your applications in ~/.config/summon/summon.toml, wire them to your preferred hotkey tool, and use one command to launch, focus, or cycle through app windows.

summon terminal
summon browser
summon editor

Summon is designed to be fast, boring, and easy to keep in your dotfiles.

Installation

cargo install summon-switcher

brew install liamwh/summon-switcher/summon-switcher

# from source, install to ~/bin and start the warm daemon path
just install

Quick Start

Create ~/.config/summon/summon.toml:

[settings]
cycle_when_focused = true
launch_if_not_running = true

[bindings.terminal]
app = "com.mitchellh.ghostty"

[bindings.browser]
app = "com.brave.Browser"

[bindings.editor]
app = "dev.zed.Zed"

Wire to your hotkey tool (e.g. skhd):

cmd + alt + ctrl + shift - return : summon terminal
cmd + alt + ctrl + shift - b      : summon browser
cmd + alt + ctrl + shift - z      : summon editor

Usage

summon <binding>        # Launch, focus, or cycle the configured app
summon app <app>        # Summon an app directly by name or bundle ID
summon list             # List all configured bindings
summon config path      # Print the active config file path
summon config check     # Validate the config file
summon doctor           # Check macOS permissions
summon daemon status    # Inspect the optional warm daemon
summon inspect windows dev.zed.Zed --pretty

By default, summon will try the daemon first and fall back to direct mode if the socket is unavailable. Set SUMMON_DAEMON=off to force direct mode, or SUMMON_DAEMON=required to require the daemon.

Configuration

Summon reads from $XDG_CONFIG_HOME/summon/summon.toml (defaults to ~/.config/summon/summon.toml).

Each binding maps a name to an application target:

[bindings.terminal]
app = "com.mitchellh.ghostty"
cycle_when_focused = true
launch_if_not_running = true

Applications can be resolved by bundle identifier, name, or path:

[bindings.terminal]
app = "com.mitchellh.ghostty"    # Bundle ID (preferred)

[bindings.preview]
app = "Preview"                   # App name

[bindings.custom]
app = "/Applications/My App.app"  # Path

How it works

  1. Resolve the configured target application
  2. If not running — launch it
  3. If running but not focused — focus its most recent window
  4. If already focused and cycle_when_focused is enabled — cycle to the next window

This makes repeated keypresses useful rather than redundant.

For the snappiest hot path, just install restarts a background daemon that caches config and handles repeated invocations over a Unix socket. That keeps keypresses off the cold CLI startup path while still preserving a direct-mode fallback.

The daemon logs to ~/Library/Logs/summon/summond.log. Use summon inspect windows <app> --pretty to capture the live AX window state that Summon will use for cycling.

Integrations

Summon works with any tool that can execute a command. Example configs are in the examples/ directory.

skhd

Add to ~/.skhdrc:

hyper - return : summon terminal
hyper - b      : summon browser
hyper - z      : summon editor
hyper - f      : summon finder

See examples/skhdrc for a complete example.

Raycast

Copy the script commands from examples/raycast/ to your Raycast scripts directory:

cp examples/raycast/summon-*.sh ~/.config/raycast/scripts/

Shell aliases

Add to ~/.zshrc or ~/.bashrc:

alias st='summon terminal'
alias sb='summon browser'
alias se='summon editor'

See examples/shell-aliases.sh for more.

Other tools

Summon also works with Karabiner-Elements, Hammerspoon, Alfred, and AeroSpace. Any tool that can run a shell command can invoke summon <binding>.

License

Apache-2.0