KeyPath is Kanata made easy for macOS.
Kanata is a powerful, cross-platform keyboard remapping engine that can transform your keyboard into exactly what you need. However, using Kanata on macOS requires navigating a maze of technical challenges:
- Driver installation via command line
- Permission debugging (TCC, Input Monitoring, Accessibility)
- Service management (launchd, LaunchDaemons, SMJobBless)
- Configuration syntax written by hand in Kanata's DSL
- Code signing & notarization for system-level access
- Debugging when things go wrong
KeyPath eliminates all of this complexity while preserving Kanata's full power. You get enterprise-grade keyboard remapping with consumer-grade ease of use.
Before KeyPath: To remap keys on macOS with Kanata, you need to:
- Install the Karabiner VirtualHID driver manually
- Understand macOS security frameworks (TCC)
- Configure launchd services with root privileges
- Write Kanata configuration files in a custom syntax
- Debug permission issues, service conflicts, and connectivity problems
- Handle code signing and notarization for system components
With KeyPath: Click record, press keys, click save. Done.
KeyPath is a complete macOS integration layer that:
- โ Handles all system setup automatically
- โ Provides a beautiful, native SwiftUI interface
- โ Manages permissions, services, and drivers
- โ Generates Kanata configurations from visual recordings
- โ Offers intelligent troubleshooting and diagnostics
- โ Ensures reliable operation with proper system integration
No configuration files, no command line, no technical knowledge required.
- Click "Record Input"
- Press the key(s) you want to remap
- Click "Record Output"
- Press what you want it to do
- Click Save
Your remapping is active immediatelyโno restart, no manual service management, no file editing.
- Hot reload - Changes apply instantly via localhost TCP (JSON; default port 37001)
- System integration - Runs as LaunchDaemon, works at boot time
- Crash recovery - Automatic service restart and conflict resolution
- Health monitoring - Real-time status checks and diagnostics
- Emergency stop - Press
Ctrl + Space + Escto immediately disable all remappings - Permission wizard - Guided setup handles all macOS security requirements
- Conflict detection - Automatically detects and resolves system conflicts
- No telemetry - Works completely offline, no data collection
- Beautiful SwiftUI interface with Liquid Glass design (macOS 15+)
- System Settings integration - Follows macOS design patterns
- Proper signing & notarization - Works with macOS security features
- Accessibility support - Respects macOS accessibility settings
Built on proven patterns (inspired by Karabiner-Elements):
- LaunchDaemon architecture - Reliable system-level service management
- SMAppService-managed daemon - Kanata always runs via SMAppService; KeyPath auto-reinstalls the service if it disappears, so helper restarts never fall back to legacy plists
- File-based configuration - Simple, debuggable, hot-reloadable
- Single source of truth - PermissionOracle prevents inconsistent state
- State-driven wizard - Handles 50+ edge cases automatically
Option 1: Download Release (Recommended)
- Download from the Releases page
- Open
KeyPath.app - Follow the setup wizard
Option 2: Build from Source
git clone https://github.com/malpern/KeyPath.git
cd KeyPath
# Canonical build (builds, signs, notarizes, deploys to ~/Applications, restarts app)
./build.shTroubleshooting builds locally
- To skip notarization during local iteration:
SKIP_NOTARIZE=1 ./build.sh - To dry-run signing/notary invocations without touching Apple services: set
KP_SIGN_DRY_RUN=1(used in CI smoke tests too)
The build script automatically:
- Compiles the Swift package
- Signs all components with Developer ID
- Notarizes the app bundle
- Verifies the bundled SMAppService plist points at
kanata-launcher(no legacy launchctl fallback) - Installs to
~/Applications/ - Restarts the app
When you first launch KeyPath, the Installation Wizard will guide you through:
- Permission Setup - Grants Input Monitoring and Accessibility permissions
- Driver Installation - Installs Karabiner VirtualHID driver if needed
- Service Configuration - Sets up LaunchDaemon services
- System Validation - Verifies everything is working correctly
The wizard handles all technical setup automatically and provides one-click fixes for common issues.
If you're already using Kanata on macOS, KeyPath can run your existing configuration with minimal changes. See the Migration Guide for details on bringing your own config (BYOC).
Quick path: Copy your config to ~/Library/Application Support/KeyPath/keypath.kbd, add (include keypath-apps.kbd) at the top, and run the setup wizard.
-
Record Input: Click the record button next to "Input Key"
- Press a single key (e.g., Caps Lock)
- Or a key combo (e.g., Cmd+Space)
- Or a sequence (e.g., press A, then B, then C)
-
Record Output: Click the record button next to "Output Key"
- Press what you want it to do (e.g., Escape)
- Or a combo (e.g., Cmd+C for copy)
- Or type multiple keys (e.g., "hello world")
-
Save: Click Save - your mapping is now active!
| Feature | Description |
|---|---|
| Flexible Input | Record single keys, combos (Cmd+C), or sequences (AโBโC) |
| Flexible Output | Map to single keys, combos, or entire phrases |
| Visual Recording | See exactly what keys you're pressing in real-time |
| Keyboard Overlay | Live overlay with selectable physical layout and keymap labels (QWERTY/Colemak-DH/etc) |
| Instant Apply | Changes work immediately - no restart needed |
| Safety Features | Emergency stop (Ctrl+Space+Esc) prevents getting locked out |
| Smart Setup | Installation wizard handles all technical setup automatically |
| Native macOS UI | Beautiful SwiftUI interface with Liquid Glass design (macOS 15+) |
| Feature | Description |
|---|---|
| Tap-Hold (Dual-Role) | Keys that do one thing when tapped, another when held (e.g., home-row mods) |
| Tap-Dance | Keys that do different things based on tap count (single, double, triple) |
| Complex Mappings | Chain multiple actions from a single trigger |
| Hot Reload | Edit config files directly, changes apply instantly via TCP (localhost, default 37001) |
| System Integration | Runs as LaunchDaemon at startup, works everywhere |
| Extensive Logging | Debug issues with detailed logs and diagnostics |
| Full Kanata Power | Access to all of Kanata's remapping capabilities |
| Configuration Access | Edit Kanata configs directly if needed |
| Service Health Dashboard | Visual helper/SMAppService/driver status with one-click fixes |
- Caps Lock โ Escape - Essential for Vim users
- Right Cmd โ Delete - Easier reach for frequent deleters
- F1-F12 โ Media Keys - Volume, brightness, playback control
- Broken Key Workaround - Remap a broken key to a working one
- Home Row Mods - Turn home row keys (A, S, D, F) into modifiers when held, letters when tapped
- Hyper Key - Turn Caps Lock into Cmd+Ctrl+Alt+Shift combo
- Tap-Dance Caps - Single tap for Escape, double tap for Caps Lock
- App Launchers - Map key sequences to launch favorite apps
- Text Snippets - Type your email address with a key combo
- Gaming - Create custom key combinations for complex moves
- Workflows - Map one key to perform multiple actions in sequence
KeyPath isn't just a wrapper around Kanataโit's a complete macOS integration layer that solves real problems:
- PermissionOracle - Single source of truth for all permission detection
- Handles macOS TCC (Transparency, Consent, Control) complexity
- Detects permission issues before they cause problems
- Provides one-click fixes for common permission problems
- Installs and manages Karabiner VirtualHID driver
- Handles code signing and notarization for all components
- Manages LaunchDaemon services and lifecycle
- Resolves conflicts with other keyboard remappers automatically
- Converts visual key recordings into valid Kanata configuration
- Handles complex modifier combinations and sequences
- Generates optimized Kanata configs automatically
- No need to learn Kanata's configuration syntax
- LaunchDaemon architecture ensures remappings work at boot time
- Automatic crash recovery and conflict resolution
- Health monitoring with real-time status checks
- Hot reload via TCP for instant configuration updates
- Localhost-only TCP (port 37001); Kanata's TCP server currently has no authโfuture releases may add token-based TCP authentication
- SMAppService-managed Kanata daemon with a packaged launcher guarantees absolute config paths and Login Items approval flow
- Built-in system state detection
- Automatic log analysis and error interpretation
- Visual permission status with fix suggestions
- Real-time service health monitoring
- Swift 6.0 - Modern Swift concurrency (async/await, actors)
- SwiftUI - Native macOS UI with Liquid Glass design
- Kanata - Cross-platform keyboard remapping engine
- LaunchDaemon - System-level service management
- Karabiner VirtualHID - macOS HID driver for system-level remapping
If your keyboard becomes unresponsive, press Ctrl + Space + Esc simultaneously. This immediately disables all remappings and restores normal keyboard functionality.
KeyPath needs two macOS permissions to work:
- Input Monitoring - To detect key presses
- Accessibility - To send remapped keys
The setup wizard guides you through granting these permissions with one-click access to System Settings.
- IPC runs over localhost TCP (default port 37001); Kanata's TCP server currently ignores authentication messages.
- Threat model: any local process could trigger reloads/status calls; scope is limited to config reload + diagnostics (no arbitrary code execution).
- Future: plan to add token-based TCP authentication when upstream Kanata exposes it (mirroring the UDP auth flow).
For stable TCC permissions, LaunchDaemon services use the system-installed kanata binary:
/Library/KeyPath/bin/kanata
The helper keeps this binary updated from the bundled copy when needed and ensures proper ownership/permissions. The bundled binary inside KeyPath.app is not used by LaunchDaemons.
- โ No internet connection required (offline by default; optional AI config generation contacts Anthropic if ANTHROPIC_API_KEY is present)
- โ No data collection or telemetry
- โ No modification of system files
- โ No kernel extensions
- Check macOS version - Requires macOS 15.0 (Sequoia) or later
- Run setup wizard - Go to File โ Run Setup Wizard
- Check logs - View system logs:
tail -f /var/log/kanata.log
- Check status indicator - Look for green checkmarks in the app
- Verify permissions - Ensure permissions granted in System Settings
- Use Fix Issues - Click "Fix Issues" button in the app for automated fixes
- ๐ FAQ - Frequently asked questions
- ๐ Debugging Guide - Advanced troubleshooting
- ๐ง Helper Troubleshooting - SMAppService issues
- ๐ฌ GitHub Issues - Report bugs or ask questions
Xcode 26 beta test runner crash (Swift 6.2)
If you're using Xcode 26.0 beta, swift test can crash with SIGABRT after tests pass. Use the workaround:
./run-tests-workaround.shOur main test runners (./test.sh and ./Scripts/run-tests-safe.sh) already include this workaround.
- macOS 15.0 (Sequoia) or later
- Apple Silicon or Intel Mac
- Kanata - The remapping engine (bundled with app)
- Karabiner VirtualHID Driver - For system-level key events
The setup wizard automatically checks for these and helps you install them if needed.
- Open KeyPath
- Choose File โ Uninstall KeyPathโฆ (you can also open Settings โ Advanced โ Uninstall KeyPathโฆ)
- Confirm the admin prompt and let the bundled uninstaller remove LaunchDaemons, helper tools, and the app bundle.
sudo ./Scripts/uninstall.sh
# or for automation:
sudo ./Scripts/uninstall.sh --assume-yesThis removes:
- LaunchDaemon services
- System binaries
- Configuration files
- Application bundle
When running outside the repository, the same script is bundled at KeyPath.app/Contents/Resources/uninstall.sh and can be invoked directly.
We welcome contributions! KeyPath is designed to make keyboard remapping accessible to everyone, and contributions help make it better.
# Clone the repository
git clone https://github.com/malpern/KeyPath.git
cd KeyPath
# Build and test (development)
swift build
swift test
# Production-like build & deploy (recommended for real testing)
./build.sh
mkdir -p ~/Applications && cp -R dist/KeyPath.app ~/Applications/
osascript -e 'tell application "KeyPath" to quit' || true
open ~/Applications/KeyPath.appSee CONTRIBUTING.md for detailed guidelines, architecture overview, and contribution patterns.
- Architecture Overview - Deep dive into system design and architecture decisions
- Tap-Hold & Tap-Dance Guide - Advanced key behaviors (dual-role, tap-dance)
- Contributing Guide - How to contribute to KeyPath
- Debugging Guide - Advanced troubleshooting and diagnostics
- FAQ - Frequently asked questions
MIT License - see LICENSE for details.
- Unit & integration tests:
./Scripts/run-tests-safe.shโ configures an isolated module cache (.build-ci/ModuleCache.noindex) so SwiftPM never tries to write to~/.cache(which can be blocked on shared machines). - Full developer suite:
./test.shโ wraps the safe runner and then executes the higher-level integration scripts. - CI-full replicator:
CI_INTEGRATION_TESTS=true ./Scripts/archive/run-core-tests.shโ runs the Unit, Core, and IntegrationTestSuite buckets defined inrun-core-tests.sh; by default the CI runs withCI_INTEGRATION_TESTS=false, so set this flag manually (or adjust CI) when you need the deeper installer/privileged coverage to execute alongside unit/core tests. - SMAppService sanity check:
./Scripts/verify-kanata-plist.shโ use before distributing a build (CI runs it againstSources/KeyPath/com.keypath.kanata.plist).
If swift test ever complains about ~/.cache/clang/ModuleCache, just use the safe runner above or pass -Xcc -fmodules-cache-path=$(pwd)/.build/ModuleCache.noindex manually.
KeyPath stands on the shoulders of giants:
- Kanata - The powerful keyboard remapping engine that powers KeyPath
- Karabiner-Elements - VirtualHID driver and architectural inspiration
- SwiftUI - For the beautiful, native macOS experience
- macOS Security Team - For the robust security frameworks that make safe keyboard remapping possible
If KeyPath helps you, consider โญ starring the repo!
KeyPath makes Kanata's power accessible to everyoneโno command line required.
