# Command reference

Every command and flag of the `neverwiped` agent (version 0.3.0, restic 0.18.1). This page is generated from the agent’s source code, so it can’t drift from what the CLI accepts.

## How commands work {#basics}

The agent lives in `/usr/local/bin/neverwiped`. Every command runs **as root** (otherwise: `neverwiped doit être lancé en root`, “must be run as root”). Flags go before or after arguments, as `--flag value` or `--flag=value`. `-y` is short for `--yes`.

The CLI prints its messages in English by default, or in French or Spanish with `--lang fr|es` or `NEVERWIPED_LANG`; the [error messages page](/docs/errors) gives each one with its meaning. Example outputs on these pages are from a French session and are labelled.

## The install script {#install-sh}

```sh
curl -fsSL https://neverwiped.com/install.sh | sh
curl -fsSL https://neverwiped.com/install.sh | sh -s -- --api-key "$NEVERWIPED_API_KEY" --yes
curl -fsSL https://neverwiped.com/install.sh | NEVERWIPED_NO_SETUP=1 sh
```

The script detects the architecture (amd64 or arm64), downloads the agent, checks its SHA-256 fingerprint (written in the script itself), installs it in `/usr/local/bin/neverwiped`, then runs `neverwiped install` with everything you put after `sh -s --`. With `NEVERWIPED_NO_SETUP=1` it only installs the binary.

## Commands {#commands}

### `neverwiped install` {#cmd-install}

Registers this server, detects what to back up, shows the plan, schedules backups and runs the first one. Running it again on an installed server recomputes the plan; it never creates a second server.

```text
neverwiped install [--api-key KEY] [--yes] [--no-backup] [--include PATH]... [--exclude PATTERN]... [--preset NAME]... [--no-databases] [--no-docker] [--no-estimate] [--limit-upload RATE] [--limit-cpus N] [--priority low|normal] [--same-server] [--api-url URL]
```

| Option | What it does |
|---|---|
| `--api-key KEY` | Account API key (`nw_acc_…`) from your dashboard, API keys. Else `NEVERWIPED_API_KEY`, else a question on the terminal. Ignored once the server is registered. |
| `--api-url URL` | Platform address; install.sh already passes it. Else `NEVERWIPED_API_URL`. |
| `--include PATH` | Adds a folder to the plan. Repeatable: `--include /data --include /opt/app`. |
| `--exclude PATTERN` | Excludes files (restic pattern such as `"*.log"` or `/var/www/site/tmp`). Repeatable. |
| `--preset` | Adds a set of exclusions: `logs`, `build`, `trash`, `disk-images`, `archives`, or `all`. Repeatable, or comma-separated. None is on by default; the size estimate says what each would save. See the getting-started guide for the patterns. |
| `--pause-volume` | Backs this Docker volume up with its running containers paused for a local copy (seconds to minutes), instead of reading it live. Repeatable. |
| `--live-volume` | Reads this Docker volume live, without pausing its containers (the default for volumes that are not a database). Repeatable. |
| `--limit-upload RATE` | Caps the upload to the storage, for example `20mbit` (also `20Mbps`), `800kbit`, `2MB`, `500KiB`; `off` removes the limit. A unit is required: Mbit/s and MB/s differ by 8. The restore is never limited. Kept when `install` runs again without it. |
| `--limit-cpus N` | Lets restic use at most N cores (GOMAXPROCS) for reading, compressing and encrypting; `off` uses every core. A cap on parallel work, not an exact quota. Kept when `install` runs again without it. |
| `--priority` | `low` (default): restic and the local database export tools run under nice 10 and the idle disk class, so the site comes first. `normal`: as any other process, for a faster backup. Kept when `install` runs again without it. |
| `--yes`, `-y` | Answers yes to every question: accepts the plan and runs the first backup. Required without a terminal (scripts, AI agents). `-y` works too. |
| `--no-backup` | Doesn’t run the first backup; it runs at the scheduled time or with `neverwiped backup now`. |
| `--no-databases` | Backs up no database, local or in Docker. |
| `--no-docker` | Ignores Docker: no volumes, no databases in containers. |
| `--no-estimate` | Skips the size estimate shown with the plan (and the quota check before the first backup). Useful on servers with millions of files. |
| `--same-server` | Only when the agent stopped with “this configuration belongs to the server … and was copied to another machine” on the server itself, because its machine ID changed (OS reinstalled with `/etc/neverwiped` put back, `/etc/machine-id` regenerated). Records the new machine ID and keeps the same server and keys. Never on a copy: there, run `neverwiped uninstall --yes`, then install again, so the copy gets its own keys. |

### `neverwiped estimate` {#cmd-estimate}

Shows the plan `install` would propose and measures it: size and files of each folder and Docker volume after the exclusions, the largest folders, the size of local database files, and how much each preset would remove. Reads file sizes only, registers nothing, makes no network call. Run it before subscribing to pick a plan.

```text
neverwiped estimate [--include PATH]... [--exclude PATTERN]... [--preset NAME]... [--no-databases] [--no-docker] [--json] [--max-seconds N]
```

| Option | What it does |
|---|---|
| `--include PATH` | Adds a folder, as with `install`. |
| `--exclude PATTERN` | Excludes files (restic pattern), as with `install`. |
| `--preset` | Applies a preset of exclusions, as with `install`. |
| `--pause-volume` | Marks a Docker volume as copied paused, as with `install` (its copy size is shown). |
| `--live-volume` | Marks a Docker volume as read live, as with `install`. |
| `--max-seconds` | Stops measuring after N seconds and prints the result as “at least”. No limit by default (install stops at 90 s). |
| `--json` | JSON output (`plan`, then `estimate` with `files.bytes`, `files.files`, `files.partial`, `files.sources`, `files.largest`, `files.savings`, `databases_on_disk_bytes`, `databases_not_measured`, `pause_copy_bytes`), for scripts and AI agents. |
| `--no-databases` | Leaves the databases out, as with `install`. |
| `--no-docker` | Ignores Docker, as with `install`. |

### `neverwiped status` {#cmd-status}

Shows the server, the plan of what is backed up, your subscription, whether backups are active, storage used, the last successful backup, the schedule found and the last log lines.

```text
neverwiped status [--json]
```

| Option | What it does |
|---|---|
| `--json` | JSON output (`hostname`, `server_id`, `agent_version`, `plan`, `platform` with the subscription, storage used and last backup, `schedule`, `limits`, `log_file`; `platform_error` when the platform can’t be reached), for scripts and AI agents. Field names don’t change with the language. |

### `neverwiped limits` {#cmd-limits}

Shows or changes what backups may take from this server: the upload rate, the CPU cores restic may use, and the priority (low by default: nice 10 and the idle disk class). Without an option, it shows the current limits. They apply to every backup, scheduled or manual, and to the clean-up of old backups; restores are never limited. Works offline: the limits are kept in `/etc/neverwiped/config.json`.

```text
neverwiped limits [--limit-upload RATE|off] [--limit-cpus N|off] [--priority low|normal] [--json]
```

| Option | What it does |
|---|---|
| `--limit-upload RATE` | Caps the upload to the storage, for example `20mbit` (also `20Mbps`), `800kbit`, `2MB`, `500KiB`; `off` removes the limit. A unit is required: Mbit/s and MB/s differ by 8. The restore is never limited. |
| `--limit-cpus N` | Lets restic use at most N cores (GOMAXPROCS) for reading, compressing and encrypting; `off` uses every core. A cap on parallel work, not an exact quota. |
| `--priority` | `low` (default): restic and the local database export tools run under nice 10 and the idle disk class, so the site comes first. `normal`: as any other process, for a faster backup. |
| `--json` | JSON output (`upload_kib_s`, 0 = no limit; `cpus`, 0 = every core; `cpus_total`; `priority`: `low` or `normal`), for scripts and AI agents. Also in `status --json` as `limits`. |

### `neverwiped backup now` {#cmd-backup}

Runs a backup now, with the saved plan. Only changes since the last backup are sent.

```text
neverwiped backup now
```

| Option | What it does |
|---|---|
| `--scheduled` | The form the schedule uses (systemd timer or cron). You don’t need to run it by hand. |

### `neverwiped check` {#cmd-check}

Checks that the stored backups are readable and complete, with `restic check` and your key (the platform and the storage cannot do it for you: they do not have the key). Changes nothing. Without an option only the structure is read; `--read` also reads back and decrypts part of the content, `--full` all of it. About once a week, after a successful backup, the agent runs it by itself on a different part each time. Exit code 0 when no error is found, 1 otherwise.

```text
neverwiped check [--read 5%|1/26|2G] [--full]
```

| Option | What it does |
|---|---|
| `--read` | Also reads back and decrypts part of the content: a percentage (`5%`), a part out of N (`1/26`) or an amount (`2G`), picked at random. |
| `--full` | Reads back all the content: long, and as much download as the size of the repository. |

### `neverwiped list` {#cmd-list}

Lists the backups you can restore, with date (server time), id, size added and contents.

```text
neverwiped list [--json]
```

| Option | What it does |
|---|---|
| `--json` | JSON output (restic snapshots: `id`, `short_id`, `time`, `hostname`, `paths`, `tags`, `summary`), for scripts and AI agents. |

### `neverwiped restore` {#cmd-restore}

Restores a backup: `latest`, a day `2026-11-03` (the last backup of that day), a minute `"2026-11-03 22:59"` or an id of at least 4 characters. With `--target`, into a separate folder; without it, in place, after you type RESTORE (or pass --yes). With an AI agent: `--plan` first, then the printed command with `--approve` after your OK.

```text
neverwiped restore <date|id|latest> [--target FOLDER] [--include PATH]... [--yes] [--plan | --approve CODE]
```

| Option | What it does |
|---|---|
| `--target FOLDER` | Restores into this folder, **without touching live files**. Original paths are recreated under it: `/var/www` becomes `FOLDER/var/www`. Asks before writing into a folder that isn’t empty. |
| `--include PATH` | Restores only this path, as it was on the server (for example `/var/www/site`). Repeatable. |
| `--approve CODE` | Runs the restore only if the code is the one `--plan` printed for this backup, folder and paths; otherwise refuses before writing anything. Stands for the confirmations the plan showed. The code is not a password: it ties an OK to one plan. Cannot be combined with `--plan`. |
| `--yes`, `-y` | Confirms without asking. For an in-place restore it is an explicit OK to overwrite. |
| `--plan` | Writes nothing: shows which backup, which paths and where the restore would write (in place or a separate folder, empty or not), an approval code and the exact command to run it. Takes no lock and does not contact the platform. For AI agents: show this plan, wait for the OK. |

### `neverwiped recover` {#cmd-recover}

On a new server, after losing the old one: gives this server access to the old server’s backups, with an account API key and the recovery key printed at install. The lost server’s storage credential and agent key are revoked; nothing is restored until you run `neverwiped restore`.

```text
neverwiped recover [--api-key KEY] [--server ID|HOSTNAME] [--recovery-key-file FILE] [--repo-key] [--yes] [--api-url URL]
```

| Option | What it does |
|---|---|
| `--api-key KEY` | Account API key (`nw_acc_…`). Else `NEVERWIPED_API_KEY`, else a question on the terminal. |
| `--server ID|HOSTNAME` | The lost server, by its ID or hostname (see the dashboard). Needed with `--yes` when the account has several servers; without it you choose from a list. |
| `--recovery-key-file FILE` | File holding the recovery key (printed once at install). Else `NEVERWIPED_RECOVERY_KEY`, else a hidden question on the terminal. The key is never sent to NeverWiped. |
| `--api-url URL` | Platform address. Else `NEVERWIPED_API_URL`. |
| `--yes`, `-y` | Confirms without asking (the lost server’s credentials are revoked). Required without a terminal. |
| `--repo-key` | The key file holds a copy of the lost server’s `/etc/neverwiped/repo.key` (from a copy of that folder or a disk snapshot), not a recovery key. The check code is not compared; restic checks the key once the storage credential is re-issued, so a wrong key still revokes the lost server’s credential. |

### `neverwiped recovery-key` {#cmd-recovery-key}

For a lost or doubtful recovery key, on the server itself while it still runs. `check` tests a key against this server’s backups and says whether it is the current one; the key is not sent anywhere. `new` adds a new recovery key with this server’s `repo.key`, checks that it opens the backups, shows it once with its check code, and sends only the code to NeverWiped (the account owner gets an e-mail). The old recovery key is not removed and still opens the backups. Once the server is gone, neither command can help. See [Encryption](/docs/encryption#lost).

```text
neverwiped recovery-key check [--recovery-key-file FILE] | recovery-key new [--yes]
```

| Option | What it does |
|---|---|
| `--recovery-key-file FILE` | `check` only: file holding the key to test. Else `NEVERWIPED_RECOVERY_KEY`, else a hidden question on the terminal. |
| `--yes`, `-y` | `new` only: creates the key without asking. The key is still printed once: keep the output out of logs you share. |

### `neverwiped feedback` {#cmd-feedback}

Sends a message to the NeverWiped team: the message, its kind and the agent version, nothing else (no hostname, no logs). It shows what will be sent and asks first. Without a message on the command line, it reads it from the standard input.

```text
neverwiped feedback [MESSAGE...] [--kind bug|idea|help|other] [--yes] [--api-key KEY]
```

| Option | What it does |
|---|---|
| `--kind KIND` | `bug`, `idea`, `help` or `other` (default). |
| `--api-key KEY` | Account API key, for a server where the agent isn’t installed. Else the agent key of this server, else `NEVERWIPED_API_KEY`. |
| `--api-url URL` | Platform address. Else the one saved at install, else `NEVERWIPED_API_URL`. |
| `--yes`, `-y` | Sends without asking. |

### `neverwiped update` {#cmd-update}

Updates the agent to a signed release. The list of releases must be signed by a release key built into the agent (the platform does not hold it), not expired and not older than the last one this server accepted; the binary must match its signed SHA-256 and size and pass a test run before it replaces the current one, which is kept for `--rollback`. If any step fails, nothing changes. Configuration, keys, repository and plan are untouched. Automatic update after the nightly backup is off by default.

```text
neverwiped update [--check] [--to VERSION] [--yes] | update --rollback | update --pin VERSION|X.Y|none | update --auto on|off
```

| Option | What it does |
|---|---|
| `--to` | Installs that exact version, older ones too (the confirmation then defaults to no). |
| `--pin` | `0.3.1` stays on that version, `0.3` on that line (fixes only), `none` follows the newest release. Settings only: installs nothing. |
| `--auto` | `on`: after the scheduled backup, at most once a day, installs what the pin allows; never changes the backup result. Off by default. |
| `--check` | Shows the installed version, the pin, automatic update and the release available. Installs nothing. |
| `--rollback` | Puts back the binary replaced by the last update, without network, and pins that version. Run again to undo. |
| `--yes`, `-y` | Confirms without asking. |

### `neverwiped uninstall` {#cmd-uninstall}

Removes the agent from this server: schedule, binary, restic, state, cache, configuration (unless --keep-config). It refuses while a backup, restore or check is running, and resumes any container a killed run left paused. The platform is told and the server’s key revoked. Your backups stay on the storage, or with --delete-backups their deletion is asked: the account owner confirms it in the dashboard. The log is kept unless --remove-log.

```text
neverwiped uninstall [--yes] [--keep-config] [--keep-backups | --delete-backups] [--remove-log]
```

| Option | What it does |
|---|---|
| `--yes`, `-y` | Confirms without asking. |
| `--keep-config` | Keeps `/etc/neverwiped` (configuration and the local encryption key). |
| `--keep-backups` | Keeps the backups on the storage without asking (the default with `--yes`). |
| `--delete-backups` | Asks the platform to delete this server’s backups. Nothing is deleted from the server: the account owner gets an e-mail with a link and confirms in the dashboard (the server’s keys cannot delete backups on request). |
| `--remove-log` | Also removes the log `/var/log/neverwiped.log` (kept by default). |

### `neverwiped mcp` {#cmd-mcp}

Runs a Model Context Protocol server on stdin/stdout for an AI agent working on this server (Claude Code, Codex, Cursor). Fixed tools: this server’s status, the account’s servers and run history (with an API token), and starting a backup. It never hands out a key, and restore, recover, uninstall and the other commands with a confirmation stay commands you type yourself.

```text
neverwiped mcp [--read-only] [--token-file FILE]
```

| Option | What it does |
|---|---|
| `--token-file` | File holding a read-only API token (`nw_tok_…`, client area > API keys > API tokens) for the account tools; otherwise `NEVERWIPED_API_TOKEN`. An account API key is refused. |
| `--read-only` | Leaves out the only write tool (starting a backup): the agent can only read. |

### `neverwiped version` {#cmd-version}

Prints the agent and restic versions.

```text
neverwiped version
```

Also: `neverwiped --version`, `neverwiped -v`

### `neverwiped help` {#cmd-help}

Prints the built-in help, in the CLI language.

```text
neverwiped help
```

Also: `neverwiped --help`, `neverwiped -h`


### Restoring databases in Docker {#docker-databases}

```sh
docker exec -i CONTAINER sh -c 'exec psql -U "${POSTGRES_USER:-postgres}" -d postgres' < /root/restore/var/lib/neverwiped/dumps/postgresql-docker-CONTAINER.sql
docker exec -i CONTAINER sh -c 'M=$(command -v mariadb || command -v mysql); MYSQL_PWD="${MARIADB_ROOT_PASSWORD:-${MYSQL_ROOT_PASSWORD:-}}" exec "$M" -uroot' < /root/restore/var/lib/neverwiped/dumps/mysql-docker-CONTAINER.sql
```

If the container reads its root password from a file (`MARIADB_ROOT_PASSWORD_FILE` or `MYSQL_ROOT_PASSWORD_FILE`), as the backup does, start the MySQL line's script with `MYSQL_PWD=$(cat "$MARIADB_ROOT_PASSWORD_FILE"); export MYSQL_PWD;` (or the `MYSQL_` name). To bring back one database alone, build its file first as shown in [A database](/docs/getting-started#database).

## Environment variables {#env}

| Variable | What it does |
|---|---|
| `NEVERWIPED_API_KEY` | Account API key for `install`, instead of `--api-key`. |
| `NEVERWIPED_API_TOKEN` | Read-only API token (`nw_tok_…`) for `mcp`, instead of `--token-file`: lets the AI agent list the account’s servers and run history. An account API key is refused. |
| `NEVERWIPED_API_URL` | Platform address for `install`, instead of `--api-url`. |
| `NEVERWIPED_LANG` | Language of the CLI: `en`, `fr` or `es`. Wins over the system locale (`LC_ALL`, `LC_MESSAGES`, `LANG`); `--lang` wins over it. English by default. |
| `NEVERWIPED_RECOVERY_KEY` | Recovery key for `recover` and `recovery-key check`, instead of `--recovery-key-file`. Avoid it in a shared shell history. |
| `NEVERWIPED_RELEASES_URL` | For `update`: another address for the signed releases (a mirror; default `<platform>/downloads/releases`). The signature is still checked with the built-in keys. |
| `NEVERWIPED_RESTIC_BASE_URL` | Download mirror for restic (same file names as the GitHub releases). The SHA-256 fingerprint is still checked. |
| `NEVERWIPED_ROOT` | Prefix for every path the agent uses (tests, containers). Not for production. |
| `NEVERWIPED_NO_SETUP` | install.sh only: installs the binary without running `neverwiped install`. |

## Exit codes {#exit}

| Code | Meaning |
|---|---|
| `0` | Success |
| `1` | Failure: the message follows `Erreur :` on standard error |
| `2` | Wrong usage: unknown flag, missing argument, API key missing with `--yes`, no command given |

## Check the schedule {#schedule}

```sh
systemctl list-timers neverwiped-backup.timer
cat /etc/cron.d/neverwiped
crontab -l | grep neverwiped
```

One of the three shows the schedule (systemd, cron, or root’s crontab on Alpine and BusyBox). If none does, run `neverwiped install --yes` again.
