> ## Documentation Index
> Fetch the complete documentation index at: https://xanots.docs.xano.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment & identity

> The environment variables XanoTS reads, and how `xano.lock` pins object identity across deploys.

## Environment variables

Every variable the CLI and SDK read. All are optional — the defaults in the right column
are what you get when the variable is unset.

**Authentication** (see [Signing in & deploying](/guides/deploying) for the full precedence ladder)

| Variable             | What it does                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `XANO_INSTANCE_URL`  | Instance origin for the meta credential (CI, agents), e.g. `https://your-instance.xano.io`. Set with `XANO_WORKSPACE_ID` + `XANO_META_TOKEN` — all three together, or none.                                                                                                                                                                                                                                                                                                |
| `XANO_WORKSPACE_ID`  | Numeric workspace the meta credential acts on.                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `XANO_META_TOKEN`    | Meta API bearer token. With the two above it forms a complete credential that outranks every other source, reads no file, and never rotates.                                                                                                                                                                                                                                                                                                                               |
| `XANO_REFRESH_TOKEN` | OAuth refresh token for non-interactive runs (CI, agents). Paired with `XANO_CLIENT_ID`; the target instance comes from the token's own `aud` claim. Rotates on use — prefer the meta credential above.                                                                                                                                                                                                                                                                    |
| `XANO_CLIENT_ID`     | OAuth client id that goes with `XANO_REFRESH_TOKEN`. Both are copied once out of `auth.json` after a local `xanots login`.                                                                                                                                                                                                                                                                                                                                                 |
| `XANO_CONFIG`        | Explicit path to the credential file. Wins over `--local` and over both default locations — the same thing `--config <path>` does.                                                                                                                                                                                                                                                                                                                                         |
| `XANO_GLOBAL_CONFIG` | Moves the **shared** credential cache off `~/.xanots/auth.json`. Only changes where the global cache lives; the project-local `./.xano/auth.json` and the `XANO_CONFIG`/`--config` override are unaffected.                                                                                                                                                                                                                                                                |
| `XANO_CLIENT_FILE`   | Moves the OAuth **client-registration** cache off `~/.xano/xanots-clients.json`. That file holds the `client_id` minted per auth host + redirect URI, not a credential.                                                                                                                                                                                                                                                                                                    |
| `XANO_ORIGIN`        | OAuth host to sign in against, instead of the default — the same thing `--origin` does.                                                                                                                                                                                                                                                                                                                                                                                    |
| `XANO_NO_BROWSER`    | Set to anything non-empty and `xanots login` will **not** launch a browser; it prints the authorize URL to stderr for you to open yourself. The loopback server still runs and still waits for the redirect, so the flow completes only if the browser you open it in can reach this machine's `127.0.0.1`. For a machine that has no browser to launch. When the browser is on a **different** machine, that redirect cannot arrive — use `xanots login --paste` instead. |

**`xanots preflight`** — its own target, deliberately separate from the deploy login

| Variable                     | What it does                                                                                                                                                            |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `XANO_VALIDATE_INSTANCE`     | Base URL of the instance to validate against (`https://your-instance.xano.io`, or `http://localhost:8080` for local Docker). Required; `--instance <url>` overrides it. |
| `XANO_VALIDATE_TOKEN`        | Meta API bearer token for that instance. Required.                                                                                                                      |
| `XANO_VALIDATE_WORKSPACE_ID` | Parent workspace the run's throwaway environment is created under. Defaults to `1`.                                                                                     |

**Output & diagnostics**

| Variable       | What it does                                                                                                                                      |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `XANOTS_DEBUG` | Appends the untouched underlying error to a failure message, instead of only the mapped explanation.                                              |
| `NO_COLOR`     | Suppresses ANSI color on the stderr progress output ([no-color.org](https://no-color.org)). Color is off by default whenever stderr is not a TTY. |
| `FORCE_COLOR`  | Forces color on even when stderr is not a TTY; `FORCE_COLOR=0` forces it off and beats `NO_COLOR`'s absence either way.                           |

**Update notifier**

| Variable                 | What it does                                                                                                           |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| `XANOTS_NO_UPDATE_CHECK` | Turns the once-a-day "a newer version is out" notice off.                                                              |
| `NO_UPDATE_NOTIFIER`     | The de-facto convention, honored identically. `CI` being set also silences the notice.                                 |
| `XANOTS_INSTALL_MODE`    | `global` or `local` — pins whether the notice suggests `npm i -g` or a project-local upgrade, instead of detecting it. |
| `XANOTS_UPDATE_REGISTRY` | Registry URL the check reads, instead of the npm endpoint for `@xanots/sdk`.                                           |
| `XANOTS_UPDATE_CACHE`    | Moves the check's cache file off `~/.xanots/update-check.json`.                                                        |

**Escape hatches**

| Variable                 | What it does                                                                                                                                                                                                                                         |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `XANOTS_MARKETPLACE_URL` | Base URL the `xanots marketplace` reads hit, instead of the published catalogue. Repoints the three read verbs without waiting for a release.                                                                                                        |
| `XANOTS_PROVE_DIFF`      | A file path. Codegen appends one JSON line per statement that fell back to `raw()` — the arm that declined and the key paths where the re-encode disagreed. The decline *reason* is on the report either way; this adds the machine-readable detail. |

> `process.env` read inside a **workspace definition** is a different thing entirely: it
> resolves at export time and bakes the literal into the bundle. For a value the deployed
> stack reads at runtime, use `workspaceConfig({ env })` + `env("NAME")`.

## Identity & the xano.lock file

Every top-level object carries a stable `guid` — Xano's identity anchor. On a sync import
the engine matches an incoming object to an existing one **by guid** and updates it in
place; no match means a new object. So re-running `export`/`deploy` on the same code maps
cleanly onto the same workspace — **no duplicates**. By default the guid derives from the
object's `name` — for a **query**, from its api group, verb, and name together, which is
the engine's own uniqueness for an endpoint, so `GET items` and `POST items` are distinct
objects and a path may repeat across groups. Set an explicit `guid` to pin identity across
a rename, or to adopt an existing workspace object into code.

The opt-in **`xano.lock`** freezes the whole workspace's identities at once — every
auto-derived guid, plus the `canonical` URL tokens of API groups and toolsets (which the
engine otherwise randomizes, giving the same code different public URLs per environment).
Create it once with `xanots export ./xano/index.ts --lock`; from then on it's read automatically and
updated on every export (written atomically before the bundle). **Commit it next to your
code.** A project from `xanots init` is locked from its first export — both its `xano:export`
and `xano:deploy` scripts pass `--lock`, and `npm run xano:check` is the `--frozen-lock` CI
guard. Adopt it early either way: once identities have drifted, the only way back is
`lock import` against the deployed workspace.

Precedence at emit is always **explicit in-code value → lock entry → name derivation**.

**When the lock is actually load-bearing.** Because the default derivation is deterministic
— `md5("<type>:<name>")`, and `md5("query:<group>|<verb>|<name>")` for a query — a project
that created all of its own objects can regenerate a
byte-identical lock from its own source. Delete that lock, release again, and the same guids
come back: the objects match and update in place. For that project the lock is a *cache*, and
losing it costs nothing.

The lock is load-bearing exactly where a live guid **diverges** from that derivation, which
happens two ways:

* **Adopted** objects — anything built in the Xano UI first and taken over with `lock import`.
  The engine assigned those guids randomly; nothing in your code can re-derive them.
* **Renamed** objects — `lock rename` pins the original guid under the new name, so the
  derivation no longer reproduces it.

For those entries the lock is irreplaceable, and losing it means the next release matches
nothing and creates a duplicate of every diverged object. A workspace adopted wholesale from
the UI can be almost entirely divergent, so treat *that* lock as the critical artifact.
Either way, commit it — the cache is worth having, and you generally will not know which
entries have diverged without looking.

**Renames** — with a lock, a rename in code no longer means delete+create on sync. The
export warns about the orphaned entry and names the fix-up:

```bash theme={null}
# code: defineFunction({ name: "signup" }) → { name: "register" }
xanots export ./xano/index.ts             # stderr: lock entry "function:signup" matches no exported object…
xanots lock rename --entry=xano/index.ts function signup register
xanots export ./xano/index.ts             # emits signup's original guid under "register" → engine renames in place
```

`rename`/`adopt` take no entry file, so on their own they look for `xano.lock` in the
**current directory**. Pass `--entry=<path>` to derive it beside the entry the way
`export`/`deploy`/`prune` do, or `--lock=<path>` to name the file outright. They never
reach for a lock you did not point them at — when they spot one next door they say so and
stop, rather than writing a file you did not name.

**After `--replace`** — a replace rebuilds the workspace with fresh engine identities, so the
lock is stale the moment it finishes and the next ordinary release would match nothing and
try to create everything. `xanots release ./xano/index.ts --replace` now re-pins the lock from the rebuilt
workspace itself and tells you to commit it. If there is no lock to re-pin, it says so —
without one, the next release duplicates every object.

**Importing a live workspace's identities** — `xanots lock import <bundle.json>` seeds the lock from a
real engine `packageExport`, capturing the live workspace's random guids by `(type, name)`
so code takes over an existing workspace and the first sync updates in place instead of
duplicating.

**CI** — `xanots export ./xano/index.ts --frozen-lock` fails instead of changing the lock, so a canonical
minted in a throwaway container can never silently diverge public URLs. Mint locally, commit
the lock.
