- Your repo. TypeScript is authoritative; the workspace is a deployment target. Changes arrive through pull requests. This is flows 1–3.
- Your Xano workspace. The workspace is authoritative; code is pulled out, worked on, and pushed back. Changes arrive through Xano branches, and git may not be involved at all. This is flow 4.
The three places XanoTS writes
xanots init <dir> --from workspace, which turns the live branch into
TypeScript. See Pulling an existing workspace.
What goes in git
For the flows where the repo is authoritative:Commit
xano/** (your defs), xano.lock, package.json, and your frontend source.
The lock pins every object’s identity — without it a release can duplicate objects
instead of updating them.Never commit
.xano/auth.json (xanots login --local gitignores it for you), .env,
node_modules, frontend/dist, and any exported bundle — a bundle carries your
workspace’s environment variable values.1. Solo developer, repo is the truth
One person,main, one workspace. Branches in git are optional; the ephemeral is where you
try things.
Sign in once
Work, and deploy as often as you like
Prove it, then merge
Release to production
2. A team, all on XanoTS, repo is the truth
Same shape, plus review. What makes it work is that everybody’sdeploy goes to their own
ephemeral, so two people can be mid-change at once without touching each other or
production.
Everyone signs in to the same workspace
--workspace flag — one credential addresses one workspace. xanots workspace details says which.Branch, deploy, share a URL
xanots ephemeral list shows what everyone has up;
xanots ephemeral delete <tenant> --yes cleans one up early.Open the PR
- a removed table column or removed table — that is data loss on release;
- a change to
xano.lockthat isn’t a rename you expected.
Merge to main, then release
main:xano.lock in the same PR as the rename.
Merge conflicts in xano.lock are normal — two branches each added objects. Take both
sides, then re-run xanots export ./xano/index.ts to rewrite the file cleanly and commit
that.
3. Automated: main is what production runs
Same commands, run by a machine. Any runner works — the requirement is three environment variables, the credential shape that never expires or rotates:--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 — reconcile production:
"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.
A staged pipeline puts the merge on a branch and makes promotion a separate, human
button:
--prune (delete objects the project no longer defines) is deliberately absent above.
Deletions are worth a human reading the plan: xanots release ./xano/index.ts --prune --dry-run.4. The workspace is the truth, and branches are the merge
This is the flow for a team that lives in Xano. Nobody keeps a long-lived repo. Everyone — whether they write TypeScript, read XanoScript, or build in the no-code builder — does the same four things:- Take a copy of what is live.
- Work on it, trying it out on a disposable ephemeral.
- Push it back as a branch, which stages it without serving it.
- Promote the branch, which is the merge.
First, what a Xano branch actually isolates
The CLI refuses rather than letting that happen quietly.release --branch reads the live
workspace, diffs the shared objects, and stops with the tables named:
--branch because
applying it is what you wanted; or pass --allow-shared-schema-changes to stage the logic and
apply the schema knowing both happen. If the live workspace could not be read, that is
also a refusal — a failed read is not evidence that there is no schema change.
The TypeScript developer, and the XanoScript developer
One flow, two artifacts. No repo — the working copy is a folder you delete when you are done.Pull the live branch
guid, so what you push back matches in place rather
than duplicating. xano/README.md lists anything that did not translate cleanly — read
it before you start editing.Work on it against an ephemeral
Push it back as a branch
orders yet — the live branch is untouched. --backup-branch snapshots
the live branch’s logic first, so the promote in the next step has something to go back
to. The release refuses outright unless the instance confirms it planned against the
branch you named, so an instance without branch support fails closed instead of
overwriting production.Review it in the builder
Promote — this is the merge
--yes in a script).Clean up
The builder developer
Someone building in the Xano no-code UI does steps 1, 2 and 3 in the builder itself: they work on a branch in Xano rather than on the live one, and click through it there. Then the last step is identical, from the builder or the CLI:Rolling back
The branch you replaced is still there, so undoing a promote is one command:v1 is the label every workspace starts with, and it is reserved — --branch v1 is refused
rather than silently writing to whatever is live. Pick your own labels.Other arrangements
Adopting a workspace into a repo
Adopting a workspace into a repo
xano.lock is irreplaceable — losing it means the next release duplicates every
object instead of updating it. From here you are in flow 2, and the workspace stops being
a place people edit.A preview environment per pull request
A preview environment per pull request
A hotfix someone made in production by hand
A hotfix someone made in production by hand
--prune would remove it. Get it
into git the same day:An AI builder (Bolt, Lovable) driving the backend
An AI builder (Bolt, Lovable) driving the backend
Several backends in one repo
Several backends in one repo
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.The rules that survive every flow
- Pick one source of truth per workspace and say so out loud. The repo, or the workspace.
- Ephemerals are free; production is not. Iterate on
deploy, promote withrelease. --dry-runbefore a release, and read the column drops.- A branch stages logic and shares schema. If the shared-schema check refuses, it is telling you something true.
xano.lockis committed, always — wherever a repo is authoritative. It is what makes a release update instead of duplicate.- Credentials never enter git. People use
xanots login; machines use the three environment variables.