SkillAgentSearch skills...

Skhd.zig

Simple Hotkey Daemon for macOS, ported from skhd by koekeishiya

Install / Use

/learn @jackielii/Skhd.zig
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

SKHD in Zig

Simple Hotkey Daemon for macOS, ported from skhd to Zig.

This implementation is fully compatible with the original skhd configuration format - your existing .skhdrc files will work without modification. Additionally, it includes new features like process groups and command definitions (.define) for cleaner configs, key forwarding/remapping, and improved error reporting.

📋 View Changelog

Installation

Homebrew

The easiest way to install skhd.zig:

brew install jackielii/tap/skhd-zig

Pre-built Binaries

Download the latest release for your architecture:

  • skhd-arm64-macos.tar.gz - For Apple Silicon Macs
  • skhd-x86_64-macos.tar.gz - For Intel Macs

Extract and install:

tar -xzf skhd-*.tar.gz
sudo cp skhd /usr/local/bin/

Development Builds from GitHub Actions

If you need builds with different optimization levels (Debug, ReleaseSafe, ReleaseFast, ReleaseSmall), you can download them directly from GitHub Actions:

  1. Go to the CI workflow in Actions tab. Filter by branch main.
  2. Click on the latest successful run
  3. Scroll down to the "Artifacts" section
  4. Download the build artifact for your desired optimization level:
    • skhd-Debug - Debug build with full debugging symbols
    • skhd-ReleaseSafe - Release build with safety checks and runtime safety
    • skhd-ReleaseFast - Optimized for performance (recommended for daily use)
    • skhd-ReleaseSmall - Optimized for binary size

Build from Source

# Clone the repository
git clone https://github.com/jackielii/skhd.zig
cd skhd.zig

# Build in release mode
zig build -Doptimize=ReleaseFast

# Install (copy to /usr/local/bin)
sudo cp zig-out/bin/skhd /usr/local/bin/

Running as Service

After installation, run skhd as a service for automatic startup:

# Install and start the service
skhd --install-service
skhd --start-service

# Check if skhd is running properly
skhd --status

# Restart service (useful for restarting after giving accessibility permissions)
skhd --restart-service

# Stop service
skhd --stop-service

# Uninstall service
skhd --uninstall-service

The service will:

  • Start automatically on login
  • Create logs at /tmp/skhd_$USER.log
  • Use your config from ~/.config/skhd/skhdrc or ~/.skhdrc
  • Automatically reload on config changes

Features

Core Functionality

  • Event capturing: Uses macOS Core Graphics Event Tap for system-wide keyboard event interception
  • Hotkey mapping: Maps key combinations to shell commands with full modifier support
  • Process-specific bindings: Different commands for different applications
  • Key forwarding/remapping: Remap keys to other key combinations
  • Modal system: Multi-level modal hotkey system with capture modes
  • Configuration file: Compatible with original skhd configuration format
  • Hot reloading: Automatic config reload on file changes

Additional Features (New in skhd.zig!)

  • Process groups: Define named groups of applications for cleaner configs
  • Command definitions: Define reusable commands with placeholders to reduce repetition
  • Key Forwarding: Forward / remap key binding to another key binding
  • Mode activation with command: Execute a command when switching modes (e.g., cmd - w ; window : echo "Window mode")

Command-Line Interface

  • --version / -v - Display version information
  • --help - Show usage information
  • -c / --config - Specify config file location
  • -o / --observe - Observe mode (echo keycodes and modifiers)
  • -V / --verbose - Debug output with detailed logging
  • -k / --key - Synthesize keypress for testing
  • -t / --text - Synthesize text input
  • -r / --reload - Signal reload to running instance
  • -h / --no-hotload - Disable hotloading
  • -P / --profile - Profile event handling (Debug and ReleaseSafe builds only)

Service Management

  • --install-service - Install launchd service
  • --uninstall-service - Remove launchd service
  • --start-service - Start as service
  • --restart-service - Restart service
  • --stop-service - Stop service
  • PID file management (/tmp/skhd_$USER.pid)
  • Service logging (/tmp/skhd_$USER.log)

Advanced Features

  • Blacklisting: Exclude applications from hotkey processing
  • Shell customization: Use custom shell for command execution
  • Left/right modifier distinction: Support for lcmd, rcmd, lalt, ralt, etc.
  • Special key support: Function keys, media keys, arrow keys
  • Passthrough mode: Execute command but still send keypress to application
  • Config includes: Load additional config files with .load directive
  • Comprehensive error reporting: Detailed error messages with line numbers

Build Commands

# Build the project (creates executable in zig-out/bin/)
zig build

# Build in release mode with optimizations
zig build -Doptimize=ReleaseFast

# Run the application
zig build run

# Run with arguments
zig build run -- -V -c ~/.config/skhd/skhdrc

# Run tests
zig build test

Configuration & Usage

Default Configuration Locations

skhd.zig looks for configuration files in the following order:

  1. Path specified with -c flag
  2. ~/.config/skhd/skhdrc
  3. ~/.skhdrc

The configuration syntax is fully compatible with the original skhd. See SYNTAX.md for the complete syntax reference and grammar.

Configuration Directives

# Use custom shell (skips interactive shell overhead)
.shell "/bin/dash"

# Blacklist applications (skip hotkey processing)
.blacklist [
    "dota2"
    "Microsoft Remote Desktop"
    "VMware Fusion"
]

# Load additional config files
.load "~/.config/skhd/extra.skhdrc"

# Define process groups for reuse (New in skhd.zig!)
.define terminal_apps ["kitty", "wezterm", "terminal"]
.define native_apps ["kitty", "wezterm", "chrome", "whatsapp"]
.define browser_apps ["chrome", "safari", "firefox", "edge"]

# Define reusable commands with placeholders (New in skhd.zig!)
.define yabai_focus : yabai -m window --focus {{1}} || yabai -m display --focus {{1}}
.define yabai_swap : yabai -m window --swap {{1}} || (yabai -m window --display {{1}} && yabai -m display --focus {{1}})
.define toggle_app : open -a "{{1}}" || osascript -e 'tell app "{{1}}" to quit'
.define resize_window : yabai -m window --resize {{1}}:{{2}}:{{3}}
.define toggle_scratchpad : yabai -m window --toggle {{1}} || open -a "{{2}}"

Basic Hotkey Syntax

# Basic format: modifier - key : command
cmd - a : echo "Command+A pressed"

# Multiple modifiers
cmd + shift - t : open -a Terminal

# Different modifier combinations
ctrl - h : echo "Control+H"
alt - space : echo "Alt+Space"
shift - f1 : echo "Shift+F1"

Supported Modifiers

# Basic modifiers
cmd     # Command key
ctrl    # Control key
alt     # Alt/Option key
shift   # Shift key
fn      # Function key

# Left/right specific modifiers
lcmd, rcmd    # Left/right Command
lctrl, rctrl  # Left/right Control
lalt, ralt    # Left/right Alt
lshift, rshift # Left/right Shift

# Special modifier combinations
hyper   # cmd + shift + alt + ctrl
meh     # shift + alt + ctrl

Special Keys

# Navigation keys
cmd - left : echo "Left arrow"
cmd - right : echo "Right arrow"
cmd - up : echo "Up arrow"
cmd - down : echo "Down arrow"

# Special keys
cmd - space : echo "Space"
cmd - return : echo "Return/Enter"
cmd - tab : echo "Tab"
cmd - escape : echo "Escape"
cmd - delete : echo "Delete/Backspace"
cmd - home : echo "Home"
cmd - end : echo "End"
cmd - pageup : echo "Page Up"
cmd - pagedown : echo "Page Down"

# Function keys
cmd - f1 : echo "F1"
cmd - f12 : echo "F12"

# Media keys
sound_up : echo "Volume Up"
sound_down : echo "Volume Down"
mute : echo "Mute"
brightness_up : echo "Brightness Up"
brightness_down : echo "Brightness Down"

Process-Specific Bindings

# Different commands for different applications
cmd - n [
    "terminal" : echo "New terminal window"
    "safari"   : echo "New safari window"
    "finder"   : echo "New finder window"
    *          : echo "New window in other apps"
]

Key Forwarding/Remapping

# Keyboard layout fixes
0xa | 0x32             # UK keyboard § to `
shift - 0xa | shift - 0x32  # shift - § to ~

# Function key navigation (for laptop keyboards)
fn - j | down
fn - k | up
fn - h | left
fn - l | right

# When you have cmd - number for yabai spaces,
# and you still want the cmd - number to work in applications
ctrl - 1 | cmd - 1
ctrl - 2 | cmd - 2
ctrl - 3 | cmd - 3

Passthrough Mode

# Execute command but still send keypress to application
cmd - p -> : echo "This runs but Cmd+P still goes to app"

Modal Workflow with Visual Indicators

# Window management mode with anybar visual indicator
# Install anybar: brew install --cask anybar

# Define window management mode for warp/stack operations
# Use anybar to indicate the mode: https://github.com/tonsky/AnyBar
:: winmode @ : echo -n "red" | nc -4u -w0 localhost 1738
:: default : echo -n "hollow" | nc -4u -w0 localhost 1738

# Enter window mode with meh + m (shift + alt + ctrl + m)
meh - w ; winmode
winmode < escape ; default
winmode < meh - w ; default

# Alternative: Enter window mode AND show notification (New in skhd.zig!)
# This executes the command when switching to the mode
# It allows for different commands to execute and switch to another mode
meh - w ; winmode : osascript -e 'display notification "Window mode active" with title "skhd"'
winmode < escape ; default : osascript -e 'display notification "Normal mode" with title "skhd"'

# Focus operations - basic hjkl for focus
winmode < h : yabai -m window --focus west || yabai -m display --focus west
winmode < j : yabai -m window --focus south || yabai -m display --focus south
winmode < 
View on GitHub
GitHub Stars476
CategoryDevelopment
Updated2d ago
Forks11

Languages

Zig

Security Score

100/100

Audited on Mar 24, 2026

No findings