Written from the source of Keysi 1.0.30, October 2026.
Keysi is closed source and will stay that way. An app that asks for Accessibility access deserves more than “trust me”, so this page does the next best thing. It lists every call Keysi makes with that permission, every network request, and every file outside its own folder that it reads, and then shows you how to watch each one happen on your own Mac instead of taking my word for it. Every claim below was checked against the code, not remembered.
What is collected when you opt in to analytics, and how feedback is handled, is on the privacy page. This page is the technical inventory behind it.
These are all of them. The calls are Apple’s public Accessibility API; nothing here is private or undocumented.
| What Keysi does | The macOS call | Why, and when |
|---|---|---|
| Checks whether you have granted access | AXIsProcessTrusted, AXIsProcessTrustedWithOptions |
To know whether it can start. The system prompt appears once, on first run. |
| Reads the menu bar of the app in front | AXUIElementCreateApplication, AXUIElementCopyAttributeValue for AXMenuBar and AXChildren. For each menu item: AXRole, AXTitle, AXEnabled, AXIdentifier and the key-equivalent attributes (AXMenuItemCmdChar, …CmdVirtualKey, …CmdGlyph, …CmdModifiers, …MarkChar) |
This is the product: the list of shortcuts. It runs when you hold the trigger key or open the panel, and for Practice, an export, or a Shortcuts or Siri action you started. Each read is capped at a fraction of a second so a stuck app can’t hang Keysi. |
| Presses a menu item | AXUIElementPerformAction with AXPress |
Click-to-run. Only when you click a row in Keysi’s overlay. This is the one thing Keysi does to another app. |
| Hears that a menu opened or closed | AXObserverCreate, AXObserverAddNotification for AXMenuOpened, AXMenuClosed and AXSelectedChildrenChanged, on the app in front |
Shortcut Coach uses it to time your menu trips and to notice a command you picked by hand. As you move the highlight in an open menu it reads that one item: its title, its key equivalent and the names of the menus above it. With Coach off (Settings ▸ Coach) the notifications are ignored and nothing is read. |
| Looks at what is under the pointer | AXUIElementCopyElementAtPosition, AXUIElementGetPid, AXParent |
When you release a mouse button while one of the front app’s menus is open, to learn which command you chose. It checks the element’s role first and discards it unless it is a menu item belonging to that app. For a menu item it reads the title, the key equivalent and the names of the menus above it. In an app that refuses menu notifications it makes that check on every click in the app instead, and discards the same things. |
| Reads a terminal’s window title | AXFocusedWindow, AXTitle |
Only when the app in front is a known terminal (Terminal, iTerm2, Ghostty, Warp, Alacritty, WezTerm, kitty, Hyper, Tabby, or one you added). With Vim in one tab and a bare prompt in another, the title helps pick which program’s sheet to show. It is compared in memory and then dropped: not stored, not logged, not sent. |
Holding a modifier to open the overlay means Keysi has to notice a key
held down in other apps. It does that with Apple’s global event
monitors (NSEvent.addGlobalMonitorForEvents) for modifier
changes, key presses, mouse buttons and scrolling. A global monitor can
observe an event but cannot consume, change or inject one. Keysi installs
no event tap (CGEventTapCreate appears nowhere in it) and
posts no key or mouse events (nor CGEventPost).
What it does with what it observes:
CGEventSource.keyState), which holds key codes and no
characters, to catch a key a monitor can’t see, such as one
another app has claimed as a hotkey. Under secure input, such as a
password field, macOS does not report the key to Keysi at all, and the
overlay shows a lock.AXValue,
AXSelectedText or any document attribute, and it uses no
screen-capture API, so it never needs Screen Recording. It never reads
the clipboard. It only writes to it when you press a Copy button. The
one time it receives text is when you pick “Search Shortcuts in
Keysi” from the Services menu, which hands it your selection.The networking code is in three places: the licence check, the feedback sender, and two open-source libraries, Sparkle (updates) and PostHog (analytics), whose code you can read. There are no others, and no embedded web views.
| Request | Host | When | What is sent | Off switch |
|---|---|---|---|---|
| Update check (Sparkle) | keysi.io, the file appcast.xml |
Once a day while Keysi runs, and when you choose Check for Updates | A plain request for a static file. Sparkle’s User-Agent names Keysi and its version. Keysi does not turn on Sparkle’s system profile, so nothing about your Mac is added. If you accept an update, the signed download comes from keysi.io/releases and is verified against a key built into the app before it installs. |
Settings ▸ Updates |
| Licence check | api.gumroad.com |
Only if you have entered a licence key: when you activate it, then at most once a week. A free or trial install makes no request. | The product id and your licence key, to Gumroad’s licence endpoint, plus whether this counts as an activation. Nothing about your Mac. | Deactivate This Mac, or don’t enter a key |
| Usage analytics | eu.i.posthog.com, and PostHog’s config host eu-assets.i.posthog.com |
Only after you opt in. The library isn’t even started until you do. | The anonymous events listed on the privacy page, under a random install id that is discarded when you turn it off. Never a licence key, a shortcut’s name or a menu. | Off by default. Settings ▸ General |
| Feedback message | eu.i.posthog.com |
Only when you press Send in the feedback form (or when a message queued while you were offline goes out on the next start). | Exactly the payload the form shows you first. Nothing is sent in the background. | Don’t press Send |
Links in Keysi that open keysi.io pages, the checkout or the changelog open in your browser. They are not requests Keysi makes. This website has its own analytics, off until you accept its banner, described on the privacy page.
Keysi reads these and changes none of them. Everything it stores goes to
~/Library/Application Support/Keysi/, its own preferences
(me.manulorenzo.Keysi), the Keychain item that holds your
licence, a Spotlight index entry for each custom sheet if you use them, and
wherever you choose to save an export.
| What | Where | Why, and when |
|---|---|---|
| macOS’s own shortcuts | ~/Library/Preferences/com.apple.symbolichotkeys.plist |
To warn you when macOS will grab a shortcut first, and to list the system shortcuts. |
| Raycast’s and Rectangle’s hotkeys | ~/Library/Preferences/com.raycast.macos.plist, ~/Library/Preferences/com.knollsoft.Rectangle.plist |
To warn you when one of their hotkeys swallows a shortcut. Only while that app is running. Keysi reads the file and uses only the hotkey settings. |
| App Shortcuts you set in System Settings | The NSUserKeyEquivalents key in the front app’s own preferences, read through macOS |
To show a menu command you remapped. Nothing else in those preferences is read. |
| Your editor keymaps |
VS Code and forks (Cursor, Windsurf, VSCodium and others): ~/Library/Application Support/<editor>/User/keybindings.jsonJetBrains IDEs and Android Studio: ~/Library/Application Support/JetBrains/<product><version>/ (or Google/), the options/keymap.xml file and the active keymap in keymaps/Xcode: ~/Library/Developer/Xcode/UserData/KeyBindings/, and Xcode’s setting that names the active setSublime Text and Sublime Merge: ~/Library/Application Support/<Sublime Text | Sublime Text 3 | Sublime Merge>/Packages/User/Default (OSX).sublime-keymap (or Default.sublime-keymap)Zed: ~/.config/zed/keymap.jsonFinal Cut Pro: the command set in ~/Library/Application Support/Final Cut Pro/Command Sets/ that Final Cut’s “Active Command Set” setting names
|
To show the bindings you changed that an app’s menus can’t show. Only when that app is the one in front. For an editor Keysi has not been told about, it looks for the same folder under the app’s own name. |
| Vim and Emacs config | ~/.vimrc, ~/.vim/vimrc, ~/.config/nvim/init.vim, ~/.emacs.d/init.el, ~/.config/emacs/init.el, ~/.emacs |
The first one that exists, only when Vim, Neovim or Emacs is the running program in the terminal in front. Keysi reads the file in memory and uses only the key-mapping lines. |
| The sync folder, if you turn Sync on | The folder you choose in Settings ▸ Sync (by default ~/Library/Mobile Documents/com~apple~CloudDocs/Keysi in iCloud Drive) |
Off until you turn it on. Keysi reads and writes its own keysi-sync-*.json files there: your custom sheets, favourites, hidden shortcuts and appearance and trigger settings. Moving them between Macs is iCloud Drive’s (or your sync app’s) job; Keysi makes no network request for it. |
| Which programs are running | The process list (sysctl), the running-apps list and the front app |
To find the foreground program in a terminal, to know whether Raycast or Rectangle is running, and to name the app that turned on secure input. Process names and parent links only. Nothing is stored. |
Whether Raycast, Alfred and the keysi command are set up |
Application lookup by bundle id; the existence of a keysi link in /usr/local/bin, /opt/homebrew/bin, ~/.local/bin and ~/bin |
Only when you open the Integrations window, so it can show what is installed. File contents aren’t read. |
| Files you choose | Anything you pick in an Open or Save panel | Importing a sheet, exporting shortcuts. Keysi sees only what you pick. |
Keysi starts two programs, and no others. It runs its own executable with
a flag that asks a fresh process whether Accessibility is granted, because
the answer inside a running app can be stale. And if you press the repair
button after macOS keeps a stale entry, it runs
/usr/bin/tccutil reset Accessibility me.manulorenzo.Keysi,
which clears Keysi’s own entry and nobody else’s.
Nothing below needs my help or my build tools. Each command is yours to run.
Apple’s Gatekeeper verdict. Expect accepted and source=Notarized Developer ID.
spctl -a -vv /Applications/Keysi.app
The signature details. Expect TeamIdentifier=2357A78TMR, an
Authority=Developer ID Application line ending in that same
team id, and flags=0x10000(runtime), which is the hardened
runtime.
codesign -dv --verbose=4 /Applications/Keysi.app
That nothing has been altered since it was signed, and that Apple’s notarization ticket is attached:
codesign --verify --deep --strict --verbose=2 /Applications/Keysi.app && xcrun stapler validate /Applications/Keysi.app
The entitlements should print nothing. The usage descriptions should be the two named above.
codesign -d --entitlements - /Applications/Keysi.app
plutil -p /Applications/Keysi.app/Contents/Info.plist | grep -i UsageDescription
Use a firewall that shows connections per app, such as Little Snitch or
LuLu (free and open source). Leave analytics off and expect keysi.io
and, if you have entered a licence key, api.gumroad.com, and
nothing else. Deny both and everything in the free tier keeps working;
updates and the licence check simply don’t happen. Without a firewall,
ask macOS for Keysi’s open connections:
lsof -a -i -n -P -c Keysi
Keysi writes its own log, by category (AX, Hold, License, Updates and so on). Watch it live while you hold ⌘, open a menu or run a shortcut:
log stream --level info --predicate 'subsystem == "me.manulorenzo.Keysi"'
Everything Keysi stores lives in two places. Open them and read them; they are JSON and a preferences domain.
ls -l ~/Library/Application\ Support/Keysi/
defaults read me.manulorenzo.Keysi
System Settings ▸ Privacy & Security ▸ Accessibility lets you switch Keysi off at any time. Without it Keysi cannot read another app’s menus or see a key held, and it says so rather than guessing.
Keysi has not had an independent security review. The checks above are how you can verify it without one, and if you need a review for your organization, tell me and I will support it.
If anything here is wrong, or you find Keysi doing something this page doesn’t say, email support@keysi.io. I answer myself, and a mismatch between this page and the app is a bug in one of them.