A macOS menu-bar app that remaps keys using custom, user-defined rules — e.g.
⌥ + Numpad 5 → ↓ Down Arrow, or a key sequence like A , S , D → ↑.
Rules are created by recording the physical keys you press, persist to disk,
and are applied system-wide via a CGEvent tap.
Proof-of-concept. Ad-hoc signed, not notarized. macOS 13+.
- Chord remaps — modifier + key (⌥ + Numpad 5) → any other key.
- Sequence triggers — type keys in order (A → S → D within 1s) to fire one output.
- Record to capture — press the keys instead of guessing key codes; held modifiers show live while recording.
- Global toggle shortcut — record a hotkey (e.g. ⌃⌥⌘R) that turns remapping on/off from anywhere, even while it's off.
- Persists rules and shortcut to
~/Library/Application Support/KeyModifier/rules.json. - Menu-bar only (no dock icon).
- Download
KeyModifier-*.zipfrom the Releases page and unzip. - Move Key Modifier.app to
/Applications. - Because the build is ad-hoc signed (not notarized), clear the quarantine flag once:
xattr -dr com.apple.quarantine "/Applications/Key Modifier.app" - Open the app. A ⌨ icon appears in the menu bar.
The event tap cannot run without Accessibility permission. On first enable, the app opens System Settings → Privacy & Security → Accessibility — toggle Key Modifier on there. The app auto-starts the tap within ~1.5s of the grant (no restart needed). The menu shows a ⚠︎ warning until granted.
- Menu bar ⌨ → Edit Rules…
- Add Rule → next to Trigger click Record, then press your trigger.
- Single chord: hold ⌥ and press Numpad 5 → Done.
- Key sequence: press keys in order (e.g.
A S D) — each is added automatically — then Done.
- Next to Output click Record, then press the target key (e.g. ↓ Down).
- Save. Toggle Remapping: On from the menu.
In Edit Rules…, the Toggle shortcut row records a system-wide hotkey. Once set, pressing it anywhere flips remapping on/off — handy to disable quickly without opening the menu.
Requires the Swift toolchain (Command Line Tools is enough).
# Build the .app bundle (stable bundle identity for Accessibility permission)
./scripts/build-app.sh release
open "build/Key Modifier.app"
# Verify the pure engine (no Xcode required)
swift run kmverifyPush a tag matching release-v*.*.* and the GitHub Action in
.github/workflows/release.yml builds the app, zips it, and publishes a
downloadable GitHub Release:
git tag release-v0.1.0
git push origin release-v0.1.0Physical keypress
│
▼
CGEvent tap (EventTapController) ── reads keyCode + modifier flags
│
▼
SequenceMatcher.feed(key)
├─ toggle shortcut → flip remapping (always, even when off)
├─ passThrough → let the key reach the app
├─ swallow → part of an in-progress sequence
└─ fire(output) → swallow the trigger, post the output key
KeyModifierCore(library, verified):KeyEvent(normalized keystroke),RemapRule,RuleStore(JSON persistence + active-rule set), and the pureSequenceMatcherstate machine.KeyModifier(executable): the SwiftUI menu-bar app, the live CGEvent tap, Accessibility handling, and the key-recording editor.kmverify: a standalone check harness (full Xcode not required).
- Fn is not usable as a chord modifier — it's handled in keyboard firmware and doesn't surface reliably through a CGEvent tap. Use ⌘/⌥/⌃/⇧.
- Output is a single key(+modifiers), not a macro. (Trigger sequences are supported; sequence output is not.)
- Prefix shadowing: if one trigger is a prefix of another (
AandA , S), typing justAwaits for the sequence window before firing the short rule. - Ad-hoc signed: rebuilding changes the code identity, so macOS may re-ask for
Accessibility. Reset during development with
tccutil reset Accessibility com.poc.keymodifier.
Sources/
KeyModifierCore/ KeyEvent, KeyCodes, RemapRule, RuleStore, SequenceMatcher
KeyModifier/ App, MenuBar, EventTap, Permission, Recorder, Views
kmverify/ standalone engine check harness
scripts/
build-app.sh assembles Key Modifier.app
make-icon.swift renders the app icon
.github/workflows/
release.yml builds + publishes a release on release-v*.*.* tags
docs/ landing page