CLI for Apple Notes on macOS. CRUD and search from the command line.
- Read operations (list, show, search, folders) use direct SQLite queries for speed (~50ms)
- Write operations (create, update, delete) use AppleScript via
osascript
- macOS with Full Disk Access granted to your terminal (for reading the Notes SQLite database)
- Ruby (via rbenv or system)
- Notes.app (for write operations via AppleScript)
cd ~/tools/apple-notes
bundle install
ln -sf ~/tools/apple-notes/apple-notes ~/bin/apple-notesapple-notes foldersapple-notes list # 20 most recent notes
apple-notes list --limit 10 # Limit results
apple-notes list --folder "Blog posts" # Filter by folderapple-notes show 1214 # By numeric ID (plaintext body)
apple-notes show 1214 --html # Get HTML body insteadFull-text search across titles and note bodies. Uses SQLite for speed (~60ms for 400+ notes).
apple-notes search "grocery" # Search all notes
apple-notes search "grocery" --limit 5 # Limit results
apple-notes search "trip" --folder "Notes" # Search within a folderapple-notes create "My Title" # Empty note
apple-notes create "My Title" --body "Some text content" # With plain text body
apple-notes create "My Title" --html "<div><b>Rich</b></div>" # With HTML body
apple-notes create "My Title" --body "Text" --folder "Blog posts" # In a specific folderapple-notes update 1214 --body "Replaced body" # Replace body (plain text)
apple-notes update 1214 --html "<div>New HTML</div>" # Replace body (HTML)
apple-notes update 1214 --append "More text at the end" # Append to existing body
apple-notes update 1214 --name "New Title" # Rename
apple-notes update 1214 --name "New" --append "More" # Combine operationsMoves the note to Recently Deleted (same as deleting in Notes.app).
apple-notes delete 1214Notes are identified by their numeric SQLite primary key (e.g., 1214). You can also use the full CoreData URI:
x-coredata://B9669079-92D2-48C1-91ED-8D55A8441D00/ICNote/p1214
Both formats are accepted for show, update, and delete commands.
All commands output JSON to stdout:
{"ok":true,"data":{"notes":[...],"count":3}}Errors:
{"ok":false,"error":"Note 999999 not found","code":"ERROR"}- Reading: Direct SQLite queries against
~/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite(read-only). Note bodies are gzipped protobufs; theshowcommand uses AppleScriptplaintextfor accurate body extraction. - Searching: SQLite for title/snippet matching, with gzip decompression for full-body search (~60ms for 400+ notes).
- Writing: AppleScript via
osascriptto Notes.app. Notes.app will briefly activate on write operations.
bundle exec ruby test/test_notes_db.rb # Unit + SQLite integration tests
bundle exec ruby test/test_notes_apple.rb # AppleScript integration tests (creates/deletes real notes)
bundle exec ruby test/test_cli.rb # End-to-end CLI tests