Saving and changes on disk
n0te’s promise is that it never loses your words and never clobbers anyone else’s. This page is how it keeps it.
When n0te saves
There’s no save button to forget. n0te saves:
- a second after you stop typing;
- when you press
escto finish an edit; - when its window loses focus;
- when you close the window, or leave the note for another;
- for every open note, on
n0 --quit. If one can’t be saved, the service doesn’t quit, and says which.
A note you only read is never written. (The exception is today’s daily note: --today, the palette’s Today’s daily note and -t create it from your template as soon as they need it.)
How it writes
- It checks the disk first. Just before writing, n0te reads the file again. If it changed since n0te last saw it, that change is merged first (see below), so nothing is ever overwritten blind.
- It changes only what you changed. The new text is your edited block spliced into the file as it is on disk. Every other block goes back byte for byte.
- It writes atomically. The text goes to a hidden temporary file next to the note (
.NAME.n0te-PID~), which is flushed to disk, then renamed over the note. Readers see the old file or the new one, never half of one, and Obsidian sees one clean change.
It keeps the file’s permissions, follows symlinks (the file they point to is replaced, and the link stays), and keeps the line endings (LF or CRLF) and the final newline, or the lack of one.
In a folder you can’t write to, the temporary file can’t be made; a note there that you can write is saved in place instead.
When a save fails
No permission, a full disk, a missing folder: the status line turns red and says why (NOT SAVED · …). Your text stays in the window. Closing the window or leaving the note then takes a second try (do that again to discard your changes), and only that drops the change.
When the file changes on disk
n0te watches the file it shows. When something else writes to it (Obsidian, Obsidian Sync, Syncthing, git pull, a script) n0te waits until two reads in a row agree, so a file still being written isn’t taken half-done. Its own saves are recognised and ignored.
- Nothing unsaved: the page reloads in place, without jumping, and the status line says
Reloaded: changed on disk. - You’re editing: n0te merges. It compares three versions: the file as it was when you started, yours, and the one on disk now. Changes on either side are kept. Notes merge block by block, and then line by line inside a block; code merges line by line. Your edit stays open where it was. The status line says
Merged changes from disk. - The same lines changed on both sides: in a note, n0te keeps both versions, yours first, saves, and says
kept both versions, yours first. Tidy up whichever you don’t want.
Holds
A few situations are too risky to settle on its own. Then n0te holds: autosave pauses, the status line says why in red, and you decide.
| Status line | What happened | What to do |
|---|---|---|
CONFLICT MARKERS FROM A MERGE | A merge in a code file hit lines changed on both sides, and n0te wrote git-style <<<<<<< markers into your copy | Fix them, then ctrl s |
CHANGED ON DISK TOO | Both sides changed, and the file was too big to merge | ctrl s keeps yours. To take the disk’s, esc, then r twice |
MOVED OR DELETED ON DISK | The file is gone from where it was | ctrl s writes your unsaved changes back at the old path. With nothing unsaved, there’s nothing to keep: close the window |
BINARY ON DISK NOW | The file on disk turned binary (NUL bytes) | ctrl s keeps yours. To take the disk’s (read-only), r twice |
ctrl s works while reading and while editing. r reloads only while reading, and during a hold the first press warns that your version will be dropped (do that again to discard your changes); a second press within five seconds does it.
A moved file isn’t silently recreated, because that would undo a deliberate move or delete. But two common cases need no hold:
- A rename in Obsidian is followed: the window switches to the new name.
- Vim and Emacs rename a file to a backup while saving it. n0te ignores that rename and stays on the file.
Undo across changes
u undoes your edits as merges, too: it takes out your change and keeps anything that changed on disk since. History is kept per file for as long as the service runs, so it survives closing and reopening a note, but not n0 --quit or a logout.
The updated: date
With Set updated: to today when saving on, a save that changes something also sets a plain updated: YYYY-MM-DD in the frontmatter to today. The new date is exactly as long as the old one, so nothing else moves. It’s skipped while you’re editing the frontmatter yourself, or the whole note as source.