Security

What Keysi can see, and what it sends

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.

The short version

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.

Every Accessibility call, and why

These are all of them. The calls are Apple’s public Accessibility API; nothing here is private or undocumented.

What Keysi doesThe macOS callWhy, 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.

Watching keys and clicks

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:

What Keysi never does

Every network request

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.

RequestHostWhenWhat is sentOff 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.

Every file outside its own folder that Keysi reads

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.

WhatWhereWhy, 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.json
JetBrains 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 set
Sublime 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.json
Final 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.

Check it yourself

Nothing below needs my help or my build tools. Each command is yours to run.

That it is the signed, notarized build

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

That it asks for nothing else

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

What it sends

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

What it is doing right now

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"'

What it keeps

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

And the off switch

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.

Independent review

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.

Found something?

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.