macOS menu bar utility that auto-corrects keyboard layout mistakes. Type in the wrong layout (English instead of Ukrainian/Russian) and SwitchFix detects it, deletes the mistyped word, switches the layout, and retypes the correct text — like PuntoSwitcher, but native and lightweight.
- Automatic correction — detects wrong-layout words on space/enter and corrects them instantly
- Hotkey mode — correct only when you press Ctrl+Shift+Space (configurable)
- Selection correction — select text and press the hotkey to convert it
- Undo — Cmd+Z within 5 seconds reverts the last correction
- Revert hotkey — CapsLock reverts the last correction (configurable)
- Three layouts — English (US/ABC/British/Dvorak/Colemak), Ukrainian, Russian
- Ukrainian variants — auto-detects and supports both Ukrainian and Ukrainian Legacy keymaps
- Smart filtering — skips password fields, URLs, emails, camelCase, mixed scripts
- App blacklist — disabled in terminals, IDEs, and code editors by default (toggle per app)
- Launch at Login — optional auto-start via SMAppService
- Confidence-based switching — delays layout switch for ambiguous short words
- Expanded Ukrainian dictionary — runtime
uk_UA.txtnow includes 2,958,567 normalized single-word entries - Binary dictionary loading — precompiled
.bindictionaries are packaged for faster startup paths
- macOS 13.0+
- Accessibility permission (prompted on first launch)
- Input Monitoring permission (prompted on first launch)
- Swift 5.9+ and Command Line Tools (for building from source)
Download the latest release from the Releases page.
- Open the downloaded
.dmgfile. - Drag
SwitchFix.appto your Applications folder. - Launch the app. You will need to grant both Accessibility and Input Monitoring permissions for it to work.
Note: Because this is a free, open-source app and is not signed with a paid Apple Developer certificate ($99/yr), macOS Gatekeeper will try to block it.
- If you see "App cannot be opened because the developer cannot be verified": Right-click (or Control-click) the app and choose Open.
- If you see "SwitchFix is damaged and can't be opened": Open your Terminal and run this command:
xattr -cr /Applications/SwitchFix.app
- Yes, users on macOS 13 can build and run the current app from source.
- Release artifacts are built on GitHub macOS 15 runners, but the app target is still macOS 13+.
- If a downloaded release does not launch on your Mac, build locally:
xcode-select --install
swift --version
scripts/build-app.sh
scripts/create-dmg.sh- macOS 12 and older are currently unsupported by this repository (minimum target is macOS 13 in
Package.swift).
# Debug build
swift build
# Run tests (standalone runner — no Xcode required)
swift run TestRunner
# Build .app bundle (ad-hoc signed)
scripts/build-app.sh
# Optional: use a stable signing identity to preserve TCC permissions across rebuilds
SWITCHFIX_CODESIGN_IDENTITY="Apple Development: Your Name (TEAMID)" scripts/build-app.sh
# Create DMG for distribution
scripts/create-dmg.shThe built app is at dist/SwitchFix.app.
If you use ad-hoc signing (default), macOS may treat each rebuilt app as a new binary and drop Accessibility/Input Monitoring approval.
Use:
scripts/regrant-permissions.shOr set SWITCHFIX_CODESIGN_IDENTITY when building so permissions remain stable across rebuilds.
The release workflow builds and uploads separate assets for Apple Silicon and Intel:
SwitchFix-arm64.dmgSwitchFix-intel.dmgSwitchFix-arm64.app.zipSwitchFix-intel.app.zipAppIcon.svg
The workflow runs on tag push (v*).
By default, CI builds are ad-hoc signed.
You can set signing identity in CI by configuring secrets:
SWITCHFIX_CODESIGN_IDENTITY(for exampleDeveloper ID Application: ...)APPLE_CERTIFICATE_P12_BASE64APPLE_CERTIFICATE_PASSWORD
When these secrets are present, the workflow imports the certificate and signs using SWITCHFIX_CODESIGN_IDENTITY.
- KeyboardMonitor installs a CGEventTap (listen-only) to capture keystrokes
- Characters accumulate in LayoutDetector's word buffer
- On word boundary (space, enter, tab), the buffer is checked:
- Convert the word to alternative layouts via LayoutMapper character tables
- Validate each conversion against dictionary indices (binary
mmapwhen available, text fallback otherwise) - Current dictionary sizes: EN
48,241, UK2,958,567, RU146,229single-word entries
- If a valid word is found in another layout, TextCorrector:
- Deletes the mistyped characters (+ boundary char) via CGEvent backspaces
- Switches the input source via TIS API
- Retypes the correct text via
keyboardSetUnicodeString - Retypes the boundary character (space/enter)
Sources/
├── SwitchFixApp/ # Entry point, AppDelegate (wires the pipeline)
├── Core/ # KeyboardMonitor, LayoutDetector, LayoutMapper,
│ # TextCorrector, InputSourceManager
├── Dictionary/ # DictionaryLoader, index abstractions, WordValidator
│ └── Resources/ # en_US.txt, uk_UA.txt, ru_RU.txt, overrides/
├── UI/ # StatusBarController, PreferencesManager
└── Utils/ # Permissions (AXUIElement), AppFilter, KeyCodeMapping,
# SystemHotkeyConflicts
SwitchFix lives in the menu bar with an Ab icon. The menu provides:
- Enable/Disable toggle
- Correction Mode — Automatic or Hotkey Only
- Conflict warning — shows when CapsLock is also used by macOS for input source switching
- Installed Layouts — shows all detected system layouts
- Launch at Login
- Quit
SwitchFix stores hotkeys in UserDefaults:
SwitchFix_hotkeyKeyCode+SwitchFix_hotkeyModifiersfor correction hotkey (default: Ctrl+Shift+Space)SwitchFix_revertHotkeyKeyCode+SwitchFix_revertHotkeyModifiersfor revert hotkey (default: CapsLock)
Examples:
# Set revert hotkey to CapsLock (no modifiers)
defaults write com.switchfix.app SwitchFix_revertHotkeyKeyCode -int 57
defaults write com.switchfix.app SwitchFix_revertHotkeyModifiers -int 0
# Set correction hotkey to Ctrl+Shift+Space
defaults write com.switchfix.app SwitchFix_hotkeyKeyCode -int 49
defaults write com.switchfix.app SwitchFix_hotkeyModifiers -int $((262144+131072))If SwitchFix observes that pressing CapsLock also triggers a macOS input-source switch, it shows a conflict warning in the menu.
SwitchFix logs key decisions via NSLog. Open Console.app and filter for [SwitchFix] to see:
- Discovered input sources at startup
- Dictionary loading (word counts, paths)
- Detection decisions (buffer contents, conversion results)
- Correction actions (deletion count, layout switch, typed text)
- App switching (allowed/blocked)
uk_UA.txtgrew from320,307(v0.0.2) to2,958,567single-word entries.- Multi-word phrases are intentionally filtered out from runtime
uk_UA.txt(kept at0). - Release bundles are larger now because
uk_UA.binis packaged for runtime lookup.
MIT
