ideas.
June 05, 2026 3 min read desktopsolo-devautomation

Global hotkey manager for shell commands and webhooks

A cross-platform desktop app where developers bind system-wide keyboard shortcuts to shell commands, HTTP webhooks, or app launches, configured via a plain JSON file.

The idea

A desktop app that runs in the system tray and lets you bind global keyboard shortcuts to three types of actions: run a shell command, fire an HTTP request, or launch an application. You define the bindings once in a GUI, the config is persisted as a plain JSON file, and every shortcut fires from anywhere on the desktop regardless of which window has focus. Hot-reload means editing the JSON directly is just as valid as using the GUI.

Why build this

Power users on macOS have Keyboard Maestro and BetterTouchTool. On Linux the ecosystem is a patchwork of window-manager-specific configs, sxhkd scripts, and xdotool incantations that break across distros. Windows has AutoHotkey but it requires learning a bespoke scripting language to do anything non-trivial. Across all three platforms, the gap is the same: no tool treats HTTP webhooks as a first-class trigger type.

Developers who run n8n, Home Assistant, or local dev servers have no clean way to bind a global shortcut to an HTTP call without wrapping it in a shell script and losing all context about what it does. The demand for this is visible in every "how do I trigger my webhook from a keyboard shortcut" thread across Reddit and HN, and the standard answer is still "write a shell script and bind it with your window manager."

Tauri reached stable v2 in late 2024 and its plugin ecosystem — including tauri-plugin-global-shortcut — now covers macOS, Linux, and Windows from one codebase, making the cross-platform implementation practical where it was previously painful.

Stack sketch

  • Desktop shell: Tauri v2 (Rust + WebView2/WebKit) — smaller binary than Electron, native system tray support, stable global hotkey registration via tauri-plugin-global-shortcut
  • UI: React + Vite inside the Tauri WebView; plain forms, no component framework needed
  • HTTP actions: reqwest (Rust, async) with configurable method, URL, headers, and an optional JSON body supporting {{clipboard}} and {{timestamp}} interpolation
  • Shell actions: std::process::Command with optional working directory; stdout and stderr captured and shown in the in-app event log
  • Config: ~/.config/hotkey-runner/config.json — plain JSON, version-controllable, hot-reloaded via the notify file-system watcher crate within one second of a change
  • System tray: right-click menu listing active bindings and a toggle to pause all shortcuts temporarily

Scope for v1

  • Add, edit, and delete bindings through a GUI form — combo picker, action type selector, and action-specific fields
  • Three action types: shell command, HTTP request, app launch
  • Starts with the system at login; system tray is the only persistent UI surface
  • Config hot-reload: edits to config.json take effect without restarting the app
  • In-app event log showing the last 50 trigger fires with timestamp, shortcut name, action, and exit code or HTTP status code
  • macOS and Linux only for v1; Windows support once global-shortcut behavior there is validated

Deliberately out of scope for v1: action chaining, conditional logic, secrets management, a GUI import/export flow.

Where it could go

Action chaining is the most natural extension — one hotkey fires a sequence of actions with configurable delays between them. Combined with named variables defined in the config and substituted into shell and HTTP actions at fire time, this gives developers a lightweight no-code scripting layer that lives entirely in a single JSON file and requires no separate automation platform.

A second direction is a community config repository. Since the format is plain JSON, sharing a set of bindings is a gist or a git clone. A small index site listing packs by category — Docker management, CI triggers, Home Assistant integrations, media controls — lowers the barrier to adoption significantly. Users install the app, import a pack, and get immediate value before writing a single custom binding. That network effect is what separates a useful tool from a widely-adopted one.

Watch out for

Global shortcut registration fails silently on many systems when another app or the OS has already claimed the same combo. Register each binding individually at startup, catch failures per-binding, and surface them explicitly in both the event log and the tray icon tooltip. A binding that silently does nothing is the worst possible failure mode for a tool whose entire value is reliability.