Help us improve
Share bugs, ideas, or general feedback.
From mac
Authors JXA (JavaScript for Automation) scripts for macOS app automation using Application() calls. Covers ES5 syntax constraints, run() function structure, for-loops, properties(), and .whose() filtering.
npx claudepluginhub bendrucker/claude --plugin macHow this skill is triggered — by the user, by Claude, or both
Slash command
/mac:jxaThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
JavaScript for Automation (JXA) automates macOS apps via the `Application()` bridge. It runs on JavaScriptCore (ES5).
Executes JXA scripts scoped to macOS applications via osascript. Validates Application() scope via AST analysis. Use for running JavaScript automation on apps like Finder or Safari.
Automates macOS apps via Apple Events using AppleScript (discovery), JXA (legacy), and PyXA (modern Python). Use when asked to "automate Mac apps", "write AppleScript", "JXA scripting", "osascript automation", or "PyXA Python automation". Foundation skill for all macOS app automation.
Sets up hot-reload workflow for JXA scripts automating Apple Notes on macOS, with chokidar file watching, osascript runner, and test helpers for note CRUD.
Share bugs, ideas, or general feedback.
JavaScript for Automation (JXA) automates macOS apps via the Application() bridge. It runs on JavaScriptCore (ES5).
var (not let/const).map(), .filter(), .forEach())run() (not an object)// WRONG: JXA arrays don't have .map()
// var names = app.windows().map(function(w) { return w.name(); });
// CORRECT: use a for-loop
var windows = app.windows();
var names = [];
for (var i = 0; i < windows.length; i++) {
names.push(windows[i].name());
}
Script files define a function run(argv) entry point. osascript calls it automatically and prints the return value. The function must be named run, not _run.
#!/usr/bin/env osascript -l JavaScript
function run(argv) {
var finder = Application("Finder");
var items = finder.desktop.items();
var names = [];
for (var i = 0; i < items.length; i++) {
names.push(items[i].name());
}
return JSON.stringify(names);
}
properties() for batch reads instead of individual getters.whose() for filtering when the app supports it (pushes work to the app)Application.currentApplication() accesses the current app contextsdef /Applications/AppName.app