| Crates.io | apple-notes-exporter-rs |
| lib.rs | apple-notes-exporter-rs |
| version | 3.0.0 |
| created_at | 2026-01-13 04:31:13.508042+00 |
| updated_at | 2026-01-13 15:47:56.462005+00 |
| description | A library and CLI tool for recursively exporting Apple Notes folders to the file system via AppleScript |
| homepage | |
| repository | https://github.com/pRizz/apple-notes-exporter-rs |
| max_upload_size | |
| id | 2039315 |
| size | 84,204 |
A library and CLI tool for recursively exporting Apple Notes folders to the file system via AppleScript. This Rust-based tool allows you to export entire folder hierarchies from Apple Notes, creating a mirrored directory structure with each note saved as an HTML file.
Install from crates.io using Cargo:
cargo install apple-notes-exporter-rs
Or install directly from GitHub:
cargo install --git https://github.com/pRizz/apple-notes-exporter-rs.git
cargo install apple-notes-exporter-rs
Install directly from the GitHub repository:
cargo install --git https://github.com/pRizz/apple-notes-exporter-rs.git
git clone --recursive https://github.com/pRizz/apple-notes-exporter-rs.git
cd apple-notes-exporter-rs
cargo build --release
The binary will be available at target/release/apple-notes-exporter.
The tool provides three subcommands: list (or ls), export, and extract-attachments.
List all top-level folders across all Apple Notes accounts:
apple-notes-exporter list
# or
apple-notes-exporter ls
Export a folder recursively to HTML files. By default, embedded images are automatically extracted to separate files:
apple-notes-exporter export <FOLDER> <OUTPUT_DIR>
This creates a structure like:
exports/
├── My Notes/
│ ├── Note Title -- abc123.html
│ ├── Note Title -- abc123-attachments/
│ │ ├── attachment-001.jpg
│ │ └── attachment-002.png
│ └── Another Note -- def456.html
To skip image extraction (keep images as embedded base64):
apple-notes-exporter export "My Notes" ./exports --no-extract-attachments
If you have previously exported notes without extracting images, you can extract them later:
apple-notes-exporter extract-attachments ./exports
List all available folders:
apple-notes-exporter list # or: apple-notes-exporter ls
Export a folder (searches all accounts):
apple-notes-exporter export "My Notes" ./exports
Export a folder from a specific account (useful when folder names exist in multiple accounts):
apple-notes-exporter export "iCloud:My Notes" ./exports
apple-notes-exporter export "Google:Work Notes" ./exports
Export without extracting images:
apple-notes-exporter export "My Notes" ./exports --no-extract-attachments
If you want to run the tool directly from the source code without installing:
# Clone the repository with submodules
git clone --recursive https://github.com/pRizz/apple-notes-exporter-rs.git
cd apple-notes-exporter-rs
# List folders
cargo run -- list # or: cargo run -- ls
# Export a folder
cargo run -- export "My Notes" ./exports
If you already cloned without --recursive, initialize the submodules:
git submodule update --init --recursive
Add the dependency to your Cargo.toml:
[dependencies]
apple-notes-exporter-rs = "1.0"
use apple_notes_exporter_rs::{list_folders, export_folder, export_folder_from_account};
fn main() -> apple_notes_exporter_rs::Result<()> {
// List all available folders (prints to stdout)
list_folders()?;
// Export a folder to a directory (searches all accounts)
export_folder("My Notes", "./exports")?;
// Export from a specific account (useful when folder names are duplicated)
export_folder_from_account("iCloud", "Work", "./exports")?;
export_folder_from_account("Google", "Work", "./google_exports")?;
Ok(())
}
For more control, use the Exporter struct:
use apple_notes_exporter_rs::Exporter;
fn main() -> apple_notes_exporter_rs::Result<()> {
// Create an exporter with the embedded AppleScript
let exporter = Exporter::new();
exporter.list_folders()?;
// Export and extract images (recommended)
let results = exporter.export_folder_with_attachments("My Notes", "./exports")?;
println!("Extracted {} images", results.iter().map(|r| r.attachments.len()).sum::<usize>());
// Or export without extracting images
exporter.export_folder("Work", "./work_exports")?;
Ok(())
}
If you need to use a modified AppleScript:
use apple_notes_exporter_rs::Exporter;
fn main() -> apple_notes_exporter_rs::Result<()> {
let exporter = Exporter::with_script_path("./custom_script.applescript")?;
exporter.list_folders()?;
exporter.export_folder("My Notes", "./exports")?;
Ok(())
}
You can also extract images from previously exported HTML files:
use apple_notes_exporter_rs::{extract_attachments_from_html, extract_attachments_from_directory};
fn main() -> apple_notes_exporter_rs::Result<()> {
// Extract from a single HTML file
let result = extract_attachments_from_html("./exports/My Note -- abc123.html")?;
println!("Extracted {} images", result.attachments.len());
// Extract from all HTML files in a directory (recursive)
let results = extract_attachments_from_directory("./exports")?;
let total: usize = results.iter().map(|r| r.attachments.len()).sum();
println!("Extracted {total} images from {} files", results.len());
Ok(())
}
The library provides a custom ExportError type:
use apple_notes_exporter_rs::{export_folder, ExportError};
fn main() {
match export_folder("My Notes", "./exports") {
Ok(()) => println!("Export successful!"),
Err(ExportError::ScriptNotFound(path)) => {
eprintln!("Script not found: {}", path.display());
}
Err(ExportError::ScriptFailed(code)) => {
eprintln!("AppleScript failed with exit code: {}", code);
}
Err(e) => eprintln!("Error: {}", e),
}
}
Folder Search: The tool uses breadth-first search (BFS) to find the specified folder at any level in your Apple Notes hierarchy (not just top-level folders).
Export Process: Once found, it recursively exports that folder and all its subfolders, creating a mirrored directory tree.
Output Format: Each note is exported as an HTML file, preserving the folder structure in the output directory.
Image Extraction: By default, embedded base64 images in the HTML are extracted to separate files in a companion <note-name>-attachments/ folder. The HTML is updated to reference the local files. Supported formats: PNG, JPEG, GIF, WebP, SVG, BMP, TIFF.
Account Handling: By default, the folder search looks in all accounts. If a folder name exists in multiple accounts, you can specify the account using the AccountName:FolderName format.
This tool is macOS-specific as it relies on AppleScript to interact with the Notes app. While the library can be compiled on any platform, running it on non-macOS systems will return an error at runtime.
Important: This tool requires Automation permissions for the Notes app. You'll need to grant these permissions when you first run the tool:
If permissions are not granted, the export will fail.
apple-notes-exporter-rs/
├── src/
│ ├── lib.rs # Library: export API + attachment extraction
│ └── main.rs # CLI application
├── vendor/
│ └── apple-notes-exporter/
│ └── scripts/
│ └── export_notes.applescript # AppleScript used for export
├── Cargo.toml
└── README.md
This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.
This tool uses the AppleScript from the apple-notes-exporter project, which is included as a git submodule.