summon-switcher 0.2.0

A tiny macOS command-line tool for opening, focusing, and cycling applications from declarative keybindings.
docs.rs failed to build summon-switcher-0.2.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

Homebrew

brew install liamwh/summon-switcher/summon-switcher

Cargo

cargo install summon-switcher

From source

Builds from the repo and installs to ~/bin, also starting 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

Settings

These can be set globally under [settings], or overridden per binding.

  • cycle_when_focused (bool, default false) — when the app is already focused, cycle to its next window.
  • launch_if_not_running (bool, default false) — launch the app if it isn't running. (The summon app <app> shorthand forces this on.)
  • open_window_when_empty (bool, default false) — open a new window if summon brings the app to the foreground but it has none open. Currently Finder-only.
  • focus_strategy ("recent-window", default) — focus strategy. Only recent-window is supported.
[bindings.finder]
app = "com.apple.finder"
open_window_when_empty = true

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.

With open_window_when_empty = true (Finder for now), summon also opens a new window whenever it brings the app to the foreground but the app has no windows — so pressing your Finder binding with no window open creates one, like Cmd+N.

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