Operate
Backup & updates
Keeping a copy of your Omnesis data, getting it back, and moving every machine to a new
release: omnesis backup, restore and export,
omnesis update on one machine or the whole fleet, Docker and source installs,
and how the gateway judges which device versions it still supports. Commands run on the
gateway machine unless a section says otherwise.
Backup
omnesis backup takes a snapshot while the gateway keeps running, into
~/.config/omnesis/backups/<timestamp>/ on the gateway machine. It holds
the databases (documents, index, analytics), omnesis.json,
OMNESIS.md, tokens, config secrets, TLS certificates and a manifest.
--note labels a backup, --list shows the ones you have, and
--no-index leaves out index.db, the largest file, which the
gateway can rebuild from the documents.
❯ omnesis backup --note before-cleanup
Backup started… ✔ Backup complete: 8 files, 812.4 MB omnesis.db.enc 611.3 MB index.db.enc 182.0 MB analytics.db.enc 18.4 MB … Saved on the gateway host at ~/.config/omnesis/backups/2026-03-14T09-12-05
A backup leaves out four things:
- Models, which can be downloaded again.
-
Agent conversations (
conversations/): copy that directory yourself if you want to keep your chat history. - OAuth sign-ins (Google, Microsoft and similar): sources that use them ask you to sign in again after a restore. Pasted API keys are kept, because a platform that shows a key once cannot show it again.
- The root key of an encrypted install. With encryption at rest on, the backup's files are encrypted with that key, so keep the recovery code as well: without the key or the code, an encrypted backup cannot be opened.
omnesis update takes a backup of its own before it changes anything. After
each successful one, Omnesis keeps the newest two such pre-update backups and deletes
older ones; backups you took yourself are never deleted. Set
backupRetention.preUpdateCount to keep a different number, or
0 to keep them all.
Restore and export
omnesis restore <backup-dir> rebuilds a configuration directory from a
backup. Run it with the gateway stopped. It writes to ~/.config/omnesis/, or
to --target, and swaps the result in only once every file is in place, so a
failed restore leaves nothing half-written. Restoring over an existing corpus needs
--force, which replaces the whole directory.
An encrypted backup needs its root key. On the same machine, restore uses the key already
in the keyring. On a new machine, pass the recovery code with --code (or on
standard input) and restore rebuilds the key from it. The databases come back plaintext
and the gateway encrypts them again at its next start.
❯ omnesis backup --list
❯ omnesis service stop collector
❯ omnesis service stop gateway
❯ omnesis restore <backup-dir> --force
❯ omnesis service start gateway
❯ omnesis service start collector
Export
omnesis export writes your documents to
~/.config/omnesis/exports/<timestamp>/, as JSON lines by default or as
CSV, which leaves out the full text and adds one file per analytics table. It is for
taking your data elsewhere, not for restoring. On an encrypted install the export is
encrypted too; decrypt it with
omnesis keyring decrypt-artifact <export-dir> on a machine with the
same root key before using it outside Omnesis.
Updating
omnesis update moves a machine to the newest stable release and restarts what
runs there. It works the same for a source or Docker install, and Omnesis never starts it
on its own. Run it on the gateway machine first, then on each other machine, or add
--fleet to have the gateway ask the other machines to run it (see
Updating every machine).
❯ omnesis update
# or, for an unattended rollout
❯ omnesis update --yes
On a machine that runs the gateway, it does the following, in order:
- Back upthrough the gateway, skipping the index
- Installbuild the release, or pull the images
- Restart the gatewayits data migrations run; they only go forward
-
Wait for health
/healthmust report the new version - Restart the collectoronly now, so it never meets a half-migrated gateway
- Refresh agent harnessupdate the plugin; ask before restarting it
If it fails before health
- Automaticthe previous release is put back and restarted
Code returns; migrations that already ran do not.
To get the exact data back
- Stopcollector, then gateway
- Restorethe backup from step one
- Startgateway, then collector
By hand, with the commands under Restore.
A machine that only collects has nothing to back up: its collector simply restarts on the
new release. A machine with a connected agent harness (OpenClaw or Hermes) refreshes the
installed plugin, then asks before restarting the harness, since that interrupts whatever
the agent is doing; --yes answers that prompt too. If the harness's
authorization has lapsed, the update prints the command to renew it and leaves the harness
alone. omnesis devices list, omnesis doctor and the portal's
Devices page show any plugin refresh or restart still owed, with the command that finishes
it.
If it fails
A build that does not compile, or a gateway that does not come back healthy, returns the machine to the release it was running and restarts it there. Ctrl+C during the install or the health wait does the same once the running step has stopped. Once the gateway serves the new release nothing is undone; a collector the update did not reach is reported with the command to restart it.
The health wait lasts up to ten minutes, so a long migration can finish. A gateway whose process has exited does not use that time: when the service manager (systemd or launchd) has relaunched it twice during the wait, or has held no gateway process for 15 seconds, the update rolls back at once. A gateway that is still running keeps the whole wait.
Rolling back the code does not roll back the data. If the new gateway got far enough to
run its migrations, the previous release clears the sync positions the newer version wrote
and those sources sync again from the start. For the exact state before the update,
restore the backup from step one with the commands under Restore.
Skip that backup with --no-backup only when you have taken one yourself.
If the update was cut short by a power loss or a forced kill, run
omnesis update again: it notices the unfinished run, says what it will do,
and completes or repeats it.
On a machine with less than about 5 GB of memory in total (or a container limited to
less), a source build (which needs at least 3 GB for itself and about 2 GB beside it)
stops this account's collector while it builds and starts it again afterwards; the gateway
keeps serving. If the system stops the gateway for memory instead, it stays down until the
build is in place, and the update's own restart brings it up on the new release, however
often its service manager had tried to start it meanwhile. If the build is still killed,
the update says the machine most likely ran out of memory and rolls back. Stop the
collector and gateway (omnesis service stop collector,
omnesis service stop gateway), add swap or free memory, and run
omnesis update again.
On a source install, npm ci installs over the node_modules the
running release left. If that install fails, the update removes
node_modules and installs once more before it rolls back, and the rollback's
own install is retried the same way.
Options
| Flag | Effect |
|---|---|
--yes |
Answers every prompt, including harness restarts. Needed in scripts. |
--dry-run |
Prints the plan without changing anything. |
--target-version X.Y.Z |
Moves to one exact release instead of the newest. |
--commit <full-sha> |
Source installs only: fetches that exact 40-character commit from the checkout's
origin, for controlled testing between releases. With --fleet it is
offered only to paired machines verified as source installs; Docker installs and
phone apps are left alone. The portal's update action always targets releases.
|
--edge |
Follows the main branch instead of stable releases (source and Docker
installs).
|
--no-restart |
Installs, then reports which daemons still run the previous release. |
--no-backup |
Skips the pre-update backup. |
--health-timeout <seconds> |
Allows a long migration more than the default ten minutes. |
--wait-for-lock=<minutes> |
Waits for an update already running on this machine instead of refusing to start. |
--allow-rewind |
Source installs only: allows a target that is not a newer release and does not
contain the build installed now, such as going back from an exact-commit test
build. The commits it drops are listed. With --fleet, it is passed to
each machine commanded at that moment.
|
--force |
Allows moving to an older release, and implies --allow-rewind. There
are no down-migrations, and an older release clears the sync positions the newer
one wrote.
|
--fleet |
Afterwards, asks the gateway to update the other machines. |
Unless you pass --edge, the update installs only stable release tags. It
refuses a source checkout it did not install or adopt, a
checkout with local changes, and a tag whose contents do not match its name.
A source install that was moved to an exact commit, for example an unmerged test build,
updates to the next release normally: a newer release is a forward update even when it was
cut without that commit, and the update lists the commits it leaves behind. A target at
the same or an older version that does not contain the installed build is refused unless
you pass --allow-rewind.
The same rule covers a repository whose history was replaced, so that the target shares no
commits with the installed build: a newer version is a forward update, and the update says
the history was replaced instead of listing commits. This holds for stable and edge
installs alike. When the installer itself moves an existing checkout, as it does with
--reconfigure, it applies the same rules, with --force in place
of --allow-rewind.
Running the install command again on a machine it already set up is an update: the
installer finds the checkout the earlier install recorded, makes sure it can fetch from
its origin, and runs omnesis update on the machine, so the update backs up,
rebuilds, refreshes the service definitions, restarts and rolls back exactly as described
above. The certificate, keyring, embedding model and pairing stay as they are, so a
collector does not pair again. A plain re-run updates any machine that runs a gateway or a
collector; to turn a collector machine into a gateway, pass --reconfigure.
The full install also runs for --collector or --client-only on a
machine with another role, for a first install that never registered its services, and for
a flag that sets one of the kept choices, such as --code,
--mkcert or --embedder.
Several collectors, one source
Update the gateway first, then every collector. A collector newer than its gateway reports
Gateway upgrade required and waits. If several collectors host the same
source, update all of them: until they are all on the new release, the older ones may be
unable to sync that source or change its settings, and the sync status of each collector
that needs updating says so. Sources hosted only by older collectors keep working.
Release notices
The gateway checks for a newer stable release shortly after it starts and every 24 hours,
asking the source checkout's origin or the container registry, according to how it was
installed. Clients do not check. A newer release shows as a quiet line in the portal
sidebar and in omnesis doctor; failures say nothing. The check never
downloads or installs anything. What each release changes is in the
release notes and the
changelog.
It does tell that Git host or registry the gateway's network address. Omnesis adds no
install identifier, corpus data or version information to the request. Turn it off with
omnesis config set /releaseCheck false.
Daemons the update cannot restart
The update restarts only services that belong to the account running it. A daemon started
by hand, a hardened gateway, or a named instance is
reported as still running the previous release, with the command to restart it when the
machine knows it. A collector is restarted only once its own gateway is serving the new
release; if the gateway could not be restarted, the collector is reported instead. A
hardened gateway is updated with its own root
command, which omnesis update prints.
How the updater works
The update runs in two halves. The release already installed finds the target and puts
it in place. Everything after that (the backup when it can wait, the restarts, the
health wait, the harness refresh and any rollback) is run by the newly installed
release, so a fix to those steps applies to the update that delivers it. Only one update
runs on a machine at a time; a second is refused with the running process and its
current step, or waits with --wait-for-lock. The lock of a killed update is
recovered automatically after a short interval.
Where the gateway runs from the installation being updated, it is backed up before the install. A gateway in a container or on a hardened release keeps serving its current build during the install and is backed up after it, before anything restarts. A gateway that is not running is backed up by copying its closed databases into the same backups folder.
Before restarting a daemon, the update rewrites its launchd plist or systemd unit to
what the new release's omnesis service install would write, keeping its
executable, configuration directory, keyring wiring and environment. A unit it cannot
rewrite without losing something (a systemd drop-in, EnvironmentFile=, a
comment, or a setting service install does not write) is left alone and
reported; a hardened gateway's unit and named instances are never rewritten.
A source install writes a completion record once its build succeeds, and a Docker
install once the gateway answers with the new image; the next run uses it to decide
whether an interrupted update must be repeated. A source build sizes its memory from the
machine as the installer does, and never overrides a heap size you set in
NODE_OPTIONS.
Updating every machine
omnesis update --fleet on the gateway machine updates that machine, waits up
to 90 seconds for the collectors and agent harnesses that were connected to reconnect, and
then asks each one to run omnesis update on itself. You confirm each machine
after seeing its current and target version; --yes confirms them all. It then
waits, up to 45 minutes, for each commanded machine to report: updated, restart still
owed, or failed with its reason. The command exits with an error when any machine failed
or never answered, so a machine that refused cannot pass for one that updated.
# on the gateway machine
❯ omnesis update --fleet
No code travels over the connection. A device receives only a version number, runs its own update against its own release source, and refuses a version that is not a real release there, so a tampered gateway cannot make a machine run code of someone else's choosing. A device is only ever sent the version the gateway is serving, so it can never be moved past its gateway; if the gateway could not be restarted, the fleet step stops and says so. A device that is offline keeps the request and runs it when it next connects.
A collector restarts on the new release when it finishes, through its service or, when it was started some other way, by exiting for its supervisor to restart. A machine with an agent harness installs the new plugin and restarts the harness. OpenClaw restarts at once, interrupting any agent run in progress. Hermes lets running work finish for up to its drain timeout (three minutes by default) first. When the harness cannot be restarted from there, its device row records the restart still owed and the command to run.
--dry-run cannot be combined with --fleet, because the fleet
step depends on what the gateway serves after this machine moves; preview this machine
with omnesis update --dry-run. --edge cannot be combined with it
either, since a branch build has no release number to send.
The gateway will not command these devices, and says which ones to update yourself:
- Phones and the browser extension, whose builds are installed outside the gateway (see Getting the apps).
-
A device that has never reported its version, or one below the oldest
release the gateway supports (the unknown and unsupported states under
Version compatibility). Run
omnesis updateon that machine. - A machine with no Omnesis daemon, such as a paired CLI, a portal browser or an external agent integration.
- A revoked device, until it is paired again.
-
A device whose build cannot take the command. This is not a failure:
omnesis devices list, the portal andomnesis doctorname what to run on that machine, which for an agent harness isomnesis update, thenomnesis connect hermes --refresh(oropenclaw) and the harness's own restart.
From the portal
The portal's Devices page offers the same actions: Update on one device and Update all for the fleet, with the same version comparison and confirmation. Each device's card shows where its update stands: waiting to be sent, running, failed, installed but still needing a restart, or to be updated on its own machine. A failure or restart notice stays until the device reconnects on the requested release or a newer one.
When the gateway's release notice reports a newer version, Update fleet
updates the gateway itself first, then the devices. The confirmation names the gateway's
version change and lists which devices will be updated and which you must handle
separately. The portal may be unreachable briefly while the gateway restarts, and picks
the progress up again when it is back; no device is sent anything until
/health reports the confirmed version.
Update fleet works for source installs running as the standard user
service. For named instances, hand-started or hardened gateways and Docker installs, the
button explains why it is disabled; run omnesis update --fleet on the gateway
machine instead.
External MCP clients keep their own sign-in, which an ordinary update does not affect. If
a release's notes say otherwise, reconnect them after the update, and run
omnesis connect openclaw --refresh or
omnesis connect hermes --refresh for those harnesses.
Docker installs
A machine installed with install.sh --docker updates with the same
omnesis update and the same steps. Installing means bumping the image tag
recorded beside the Compose file and pulling the new images; the backup runs after the
pull, while the gateway still serves the previous image. Rolling back is quick: the
previous tag is written back, and its image is still on the machine.
--target-version pins a release tag, and --edge follows the
images built from the main branch.
The update runs in a short-lived updater container that holds the Docker socket for that
one run. The socket gives root-equivalent control of the host, which is why the
long-running gateway and collector containers never hold it. If a run is interrupted, run
omnesis update again; it checks what the gateway actually serves before
trusting the recorded tag.
Adopting a hand-made source install
A source checkout that you cloned and built by hand has no marker saying the installer
owns it, so omnesis update refuses to touch it. If that checkout is an
installation rather than a development tree, adopt it from the repository root, then run
the first update through npm run cli; after that,
omnesis update works as usual.
❯ npm run cli -- update adopt-source
# then follow stable releases
❯ npm run cli -- update
# or follow the main branch instead
❯ npm run cli -- update --edge
Adoption requires a standalone clone of the official repository with a single official
origin, a detached HEAD, the full history and tree, and no local
changes. It then checks with the remote that HEAD is a stable release tag or
part of main. A linked worktree, local branch, fork, shallow clone or
checkout that changes during the check is refused with the reason. Adoption only records
the marker; the first update then rebuilds the checkout.
To update a checkout by hand instead, fetch the exact release tag, detach at it, install, build, restart the gateway, confirm it reports the new version, and only then restart the collector:
❯ git fetch origin refs/tags/vX.Y.Z:refs/tags/vX.Y.Z
❯ git checkout --detach vX.Y.Z
❯ npm ci
❯ npm run build
❯ npm run cli -- service restart gateway
❯ npm run cli -- status
❯ npm run cli -- service restart collector
To follow main by hand, fetch it with
git fetch origin refs/heads/main:refs/remotes/origin/main and detach at
origin/main, then build and restart in the same order. If a fetch fails,
stop: comparing against a stale origin/main can report nothing to update
while the remote is unreachable.
Version compatibility
Every Omnesis release and app build shares one product version, and each device reports
its own when it connects. The gateway compares it with its own version and with the oldest
build it still supports for that kind of device. omnesis devices list, the
portal's Devices page and omnesis doctor all show the same verdict:
| State | Meaning | What to do |
|---|---|---|
| current | On the gateway's version or newer. | Nothing. |
| behind | Older than the gateway but still supported. Normal: a phone build or a collector on another machine often lags. | Update when convenient; omnesis doctor does not fail. |
| unsupported | Older than the oldest build the gateway supports, or speaking a connection protocol it no longer speaks. |
Update the device. The portal flags it and omnesis doctor fails.
|
| unknown | The device reported no version, or one that is not a version number. | Nothing; the device keeps working. Update it by hand when you update. |
A fleet update leaves unknown and unsupported devices to you, because the gateway will not tell a build it cannot identify, or one below its floor, to replace itself. Reporting a version is optional, and a device is never refused for leaving it out.
What the gateway does refuse is a device speaking a different connection protocol: both sides exchange a protocol number when they connect. The browser extension checks the gateway's version before pairing and refuses a gateway on an older minor release than its own. Within a minor release, what the gateway accepts only grows, which is why the gateway is always updated first.
GET /health needs no token and returns the gateway's version and a
compat block with the connection and pairing protocol numbers and the
database schema version, enough for a client to decide whether it can talk to this
gateway. GET /admin/compat, with an admin token, returns the full picture:
every store and how it is versioned, every protocol and the versions it accepts, and the
oldest supported build per device kind.