Files
narl-workspace/docs/wiki/Not-Losing-Things.md
T
nvrl 4eb663e2d7 docs: a guide, a wiki and screenshots
The README grew a section per feature and is a good reference, but nothing
said where to begin. docs/wiki now has a getting-started page, a guide that
walks through one day with the workspace and explains each part where it comes
up, and a page per part of the app, each with screenshots of what it
describes.

Three pages are read out of the code rather than written, so they cannot drift
from it: the keys and commands from Help.svelte and commands.ts, the same lists
`:help` draws; the settings from .env.example, which gains a heading for the
vault, trash and history settings so they no longer sit under mail; and the
API from the README's table. `make wiki` writes them, and `--check` fails when
one is stale or a link between pages leads nowhere. `--publish` lays the pages
out for a GitHub wiki: links without `.md`, images beside them, `[[` escaped so
the wiki does not take a command's help text for a link to a page.

The screenshots are taken by `make screenshots`: the debug binary on a
temporary data directory, with a password made up for the run, filled with an
example workspace over the API, and a headless Chromium driven over the
DevTools protocol through the views the docs show. Nothing outside the
temporary directory is touched but docs/images, and the pictures are cut to
256 colours, a third of their size, which a dark UI does not show.

The README opens with the banner, a CI badge, the guide, the features grouped
by what they are for, and six of the screenshots.
2026-10-21 12:07:32 +02:00

4.3 KiB

Not losing things

The workspace is meant to be the one place things are kept, so it tries hard not to lose any of them. This page covers what protects your work, and how to get it back.

Saving

Each change is written to the browser's storage as it is typed and to the server a couple of seconds later. A dropped network, an expired session or a crashed tab does not lose a draft, and a save from elsewhere is not overwritten without asking. See Writing.

History

A save keeps the text it replaces. gh or :history lists the open document's earlier versions, the newest first.

Earlier versions of a document

The version under the cursor is shown as a diff against the text as it is now: - is what bringing it back would take out, + what it would put back. Enter brings it back, and the text it replaces becomes a version of its own, so a restore can be undone the same way.

  • Autosave writes every few seconds, so an ordinary save keeps a version at most every ten minutes.
  • :w!, a save over the SFTP mount, a link rewritten by a rename, and a restore always keep one, because each of them may undo something.
  • A rename alone keeps nothing.
  • The daily sweep forgets versions older than WORKSPACE_REVISION_DAYS (90 by default), but always keeps the newest 20 of each document.
  • An upload is kept as long as a version still embeds it. A file that has been sealed since is gone from the old version, because sealing deletes the plaintext on purpose.

The trash

A delete is not final. x, dd, :delete, :rmspace and an rm over the mount put what they delete in the trash, with everything inside it.

  • u puts the last delete back where it was: the same folder, the same name, unless a new one took the name meanwhile.
  • :trash lists everything in it, the last deleted first. j/k walk it, Enter or r restores, x deletes one for good, and :trash purge empties it. Each of these asks first.
  • Something whose folder has gone since comes back to the root of its space. Something whose space is in the trash too waits until the space is restored.
  • After WORKSPACE_TRASH_DAYS (30 by default) the daily sweep deletes it for good, files and all.

While it is in the trash, a node is out of sight: not in the tree, the search, the agenda, the mails, the SFTP mount, the export or the readable view on Proton Drive. A card whose notes are in the trash finds them again after a restore, and a shared document answers like an unknown link until it is restored, with the same link its readers already have.

Export

  • :export downloads the open document as markdown.
  • :export! downloads the whole workspace as a zip.

The zip needs nothing from this application to be read: the tree as real directories, one markdown file per document, every file where it sits, every embedded upload in media/, all under their real names, with relative links between them. What plain files have no place for (when each entry was written, names as they were typed, which space is the diary, the boards with their cards and rules) goes into one .workspace.json beside them.

:export! refuses while the vault is shut, because the archive has to hold the sealed files opened.

Import

  • :import picks a folder and uploads it into the one you are in. Directories become folders, .md and .markdown files become documents (named by their first heading), and anything else becomes a file.
  • :import! does the same with a zip.
  • :import! / pours an :export! back in at the root. Each directory becomes a space again, or goes into the space already there by that name, and with .workspace.json the dates, names, boards and cards come back as they were.

Links between imported files are rewritten as they land: a link to a markdown file becomes the document's address, a link to an image its upload. Anything pointing outside the upload is left as it was. Absolute paths, .. and anything else a zip might smuggle in are refused.

Backups

The data directory, WORKSPACE_DATA_DIR, is the whole backup: diary.db and uploads/. Before a new build changes the database it copies it to diary.db.pre-<version> next to it. The server can also mirror itself to Proton Drive, end-to-end encrypted; see Backup and mail.