Deploy, preview, promote, roll back
xeer auth login # once
xeer deploy # every timeThat is the whole path to production. What follows is the rest of the toolkit: shipping to a side-by-side URL first, promoting the exact bundle you looked at, putting a previous version back, and taking an app offline.
Deploying needs a Xeer account, and accounts are currently by invitation. Everything
local — xeer new, xeer dev, xeer test, xeer build,
xeer preview — works with no account at all. See the
FAQ.
#Sign in
xeer auth login # opens a browser, prints a confirmation code
xeer auth status # who you are, and when the credential expires
xeer auth logout # revoke it, and delete it locallyThe CLI prints a verification URL and a confirmation code, then opens your browser (--no-open leaves you
to open it yourself). Approve only if the browser shows that exact code — approval never happens on a
plain page load. The credential is written to ~/.xeer/credentials/cli.json with 0600 permissions.
This signs you in, not your app's users — they need no Xeer account at all. xeer auth as and
xeer auth clear are a third thing again: the local development
persona. See Auth for the two doors.
xeer auth status reports which control plane your stored credential is for, and says so explicitly when
it is not the default.
#Deploy
xeer deploy [directory] [--environment prod|preview] [--json]The bare command targets production, and always has.
What happens: your project is compiled to a content-addressed artifact, that artifact is verified, and it
is uploaded. Then the CLI waits for the deployed app and checks it — platform health, your assets, and one
authenticated request. Only a verified authenticated request counts as success. An app that serves
static files but cannot answer a real request fails the deploy with XE5104 rather than being reported as
working.
On success you get your application's name and its URL, of the form https://xa-….xeer.run. That URL is
live on a global edge network, serving your client and your server, with its own database and real
sign-in.
Your app's identity comes from the checked-in
xeer.project.json, so deploying from a
fresh clone updates the app you already have. Deploying an appId owned by someone else is refused
(XE5111) — a clone of another person's project cannot silently fork or hijack it.
Deployed apps require a cryptographically verified identity assertion for every request, which is why the
Alice and Bob personas exist only under xeer dev. Your
deployed app gives every real visitor an identity of their own instead — see Auth.
#Look at a build before you ship it
xeer build # produce the artifact
xeer preview # run that exact artifact locallyxeer preview verifies and runs the built artifact, reading only the artifact's own contents and never
your source. It is the closest local approximation of production, and it is distinct from xeer dev,
which recompiles from source on every change.
#Preview a change
xeer deploy --environment previewA preview deployment is a second, separate app instance at its own URL. Production keeps serving
exactly what it was serving. The preview gets the values you stored with
xeer env set --environment preview. Nothing your users can reach changes until you promote.
Two things to know:
- Preview data is separate from production's, and disposable. It cannot read or corrupt production's records — and equally, it starts empty and is replaced by your next preview deploy. Do not treat it as a staging copy of your data.
- A preview deploy counts against your deploy allowance — it is a real deployment. Having a preview slot does not count as a second app, though: the apps-per-account limit counts projects.
xeer rollback … --environment preview rolls the preview slot back independently.
#Promote it
xeer promote # make what preview is serving live
xeer promote my-app --from-artifact sha256:… # or a specific versionPromotion makes the artifact your preview proved live on production. It is the same bundle, not a rebuild: every deployed payload is retained under its content address, so promoting reads that exact bundle back and activates it. The content address you looked at is the content address your users get.
Three things worth knowing:
- The environment values are production's, not preview's. A promotion carries code forward, never configuration, so a sandbox key in preview cannot end up in front of real users. The result says so.
- It is a production deployment. It records a deployment, uploads, and counts against your allowance.
- The readiness gate is the deploy gate, run against production: health, assets, and one authenticated
request. A promotion that serves assets but fails authenticated requests fails with
XE5104.
An app with nothing on preview yet is refused with XE5175, naming the command to run first.
#Deployment history
xeer deployments # the app this directory is linked to
xeer deployments my-app # by name, appId, or deployed URL
xeer deployments --limit 10 --json ENVIRONMENT STATUS CREATED ARTIFACT
* production ready 2026-07-25T09:41:12.883Z sha256:9f2c…
preview ready 2026-07-25T09:38:44.201Z sha256:9f2c…
production failed 2026-07-24T18:02:10.664Z sha256:41ab…A * marks the deployment currently serving each environment. There is no separate "active" pointer to
consult: the history is the record, and active means the latest completed deployment for that
environment. A failed or still-pending attempt is listed but never marked, even when it is the newest
thing that happened. A rollback or promote note under a row says the deployment replayed a retained
artifact and which one it displaced.
The platform answers only the account that owns the app. An unknown app, someone else's app, and a deleted
app are the same refusal (XE5143), so this command never confirms whether an app you do not own
exists.
#Roll back
xeer deployments my-app # copy an id from the ARTIFACT column
xeer rollback my-app sha256:… # put that version back on production
xeer rollback sha256:… # the app this directory is linked toRollback puts a previous version back online by redeploying an artifact the app already deployed. The
retained bundle is read back and pushed through the same activation xeer deploy uses — so it is
verified the same way, and a rollback that cannot answer an authenticated request fails (XE5104) rather
than being called a success.
A rollback is a new deployment, not an edit of history. After rolling v2 back to v1 you have three rows, the newest being v1, marked live and annotated with what it replaced. Nothing is rewritten.
- The environment values injected are the current ones, not the ones the artifact first shipped with.
- It counts against your deploy allowance, because it is a deployment.
An artifact this app never successfully deployed — a typo, another project's, or one whose deployment
failed — is refused with XE5164 pointing back at xeer deployments.
#Take an app offline
xeer disable # the app this directory is linked to
xeer disable my-app
xeer enable my-appxeer disable switches an app off at the edge: requests get 410 Gone on the very next request, and
nothing else changes — the app, its data, its environment values, and its URL all stay exactly as they
are. xeer enable puts it back.
Both are idempotent, and both keep working when something else is broken — a broken app is precisely when
you need to take it offline. A disabled app still appears in xeer link marked (disabled), still lists
its history, and can still be deployed to, so you can ship a fix before switching it back on. Disabling
covers the preview slot too.
#Delete an app
xeer delete my-app --confirm my-appPermanent. It deletes the deployed app and its preview slot, destroying their stored data
irrecoverably, removes every URL mapping, and retires the appId for good so it can never be deployed
again.
Because the appId is checked into xeer.project.json, a later xeer deploy from that checkout is
refused with a repair hint rather than resurrecting a dead app; xeer link --new mints a fresh identity
for the checkout.
The confirmation is the application's exact name. Without --confirm the CLI refuses locally (XE5150)
before it even reads your credential; with the wrong name the platform refuses it (XE5151) having
changed nothing.
#Moving data in and out
xeer export my-app --out backup.json # a deployed app you own
xeer export --state dev . --out dev-backup.json # your local dev database
xeer import --state dev . dev-backup.json # put it back locallyThe file is a readable, diffable document: the schema that produced the rows plus every record. import
replaces state wholesale, in one transaction, and validates the document against the schema currently
in force first — accepting it only when that schema is the export's own or a compatible successor. There
is no --force, because writing rows your schema does not describe would break what your own queries are
allowed to assume.
xeer import writes local dev and preview state only. To restore a deployed app, import locally,
verify, and redeploy.
#Everything at a glance
| Command | Changes what users see? | Counts as a deploy? |
|---|---|---|
xeer deploy | yes | yes |
xeer deploy --environment preview | no | yes |
xeer promote | yes | yes |
xeer rollback | yes | yes |
xeer disable / xeer enable | yes, immediately | no |
xeer delete | yes, permanently | no |
xeer env set | not until the next deploy | no |
#Next
- Environment variables and secrets — what gets injected, and when.
- CLI reference — every command and option.
- Diagnostics reference — every code mentioned above.