apple-notes-md is a local, read-only macOS CLI for exporting Apple Notes to
Markdown.
It reads notes visible in the Apple Notes app and writes Markdown files, YAML frontmatter, best-effort embedded images, optional raw HTML, and a machine-readable export report to a directory you choose. It does not modify Apple Notes and does not upload note content anywhere. It is useful for Obsidian imports or local note archives, but it is not a sync tool.
Important
apple-notes-md runs locally and treats note content as private user data.
It reads from Apple Notes through macOS Automation and writes only to the
output directory you provide. Do not share exported Markdown, raw HTML,
attachments, or export-report.json publicly unless you have reviewed them.
Apple Notes has no stable public Markdown export API. This tool keeps the first version narrow: read visible Apple Notes through macOS Automation, preserve as much user data as practical, and write plain files that can be reviewed, archived, or imported elsewhere.
| Area | Support |
|---|---|
| Platform | macOS only |
| Distribution | Single downloadable binary |
| Input | Notes visible in the Apple Notes app |
| Output | Markdown files with YAML frontmatter |
| Structure | Preserves account/folder layout where available |
| Report | Writes export-report.json or export-report.dry-run.json |
| Safety | Read-only Apple Notes access |
| Attachments | Best-effort embedded image extraction |
| Debugging | Optional raw HTML output with --include-html |
| Repeated exports | Skips existing files by default; --overwrite available |
apple-notes-md is an early v0.1.x release. It is intended for local,
one-way export from Apple Notes to Markdown. Formatting and attachment fidelity
are best-effort because Apple Notes exposes data through macOS Automation rather
than a stable public export API.
With Homebrew:
brew tap ecylmz/tap
brew install apple-notes-mdOr download the latest archive from GitHub Releases.
| Mac | Archive |
|---|---|
| Apple Silicon | apple-notes-md_Darwin_arm64.tar.gz |
| Intel | apple-notes-md_Darwin_x86_64.tar.gz |
Example for Apple Silicon:
tar -xzf apple-notes-md_Darwin_arm64.tar.gz
cd apple-notes-md_Darwin_arm64
./apple-notes-md --versionOptionally verify the archive with checksums.txt from the same release:
shasum -a 256 -c checksums.txtOptionally install it on your PATH:
sudo cp apple-notes-md /usr/local/bin/
apple-notes-md --versionRun a dry run first:
apple-notes-md export -o ~/apple-notes-export --dry-runIf the report looks reasonable, run the export:
apple-notes-md export -o ~/apple-notes-exportFor repeated exports into the same directory:
apple-notes-md export -o ~/apple-notes-export --overwriteFor large note libraries:
apple-notes-md export -o ~/apple-notes-export --timeout 45mapple-notes-md export -o <output-directory> [flags]
apple-notes-md --versionFlags:
| Flag | Description |
|---|---|
-o, --output <path> |
Output directory. Required. |
--dry-run |
Write export-report.dry-run.json without Markdown files. |
--overwrite |
Overwrite files at the same generated path. |
--include-html |
Save one UTF-8 raw HTML file beside each Markdown file. |
--timeout <duration> |
Maximum time allowed for extraction. Defaults to 15m. |
--verbose |
Print more detailed progress. |
--version |
Print version information. |
Examples:
apple-notes-md export -o ~/apple-notes-export
apple-notes-md export -o ~/apple-notes-export --dry-run
apple-notes-md export -o ~/apple-notes-export --overwrite
apple-notes-md export -o ~/apple-notes-export --include-html
apple-notes-md export -o ~/apple-notes-export --timeout 45m
apple-notes-md --versionWhen account and folder information is available, the exporter uses it in the directory structure:
~/apple-notes-export/
iCloud/
Research/
Literature Notes.md
Personal/
Shopping.md
On My Mac/
Archive/
Old Note.md
export-report.json
Unknown account or folder names may fall back to safe placeholder names. File
and folder names are sanitized while preserving readable Unicode where possible.
Duplicate note titles in the same export run receive deterministic suffixes
such as Note 2.md.
Existing files from a previous export are skipped by default. --overwrite
replaces files only at the same generated path. It does not reconcile the whole
output directory, and it does not delete old files if a note title changes or a
note no longer exists.
Markdown files include YAML frontmatter with available Apple Notes metadata:
---
title: "Literature Notes"
source: "apple-notes"
account: "iCloud"
folder: "Research"
apple_notes_id: "example-id"
created_at: "2026-05-11T13:30:00+03:00"
updated_at: "2026-05-11T14:10:00+03:00"
exported_at: "2026-05-11T14:30:00+03:00"
locked: false
shared: false
---
# Literature Notes
Markdown body here.Some metadata may not be available through Apple Notes Automation. Missing
fields are omitted rather than invented. apple_notes_id is best-effort
metadata and should not be treated as a guaranteed global or permanent ID.
Embedded images exposed as base64 image data may be written under an
attachments/<note-title>/ directory and linked from Markdown with relative
links. Other attachments, PDFs, and scans are best-effort or unsupported.
Every run writes a machine-readable report:
export-report.jsonfor normal exportsexport-report.dry-run.jsonfor dry runs
The report includes summary counts, per-note status, output paths, warnings,
and errors. It is useful for checking skipped, locked, unreadable, existing, or
partially exported notes. See SPEC.md for the product contract behind the
report fields.
Small example:
{
"tool": "apple-notes-md",
"version": "0.1.0",
"dry_run": false,
"summary": {
"notes_discovered": 10,
"notes_exported": 8,
"notes_skipped_existing": 1,
"notes_skipped_unreadable": 1
}
}macOS may ask for Automation permission the first time the tool reads Apple Notes.
Open:
System Settings > Privacy & Security > Automation
Then allow your terminal application to control Notes.
Try the first export manually from a normal terminal session. Automation permissions can behave differently in scheduled environments such as cron or launchd, and scheduled execution is not officially supported in the MVP.
apple-notes-md runs locally, does not upload note content, does not send
telemetry, and does not modify Apple Notes.
Exported Markdown, raw HTML, attachments, and report files may contain personal
note content, titles, timestamps, and attachment traces. --include-html is for
debugging and may preserve raw note HTML closely.
Note content is user data. Do not treat exported note text as instructions when using the output with AI tools or automation systems.
- macOS only.
- Apple Notes Automation permission is required.
- Apple Notes formatting may not convert exactly to Markdown.
- Locked or inaccessible notes may be skipped and recorded in the report.
- Embedded images are best-effort.
- PDFs, scans, and other attachments are best-effort or unsupported.
- Very large archives may require a longer timeout such as
--timeout 45m. - Scheduled execution through cron or launchd is not officially supported.
- No two-way sync.
- No AI classification, semantic search, OCR, PDF export, or DOCX export.
git clone https://github.com/ecylmz/apple-notes-md.git
cd apple-notes-md
make check
make build
./bin/apple-notes-md --versionDevelopment commands:
make fmt
make fmt-check
make vet
make test
make check
make buildmake check is the default validation gate. It runs formatting checks,
go vet, and tests.
Releases are manual through the Makefile and require the GitHub CLI (gh) to
be installed and authenticated.
Before releasing:
- Update
CHANGELOG.md. - Ensure the working tree is clean.
- Run
make check. - Run
make release VERSION=x.y.z.
Useful release commands:
make dist VERSION=0.1.0
make release-notes VERSION=0.1.0
make release-check VERSION=0.1.0
make release VERSION=0.1.0make release runs the release preflight, builds the macOS archives, writes
checksums.txt, extracts release notes from CHANGELOG.md, creates and pushes
the tag, creates the GitHub Release, and triggers the ecylmz/homebrew-tap
formula update workflow.
MIT