æaem
A tiny CLI for append-encrypted manifest snapshots.
aem takes the file tree you point it at, computes per-file content hashes,
seals them into a single append-only manifest, and never overwrites old entries.
It is a snapshot tool, not a sync tool: every run adds a row, nothing is ever deleted.
Designed for people who back up a small home server, a notebook, a single project directory — and want to know, years later, that a particular file existed on a particular date, with a particular hash.
Install
# go install
go install codeberg.org/mb/aem/cmd/aem@latest
# or download a release binary
curl -L https://aem.mectest.ru/dl/v0.4.2/aem_linux_amd64.tar.gz | tar xz
Quickstart
# 1. initialise a manifest in the current directory
$ aem init --passphrase-file ~/.aem.key
created .aem/manifest.aem (encrypted, append-only)
# 2. snapshot a directory
$ aem snap ~/photos
scanned 4128 files (12.7 GiB)
appended snapshot 0001 → manifest grew to 184 KiB
# 3. snap again later — only the delta is recorded
$ aem snap ~/photos
+ 24 new files, ~ 6 changed, − 0 missing
appended snapshot 0002 → manifest grew to 191 KiB
# 4. find what existed at a given date
$ aem at 2026-03-14 -- find img_4128.jpg
snapshot 0011 (2026-03-14 02:11 UTC)
img_4128.jpg sha256:a1c4… size:4.2 MiB mtime:2026-03-12 21:08
Manifest format
The manifest is a single append-only file (.aem/manifest.aem) — a stream
of length-prefixed CBOR records, each encrypted with XChaCha20-Poly1305 under a
key derived from your passphrase via Argon2id. Records carry their own MAC, so
truncation past any record boundary is detected on read.
| field | type | notes |
|---|---|---|
| id | uint64 | sequence, monotonic |
| at | uint64 | UTC unix seconds |
| path | bytes | relative, NFC |
| hash | bytes(32) | BLAKE3 |
| size | uint64 | file size at snap time |
| mtime | int64 | unix nanos |
Schema is versioned via a leading magic record. Older versions are read forward-compatibly; new fields are ignored gracefully.
Why "append-encrypted"
- Append-only — accidental deletion in one snapshot doesn't erase history. Old entries remain readable.
- Encrypted at rest — the manifest reveals nothing about your file tree to anyone without the passphrase.
- Single file — copy
.aem/manifest.aemanywhere. No state directories, no databases. - No daemons, no servers — runs locally, exits, leaves a file.
Roadmap
- v0.5 — incremental hashing on large files (currently rehashes whole file)
- v0.5 —
aem prunewith care-flags (manifest stays append-only; prune writes a new compacted file alongside) - v0.6 — Windows path normalisation
- v1.0 — frozen format, stable CLI
FAQ
Is the manifest format stable?
Not yet. Pre-1.0 means I reserve the right to break it. v0.x manifests will remain readable by future versions via the magic record.
What if I lose the passphrase?
The manifest is unrecoverable. The tool refuses to "help" you by being clever about this. Write the passphrase down. Argon2id parameters mean even a state actor takes years per guess for a 6-word diceware phrase.
Where do I report bugs?
The Codeberg repo — link at the bottom of the page.