Skip to main content

appletextnotes

Synchronize one IMAP Notes mailbox with editable UTF-8 plain-text files. Python 3.14 and Git (for the default merge command) are required. macOS and Linux are supported.

Install uv, then install appletextnotes:

uv tool install appletextnotes
appletextnotes --help

Set connection settings in your environment or an optional .env in the current working directory. Explicit command-line settings take precedence over environment variables, which take precedence over .env. Passwords have no CLI argument. If APPLETEXTNOTES_IMAP_PASSWORD is unset, network commands prompt for it with input hidden. The entered password is used only for that invocation and is never saved. Set the variable for unattended commands. An explicitly empty password is invalid.

export APPLETEXTNOTES_IMAP_SERVER=imap.example.org
export APPLETEXTNOTES_IMAP_USERNAME=you@example.org
# Optionally set APPLETEXTNOTES_IMAP_PASSWORD to skip the password prompt.
mkdir notes
cd notes
appletextnotes init
appletextnotes sync --dry-run
appletextnotes sync
appletextnotes status --json

init --create-folder explicitly permits creating a missing mailbox. Subsequent commands never recreate a missing mailbox. The default mailbox is Notes. --workspace PATH selects a workspace; other commands also search parent directories for an initialized workspace. Global options precede the command. status is offline and does not read credentials.

  • pull downloads remote changes and propagates unchanged remote deletions locally.
  • push uploads local changes and propagates unchanged local deletions remotely.
  • sync reconciles both directions, including three-way merges.
  • --dry-run on these commands reads and plans without writing local or remote data.
  • resolve FILE uploads an edited conflict file after checking the latest remote version.
  • link FILE --remote-uid UID explicitly associates a tracked file with a remote note.

Directional commands defer merges requiring writes to both sides; use sync for those changes. JSON plans name each action. Exit codes are 0 for success, 1 for operational errors, 2 for invalid configuration/input, and 3 for conflicts or uncertain identity. status --json reports persisted state, including pending operations and original conflict versions. Text status also compares local files.

Each note's first line is its title. Imported names have a permanent local ID: Title--id.txt. Title edits do not rename files. Create new notes as .txt files in the workspace root. Files are compared by content, independently of mtimes. Deletion is a synchronization action: use a dry run to review it.

All incoming HTML becomes plain text before comparison, storage, or merging. Formatting, images, attachments (including text attachments), scripts and styles are discarded. HTML alternatives take precedence over plain alternatives. Block breaks, list labels and table cells remain readable. Outgoing messages are always UTF-8 text/plain, with Apple note identification headers. Importing HTML alone does not replace the remote message.

Complete groups of four leading spaces become actual tabs; remainder, inline and trailing spaces remain. LF line endings and final-newline differences are preserved. Set APPLETEXTNOTES_INDENT_SPACES or --indent-spaces to change the width before initializing a workspace; changing it later can appear as content edits.

Setting (APPLETEXTNOTES_ prefix) Default
IMAP_SERVER, IMAP_USERNAME Required for network commands
IMAP_PASSWORD Prompted if unset
IMAP_FOLDER Notes
IMAP_SECURITY tls; alternatively starttls (required, verified)
IMAP_PORT 993 for TLS; 143 for STARTTLS
TIMEOUT_SECONDS 30
INDENT_SPACES 4
MERGE_TIMEOUT_SECONDS 30
MERGE_COMMAND JSON argv shown below

The default merge command works outside a Git repository:

["git", "merge-file", "--stdout", "--diff3", "{local}", "{base}", "{remote}"]

Override it using APPLETEXTNOTES_MERGE_COMMAND or --merge-command with a JSON argument array. All three placeholders are required. No shell is involved; shell metacharacters are literal. Literal braces in other arguments must be doubled. Inputs are UTF-8 files in a temporary .appletextnotes directory. The tool must output the complete merged text on stdout: exit 0 means clean, exit 1 means conflicted. The built-in Git adapter also accepts Git's positive conflict counts up to 127. Timeouts, invalid UTF-8, missing executables and other exit codes stop the operation without uploading. Interactive tools require a noninteractive wrapper.

Unresolved merges create identical marked copies in the tracked file and a .remote-conflict.txt companion. The remote stays unchanged. Edit the tracked file, remove all conflict markers, then run resolve FILE. Further remote edits are merged against the remote version observed at conflict creation. Companions are excluded from note discovery and removed after successful resolution. Edit-versus-delete conflicts also preserve both observations. Saving a resolved file and running resolve chooses to retain that note.

Identity uses known UIDs within UIDVALIDITY, then unique Apple UUIDs, Message-IDs, and exact canonical content. Titles and timestamps are never identity evidence. Clients that replace both UUID and content can require explicit linking; ambiguous remote additions are held for review rather than causing local deletions. Use a read-only IMAP client to inspect UIDs when linking.

Durable metadata lives solely in .appletextnotes/state.json, including merge bases, identity evidence, conflicts, completed tombstones, operation intents and recovery checkpoints. Atomic replacements and a transient directory lock protect writes. Symlinks and workspace escapes are rejected. Credentials are not stored in state. The state file does contain note content; protect and back it up with your files. Do not reuse a workspace with a different account, mailbox or transport identity.

APPEND intent is saved before transmission. Uploads use an operation-specific Message-ID and verify content before retiring the old UID. Restart searches before retrying an uncertain APPEND, preventing duplicate uploads. Only the exact old UID is flagged deleted. Selective expunge requires UIDPLUS; other servers keep that message flagged until another client expunges it. Mailbox-wide EXPUNGE and CLOSE are never issued. IMAP cannot provide a cross-client transaction: ambiguous races stop and retain observations in pending state. Back up state before manually repairing pending operations; do not delete state to bypass a recovery error.

See contributing, release procedures, and validation and Apple interoperability. Background scheduling, OAuth, attachment synchronization and CloudKit are outside this version's scope.

The development/release conventions are adapted from mdfluence. Apple note headers and replacement identity behavior were inspected in ImapNotes3.

Metadata

Release files for appletextnotes 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for appletextnotes 0.1.0
File Size Uploaded
appletextnotes-0.1.0.tar.gz 90.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for appletextnotes 0.1.0
File Interpreter ABI Platform
appletextnotes-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 115.9 kB

Release files / appletextnotes-0.1.0.tar.gz

Download URL appletextnotes-0.1.0.tar.gz
Size 90.8 kB
Tags Source
SHA-256 checksum
How to use checksums
4806bd30a59ec88e0c753df58f143893fec435d46e1f948251e22048967c1ef2
BLAKE2b-256 checksum
How to use checksums
ae5d9851bd641a6b71b9a3bf64b5749550c18ab72fe1818ec7b426cd06107988
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / appletextnotes-0.1.0-py3-none-any.whl

Download URL appletextnotes-0.1.0-py3-none-any.whl
Size 25.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4b589e99bffe63a925a50e59d9cb7edfd009a641613cafd6d869bcf8ae76778b
BLAKE2b-256 checksum
How to use checksums
6f0be2939ee580d1f1835bb8fdb58e624ae911911f7bef6538632bdd3ce1c858
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page