Security
A plugin runs with all of Macotron's access: your files, the shell, the network, and every permission you granted. Macotron's protection is about which code runs. It makes sure no plugin runs, or changes, without your approval.
What an enabled plugin can do
Enabling a plugin is the same as running its code yourself. In particular:
macotron.shell.runruns any command through/bin/zsh. There is no allowlist and no prompt for each command.macotron.fsreads and writes files with Macotron's access.macotron.httpsends data anywhere.- The
permissionsa plugin declares are a request, not a limit. Macotron cannot stop a plugin from using an API it did not declare.
So read a plugin, or have your agent explain it, before you approve it, and approve only code from a source you trust.
Approval and hashes
Macotron keeps a ledger of the SHA-256 hash of every plugin file you approved. The ledger lives in the macOS Keychain, apart from plugin secrets, so no plugin can read or change it.
- At launch, a plugin runs only if its bytes match the approved hash.
- When a running plugin's file changes, the new bytes do not run. The copy already in memory keeps running until the next reload or restart; after that, the plugin stays stopped until you review it. The Macotron menu says how many plugin files changed and offers Review & Reload.
- A new file in
plugins/waits too, with Review & Load. Macotron posts a notification when one appears.
This is what stops another program from quietly editing a plugin to run its own code. Files that a plugin imports go through the same check.
The review sheet
Reviewing a changed or new plugin opens a sheet with its title, its description, the permissions it declares, and View Source…. Macotron also scans the code:
- On macOS 26 with Apple Intelligence on, the on-device model reads the code three times, looking for harmful behavior.
- Static checks flag
eval(), reading the Keychain and sending HTTP in the same file, runningcurlorwgetin a shell, and comments that try to talk to the scanner.
A clean scan makes Load (or Reload) the default button. When a check fails, or the model is not available, the button reads Run Anyway. The scan is advice, not a gate: you decide. Approving records the new hash.
Built-in plugins ship inside the signed app, so adding one from the catalog skips the scan. Scan Anyway runs it on demand.
Hot Reload
Hot Reload skips the hash check and the scan. Every save loads at once. It is for writing plugins, and it is off by default.
- Turn it on with Enable Hot Reloading in the Macotron menu, or Settings → General → Hot Reload.
- While it is on, the menu bar icon has an orange reload badge and the menu says Hot Reload is on — plugins load without a scan.
- Only you can turn it on, from the menu or Settings. A released build of Macotron has no other switch for it.
Turn it off when you finish, so a later change to a file has to be approved again.
The block list
Macotron downloads a published list of SHA-256 hashes of known-bad plugin code at launch, and keeps a copy on disk, so it works offline too. A blocked file does not load, does not install, and cannot be approved with Run Anyway, even with Hot Reload on.
Secrets
Keep API keys in a password option, which Settings stores in the Keychain, or in macotron.keychain. settings.json holds only a reference to the Keychain item, so you can commit it. Never put a key in plugin source, localStorage, or git.
Links from other apps
Any app or web page can open a macotron:// link. Macotron asks before it passes one to a plugin, and shows the link and the app that sent it. If you write a plugin that handles links, treat every part of the link as untrusted input.
The background helper
Fan control needs root, so Macotron can install a helper that runs as root. It installs only when you select Install… and approve it in System Settings, and you can remove it from Settings → Permissions. See Permissions.
Updates
Macotron updates are signed. It installs an update only when the signature matches the public key inside the copy you already have, so a hijacked download cannot replace it. See Updates.