Claude-skill-registry automating-notes
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.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/automating-notes" ~/.claude/skills/majiayu000-claude-skill-registry-automating-notes && rm -rf "$T"
manifest:
skills/data/automating-notes/SKILL.mdsource content
Automating Apple Notes (JXA-first, AppleScript discovery)
Relationship to the macOS automation skill
- Standalone for Notes; reuse
for permissions, shell, and Objective-C/UI scripting patterns.automating-mac-apps - PyXA Installation: To use PyXA examples in this skill, see the installation instructions in
skill (PyXA Installation section).automating-mac-apps
Core framing
- Notes uses an AEOM hierarchy: Application → Accounts → Folders → Notes (with nested folders).
- Load:
for complete specifier reference.automating-notes/references/notes-basics.md
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
and HTMLname
; verify creation success.body - Query/update with
filters; batch delete/move as needed; check counts before/after operations..whose - For checklists/attachments, use clipboard/Objective-C scripting if dictionary support is insufficient; test fallbacks.
- For meeting/people workflows, file notes under
andmeetings/<company>/<date>-<meeting-title>
; validate final structure.people/<first>-<last>/...
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": "<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}")
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
-
queries return expected results.whose - 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>
, or event handlers to prevent XSS in rendered notes.<style> - Checklists/attachments: Objective-C/clipboard fallback (Cmd+Shift+L for checklist, paste image via NSPasteboard + System Events).
- Append helper: replace
with extra HTML, or append when missing; validate HTML structure post-modification.</body>
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