Automates Apple Notes via JXA. Use when asked to "create notes programmatically", "automate Notes app", "JXA notes scripting", or "organize notes with automation". Covers accounts/folders/notes, HTML bodies, queries, moves, and Objective-C/UI fallbacks for Notes.app automation on macOS.
automating-mac-apps for permissions, shell, and Objective-C/UI scripting patterns.automating-mac-apps skill (PyXA Installation section).automating-notes/references/notes-basics.md for complete specifier reference.name and HTML body; verify creation success..whose filters; batch delete/move as needed; check counts before/after operations.meetings/<company>/<date>-<meeting-title> and people/<first>-<last>/...; validate final structure.JXA (Legacy):
const Notes = Application("Notes");
// Ensure folder path exists, creating intermediate folders as needed
function ensurePath(acc, path) {
const parts = path.split("/").filter(Boolean);
let container = acc;
parts.forEach(seg => {
let f; try {
f = container.folders.byName(seg);
f.name(); // Verify access
} catch (e) {
// Folder doesn't exist, create it
f = Notes.Folder({ name: seg });
container.folders.push(f);
}
container = f;
});
return container;
}
try {
// Get iCloud account and ensure meeting folder exists
const acc = Notes.accounts.byName("iCloud");
const folder = ensurePath(acc, "meetings/Acme/2024-07-01-Review");
// Create new note in the folder
folder.notes.push(Notes.Note({
name: "Client Review",
body: "<h1>Client Review</h1><div>Agenda...</div>"
}));
console.log("Note created successfully");
} catch (e) {
console.error("Failed to create note: " + e.message);
}
PyXA (Recommended Modern Approach):
import PyXA
notes = PyXA.Notes()
def ensure_path(account, path):
"""Ensure folder path exists, creating intermediate folders as needed"""
parts = [p for p in path.split("/") if p] # Filter empty parts
container = account
for part in parts:
try:
# Try to find existing folder
folder = container.folders().by_name(part)
folder.name() # Verify access
except:
# Folder doesn't exist, create it
folder = notes.make("folder", {"name": part})
container.folders().push(folder)
container = folder
return container
try:
# Get iCloud account
account = notes.accounts().by_name("iCloud")
# Ensure meeting folder exists
folder = ensure_path(account, "meetings/Acme/2024-07-01-Review")
# Create new note in the folder
note = folder.notes().push({
"name": "Client Review",
"body": "<h1>Client Review</h1><div>Agenda...</div>"
})
print("Note created successfully")
except Exception as e:
print(f"Failed to create note: {e}")
PyObjC with Scripting Bridge:
from ScriptingBridge import SBApplication
notes = SBApplication.applicationWithBundleIdentifier_("com.apple.Notes")
def ensure_path(account, path):
"""Ensure folder path exists, creating intermediate folders as needed"""
parts = [p for p in path.split("/") if p]
container = account
for part in parts:
try:
folder = container.folders().objectWithName_(part)
folder.name() # Verify access
except:
# Create new folder
folder = notes.classForScriptingClass_("folder").alloc().init()
folder.setName_(part)
container.folders().addObject_(folder)
container = folder
return container
try:
# Get iCloud account
accounts = notes.accounts()
account = None
for acc in accounts:
if acc.name() == "iCloud":
account = acc
break
if account:
# Ensure meeting folder exists
folder = ensure_path(account, "meetings/Acme/2024-07-01-Review")
# Create new note
note = notes.classForScriptingClass_("note").alloc().init()
note.setName_("Client Review")
note.setBody_("<h1>Client Review</h1><div>Agenda...</div>")
folder.notes().addObject_(note)
print("Note created successfully")
else:
print("iCloud account not found")
except Exception as e:
print(f"Failed to create note: {e}")
.whose queries return expected results<h1>-<h3>, <b>, <i>, <u>, <ul>/<ol>/<li>, <div>/<p>/<br>, <a>.<script>, <style>, or event handlers to prevent XSS in rendered notes.</body> with extra HTML, or append when missing; validate HTML structure post-modification.automating-notes/references/notes-basics.mdautomating-notes/references/notes-recipes.mdautomating-notes/references/notes-advanced.mdautomating-notes/references/notes-dictionary.mdautomating-notes/references/notes-pyxa-api-reference.mdSearch for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer