Macotron

macotron.app

List running apps, launch or switch to an app by bundle ID, hide or quit it, and choose a command from its menu bar. Apps are named by bundle ID, such as com.apple.Safari.

macotron.keyboard.on("Open Calendar", "ctrl+opt+c", () => {
  macotron.app.launch("com.apple.iCal");
});

Running apps

list(): Array<{ name: string; bundleID: string; pid: number }>

Every running process that has a bundle ID, which includes background apps and menu bar apps. name is the app's display name.

frontmost(): { name: string; bundleID: string; pid: number } | null

The app in front. Macotron itself is skipped: while a Macotron panel or the launcher has focus, this returns the app that was in front before it. Returns null when there is no such app yet.

Installed apps

path(bundleID: string): string | null

Where the app with that bundle ID is installed, such as "/Applications/Safari.app", or null when Launch Services knows no such app. The app does not have to be running.

info(path: string): { bundleID, name, version, build, path } | null

Reads the app bundle at path. version is the version users see (CFBundleShortVersionString) and build the build number (CFBundleVersion); either is null when the bundle does not declare it. Returns null when path is not a bundle. Each call reads the bundle from disk, so an app that has updated reports its new version.

const path = macotron.app.path("com.apple.Safari");
const info = path && macotron.app.info(path);
console.log(info?.name, info?.version);

For other keys in an app's Info.plist, read it with macotron.plist.

Launching and switching

launch(bundleID: string): boolean

Brings the app to the front, opening it first if it is not running. When the app is already running with windows, Macotron activates it directly, which is fast. A menu bar app goes through Launch Services instead, so it gets the reopen event it uses to show its window or panel.

It returns false when no app with that bundle ID is installed, and true otherwise.

switch(bundleID: string): boolean

The same as launch().

Hiding and quitting

Omit the bundle ID to act on the frontmost app. Macotron never counts itself as the frontmost app here.

hide(bundleID?: string): boolean

Hides the app, like Command-H. Returns false when the app is not running.

quit(bundleID?: string): boolean

Asks the app to quit, like Command-Q. The app can still show a save dialog or refuse. Returns false when the app is not running or does not accept the request.

Chooses a menu bar item, such as ["File", "New Window"]. Omit the bundle ID to use the frontmost app.

Each name must match the item's title exactly, in the app's language. A trailing … or ... is optional, so "Save As" matches Save As…. Returns true when the item was pressed, and false when the app is not running or a name in the path does not match.

menu() needs Accessibility permission. Without it, every call returns false.

macotron.app.menu(["View", "Enter Full Screen"], "com.apple.Safari");

Events

All three events carry { name, bundleID, pid }. None fires for Macotron itself.

app:activated

Fires when an app comes to the front.

app:launched

Fires when an app starts.

app:terminated

Fires when an app quits.

macotron.on("app:activated", ({ bundleID }) => {
  if (bundleID === "com.apple.dt.Xcode") macotron.notify.toast("Focus time");
});

See also