Skip to main content
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

A merge adds new objects and updates existing ones. Nothing is deleted and no rows are written unless you ask. Anything destructive, such as a dropped column, is previewed and confirmed before it is sent. --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.
A planned deletion outside the record is refused and nothing is sent (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.
A table --prune deletes takes every row with it, and no flag prevents that. Read the preview before you confirm.

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:
To deploy over the edit anyway, pass --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:
Tenants have no Xano branches, so none of this applies to --to tenant:<name>.

Refusals

A refusal writes nothing, not even to xano.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.

Next

Across workspaces: move a release to another workspace or instance.