# Backup and restore (/features/backup)



A backup is the **whole automation document**: every profile's shortcuts, leader
menus, snippets and flows, plus the Hyper key, double-tap, the Fn key, the alert
style, the window-arranging settings and the appearance. One file. Moving to a
new Mac is a backup and a restore, and nothing else.

It is also a **sharing format**, and that is an intended use rather than a side
effect. One person hands the file to another, and most of the care in this
feature is answering that: a Lumi document can make the recipient's Mac run a
program on a keystroke, so nothing arrives without having been described first.

**General → Backup**, two sections and two buttons.

{/* TODO: <Screenshot name="general-backup" alt="General → Backup: Back up and Restore, a button each" /> — see public/screenshots/README.md */}

## Back up [#back-up]

**Back up…** opens a form of ten ticks, a summary line, and an optional
password.

{/* TODO: <Screenshot name="backup-sheet" alt="The Back up sheet: ten ticks with counts, the Encryption section, and the summary line" /> */}

| Tick                 | Carries                                                                                                                                                               |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Shortcuts**        | Every shortcut row in every profile — leader menu steps included, because a step is a shortcut with a key instead of a combination — and Lumi's own **App shortcuts** |
| **Snippets**         | Every snippet, with its trigger, replacement, scope and expand key                                                                                                    |
| **Flows**            | Every flow file                                                                                                                                                       |
| **Hyper key**        | The modifier set, and what a tap does                                                                                                                                 |
| **Double-tap**       | Whether it runs, and the timing, shared and per key                                                                                                                   |
| **Fn key**           | Whether Fn is a modifier                                                                                                                                              |
| **Menus settings**   | The leader panel's timeout, layout and column count — **not** the menus themselves, which ride with Shortcuts                                                         |
| **Alerts settings**  | Position, size, theme and duration                                                                                                                                    |
| **Windows settings** | The arrange animation, and what happens to a window that hangs off an edge                                                                                            |
| **Appearance**       | Light / Dark / System, and whether the profile name is drawn in the menu bar                                                                                          |

Each tick carries the number of rows behind it. A tick with **nothing** behind
it is drawn disabled and says `none` where the number would be — never as a
ticked zero. The two look alike for a moment and mean opposite things: one is
*you have no snippets*, the other is *your snippets are not going in*, and a
file that claims to hold snippets and holds none is the one claim a backup must
not make.

The form opens with everything this Mac actually has switched on. The line
beside the button says what the press will produce — `All 8 · full backup`, or
`5 of 8`. **Full backup** means every tick the machine can offer, which is not
the same as every tick on: a Mac with no flows cannot write a file holding
flows, so eight of ten on a machine with two empty parts is still the whole of
what it has.

### Menus is the one tick whose name reads wrong [#menus-is-the-one-tick-whose-name-reads-wrong]

It carries the **Menus tab's own settings** and nothing else, which is why it
draws no number. The menus themselves — every step of every tier — go with
**Shortcuts**.

That is not an oversight, and splitting them was tried. A leader menu is not
only its steps: the shortcut that *opens* one is an ordinary row whose action
happens to be Open menu, so it falls on the Shortcuts side however the line is
drawn. Menus alone restored steps with no key that reaches them; Shortcuts alone
restored openers onto menus with nothing in them. One array, one owner.

### Encryption [#encryption]

A shut section under the ticks, with **Password** and **Confirm**. Leave it
empty and the file is plain text.

The **Confirm** field earns its place: a typo here is the worst failure this
feature has. One wrong keystroke writes a file that can never be opened, nothing
says so, and the day it is needed is the day the original is already gone.

A password is Argon2id over XChaCha20-Poly1305, and **only the payload is
encrypted**. The header stays readable, so a locked file still identifies itself
as a Lumi backup and still says which parts it claims to hold — which is how
somebody learns they have the right file before going to look for the password.
It leaks category names, and no trigger, no script, no URL, no profile name and
no counts.

<Callout type="warn" title="A password cannot be recovered">
  Lumi does not keep it and cannot reset it. A locked backup whose password is
  gone is gone.
</Callout>

### Before this leaves your Mac [#before-this-leaves-your-mac]

Where the document holds something notable, a second step stands between the
form and the save panel:

| Group                                     | What is listed                                                                                                                                                                     |
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Runs code on the recipient's Mac**      | Every **Run command** row, program and arguments shown whole; every **Transform selection** script; every snippet whose replacement is a script; every `script.run` node in a flow |
| **May hold a credential**                 | Free text that matched a credential's name or shape — an `Authorization` header in an HTTP node, a token-looking string in a param                                                 |
| **Addresses restoring this will request** | Every `web:` row icon. A shared document quietly tells its author's server who opened it                                                                                           |
| **Applications named**                    | Every bundle id in the file, which together are a fingerprint of a toolchain and an employer                                                                                       |
| **Rows that could not be read**           | Counted, because a reading that cannot see something must not imply it has                                                                                                         |

{/* TODO: <Screenshot name="backup-reading" alt="Before this leaves your Mac: a Run command row shown whole under Runs code on the recipient's Mac" /> */}

It is drawn **only when it has something to say**, and that is deliberate. Every
document names applications and holds free text, so a screen keyed on those is a
screen on every export — and a screen that is blank or boring most times is one
people learn to press past, then do not read on the day it is full. The button
says which of the two the press will be, so a second step is never a surprise
and neither is its absence.

It is a *reading of the source, not an enforcement*. Nothing is removed: a
silently stripped command would produce a file that restores into something
nobody described.

### What is never in a backup [#what-is-never-in-a-backup]

Your licence, your [expansion history](/features/snippets#history), the
usage-reporting state, the cached site icons and Lumi's own log — whatever is
ticked.

The licence is the one that would turn a backup into a way of handing Pro
around. The expansion history withholds the clipboard and keeps every other
expansion's output verbatim, which in a file meant for somebody else is a log of
what a person typed and where. The rest are machine identity, a cache and this
Mac's diary.

### What does not travel, and why [#what-does-not-travel-and-why]

A few more things are held back even though they look like ordinary settings,
and one rule covers all of them:

> A key travels only if it is a preference about the work. A fact about this
> Mac, and any grant of permission, never travels.

| Held back                                       | Because                                                                                                                       |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
| **Share usage data**                            | Restoring `true` turns usage reporting on for somebody who never consented                                                    |
| **Start at login**                              | It writes a real login agent — and a restored `false` would **remove** one the recipient deliberately installed               |
| **Let flows reach this network**                | A grant of access to the recipient's own LAN, which no document from elsewhere has standing to award                          |
| **Keep expansion history**                      | Plain-text logging of everything somebody types. `true` starts it on a Mac that never asked; `false` stops it on one that did |
| **Onboarding, the last pane, a skipped update** | Facts about this Mac                                                                                                          |

The two **grants** — the network switch and the history switch — are read in
**both** directions: the export leaves them out, and the restore puts this Mac's
own values back afterwards. Either half
alone gets it wrong — strip it on the way out and writing the document over a
live one *clears* the grant, which is the same mistake landing the other way up.

## Restore [#restore]

**Restore…** is two steps: where the backup is, then what it will write.

### Step one — three doors [#step-one--three-doors]

* **Choose a file…**, or drop one on the card. Dropping a backup anywhere in the
  Backup section opens the sheet already holding it.
* **From a link.** Paste an address and press **Fetch**. Fifteen seconds, five
  megabytes, and addresses on this machine or this network are refused outright
  — download the file and open it instead. *Let flows reach this network* does
  not lift that: it is about a flow node somebody wrote, and a URL Lumi fetches
  on its own behalf is the other kind.
* **Copies on this Mac** — the snapshots earlier restores left behind. Shut to
  start, because the ordinary restore is not this one.

There is no Continue here. Choosing a source *is* the advance.

{/* TODO: <Screenshot name="restore-source" alt="Restore step one: the file card, the link field, and Copies on this Mac" /> */}

A **locked** file asks for its password at this step. The password is held for
that one exchange: never logged, never put in a sentence, never sent back out,
and gone when the prompt is.

### Step two — what it will write [#step-two--what-it-will-write]

The document is read and **staged** by step one, and the restore acts on what
was staged rather than re-reading its input. That matters most for the link: a
server can serve two different files a second apart, so re-fetching at the press
would review one document and write another.

The review draws:

* **The ten ticks again**, with what the *file* holds behind each. A part the
  file does not carry is drawn disabled and says `none`.
* **Profiles**, each marked `new` or `replaced` — `replaced` meaning this Mac
  already has a profile under that id, and this restore writes over its
  documents. The profile list is written **whatever is ticked**, because a
  document holding one profile's snippets with no way to say whose they were is
  not a smaller backup, it is an unreadable one.
* **What this document reaches** — every shortcut row that touches anything
  outside Lumi, with the capabilities it claims in the same words the flow
  import review uses, and a **Run command** row's program and arguments shown
  whole.
* **Rows that could not be read**, if any. They go in exactly as written and do
  not run.
* **Parts this Lumi does not know about**, if the file came from a newer build.
  Counted and named, never fatal.

{/* TODO: <Screenshot name="restore-review" alt="Restore step two: what the file holds, the profiles it carries, and what this document reaches" /> */}

A backup claiming a **format** this build does not know is refused, and
everything else on the screen is withheld with it. Nothing was read, so there is
nothing the screen could honestly say — and a screen that drew its empty lists
anyway would tell you a file full of shell commands reaches nothing.

### Replace, or patch [#replace-or-patch]

The sentence &#x2A;"Replace. Everything in this backup takes the place of what you
have, and profiles it does not name are removed."* appears when **two** things
are true at once: every tick is on, **and** the file is a complete document
rather than a slice.

Both halves are needed, and the second is the one no reading of the switches
gets you to. Replacing a tree from a file that was only ever a slice deletes
rows nobody chose to lose — *I ticked everything* is not consent to lose what
the file never had. Ten switches all on look exactly like ten switches all on,
whichever kind of file is behind them.

Anything else is a **patch**: for the parts you ticked the document is
authoritative, including by omission, and every other setting is left exactly as
it is.

A replace asks twice. The first **Restore*&#x2A; turns into &#x2A;"This replaces
everything Lumi automates. Press Restore again to go ahead."*

### From a link, five things arrive switched off [#from-a-link-five-things-arrive-switched-off]

A backup taken off your own disk is your own state, and switching thirty rows
back on by hand is a restore that has failed at being one. A document off a link
is an outside document asking for a global hotkey, so these arrive with their
switch off:

* **Run command** — an arbitrary program with an arbitrary argument list
* **Transform selection** carrying a script
* **System command**, which reaches shut down
* **Force quit app**, which takes whatever you are looking at with nothing saved
* **Open URL** on a scheme outside `https`, `http` and `mailto`, which hands a
  payload to whichever application registered it

Every row that does is badged **Arrives off** on the review.

**Quit app is deliberately not on that list**, and the pair is the argument. The
line being drawn is whether you get a say: Quit asks the application, which puts
its own save sheet up, and Escape is the whole cost of a row that was not
wanted. Force quit asks nobody.

A row this build cannot read arrives off too, which is the subtle one. It cannot
run here, because nothing knows what it is — which is exactly what makes it look
harmless. What makes it not harmless is that it is kept verbatim and written
back on every save, so it is still there at the next upgrade, and *that* build
may know precisely what it means.

Everything else keeps the switch the document gives it. A pack of shortcuts that
open applications is the ordinary thing to share.

### Which profile you land in [#which-profile-you-land-in]

A backup names which profile was live when it was taken, and a restore makes
that one live — which is a [profile](/features/profiles) switch, and therefore a
[Pro](/pro) feature. On a free copy the switch is refused and Lumi stays on the
profile it is on; the review says which it will be before you press anything.

A leader menu that is open is closed, running flows are asked to stop, and the
keyboard is let go of before the tables are rebuilt.

## Copies Lumi keeps [#copies-lumi-keeps]

**Before the first byte moves**, a restore writes a full backup of what you
currently have, named for the date and time it was taken, and the line it
reports afterwards says where it went.

That copy ignores your ticks on purpose: what it has to be able to undo is *the
restore*, and the restore's ticks are a different question.

They are **never pruned**, and the sheet says so. What a restore replaced is
somebody's work, and an app that tidies away its own safety net after three of
them is an app that has one for the cases nobody needed. Delete them when you
want the space back — **Show in Finder**, under the list, opens the folder they
are in.

They are also the third door on the restore sheet, under **Copies on this Mac**,
each with its date and its size — restoring a copy *is* a restore, so it goes
through the same review as anything else.

## The file itself [#the-file-itself]

`Lumi Backup <date>.lumibackup.json`, and the name is the whole of what makes it
one: it is ordinary JSON, readable in any text editor unless you gave it a
password. The sheet says so out loud — &#x2A;A backup is plain text.*

<Callout title="Nothing is lost in transit">
  A setting a newer Lumi wrote and this one has never heard of survives a full
  backup and a full restore untouched, because the document is carried verbatim
  rather than rebuilt from the keys this build happens to know. That is the same
  promise a [flow file](/features/flows#flows-are-files) makes, one document up.
</Callout>

A backup from a **newer** Lumi is refused whole rather than half-applied: a
format this build does not know may put meaning in places this one does not
look, and a document half of whose meaning was skipped would do something nobody
wrote. The refusal names the format, so the answer is to update Lumi and open it
again.

## What it does not replace [#what-it-does-not-replace]

| For                             | Use                                                                                                                                        |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| One flow, to hand to somebody   | **Export** on the row in the Flows pane — see [Flows are files](/features/flows#flows-are-files)                                           |
| A set of snippets               | **Export…** at the foot of the Snippets list, which has a review of its own — see [Importing a pack](/features/snippets/#importing-a-pack) |
| One profile, copied on this Mac | **Duplicate** in [General → Profiles](/features/profiles#making-one)                                                                       |
| Your licence on a new Mac       | Paste the key — see [Moving to another Mac](/pro#moving-to-another-mac)                                                                    |
