Macotron

Plugin settings

macotron.plugin() describes a plugin to Settings: its name, what it does, the permissions it needs, and the options a user can change. It returns the current option values.

const opts = macotron.plugin({
  title: "Chat",
  description: "Talk to a model",
  help: "Set an API key below for cloud models.",
  permissions: ["accessibility"],
  options: {
    model: {
      type: "dropdown", label: "Model", default: "sonnet",
      choices: [
        { value: "sonnet", label: "Claude Sonnet" },
        { value: "opus", label: "Claude Opus" },
      ],
    },
    apiKey: { type: "password", label: "Anthropic API key", required: true },
    openHotkey: { type: "keybinding", label: "Open chat", default: "cmd+shift+c" },
  },
});

console.log("chat: model =", opts.model);

Metadata

FieldWhat it does
titleThe plugin's name in Settings → Plugins and the catalog.
descriptionOne sentence under the title.
helpExtra explanation on the plugin's Settings page.
permissionsThe macOS permissions the plugin needs. See below.
optionsSettings the user can change. See below.

Put the call at the top of the file and write title and description as plain string literals. Settings reads them from the first part of the file without running it, so it can show a plugin that is disabled or still waiting for approval.

Permissions

List what the plugin needs, and Macotron adds those permissions to the Permissions tab and to the plugin's own page:

NameNeeded for
accessibilityMoving and focusing windows, reading other apps' UI
inputMonitoringWatching keys, mouse, and trackpad gestures
screenRecordingCapturing the screen
cameraThe camera, such as scanning a QR code
microphoneRecording audio
calendarReading calendar events
helperPrivileged work through the background helper, such as fan control

A declaration is a request, not a sandbox. Macotron cannot limit a plugin to what it declared. Permissions explains each one.

Options

Each key in options becomes a row on the plugin's page in Settings → Plugins. The user edits the value there, and macotron.plugin() returns it under the same key. Changing a value reloads plugins, so the plugin reads the new value at load.

TypeControl in SettingsValue
stringText fieldString
textMulti-line text areaString
booleanCheckboxBoolean
numberNumber field, or a slider when min and max are both setNumber
dropdownPop-up menu from choices: [{ value, label }]The chosen value
keybindingShortcut recorderA combo such as "cmd+shift+c"
passwordSecure field with Set and ClearThe secret, or ""
fileChoose… button for a fileAbsolute path
directoryChoose… button for a folderAbsolute path
calendarsA checkbox for each of the user's calendarsArray of calendar names; needs Calendars access first

Every option takes these fields:

Text, number, password, file, and directory options also take placeholder, the grey hint shown while the field is empty. It is read at load, so it can show live state:

locale: { type: "string", label: "Locale", placeholder: macotron.system.locale().language },

A number option with min and max also takes step.

Secrets

A password option keeps its value in the macOS Keychain. settings.json stores only a reference to the Keychain item, so the file is safe to commit. macotron.plugin() returns the secret itself. Never write a key into plugin source or settings.json.

Checks

A plugin can report a problem it found, such as a blocked system feature, with macotron.checks(). A failed check puts an orange warning on the plugin in Settings → Plugins and a row in its Checks section. Each call replaces the list, and [] clears it.

macotron.checks([
  { title: "Speed control", ok: false, message: "This Mac blocked fan-speed writes." },
]);

macotron.settings.open() opens the plugin's own page in Settings.

The plugin page

Each plugin's page in Settings → Plugins shows, where they apply:

See also