xanosdk deploy --to skips the release and merges the build on your disk straight into your
workspace or a tenant. It has what the release flow does not: a plan preview, loss warnings,
and deletion with --prune. What it does not leave is a release, so there is nothing stored to
land again, on a second tenant, or later. Prefer releases for anything you may
need to repeat.
Use the merge path when you:
- want to see the plan before anything is written;
- are deleting objects your project no longer defines (a release never deletes);
- are landing a project whose tables hold files, which a release cannot carry;
- do not use releases at all.
Preview, then merge
--yes skips the confirmation for CI; it never skips the preview. An
unchanged project is a no-op: the plan prints no changes and nothing is sent.
After a merge, commit xano.lock. It records what this project landed on that destination,
which is what --prune reads.
Prune deletes only what this project landed
--prune deletes an object only when the landing record for that destination names it.
xano.lock keeps one record per workspace and per tenant, listing each object this project
actually wrote there. A table built in the Xano editor, or another project’s function with the
same name, is never this project’s to delete.
SDK_PRUNE_OUT_OF_SCOPE,
exit 2). --yes cannot waive it. The record is only as good as the copy you commit: a fresh
clone with no record prunes nothing, and a deploy from CI records into CI’s checkout. The remedy
for a refusal is one landing without --prune, then commit the lock.
Stage on a Xano branch
--branch creates the Xano branch as a copy of live and refuses a label that already exists
(SDK_BRANCH_TAKEN, exit 2). A Xano branch stages logic, not schema: tables are shared by
every Xano branch, so a table change reaches live as it lands. The merge refuses a table change
on a Xano branch (SDK_SHARED_SCHEMA_CHANGE, exit 2) until you pass
--allow-shared-schema-changes. Workspace settings (its name, preferences and workspace-level
middleware) are not per branch either, and a --branch deploy leaves them alone.
--backup-branch snapshots the live Xano branch first, so the way back is
npx xanosdk workspace branch set-live <backup-label>. That restores logic only: a column the
deploy dropped stays dropped, with its values. To keep data, read droppedColumns in the
--dry-run plan and keep the column in code until its data has moved.
Edits made in Xano: the drift guard
deploy --to workspace reads what has changed on each side since the last deploy or pull. If an
object it would overwrite was edited in Xano since then, it refuses (SDK_WORKSPACE_CHANGED,
exit 2) and lists the objects under details.objects. See what changed where:
changedThere was edited in Xano, changedHere in your project, changedBoth on both sides.
Pull the Xano edit into the project and commit it, then deploy again:
--overwrite; the run warns and names what it overwrote.
A --dry-run refuses nothing and lists the objects under changedInXano.
The guard covers deploy --to workspace only. promote and tenant deploy do not run it. It
also does not refuse when the Xano branch has no baseline yet, or on a --branch deploy to a
new Xano branch. Drift covers keeping both sides in step.
Replace wipes the whole workspace
--replace clears the workspace, not the Xano branch you deploy to. Every Xano branch is
deleted, along with vault secrets, request history and saved versions, and only the live Xano
branch comes back from the import. So a replace is refused while the workspace has any non-live
Xano branch, and --yes does not cover it. Export the Xano branches you want to keep, or pass
--allow-branch-deletion once you accept the loss:
--to tenant:<name>.
Refusals
A refusal writes nothing, not even toxano.lock, and exits 2. --yes cannot waive one,
because a taken identity is not a question about whether you want the plan applied.
Exit codes and outcomes lists every exit code.