Build a plugin

A Minibar plugin ("MiniApp") is a folder with a manifest.json and one JavaScript file. It runs inside a sandboxed JavaScriptCore virtual machine in a separate process, renders a small declarative UI tree, and can nominate one line of text for the menu bar slot.

  1. Scaffold

    From a checkout of the repository. The CLI validates the manifest, renders the plugin once with the real runtime, and packs it for distribution.

    swift run minibar-cli init ./hello --id com.example.hello --name "Hello"
    swift run minibar-cli validate ./hello
    node tools/jsharness/run.js ./hello      # render once with a mock host, any OS
    swift run minibar-cli pack ./hello --out hello.zip
  2. Write render() and actions

    render(ctx) returns a title for the menu bar and a body of UI nodes. Buttons call actions; host calls such as ctx.http and ctx.storage are synchronous and go through the permissions the user granted.

    // hello/main.js
    defineMiniApp({
      render(ctx) {
        const count = ctx.storage.get('count', 0);
        return {
          title: { text: 'Hello ×' + count, icon: 'hand.wave' },
          body: [
            ctx.ui.text('Rendered at ' + ctx.now().toLocaleTimeString(ctx.locale)),
            ctx.ui.button('Bump', 'bump'),
          ],
        };
      },
      actions: {
        bump(ctx) { ctx.storage.set('count', ctx.storage.get('count', 0) + 1); },
      },
    });
  3. Link the folder

    Settings › Plugins › Link Plugin Folder… (also in the menu bar's right-click menu). Minibar watches the folder and reloads the plugin on every save, keeping its data, settings and grants.

  4. Publish and submit

    Publish the folder to npm (npm publish --access public; nothing in package.json runs). Then request a listing: the exact version is scanned, rendered under the mock host and reviewed before the signed index pins its name, version and hash.

    node tools/jsharness/scan.js --strict ./hello    # the registry rules, including package.json
    node tools/jsharness/run.js ./hello --locale zh-CN
    npm publish --access public                      # the exact tarball the index will pin

What a plugin can ask for

Every permission is declared in the manifest, explained before installation and revocable in Settings. Anything not listed here does not exist: no shell, no arbitrary files, no AppleScript.

PermissionWhat it allows
Network
network
Fetch data from the websites listed in the plugin's allowed hosts.
Notifications
notifications
Show notifications (at most one per minute).
Calendar
calendar
Read your upcoming calendar events, and add an event when you tap a button.
Reminders
reminders
Read your open reminders; add or complete one when you tap a button.
Location
location
Use your approximate location.
Clipboard
clipboard
Read the text currently on your clipboard.
Files
files
Read the files and folders you pick in a file dialog. Only what you choose; you can forget any of them in the plugin's settings.
System actions
system
Free up memory, run one of your Shortcuts or keep the Mac awake, only when you tap a button in the plugin.
Other apps
apps
See which apps are running; open apps and the URL schemes listed in the plugin's manifest when you tap a button.