Tutorials
Read your notes without Sempere
With your key, a copy of the vault, age, gunzip and jq, open a note on any Mac or Linux machine. No Sempere needed.
Sempere’s files are standard age files holding compressed JSON. If Sempere disappeared tomorrow, you could still read every note. This tutorial shows how, so you know it works.
You need: a copy of the vault folder, your recovery key (the recovery kit, or where you saved it), and these tools: age 1.3 or later (the official release binaries; older distribution packages cannot read post-quantum keys), gunzip, jq and tail.
1. Make a key file
Create recovery.txt with the recovery key on one line: the AGE-SECRET-KEY-PQ-1… line from your password manager, a key file you saved with Save to Files…, or the recovery kit’s text lines typed in one after another, without the line numbers and checksums. Keep it private:
chmod 600 recovery.txt
If you only have the vault’s passphrase copy, decrypt it instead (it asks for the passphrase): age -d "My Notes.sempere"/keys/recovery-*.key.age > recovery.txt.
2. Get the vault keys
Your notes are not encrypted to the recovery key itself, but to the vault’s key, which vault.json holds wrapped for the recovery key. After a device change there is one vault key per epoch, and each epoch’s record holds the one before. These lines, also printed on page 2 of the kit, collect them all into vault-keys.txt:
cd "My Notes.sempere"
jq -r '.keys[] | select(.role == "recovery") | .wrap' vault.json \
| age -d -i ~/recovery.txt > ~/vault-keys.txt
for pass in 1 2; do
for f in $(ls epochs | sort -t- -k1,1nr); do
age -d -i ~/vault-keys.txt "epochs/$f" | tail -c +38 | gunzip \
| jq -r '.parent.identity // empty' > ~/prev.txt
cat ~/prev.txt >> ~/vault-keys.txt
done
done
rm ~/prev.txt; chmod 600 ~/vault-keys.txt
(The kit’s version has one more step, for a vault in the middle of Re-encrypt Everything.)
3. Find a note
Note folders are named with random ids, not titles. Each folder holds revision files; the newest snapshot holds the whole note as it was then. This loop prints every note’s title:
cd notes
for d in */; do
f=$(ls "$d" | grep '\.snapshot\.age$' | sort | tail -n 1)
[ -n "$f" ] || continue
printf '%s ' "$d"
age -d -i ~/vault-keys.txt "$d$f" | tail -c +38 | gunzip | jq -r '.state.meta.title'
done
(A brand-new note may have only deltas and no snapshot yet; it is skipped here.)
4. Read it
cd 3f2c…/ # the note's folder
f=$(ls | grep '\.snapshot\.age$' | sort | tail -n 1)
age -d -i ~/vault-keys.txt "$f" | tail -c +38 | gunzip | jq . > note.json
jq -r '.state.meta | .title, .notebook, (.tags | join(", "))' note.json
jq -r '.state.pages[].recognition.text // empty' note.json # your handwriting, as text
What each step does:
age -d -i vault-keys.txtdecrypts the file with the vault keys.tail -c +38skips Sempere’s 37-byte header (a marker, a version byte and an authentication tag).gunzipdecompresses the JSON;jqmakes it readable.
The JSON holds the title, notebook and tags, every page with its paper, strokes (as points), items and recognized text, and the recordings. The format is documented in docs/format.md.
A snapshot shows the note as of when it was written. Later changes are in the .delta.age files after it, read the same way; each holds a list of operations (ops).
Attachments
Pictures, PDFs and recordings are in the note’s att/ folder. Their decrypted contents start with a 45-byte header, then the file, then padding. The format specification gives the commands to cut the file out with head, tail and xxd.
With the CLI or the viewer instead
If you have the sempere binary, sempere recover FILE.age --recovery-key recovery.txt does the same for one file and also checks its authentication tag, and sempere export --all --format pdf --recovery-key recovery.txt turns a whole vault into PDFs. The web viewer shows the notes as drawn.
Afterward, delete recovery.txt, vault-keys.txt and any note.json you made: the first two open every note, and the last is a note in plain text.