apple-notes
Skill181 starsChanged 5 days agoMITView on GitHub
Use this skill when the user wants to interact with Apple Notes on macOS - creating, searching, reading, updating, deleting, organizing, or formatting notes and folders. This skill provides access to Apple Notes through MCP tools and includes safe formatting guidance.
- Reads credentials
64 other projects use a version of this.
Adopted by
Most recently taken up by
- ashleysbrain/skillstheir own version, first seen Nov 8, 2026
- insight68/Skillstheir own version, first seen Nov 8, 2026
- delorenj/skillstheir own version, first seen Nov 7, 2026
- jaywedgeworth22/BotFleettheir own version, first seen Nov 3, 2026
- Simple-With-Us/BotFleettheir own version, first seen Nov 3, 2026
- QVerisAI/QVerisBottheir own version, first seen Nov 1, 2026
Used with
Projects with it also use taskflow-inbox-triage, openclaw-release-maintainer and 10 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
AtomicBot-aiSkilltaskflow-inbox-triage
Also in 6 projects that use this
hkyutongSkillopenclaw-release-maintainer
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
Also in 4 projects that use this
AtomicBot-aiSkilltaskflow
Also in 6 projects that use this
math-incSkillfindmy
Track Apple devices and AirTags via FindMy.app on macOS using AppleScript and screen capture.
Also in 10 projects that use this
hkyutongSkillnode-connect
Diagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps. Use when QR/setup code/manual connect fails, local Wi-Fi works but VPS/tailnet does not, or errors mention pairing required, unauthorized, bootstrap token invalid or expired, gateway.bind, gateway.remote.url, Tailscale, or plugins.entries.device-pair.config.publicUrl.
Also in 8 projects that use this
math-incSkilljupyter-live-kernel
Use a live Jupyter kernel for stateful, iterative Python execution via hamelnb. Load this skill when the task involves exploration, iteration, or inspecting intermediate results — data science, ML experimentation, API exploration, or building up complex code step-by-step. Uses terminal to run CLI commands against a live Jupyter kernel. No new tools required.
Also in 5 projects that use this
- +1 more from math-inc
Other versions64 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 64
- moltbot/clawdbot★ 394ksame name
- steipete/warelay★ 394ksame name
- steipete/clawdis★ 394ksame name
- moltbot/moltbot★ 394ksame name
- clawdbot/clawdbot★ 394ksame name
- openclaw/openclaw★ 394ksame name
- molt-bot/clawdbot★ 391ksame name
- NousResearch/hermes-agent★ 262ksame name
- spinabot/brigade★ 11ksame name
- the-open-agent/openagent★ 5.7ksame name
54 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repositoryOne other file it gives its agents.
- CLAUDE.mdCLAUDE.md
The file
Show its rules and text
We split this skill into the rules it gives an agent
25 rules. 0 are common, 11 are distinctive, and 14 are very specific to this project.
0
Common
Most of the 62 edited versions we read keep these.
11
Distinctive
This author's own choices. Worth a look.
14
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
Use this skill when the user:
- Distinctive: line 156
When the user wants to save information:
- Distinctive: line 172
When the user wants to find notes:
- Very specific: line 188
When Full Disk Access is available, prefer query-notes for anything beyond a single keyword.
- Distinctive: line 231
When the user wants to see note contents:
- Very specific: line 249
Use titles for discovery only.
- Very specific: line 255
Check each attachment's status: none means Notes stored no transcript, not that the read failed.
- Very specific: line 294
Replacing a note — use
update-note: Only reach for it when the body really is being rewritten: - Distinctive: line 321
When the user wants to organize:
- Distinctive: line 353
Use HTML for predictable rich notes.
- Very specific: line 355
Use <div> for body blocks and <div><br></div> for blank spacing.
- Very specific: line 387
Use <ul><li> and <ol><li> for native bullet and numbered lists.
- Very specific: line 389
Use <b>, <i>, <u>, and <s> for inline emphasis, and <span style="color: …"> for text color.
- Very specific: line 390
Use <tt> (or <code>) for commands, code, paths, API keys, and other technical strings.
- Distinctive: line 392
Avoid nested lists when possible.
- Very specific: line 393
Avoid <sup>, <sub>, and text-align in a note you may rewrite later.
- Very specific: line 397
Do not use decorative separators between sections (horizontal rules, repeated dashes, or box-drawing characters).
- Distinctive: line 399
Do not use CDATA sections.
- Distinctive: line 419
If the user specifically requires those features, create all API-supported content first, then explain which remaining formatting must be …
- Very specific: line 423
Exact IDs for writes: Search may use titles, but update, append, delete, and move require the exact note ID.
- Very specific: line 435
Backslash Escaping: When content contains backslashes, escape them as \\ in the JSON.
- Distinctive: line 439
Shared Notes: Use extra care before edits or deletes.
- Very specific: line 447
When the stored HTML looks suspicious, get-note-plaintext is the quickest check: it returns the note's plain-text body (what Notes itself …
- Very specific: line 455
If your client shows only text, not structuredContent, every result that has it ends with a structuredContent: {…} line holding the same …
- Distinctive: line 457
"Note not found": Use search-notes to find similar titles
“Common” is measured: kept by at least 6 in 10 of the 62 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Apple Notes Skill
This skill enables you to manage Apple Notes on macOS through natural language. Use it whenever the user mentions notes, wants to save information to Notes, or needs to retrieve, update, or organize their notes.
When to Use This Skill
Use this skill when the user:
- Wants to create a new note or save information
- Asks to find, search, or look up notes
- Wants to read the contents of a note
- Needs to update or edit an existing note
- Wants to delete or remove a note
- Asks to move or organize notes into folders
- Wants to list their notes or folders
- Mentions Apple Notes, Notes app, or "my notes"
Available Tools
Note Operations
| Tool | Purpose |
create-note | Create a new note with title and content |
search-notes | Find notes by title or content |
query-notes | Find notes with a boolean expression over text, folders, tags, attachments, checklists, flags, word counts, and dates (reads the database; needs Full Disk Access) |
get-note-content | Read the full content of a note |
get-note-plaintext | Read a note's body as plain text (no HTML) |
get-note-markdown | Read note content as Markdown |
get-note-by-id | Get note metadata by ID |
get-note-details | Get metadata (created, modified, account) |
get-note-link | Get the shareable notes://showNote?identifier=… deep link for a note |
update-note | Replace a note's whole body; refused when the note holds attachments, tables, checklists, or native tags, or formatting HTML cannot carry |
append-to-note | Add content to a note without replacing it (position: "after" / "before", which inserts below the title) |
append-native | Append plaintext, the native HTML subset, or Markdown to a note that holds native objects, without replacing its body (needs scopeText) |
insert-link | Add one URL to a note as its raw text or as a labeled hyperlink, verified from the stored link |
insert-note-link | Append a real link to another note (by id) with a static label, verified after the write |
delete-note | Remove a note (moves to Recently Deleted; refuses a note already there, where delete is permanent); like update-note, append-to-note, and move-note it accepts ifFolderId, ifAncestorFolderId, and forbiddenAncestorFolderIds folder preconditions. For copy-then-retire, pass guardNoteId and expectedGuardContentHash (the verified copy's contentHash) so the original is deleted only while the copy is intact; needs Full Disk Access |
batch-delete-notes | Delete multiple notes by ID (max 500 per call; refuses notes already in Recently Deleted) |
move-note | Move a note to a different folder |
batch-move-notes | Move multiple notes by ID (max 500 per call) |
list-notes | List all notes or notes in a folder (excludes Recently Deleted unless includeRecentlyDeleted) |
list-special-notes | List pinned notes, Quick Notes, Recently Deleted, or locked notes (kind; metadata only, needs Full Disk Access) |
set-note-pinned | Pin or unpin one exact note (checks expectedPinned and expectedContentHash; never rewrites the body) |
list-recent-notes | Changes since a cursor, oldest first, for incremental sync: pass since, then keep calling with nextSince until saturated is false (needs Full Disk Access) |
show-note | Reveal a note in the Notes.app UI by ID |
get-selected-notes | Read the notes currently selected in Notes.app |
export-notes-json | Export notes as JSON one page at a time (offset/limit/modifiedSince); repeat with page.nextOffset while page.hasMore |
export-notes-markdown | Export one note or a folder as one Markdown document from the decoded body; optional create-only outputPath and assetsDir for attachment copies; template/templateFile render through a JSON Markdown template such as obsidian front matter (presentation format, not a backup) |
export-notes-html | Export one note or a folder as one standalone HTML file (semantic tables, attachments in body order); outputPath required and create-only; assets embedded (10 MiB each) or in a sidecar directory with embedAssets: false; vectorDrawings: true renders classic drawings as SVG through the public helper (default false keeps Notes' PNG; Paper keeps its PNG; failures fall back to PNG) |
list-markdown-templates | List built-in and saved Markdown export templates |
show-markdown-template | Show a template's JSON (portable form; expanded for every rule) |
validate-markdown-template | Check a template; returns every problem with a JSON path |
save-markdown-template | Save a template to the library by slug name (create-only unless force) |
delete-markdown-template | Delete a saved template (built-ins cannot be deleted) |
To edit a template visually, the user can run apple-notes-mcp templates edit [name] in a terminal: a local, token-gated web editor with live validation and a preview on sample notes. It is a command-line tool, not an MCP tool, so suggest it rather than trying to start it.
Folder Operations
| Tool | Purpose |
list-folders | List all folders in an account; with Full Disk Access, smart folders are marked smartFolder: true |
list-smart-folders | List Smart Folders with their decoded rules; optionally the notes each one shows |
get-folder-by-id | Read one folder's name, parent, account, and isRoot before a guarded rename or delete |
rename-folder | Rename one folder in place; requires its expected current name and parent |
list-folder-tree | Folder hierarchy with direct and cumulative note counts per account |
create-folder | Create a new folder |
delete-folder | Delete an empty folder |
delete-folder-by-id | Guarded delete of one exact empty folder: dry run returns a revision, apply requires it |
show-folder | Reveal a folder in the Notes.app UI by ID |
Account Operations
| Tool | Purpose |
list-accounts | List configured accounts (iCloud, Gmail, etc.) |
get-default-location | Read the default account and folder used for new notes |
show-account | Reveal an account in the Notes.app UI by ID |
Native Tags
| Tool | Purpose |
native-tags-status | Check that the Native Tags Shortcut is installed before a tag write |
list-native-tags | Native tags in one folder, or omit folder for an account-wide inventory with note counts |
add-native-tags | Add real, clickable tags to one exact note (needs expectedContentHash and a distinctive scopeText) |
remove-native-tags | Remove named tags from one exact note, keeping its other tags |
replace-native-tag | Swap one tag for another across a list of freshly read notes; stops at the first uncertain result |
Attachments, Checklists, Collaboration, and Diagnostics
| Tool | Purpose |
list-attachments | List attachments in a note; includePaths adds on-disk assetPaths/previewPath, firstImage returns the lead visual in body order |
add-attachment | Attach one local file (home, temp or /Volumes; no hidden paths or ~/Library) to an exact note (filename renames it); a macOS 27 PDF "outcome uncertain": read the note first |
create-note-with-attachment | Create a note and attach one local file in one call; on a failed attach, reuse the named note id with add-attachment |
add-attachment-from-pasteboard | Attach the copied image, PDF, or one file to an exact note (note checked first, pasteboard frozen, never modified); pasteboard_access_denied: ask before allowPasteAlert: true |
save-attachment | Save an attachment to disk |
list-paper-attachments | List Paper and classic drawings in a note, with Notes' rendered image size and any recognized handwriting text |
export-paper-image | Save Notes' rendered PNG (or JPEG) of one drawing to a new file |
analyze-svg | Read-only SVG preflight: can a local SVG become editable strokes, which losses it needs, and a digest of the result |
export-attachments | Copy a note's attachment files (or only its lead visual) into a directory; exportedKind says asset, fallback, or preview |
fetch-attachment | Fetch attachment bytes as base64 |
show-attachment | Reveal an attachment in the Notes.app UI |
get-checklist-state | Read checked/unchecked state for existing checklists |
create-checklist-item | Append one unchecked native checklist item (needs the Background Operations bridge) |
get-note-tables | Read a note's native tables as Markdown and JSON rows, in body order |
create-table | Append one native table from rectangular rows (omit rows for an empty 2 × 2 table); verified by reading the cells back |
create-checklist-items | Append several unchecked native checklist items in order (needs the Background Operations bridge; on ok: false, only landed items are verified) |
get-note-metadata | [BETA] Read pinned/trash/snippet metadata from the NoteStore DB |
get-note-drawings | Decode classic PencilKit drawings to strokes or SVG (needs apple-notes-mcp setup --public-helper once) |
transcribe-note-audio | Transcribe a note's voice recordings on-device (same helper; pass locale, and attachmentId for long recordings) |
get-note-blocks | Read a note's paragraph styles, inline formatting, and attachment positions as typed blocks |
get-native-objects | Read a note's native object ids, checklist ids and state, native tags, and decoded tables, with the current revision |
list-note-paragraphs | List a note's paragraphs with style, stored paragraph ID, and a direct link when the ID is unique |
get-paragraph-link | Get a link that opens Notes at one paragraph, refused when its ID is shared |
create-paragraph-anchor | Record an anchor for one paragraph so it can be found again after edits or ID changes (local registry only) |
resolve-paragraph-anchor | Find an anchored paragraph again; url only when status is resolved, fails closed on ambiguity |
list-paragraph-anchors | List recorded paragraph anchors, all or for one note |
get-paragraph-anchor | Show one stored paragraph anchor |
prune-paragraph-anchors | Remove anchors that no longer resolve (dry run unless dryRun: false) |
get-note-structure | Read a note's links by kind, tags, attachments (as list-attachments reports them), counts, and view/lock/share/trash state in one call |
list-note-links | List links (inline, card, note, section) in a note, folder (with subfolders), account, or the whole library |
get-audio-transcripts | Read the transcripts and summaries Notes stored for a note's audio recordings |
list-shared-notes | List notes shared with collaborators |
get-sync-status | Check whether iCloud sync is active |
health-check | Quickly verify Notes.app access |
doctor | Run detailed setup diagnostics, including the feature matrix |
get-capabilities | Check native-write operations and the OS-aware feature matrix (features.<name>.available / reason) before calling a tool that depends on them |
get-notes-stats | Summarize note counts and recent activity |
Private Helper (opt-in, read-only, unsupported Apple API)
Off unless the user built it (apple-notes-mcp setup --native-helper) and set
APPLE_NOTES_MCP_ENABLE_PRIVATE=1. Call native-helper-status first; use
native-note-state or native-checklist-state only when the corresponding
readNoteState or readChecklist feature is available. The helper is
read-only: write support was deliberately deferred by the maintainer.
| Tool | Purpose |
native-helper-status | Report opt-in, build, and live-probe state with a reason code (read-only) |
native-note-state | Read a note's native state and revision change token (read-only) |
native-checklist-state | Read exact native todo identities/state and contiguous, consistent, spansLines ambiguity flags (read-only) |
Usage Patterns
Creating Notes
When the user wants to save information:
User: "Save this meeting summary as a note"
Action: Use create-note with an appropriate title and the contentUser: "Create a shopping list note"
Action: Use create-note with title="Shopping List" and formatted contentFor structured notes, pass format="html" and use simple Apple Notes-friendly HTML. The server automatically prepends the title as an <h1> in both plaintext and HTML modes, so do not include the same <h1> title in content when creating a note.
Finding Notes
When the user wants to find notes:
User: "Find my notes about the project"
Action: Use search-notes with query="project"User: "Search for notes containing budget information"
Action: Use search-notes with query="budget" and searchContent=trueWith Full Disk Access, a searchContent search reads the Notes database and
returns quickly even for a common word; without it, a broad body search can time
out, so narrow it with folder or modifiedSince.
When Full Disk Access is available, prefer query-notes for anything beyond a
single keyword. It matches title or body in one call, runs in well under a
second, and combines conditions:
User: "Which work notes still have open to-dos?"
Action: Use query-notes with query='folder:Work checklist:open'
User: "Find invoices or anything tagged finance since July"
Action: Use query-notes with query='(title:invoice OR tag:finance) modified:>=2026-07-01'
User: "Long notes with a PDF that aren't in Archive"
Action: Use query-notes with query='words:>250 has:pdf -folder:Archive'Bare words and "quoted phrases" match title or body. Fields are title:,
body:, text:, folder:, account:, and tag:; facets are
has:link|attachment|checklist|drawing|image|video|audio|pdf|table|scan|url|map|tag
(has:url is a link preview card, has:map a map);
checklist:open|done; flags pinned, locked, shared, quicknote; and words:,
created:, modified: take =, >, >=, <, <= with YYYY-MM-DD local
dates. AND is implicit; use OR, NOT or a leading -, and parentheses.
Quote an operator word ("and") to search it literally. It scans the 500 most
recently modified notes unless scanLimit is raised (max 10000), and the
response says when older notes were left out. Recently Deleted is excluded
unless includeDeleted is true. Locked notes match on title and metadata only.
The returned ids work with every id-based tool.
Both search tools can say where a note matched and how long it is. Results
whose text came from the database carry matchedIn (title, body, or both);
query-notes always has it for readable notes, and search-notes has it for a
database body search. Pass includeWordCount: true to either tool for a
wordCount per result (null for locked notes). On a search-notes title search
it reads the bodies in one database query and adds matchedIn too, which
answers "does this note also mention it in the body?" without opening each note.
User: "Which of my budget notes are long, and do they mention it in the body?"
Action: Use query-notes with query='budget' and includeWordCount=trueReading Notes
When the user wants to see note contents:
User: "Show me my shopping list"
Action: Search by title if needed, then use get-note-content with the exact IDFor a note's tables, use get-note-tables with the note ID. It returns a page
of whole tables as Markdown and JSON rows. While page.hasMore is true,
repeat with offset: page.nextOffset and the same limit and maxBytes.
The full response defaults to 4 MiB (maximum 8 MiB) and 500 tables. An
oversized table has contentOmitted: true, a reason and no rows; the next
offset advances past it. Retry its original offset with a larger maxBytes
or export the note to a file. When tableCellsComplete is false, check each
entry's reason: undecodable cells are null in rows and shown as
[undecoded cell] in Markdown. Report missing content rather than filling
it in.
Use titles for discovery only. Mutations require the exact note ID; update,
append, and delete also require the contentHash returned by
get-note-content. This prevents duplicate-title mistakes and stale saves.
For a note with audio recordings, get-audio-transcripts returns the
transcript Notes already computed for each recording (it never transcribes).
Check each attachment's status: none means Notes stored no transcript, not
that the read failed. Ask for includeSegments only when word timings or
speakers per word matter, because segments make the response much larger.
Updating Notes
Adding to a note — use append-to-note. It takes the new content plus an
optional position ("after" is the default and appends; "before" prepends),
separator, and format ("plaintext" / "html"), and does the read-and-splice
itself, always round-tripping the body as HTML so existing rich formatting
survives. Do not hand-roll read-then-update-note for an addition.
A note that already contains native objects (a table, a checklist, native tags)
cannot be spliced, so append-to-note routes it to the native end-append bridge
instead. That path additionally needs scopeText (a unique existing phrase
from below the title line; a title-only phrase is refused),
keeps the default blank-line separator and position: "after", and accepts a
fixed HTML subset: `<a> <b> <br> <code> <del> <div> <em> <h1> <h2> <h3> <i> <li>
<ol> <p> <s> <span> <strong> <tt> <u> <ul>`, with `href` on `<a>` and a
`font-size` style on `<span>` as the only attributes. A table, whole or in
part, is refused here — use `create-table` instead. Anything else outside that
subset is refused by name — rewrite the whole body with `update-note` instead.Adding a web link — use insert-link. Pass url and either mode: "raw"
(the URL is its own clickable text) or mode: "hyperlink" with a label.
position is "end" (default) or "after-title". It checks the stored link
afterwards and reports linkStored and storedUrl. A plain URL typed into
append-to-note content stays plain text: Notes does not turn it into a stored
link. Rich URL preview cards cannot be created. For a link to another note, use
insert-note-link.
User: "Add milk to my shopping list"
Action:
1. Use search-notes if needed to get the note ID
2. Read it with get-note-content and retain contentHash
3. Use append-to-note with its exact ID, expectedContentHash, and content="Milk"Replacing a note — use update-note. Only reach for it when the body really
is being rewritten:
User: "Rewrite my project brief with this new version"
Action:
1. Use search-notes if needed to get the note ID
2. Read it with get-note-content and retain contentHash
3. Use update-note with its exact ID, expectedContentHash, and complete new bodyupdate-note replaces the entire note body. It is not an append operation. If format="html", newTitle is ignored and the first element in newContent becomes the visible title, so start newContent with the title line (for example <h1>Project Brief</h1>). This is the opposite of create-note, which adds the title itself.
If the note has links, update-note needs format: "html", and every link get-note-content returned must still be in newContent with the same text and URL. A write that would drop or change one is refused. Pass allowLinkChanges: true only when the user asked to remove or change a link.
Do not write get-note-content's body back through another tool. For image-heavy notes that body is lossy: inline base64 images over the configured cap (default 256 KB each) come back as [inline image omitted: …] text placeholders.
update-note refuses a note whose body it cannot rewrite without loss: one that
holds attachments, tables, checklists, or native tags, or uses formatting that
Notes' AppleScript HTML does not carry (superscript, subscript, paragraph
alignment, highlight). get-note-content reports that as writable: false
with the reason. append-to-note does not refuse such a note. It switches to
native end-append, which needs scopeText and the HTML subset above, and keeps
the existing objects. Any other change to such a note belongs in Notes.app.
Organizing Notes
When the user wants to organize:
User: "Move my old notes to Archive"
Action: Search for each note, then use move-note with its exact ID and folder="Archive"User: "Create a Work folder"
Action: Use create-folder with name="Work"create-folder takes a whole nested path (name="Work/Clients/Omnia") and creates every missing segment, skipping ones that already exist — so it is idempotent and safe to call unconditionally. Do call it first: create-note, create-note-with-attachment, move-note, and batch-move-notes all require the destination folder to already exist (and never a smart folder: those destinations, and a smart folder anywhere in a create-folder path, are refused with reason: "smart_folder_destination", since Notes would send a moved note to Recently Deleted; the guard needs Full Disk Access to detect one), and create-note reports a missing folder with a generic "check that Notes.app is configured and accessible" message that looks like a permissions problem but is not.
Sharing and Revealing Notes
User: "Send me a link to that note"
Action: Use get-note-link with the note ID → notes://showNote?identifier=<uuid>Hand out that deep link, not the x-coredata:// id — the link opens the note in Notes.app on macOS and iOS and can be pasted into a Reminders task or a message. It needs Full Disk Access for the process that runs the server (under Claude Desktop, the Node binary itself) (it reads the note's identifier from the Notes database; macOS 12–15 has an AppleScript fallback), and password-protected notes cannot be linked.
User: "Open that note for me" / "What note am I looking at?"
Action: show-note by ID to reveal it in Notes.app; get-selected-notes to read the current selectionshow-note, show-folder, show-account, and show-attachment activate the Notes.app GUI, so they only do something useful on a Mac with an active desktop session.
Formatting Guidance
Use HTML for predictable rich notes. Apple Notes normalizes HTML internally, but these tags are reliable for most API-created content:
- Use
<div>for body blocks and<div><br></div>for blank spacing. create-notealready creates the top<h1>from thetitle, but<h2>/<h3>in itscontentdo not produce real Heading/Subheading styles — AppleScript'sbodyproperty renders them as plain bold text (#172). For a new note with real headings, usecreate-notewithformat: "markdown"(##/###→ Heading/Subheading, flat lists,**bold**/*italic*and inline links; iCloud only, noaccount).tagsare refused with this format: create the note, then useadd-native-tagson the returned id. It needs the optional Create Markdown Note Shortcut (macOS 26+); checkget-capabilitiesforcreate-note-markdown. On an existing note, useappend-nativewithformat: "markdown". Both refuse Markdown Notes would rewrite, such as_emphasis outside a word or backslash escapes; underscores inside a link destination are fine.- With
format: "markdown", do not repeat the title as a#line; if the first line is exactly# <title>, the server removes it. Without the Shortcut, or in another account, passmarkdownRoute: "html": same Markdown subset through AppleScript HTML, no real Heading styles, and- [ ]/- [x]task items become list rows with a visible ☐ / ☑ character (text, not a checkable checklist; say so to the user). - To import a Markdown or text file, pass its absolute path as
contentPathinstead ofcontent(UTF-8, at most 1 MiB, inside home, temp, or/Volumes; hidden paths such as~/.sshand anything in~/Libraryare refused, except iCloud Drive and~/Library/CloudStorage). - On the default Shortcut route,
create-notewithformat: "markdown"also maps block constructs to native Notes styles (create-note-markdown-blocksinget-capabilities):- [ ]/- [x]→ native checklist items with that done state,> text→ a block quote, a bare```fence (no language) → Monospaced paragraphs, a---line after a blank line → a divider, and`inline code`→ highlighted text (not monospace). Code content is kept literal.append-nativestill refuses all of these, because its converter flattens them (quotes and code to plain body text,- [ ]to a bullet with literal brackets,---dropped).markdownRoute: "html"does not map them either: it renders- [ ]/- [x]as ☐ / ☑ glyph rows, keeps---as literal text, and refuses the rest. - Pass
titleas plain text. The server escapes&,<, and>in it, so an entity such as&in a title shows up literally. - Use
<ul><li>and<ol><li>for native bullet and numbered lists. Add<div><br></div>after closing</ul>or</ol>so the next section has spacing. - Keep each
<li>to one line of inline text. Do not put<div>,<p>, headings, or tables inside a list item, and do not send an empty<li>, which shows as a blank bullet or number. A<br>inside an item does not start a new line in Notes; the text after it joins the line. For sub-points, write the parent as its own<div>line and follow it with a separate flat list. HTML from a Markdown converter often wraps list items in<p>, so flatten it before sending. The server's own Markdown converter likewise emits only flat, one-line list items and refuses nested lists. - Use
<b>,<i>,<u>, and<s>for inline emphasis, and<span style="color: …">for text color. - Use
<tt>(or<code>) for commands, code, paths, API keys, and other technical strings. - Escape literal
&,<, and>in user content as&,<, and>. - Avoid nested lists when possible. Apple Notes can flatten or misplace nested list markup.
- Avoid
<sup>,<sub>, andtext-alignin a note you may rewrite later. Notes applies them, but its AppleScript HTML does not return them, so the note becomeswritable: falseandupdate-noterefuses it. <blockquote>does not create a Notes block quote. Use the Markdown route's> textinstead (see below).- For a table, use
create-tableon an existing note; it builds a native table and verifies its cells. A table is a native object, so afterwardsupdate-noterefuses the note andappend-to-noteswitches to native append. Read tables back withget-note-tables. - For a clickable link, use
<a href="…">in HTML content orinsert-link. A bare URL written as text is stored as plain text, not as a link. - Do not use decorative separators between sections (horizontal rules, repeated dashes, or box-drawing characters). They render inconsistently in Notes; use an empty
<div><br></div>spacer instead.
Do not use CDATA sections. They can render literally in Apple Notes.
Attachment-Safe Updates
update-note refuses any note containing an attachment (a table counts, since
Notes stores it as an embedded object). Do not bypass this control. To add
text to such a note, use append-to-note with scopeText, which appends
natively and leaves the attachments in place; to add a file, use
add-attachment. For any other edit, use Notes.app or create a separate
formatted note.
Formatting Limits
Some Notes UI features cannot be created through AppleScript HTML. Several have another route:
- Interactive checklists: in plaintext or HTML, create a plain list instead;
create-notewithformat: "markdown"and- [ ]/- [x]lines creates real ones, andcreate-checklist-item/create-checklist-itemsappend unchecked items to an existing note. Useget-checklist-stateto read checklist state. - Headings and collapsing: HTML
<h2>/<h3>become bold text, not heading styles, so they get no collapse control.##/###throughcreate-noteorappend-nativewithformat: "markdown"produce real Heading/Subheading styles. - Block quotes and highlights: only the Markdown Shortcut route of
create-notecreates them (> textfor a block quote,`inline code`for highlighted text, with no choice of color). Otherwise apply them in Notes.app. - Dashed lists: no tool creates them; apply them in Notes.app.
If the user specifically requires those features, create all API-supported content first, then explain which remaining formatting must be applied in Notes.app.
Important Guidelines
- Exact IDs for writes: Search may use titles, but update, append, delete,
and move require the exact note ID. Update, append, and delete also require
the
contentHashfrom the version just read. A note ID may be thex-coredata://…id, the note's Notes UUID (theidentifierfield list and read tools return with Full Disk Access), or its numeric key (the digits afterp). UUIDs and numeric keys need Full Disk Access; store theidentifierwhen a reference must outlive this session. - Default Account: Operations default to iCloud. Use the
accountparameter for other accounts (Gmail, Exchange). - Content Format: Notes store content as HTML. Use
format="html"for structured content. Retrieved HTML is normalized by Notes and may not match the submitted HTML byte-for-byte.verifiedVisibleTextproves the words survived, not every rich-formatting detail. - Backslash Escaping: When content contains backslashes, escape them as
\\in the JSON. - Password-Protected Notes: Cannot be accessed via this skill. Inform the user if they try.
- Shared Notes: Use extra care before edits or deletes. Changes to shared notes are visible to collaborators.
- macOS Only: This skill only works on macOS systems.
Verification
get-note-content returns Apple Notes' stored HTML, which may differ from the original HTML while still rendering correctly. Use get-note-markdown, get-note-content, or a quick reread of the note after create/update to verify the title, line breaks, list spacing, and important content. Do not rewrite normalized HTML just because Notes transformed tags such as headings or monostyled text.
When the stored HTML looks suspicious, get-note-plaintext is the quickest check: it returns the note's plain-text body (what Notes itself shows) with no markup, so you can confirm the title, line breaks, and text survived without reading through normalized HTML.
Plain text cannot confirm structure. It carries no list markers, so it cannot show whether items became bullets or numbers, and a table's cell text is not part of it. With Full Disk Access, use get-note-blocks to check paragraph styles, list types, and indentation, and get-note-tables to check table cells. Stored HTML can also contain entities without a closing semicolon, such as ". That is how Notes writes them, not damage to repair.
Error Handling
Every error result carries structuredContent.code (not_found, ambiguous, permission_denied, full_disk_access_missing, shortcut_not_installed, timeout_indeterminate, verification_failed, revision_conflict, validation_error, unsupported, notes_unavailable, operation_failed). Branch on the code rather than the wording. If indeterminate is true, the write may have landed: read the exact note before deciding whether to retry. committed: false means nothing was written.
If your client shows only text, not structuredContent, every result that has it ends with a structuredContent: {…} line holding the same JSON. Take contentHash (for expectedContentHash), ids, and the error code from that line.
- "Note not found": Use search-notes to find similar titles
- "Permission denied": User needs to grant automation permission in System Settings > Privacy & Security > Automation. The user can run
apple-notes-mcp setup --permissions --open --probe-automationin their terminal to check every grant and open each missing pane - Native write times out or reports an uncertain outcome ("Shortcuts timed out waiting for …", "Operation outcome uncertain", "readback was not verified"): do not retry. Read the exact note first — the write may have landed. If it did not, the named bridge Shortcut is likely waiting on a first-run consent prompt that a background run cannot display; ask the user to run that Shortcut once in the foreground in Shortcuts.app and choose Always Allow (once per bridge, after install or upgrade), then retry
- Slow Notes.app:
create-note,update-note,append-to-note,delete-note, andmove-noteaccepttimeoutSeconds(1–120) for each automation step of that call. A timed-out write is uncertain; read the exact note before retrying - Read times out, or Notes.app cannot resolve an id the database holds:
timeout_indeterminateandnotes_unavailablefromget-note-contentmean Notes.app was busy (often iCloud sync), not that the note is gone; onlynot_foundmeans that. Retry after a moment, or read the note withget-note-structure, which does not go through Notes.app - Read times out on a note with a large image: Notes.app returns images inside the body as base64, so a multi-megabyte image can outlast the read timeout, which also blocks
delete-note. The error names the large attachments when Full Disk Access is granted. Retryget-note-content(and thendelete-note) with a largertimeoutSeconds; if it still fails, have the user remove the image or delete the note in Notes.app - "Notes.app accepted the delete, but the note is still in its original folder": nothing was deleted. Read the note again before retrying
- "Notes.app returned more than … of output": a size limit, not a timeout, so retrying will not help. Note bodies embed inline images as base64; body reads accept up to 512 MB, and other calls follow
APPLE_NOTES_MCP_MAX_BUFFER(64 MB default). A note with a large image can still be read and deleted by id - "A note may have been created, but its exact ID could not be verified": do not call
create-noteagain, or you may get a duplicate. The message carries the returned ID; read it, or search for the title, before deciding anything. After anycreate-notetimeout, search for the title first for the same reason - "The note accepted an update, but exact-ID readback visible text did not match": do not retry. Read the note and compare its text with what you sent
- "Folder not empty": Cannot delete folders with notes; move notes first
- Attachment-risk update:
update-noterejects the mutation. Append withappend-to-noteandscopeText, use Notes.app, or create a separate note. - Notes accumulate blank lines after repeated updates: Apple Notes' internal HTML processing preserves empty
<div><br></div>artifacts from previous edits, and they persist even when you update with clean content. Fix: delete the note with delete-note and create a fresh one with create-note — the artifacts are baked into the note's internal representation, so this is more reliable than trying to fix the whitespace through updates
Examples
Save conversation to notes
User: "Save our conversation about the API design to my notes"
→ create-note with title="API Design Discussion" and summarized contentDaily workflow
User: "What's on my todo list?"
→ search-notes with query="todo" or get-note-content with title="Todo"Multi-step organization
User: "Archive all my completed project notes"
→ 1. list-notes to find notes
→ 2. create-folder name="Archive" if needed
→ 3. move-note for each relevant noteDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

