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.
pulldownloads remote changes and propagates unchanged remote deletions locally.pushuploads local changes and propagates unchanged local deletions remotely.syncreconciles both directions, including three-way merges.--dry-runon these commands reads and plans without writing local or remote data.resolve FILEuploads an edited conflict file after checking the latest remote version.link FILE --remote-uid UIDexplicitly 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)
| File | Size | Uploaded | |
|---|---|---|---|
| appletextnotes-0.1.0.tar.gz | 90.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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