Skip to content

Latest commit

Β 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

KeyChord Logo

KeyChord

Version macOS Swift

Switching apps should feel like playing chords β€” different key chords open different apps.

KeyChord is a high-performance, lightweight native macOS menu-bar app built around a simple design philosophy: making app switching like playing chords on a keyboard. Just as a musician plays different key chords to evoke different harmonies, KeyChord allows you to map unique key combinations ("chords") to instantly activate, toggle, or launch your target applications.

KeyChord uses Carbon global hotkeys and AppKit for application shortcuts, which require no macOS permissions. Optional individual-window shortcuts use Accessibility to focus or minimize a selected window. No Input Monitoring or Screen Recording is required.

CleanShot 2026-07-24 at 23 11 19@2x

🎡 Design Philosophy

KeyChord was born from a desire for seamless, muscle-memory-driven workflow navigation:

  • 🎹 Chords as Shortcuts: Map distinct key combinations (chords) to your essential apps. Hitting a chord instantly switches focus to that app.
  • 🎢 Musical Fluidity: Move between your code editor, terminal, browser, and notes with the natural rhythm of playing piano chords.
  • ⚑ Zero Friction: Application switching stays lightweight; optional window control runs only when setting up or using a window shortcut.

🌟 Key Features

  • ⚑ Instant App Switching: Activate or bring all windows of target applications to the front with configurable global hotkeys.
  • πŸ”„ Smart Window Toggling: Pressing the same hotkey while a target application is active automatically hides it.
  • πŸ›‘οΈ Optional Window Control: Application shortcuts need no permissions. Window shortcuts request Accessibility during setup.
  • βš™οΈ Native SwiftUI Settings: Comprehensive preferences panel to add/remove apps, record hotkeys, toggle launch-on-login, configure Dock & menu-bar icon visibility, and tune per-app activation rules.
  • πŸš€ Optional App Launching: Per-shortcut setting (launchIfNeeded) to optionally launch stopped target applications upon pressing their hotkey.
  • ⚠️ Conflict Detection & Migration: Built-in detection for running Keyboard Maestro instances and system hotkey collisions, with clear UI indicators.
  • πŸ› οΈ Rich Command-Line Interface: CLI support for configuration validation, hotkey collision probing, default config dumping, version inspection, and diagnostic self-tests.

πŸ“‹ Requirements

Requirement Specification
Operating System macOS 14.0 (Sonoma) or later
Developer Tools Swift 6.2+ with compatible Apple Command Line Tools or Xcode
Permissions None for app shortcuts; Accessibility for optional window shortcuts

πŸš€ Quick Start & Installation

1. Build & Run from Source

To run self-tests and start the application in development mode:

# Run internal self-tests
swift run KeyChord --self-test

# Launch KeyChord directly
swift run KeyChord

2. Package as a Native macOS Application

Use the provided packaging script to compile a universal Apple Silicon + Intel release and assemble a signed .app bundle. It checks the version, runs the packaged self-tests, verifies the signature and disk image, and produces SHA-256 checksums:

./scripts/package-app.sh

The compiled application bundle will be created at:

.build/KeyChord.app
.build/KeyChord-v1.3.0.dmg
.build/KeyChord-v1.3.0.zip
.build/KeyChord-v1.3.0-SHA256SUMS.txt

Note on Code Signing: The build script automatically signs the bundle using the first available local code-signing identity, falling back to ad-hoc signing (-) if none exists.


βš™οΈ Configuration

On initial execution, KeyChord creates a default configuration file at:

~/Library/Application Support/KeyChord/config.json

Individual-window shortcuts (v1.3.0)

  1. Open the windows you want to use, then choose Add Window (β‡§βŒ˜N) in KeyChord.
  2. If asked, enable KeyChord in System Settings β†’ Privacy & Security β†’ Accessibility and return to setup.
  3. Choose the application and one of its windows. Show Window brings it forward so you can identify it; return to KeyChord to finish.
  4. Give the shortcut a memorable name, click Record Shortcut, and press your key combination. If another KeyChord assignment uses it, choose Replace Shortcut… and confirm Replace and Save to reassign it. The previous assignment is cleared and disabled. Cancel keeps it unchanged.
  5. Choose Save Shortcut. Repeat to assign other windows of the same application different chords.

Press a window shortcut to focus it; press again to minimize only that window. Clear Press again to minimize for a focus-only shortcut. Application shortcuts retain their existing hide/launch behavior. If an entire app was hidden, restoring it may also reveal its other windows.

The selected window stays linked even when its title changes. By default, after it closes or KeyChord restarts, use Choose Window… in its row to reconnect. Optional exact-title reconnection works only when exactly one window in the same app matches. It may match a different window that reuses that title, so it is off by default. Empty titles cannot be used for automatic reconnection.

Window support depends on the application's Accessibility implementation. KeyChord reports unsupported operations and missing windows instead of hiding the whole app or opening a replacement window. Full-screen windows must leave full screen before minimizing; focus across Spaces follows macOS behavior. Window titles and app names are stored locally in the private configuration file, never in usage statistics. Statistics remain aggregated per application.

For isolated manual QA, run KeyChord --preview-settings. It starts with an empty temporary configuration; only shortcuts created in that preview are registered. Build disposable test windows with ./scripts/build-window-fixture.sh and open .build/KeyChord Window Fixture.app.

Adding the first window shortcut upgrades the configuration to version 2. Older KeyChord releases reject version 2 instead of interpreting window shortcuts as whole-app shortcuts. Existing application-only version-1 files still load unchanged.

Configuration Schema

{
  "version": 1,
  "settings": {
    "showDockIcon": true,
    "showMenuBarIcon": true,
    "launchAtLogin": false
  },
  "shortcuts": [
    {
      "id": "finder",
      "name": "Finder",
      "bundleIdentifier": "com.apple.finder",
      "key": "1",
      "modifiers": ["option"],
      "enabled": true,
      "launchIfNeeded": true,
      "hideWhenFrontmost": true,
      "activateAllWindows": true
    }
  ]
}

Configuration Fields

  • settings:
    • showDockIcon: Toggles visibility of the application in the macOS Dock.
    • showMenuBarIcon: Toggles visibility of the status item in the menu bar.
    • launchAtLogin: Configures automatic startup via SMAppService.
  • shortcuts[]:
    • id: Unique identifier string for the shortcut entry.
    • name: Display label shown in the UI and menu.
    • bundleIdentifier: macOS bundle identifier for target application (e.g., com.apple.finder).
    • key: Key character or code representation.
    • modifiers: Array of modifier strings ("command", "control", "option", "shift").
    • enabled: Boolean toggle to enable or disable the shortcut.
    • launchIfNeeded: If true, launches target application when it is not currently running.
    • hideWhenFrontmost: If true, pressing hotkey when target app is active hides the app.
    • activateAllWindows: If true, brings all app windows to front; if false, brings front window only (application mode).
    • windowTarget: Optional object with bindingID (UUID), title, applicationName, and reconnectByTitle (Boolean). Omit for application mode. Use the window picker to create it; a UUID alone cannot locate a live window. Window mode ignores launchIfNeeded and activateAllWindows and uses hideWhenFrontmost to control minimizing.

Security & Validation: Configuration files are strictly validated before registering hotkeys. Malformed, duplicate, or invalid definitions fail closed, leaving shortcuts safely unregistered without crashing.


πŸ’» Command-Line Options (CLI)

KeyChord includes utility flags for automation, diagnostics, and testing:

Flag Description
-v, --version Display application name and version details
--show-settings Force open the settings window on launch
--probe-hotkeys Test hotkey registration against system conflicts without starting the app loop
--validate-config <PATH> Validate a specified config.json file for structural correctness
--print-default-config Output default configuration JSON to stdout
--self-test Execute internal diagnostic and behavioral unit tests

Examples

# Check version
KeyChord --version
# Output: KeyChord v1.3.0 (build 6)

# Test shortcut registration for system conflicts
KeyChord --probe-hotkeys

# Validate custom configuration file
KeyChord --validate-config ~/Desktop/my_config.json

πŸ”„ Migrating from Keyboard Maestro

If migrating from Keyboard Maestro:

  1. Parallel Execution: Both Keyboard Maestro and KeyChord can temporarily receive the same hotkey, which may cause activation races.
  2. Conflict Warnings: KeyChord displays a migration banner in the status menu when Keyboard Maestro Engine is detected running.
  3. Completing Migration: Disable your Keyboard Maestro App switcher macro group or quit the Keyboard Maestro Engine once KeyChord is tested and configured.

πŸ“ Repository Structure

key-chord/
β”œβ”€β”€ Package.swift               # Swift Package Manager manifest
β”œβ”€β”€ README.md                   # Project documentation
β”œβ”€β”€ Sources/
β”‚   └── KeyChord/
β”‚       β”œβ”€β”€ AppDelegate.swift   # App lifecycle, menu item & Dock management
β”‚       β”œβ”€β”€ ApplicationSwitcher.swift # Window activation & hide engine
β”‚       β”œβ”€β”€ ConfigurationStore.swift  # Config storage & JSON persistence
β”‚       β”œβ”€β”€ HotKeyManager.swift # Carbon global hotkey registration
β”‚       β”œβ”€β”€ Models.swift        # Data models, validation & version info
β”‚       β”œβ”€β”€ SelfTest.swift      # Built-in diagnostic test suite
β”‚       β”œβ”€β”€ SettingsView.swift  # SwiftUI settings panel & preferences
β”‚       β”œβ”€β”€ SettingsViewModel.swift # Settings state manager
β”‚       β”œβ”€β”€ SettingsWindowController.swift # Settings window manager
β”‚       β”œβ”€β”€ ShortcutRecorder.swift # Key recorder control
β”‚       └── main.swift          # Entry point & CLI argument parser
β”œβ”€β”€ packaging/
β”‚   β”œβ”€β”€ AppIcon.png             # Application logo image
β”‚   β”œβ”€β”€ AppIcon.icns            # macOS ICNS icon bundle
β”‚   └── Info.plist              # macOS App bundle property list
└── scripts/
    └── package-app.sh          # Build & code-signing script

πŸ§ͺ Testing

To run internal self-tests for hotkey handling, shortcut key code resolution, application state toggling, and configuration validation:

swift run KeyChord --self-test

πŸ“„ Versioning

Current Version: 1.3.0 (Build 6)

Changes in v1.3.0:

  • Added individual-window shortcuts with an Add Window wizard, preview, naming, and optional Accessibility access. App shortcuts remain permission-free.
  • Added focus/minimize toggling for the selected window and explicit reconnection after a window closes or KeyChord restarts.
  • Added confirmation before replacing conflicting KeyChord assignments. Cancellation and failed saves preserve existing assignments.
  • Fixed Remove Shortcut crashing after a row was removed due to stale array-index bindings.
  • Updated the English, Chinese, and Japanese landing page with an interactive window demo and accurate permission and privacy details.
  • Package both Apple Silicon and Intel in one universal app, with packaged self-tests, version validation, and SHA-256 checksums.

Upgrade note: Adding the first window shortcut saves configuration schema 2. Existing app-only schema-1 configurations still load. Older releases cannot read schema 2; preserve a copy of your app-only configuration before adding window shortcuts if you may need to downgrade. See v1.3.0 release notes for compatibility details.

Changes in v1.2.0:

  • Added usage statistics: KeyChord now counts the chords it handled itself, with a Statistics pane in settings (today, daily average, 30-day total, per-app leaderboard and a 14-day chart).
  • Counters live in a separate usage.json (0600), are kept for 30 days and pruned on every write; no new macOS permissions are required.
  • Added a Record usage statistics toggle to turn the counters off entirely.
  • Added an app icon resource, richer Info.plist metadata and versioned .zip / .dmg output from the packaging script.
  • Added a Statistics section to the landing page.

Changes in v1.1.2:

  • Reopen a window when activating a running app whose windows were all closed, matching the behaviour of clicking its Dock icon.
  • Added self-test coverage for the workspace reopen path.

Changes in v1.1.1:

  • Added an immediate conflict dialog when assigning a shortcut already used by another app.
  • Added one-click shortcut reassignment that disables the previous owner and enables the new one.
  • Kept validation errors visible in the fixed save bar while scrolling the application list.
  • Simplified Keyboard Maestro conflict detection by making its warning automatic.

Changes in v1.1.0:

  • Added native SwiftUI settings window with shortcut recorder.
  • Added support for launch at login, menu bar / Dock visibility settings.
  • Added per-app window activation & hide controls.
  • Added --version CLI flag and centralized version management.

About

Fast native macOS menu-bar app for global hotkey app-switching and window toggling without Accessibility permissions.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages