Developer Documentation

KeyPath

A macOS app for keyboard remapping, powered by Kanata. SwiftUI frontend, LaunchDaemon backend, live keyboard overlay.

What KeyPath Does

KeyPath gives users a visual way to remap their keyboard without writing config files. Under the hood, it generates Kanata configuration and manages a LaunchDaemon that runs the Kanata engine.

Remap

Visual key remapping with tap-hold, layers, and macros

Install

Guided wizard for permissions, helper, and daemon setup

Visualize

Live floating overlay showing real-time key state

Launch

App launcher, URL opener, and script runner from any key

SWIFTUI APP KeyPath.app FACADE InstallerEngine SYSTEM SERVICE LaunchDaemon ENGINE kanata TCP events FLOATING WINDOW Overlay USER CONFIG ~/.config/keypath/keypath.kbd The app generates Kanata config, the daemon runs it, and TCP events flow back for visualization.
The core loop is simple: the user remaps keys in the SwiftUI UI, KeyPath generates a Kanata config file, the LaunchDaemon picks it up (via TCP reload), and key events flow back through the overlay for visualization. The installation wizard ensures all system components (privileged helper, daemon plist, permissions) are in place before any of this can work.

Deep Dives

Each guide covers one major subsystem in detail: how it works, why it's designed that way, and what not to break.
Installation Wizard Ready
Three types, two pure functions, one loop. The wizard inspects the system, finds what's wrong, shows the page for the first unresolved issue, and offers a button to fix it. Covers SystemInspector, WizardRouter, and InstallerEngine integration.
Live Keyboard Overlay Ready
The floating keyboard visualization window. Seven focused extension files, two input streams (CGEvent tap + Kanata TCP), the three-guard visibility model, and the inspector drawer. Includes screenshot and data flow diagram.
Runtime & Service Lifecycle Ready
How Kanata starts, stops, and recovers. The RuntimeCoordinator, ServiceLifecycleCoordinator, ServiceHealthChecker, and KanataDaemonService. Health polling, TCP readiness, crash recovery, and the "installer success requires verified runtime readiness" invariant.
PermissionOracle & System Detection Ready
The permission detection system. Why Apple APIs are authoritative over TCC database, how IOHIDCheckAccess works, the fallback chain, and the critical invariant that makes the wizard's permission pages reliable.
Rule Collections & Config Generation Ready
How user remappings become Kanata config. The RuleCollection pattern, ConfigurationService, custom rules vs. keymap collections, the "never parse Kanata configs" principle, and TCP-based hot reload.
Privileged Helper & XPC Ready
The privileged helper tool that installs the LaunchDaemon. SMAppService registration, XPC communication, code signing requirements, and the HelperProtocol.swift duplication invariant (ADR-018).
Keyboard Layouts & Device Detection Ready
Physical layout definitions, logical keymaps, per-device configuration via defcfg conditional switch, HIDDeviceMonitor, and the "geometry follows layout, labels follow keymap" rendering principle.
KindaVim & Vim Mode Ready
The Vim-style navigation mode. Kanata layer definitions for motions and operators, the hint overlay for learning, the state adapter that bridges Kanata events to Vim concepts, and the keystream observer for feedback.

Getting Oriented

The essentials for your first day in the codebase.
Build (dev)
./Scripts/quick-deploy.sh — incremental build, deploys to /Applications
Build (release)
./build.sh — sign + notarize (SKIP_NOTARIZE=1 for local)
Tests
swift test — 413 tests, all must pass in under 5 seconds
Lint
swiftformat Sources/ Tests/ --swiftversion 5.9 && swiftlint --fix --quiet
User config
~/.config/keypath/keypath.kbd — generated Kanata config
Debug log
~/Library/Logs/KeyPath/keypath-debug.log
Daemon plist
com.keypath.kanata — managed via SMAppService
ADRs
docs/adr/ — 37 architecture decision records
Bug investigations
docs/bugs/ — root cause analyses with timestamps and evidence
Before you change anything: read CLAUDE.md at the project root. It has the critical anti-patterns, the manager class responsibilities, and the validation architecture. The ADRs explain why things are the way they are — if you're tempted to "simplify" something, check if there's an ADR explaining why it's complex.

Swift Packages

The codebase is organized into focused Swift packages. Most of the action is in KeyPathAppKit.
KeyPathAppKit
The main app module. UI, controllers, services, managers. ~50K lines.
KeyPathInstallationWizard
Installation/repair wizard. SystemInspector, WizardRouter, page views. ~18K lines.
KeyPathWizardCore
Shared protocols and DI container for wizard dependencies.
KeyPathCore
Subprocess runner, admin commands, core utilities. ~3K lines.
KeyPathHelper
Privileged helper process. XPC service, daemon installation.
KeyPathInsights
Activity logging, telemetry, usage analytics.
KeyPathDaemonLifecycle
Service lifecycle coordination. Start/stop/restart sequencing.
KeyPathLayoutTracer
Kanata config parsing for layout visualization (simulator mode).