automating-notes

Automating Apple Notes (JXA-first, AppleScript discovery)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "automating-notes" with this command: npx skills add spillwavesolutions/automating-mac-apps-plugin/spillwavesolutions-automating-mac-apps-plugin-automating-notes

Automating Apple Notes (JXA-first, AppleScript discovery)

Relationship to the macOS automation skill

  • Standalone for Notes; reuse automating-mac-apps for permissions, shell, and Objective-C/UI scripting patterns.

  • PyXA Installation: To use PyXA examples in this skill, see the installation instructions in automating-mac-apps skill (PyXA Installation section).

Core framing

  • Notes uses an AEOM hierarchy: Application → Accounts → Folders → Notes (with nested folders).

  • Load: automating-notes/references/notes-basics.md for complete specifier reference.

Workflow (default)

  • Resolve account/folder explicitly (iCloud vs On My Mac); validate existence and permissions.

  • Ensure target path exists (create folders if needed); handle creation failures gracefully.

  • Create notes with explicit name and HTML body ; verify creation success.

  • Query/update with .whose filters; batch delete/move as needed; check counts before/after operations.

  • For checklists/attachments, use clipboard/Objective-C scripting if dictionary support is insufficient; test fallbacks.

  • For meeting/people workflows, file notes under meetings/<company>/<date>-<meeting-title> and people/<first>-<last>/... ; validate final structure.

Quickstart (ensure path + create)

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": "&#x3C;h1>Client Review&#x3C;/h1>&#x3C;div>Agenda...&#x3C;/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_("&#x3C;h1>Client Review&#x3C;/h1>&#x3C;div>Agenda...&#x3C;/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}")

Validation Checklist

  • Account access works (iCloud vs On My Mac)

  • Folder creation and path resolution succeeds

  • Note creation with valid HTML body completes

  • Note appears in Notes UI

  • .whose queries return expected results

  • Error handling covers missing accounts/folders

HTML & fallbacks

  • Allowed tags: <h1>-<h3> , <b> , <i> , <u> , <ul>/<ol>/<li> , <div>/<p>/<br> , <a> .

  • Security: Always sanitize HTML input; avoid <script> , <style> , or event handlers to prevent XSS in rendered notes.

  • Checklists/attachments: Objective-C/clipboard fallback (Cmd+Shift+L for checklist, paste image via NSPasteboard + System Events).

  • Append helper: replace </body> with extra HTML, or append when missing; validate HTML structure post-modification.

When Not to Use

  • Cross-platform note taking (use Notion API, Obsidian, or Markdown files)

  • iCloud sync operations requiring status feedback (limited API support)

  • Non-macOS platforms

  • Rich formatting beyond supported HTML tags

  • Collaborative editing workflows (no multi-user support)

What to load

  • Basics & specifiers: automating-notes/references/notes-basics.md

  • Recipes (create/move/query/ensure path/checklists): automating-notes/references/notes-recipes.md

  • Advanced (HTML body rules, attachments/UI, JSON import/export, ObjC bridge): automating-notes/references/notes-advanced.md

  • Dictionary/type map: automating-notes/references/notes-dictionary.md

  • PyXA API Reference (complete class/method docs): automating-notes/references/notes-pyxa-api-reference.md

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

automating-calendar

No summary provided by upstream source.

Repository SourceNeeds Review
General

automating-keynote

No summary provided by upstream source.

Repository SourceNeeds Review
General

automating-powerpoint

No summary provided by upstream source.

Repository SourceNeeds Review