Manage multiple Git identities from your macOS menubar — without touching your dotfiles.
简体中文 · English
keychord is a menubar-only macOS app that lets you keep several GitHub accounts on one machine — personal, work, open source — each with its own SSH key, git name/email, URL rewrites, and optional gitdir:-scoped activation. keychord owns a small JSON file and generates managed SSH config and gitconfig files; it injects a single Include line into your existing ~/.ssh/config and ~/.gitconfig. Your dotfiles stay yours.
Using more than one Git identity on the same Mac usually means either:
- hand-editing
~/.ssh/config+~/.gitconfig+~/.gitconfig-workand hoping you remember which alias togit clonewith, or - sprinkling
GIT_SSH_COMMANDeverywhere.
keychord makes the identity set a first-class thing you can CRUD from a window, and projects the result back into real config files in a way that is auditable, reversible, and leaves everything else you wrote by hand untouched.
- Account CRUD — add, edit, delete accounts from a native
NavigationSplitViewwindow. Source of truth:~/.config/keychord/accounts.json. gitdir:scoping — each account can be global or scoped to a working directory via git'sincludeIf gitdir:mechanism.- URL rewrites — per-account
insteadOf/pushInsteadOfrules land in the generated gitconfig. - Selective import — detect logical accounts from your current
~/.ssh/config+~/.gitconfig, then pick which ones to import via a checkbox sheet. Existing aliases are flagged and skipped automatically. - Doctor & Fixer — diagnose common config problems (missing keys, wrong permissions, dangling
Include, conflictingIdentityFile) and apply one-click fixes. - SSH port selection — per-account Direct 22 / SSL 443 toggle. Useful on networks where port 22 is blocked.
- SSH key generator — create an ed25519 or RSA key from the app with safe filenames and correct permissions.
- Atomic backups — every write is preceded by a snapshot of
accounts.jsonin~/.config/keychord/backups/, browsable from the Restore view. - iCloud Sync — optional sync of the account list across machines via
NSUbiquitousKeyValueStore. SSH keys stay local; only metadata travels. - Probes — per-host
ssh -T git@<alias>probes so you can see at a glance which accounts authenticate. - Menubar-only —
LSUIElement = YES. No dock icon, no window stealing focus. Drag a folder onto the menubar icon to resolve which account would push from there.
keychord never rewrites the body of your existing config files. Instead:
accounts.jsonis the source of truth.- On every save,
AccountProjectorwrites three flavors of managed files under~/.config/keychord/:ssh_config.managed— oneHostblock per accountgitconfig.managed— global[user], url rewrites,[includeIf]pointers for scoped accountsgitconfig-<uuid>.managed— one pergitdir:-scoped account, holding[user]+[core] sshCommand
IncludeInstallerinjects (once, idempotently) a marker-wrappedIncludeblock at the top of your real~/.ssh/configand~/.gitconfig:# --- keychord managed --- Include ~/.config/keychord/ssh_config.managed # --- keychord managed end ---- Everything outside the marker block is left exactly as you wrote it. Uninstalling is removing the marker block.
This means keychord plays nicely with hand-written config, dotfile managers, and home-manager.
- macOS 26.2 or later
- Apple Silicon
brew tap yangflow/keychord
brew install --cask keychordGrab the latest KeyChord-<version>.dmg from Releases, open it, and drag KeyChord.app to /Applications.
If the app is not notarized, clear the quarantine flag on first launch:
xattr -cr /Applications/KeyChord.app
open /Applications/KeyChord.appgit clone https://github.com/yangflow/keychord.git
cd keychord
open keychord.xcodeprojSelect the keychord scheme and ⌘R. Or build a standalone .app with the build script:
./scripts/build.sh
mv dist/KeyChord.app /Applications/The first launch creates ~/.config/keychord/ on demand; nothing is written to your real dotfiles until you click Save on an account.
xcodebuild test \
-scheme keychord \
-destination 'platform=macOS' \
-only-testing keychordTests \
CODE_SIGNING_ALLOWED=NOThe unit test suite covers the SSH config parser, the git config IO layer, AccountProjector, AccountsStore, AccountImporter, Doctor, Fixer, BackupService, and the keygen service.
- Click the menubar icon. The popover shows your accounts, Doctor diagnostics, and the current repo context.
- Click the + row at the bottom of the accounts list to add a new account (this opens the accounts window). Or click any account row to jump to its detail.
- In the accounts window, use the sidebar bottom bar to:
- + add a new account
- Key generate an SSH key
- Restore browse and restore backups
- Import detect accounts from existing config and selectively import
- iCloud configure cloud sync
- Fill in label, git name/email, SSH alias, key path, optional
gitdir:scope and URL rewrites. ⌘S saves. - Every save regenerates the managed files and reinstalls the
Includeline if it got wiped. - Back in the popover, the Doctor section surfaces any config problems with one-click fixes.
keychord/
├── keychord/ # App sources
│ ├── Models/ # Account, ConfigModel, Diagnosis
│ ├── Services/ # AccountsStore, AccountProjector,
│ │ # AccountImporter, IncludeInstaller,
│ │ # ConfigStore, Doctor, Fixer, Prober,
│ │ # BackupService, CloudSyncService,
│ │ # KeygenService, …
│ ├── Views/ # MenuBarContent, AccountsWindowView,
│ │ # AccountDetailView, AccountsSidebar,
│ │ # ImportPickerView, RestoreView,
│ │ # CloudSyncView, KeygenView, …
│ ├── AppDelegate.swift
│ └── AppState.swift
├── keychordTests/ # Swift Testing unit tests
├── keychordUITests/
├── scripts/ # build.sh, release.sh, generate-icon
└── keychord.xcodeproj
- Quit KeyChord from the menubar (power icon, or ⌘Q).
- Delete
/Applications/KeyChord.app. - Remove managed config (optional):
rm -rf ~/.config/keychord - Remove the
Includeblocks keychord injected — look for the# --- keychord managed ---markers in~/.ssh/configand~/.gitconfigand delete through# --- keychord managed end ---.
If installed via Homebrew: brew uninstall --cask keychord.
Maintainer workflow for cutting a release:
# 1. Build the DMG (unsigned / signed / notarized)
./scripts/release.sh 0.2.0
# 2. Create a GitHub release with the artifact
gh release create v0.2.0 \
--title 'KeyChord 0.2.0' \
dist/KeyChord-0.2.0.dmg
# 3. Update the Homebrew cask with the new version + SHA256
# (SHA256 is in dist/KeyChord-0.2.0.dmg.sha256)release.sh supports four modes via environment variables:
| Mode | Env vars | Result |
|---|---|---|
| unsigned | (none) | Ad-hoc signed DMG. Gatekeeper warns on first launch. |
| signed | DEVELOPER_ID_APPLICATION |
Developer ID signed DMG. |
| notarized | signed + APPLE_ID, APPLE_TEAM_ID, APPLE_APP_PASSWORD |
Notarized + stapled. Fully Gatekeeper-approved. |
| sparkle | notarized + SPARKLE_PRIVATE_KEY |
Also emits Sparkle Ed25519 signature for appcast.xml. |
Pull requests welcome — see CONTRIBUTING.md for build, test, and commit-message guidelines.
Bug reports and feature ideas go to GitHub Issues.
MIT © 2026 yangflow



