Skip to main content
Your TypeScript is authoritative. The workspace is a deployment target that xanots release reconciles to main. This is one flow, not three. Solo is the base; a team adds review, and CI adds a machine that runs the same commands. The commands themselves never change. New here? Read Development workflows first — it covers the choice between this and letting the workspace be authoritative, and what a Xano branch does and does not isolate.
Git is the ideal path, not the only one. The Xano builder stays fully usable — open it any time to look at what is live, debug an endpoint, or read request history. What changes is writing: an edit made in the builder is invisible to your code, so your next release does not know about it. That is recoverable, and in an emergency it is exactly what you should do — see When you have to work outside git below, and read it before you need it.

Day one

Two different starting points, and only one of them is irreversible.
Nothing exists yet, so nothing can be lost.
A project from xanots init is locked from its first export, so xano.lock is created and maintained for you. See Git, locks & merges for what else belongs in that first commit.

The loop

1

Branch, and deploy to your own ephemeral

Every developer’s deploy goes to their own ephemeral, so two people can be mid-change at once without touching each other or production. It is disposable and expires on its own, so a bad deploy costs you nothing. Deploy as often as you like.
2

Prove it

3

Open a pull request

Push the branch, then open the PR on GitHub/GitLab from the URL the push prints:
Paste the ephemeral’s URL into the PR description. A reviewer gets a running backend and frontend to click through, not just a diff.
Review the TypeScript like any other code — plus the four things a normal code review misses, which are covered in the review checklist.
Working solo? Skip this step and commit straight to main — everything else on the page is unchanged. New to git or pull requests? Git, locks & merges opens with the eight commands these flows use and how a PR actually works.
4

Merge, then release from main

One person — or the pipeline below — releases:
Always --dry-run first. It prints exactly which objects would be created, updated, or dropped — including any table column your schema no longer defines, which takes its data with it. See what a release changes.

Automating it

The same commands, run by a machine. Any runner works — the requirement is three environment variables, the credential shape that never expires or rotates:
Never run xanots login in a pipeline — it blocks on browser consent. And set all three variables together; setting some is a hard error naming the rest, not a quiet fallback to whatever credential happens to be on the runner.

On every pull request

Build it, prove it, leave a live URL behind:
  • --strict turns build warnings into failures.
  • --frozen-lock fails if the export would change xano.lock, which catches someone who forgot to commit it.
  • --test runs the deployed tests; a failing suite exits 5.

On merge to main

Safe to run on every merge, and safe to re-run. When the workspace already matches the code, nothing is sent at all — the summary reports "upToDate": true and no updated_at moves. --yes skips the confirmation prompt but never skips the printed preview, so the log still shows what changed.
--prune (delete objects the project no longer defines) is deliberately absent here. Deletions are worth a human reading the plan: xanots release ./xano/index.ts --prune --dry-run.

A staged pipeline

Not available yet. Branch releases are still rolling out instance-side, so this pattern is a preview — the flags parse and run, but on an instance without support the release refuses rather than staging. Do not build a pipeline on it today; the rest of this page needs none of it.
Once it lands, you will be able to put the merge on a branch and make promotion a separate, human button:
Note that a branch stages logic and shares schema — see what a Xano branch isolates. Until then, the equivalent human gate is a manual approval on the release job itself: run --dry-run on merge, have someone read the plan, then run the release.

Nightly, or before a release

Check the code against a real engine without touching anything you own. preflight creates its own throwaway environment, imports into it, diffs the round trip, and deletes it again:

Ready-to-paste pipelines

Same four commands either way — only the YAML around them differs.
To post the ephemeral’s URL as a PR comment, capture the deploy’s stdout — it is a projected, secret-free JSON summary carrying baseUrl — and feed it to actions/github-script. The raw workspace blob is never printed, so nothing sensitive reaches the log.
Mark all three variables masked and protected in the project’s CI/CD settings.
There is nothing runner-specific in the flow — three environment variables and four commands. On a PR:
On merge to the default branch:
Exit codes are the contract: --test exits 5 on a failing suite, and a static failure after a committed backend deploy exits 3 with a resumable message.

When a release goes wrong

Your code is the record of what production should be, so rolling back is releasing an earlier version of it. There is no separate undo command — and that is a feature, because it means the rollback goes through the same reviewed, repeatable path as everything else.
1

Get main back to the last good state

revert makes a new commit undoing the old one, so the history stays honest and the rollback is itself reviewable.
2

Read the plan before you send it

Check it says what you expect. A rollback is still a release — it can drop a column just as easily as the change that caused the problem.
3

Release

What a rollback does and does not restore

Dropped column data is not recoverable by re-releasing. This is the one failure a rollback cannot fix, and it is why the release preview names every column it is about to drop and asks first. If you are ever unsure, answer no and read the plan again — a refused release costs a minute; a dropped column costs the data.
Restore from a backup, not from a rollback, when data is involved. Your Xano workspace’s own backups are the recovery path for lost rows or columns — the release pipeline only ever reconciles structure and logic to your code.

If you are not sure whether the release even landed

Run it again and read the plan. A release compares before it sends, so when the workspace already matches your code, nothing is sent at all — the plan prints no changes, the summary reports "upToDate": true, and no updated_at moves. Re-running is safe and is the fastest way to find out where you stand.

When you have to work outside git

Production is down at 2am, or someone fixed a typo in the builder because it was thirty seconds’ work. This happens on real teams, and doing it breaks nothing permanently — as long as you bring the change back into git before your next release.

What is safe, and what is not

The danger is not the edit — it is the next release. An ordinary xanots release merges, so it will not delete an object someone added in the builder. But --prune deletes objects this project released and no longer defines, and a column your code does not describe can be dropped by a release whose plan looks routine. Always --dry-run and read the plan after anyone has been working in the builder.

Bringing the change back

Reconcile the same day — the risk grows the longer the two copies disagree.
1

Pull the live workspace over your checkout

2

Read the diff — this is the whole point

You should see only the hotfix. If you see more, someone else has been editing in there too — see below.
3

PR it like any other change

Now the fix exists in code, in review, and in history — and your next release knows about it.
Doing it deliberately? Make the fix in the builder, then pull it back and open the PR while you still remember what you changed. The hotfix nobody reconciles is the one that gets silently reverted three weeks later.

If this keeps happening

One emergency hotfix a quarter is normal. If the diff regularly shows work you did not expect, that is data rather than a discipline problem: people are choosing the builder because it suits how they work. At that point the repo is not really your source of truth. The arrangement that fits is Workspace is the truth — builder edits as the expected path, with Xano branches as the merge — but the branch releases it needs are still in development, so it is not adoptable yet. Until it lands, the practical answer is to make reconciling routine rather than exceptional: pull the workspace back on a schedule (a weekly xanots init . --from workspace on a branch, reviewed and merged like any PR) so drift is caught in days rather than discovered by a --prune.

Other arrangements

Nothing extra to configure: the PR job above already deploys to an ephemeral and prints the URL. Post it as a PR comment and let it expire on its own, or tear it down on merge:
The agent authors TypeScript and deploys to ephemerals, so it slots in as a contributor: it works on a branch, you read the diff, you merge. Keep xanots release off the agent’s path — let it deploy freely and let a human release. See Bolt and Lovable.
Each entry file is its own workspace and gets its own credential, its own xano.lock beside it, and its own release. Point every command at the entry explicitly:
lock rename and friends look for xano.lock in the current directory unless you pass --entry=<path>, so always pass it in a multi-backend repo.