# Template variables

Template variables let you parameterise .surql schema files with environment-specific values, substituted at runtime by SurrealKit.

Template variables are placeholder tokens in your `.surql` schema files that SurrealKit substitutes with actual values at runtime. A single set of schema files can then cover all environments (development, staging, production) with names, prefixes, or other values varying per environment.

## Syntax

Use `${VAR_NAME}` anywhere in a `.surql` file:

```surql
-- database/schema/roles.surql
DEFINE ROLE ${talent_role} PERMISSIONS FULL;

-- database/schema/tables.surql
DEFINE TABLE ${schema_prefix}_orders SCHEMAFULL;
DEFINE FIELD owner ON ${schema_prefix}_orders TYPE record<user>;
```

Variable names are case-insensitive: `${FOO}`, `${foo}`, and `${Foo}` all match the key `FOO`.

If a variable is referenced in a file but has no value configured, SurrealKit exits with an error and a clear message indicating which variable is missing.

## Resolution order

SurrealKit resolves variable values in the following order (first match wins):

1. **CLI flag:** `--var KEY=VALUE` (repeatable)
2. **Environment variable:** `SURREALKIT_VAR_<KEY>` (case-insensitive key matching)
3. **`surrealkit.toml` `[variables]` section**

### CLI flags

```bash
surrealkit sync --var schema_prefix=acme --var talent_role=talent_rw
surrealkit rollout start my_rollout --var schema_prefix=acme
```

### Environment variables

```bash
export SURREALKIT_VAR_SCHEMA_PREFIX=acme
export SURREALKIT_VAR_TALENT_ROLE=talent_rw
surrealkit sync --user root --pass secret
```

### `surrealkit.toml`

```toml
[variables]
schema_prefix = "myapp"
talent_role = "talent_rw"
environment = "development"
```

Place `surrealkit.toml` in the root of your project. It is read automatically. The same file also holds the [`[typegen]` section](/docs/manage/schema-migration/typegen.md) when TypeScript generation is enabled.

## Escaping

To emit a literal `${...}` string in generated SQL (for example, inside a SurrealQL string value), double the dollar sign:

```surql
SET note = 'pass $${MY_VAR} literally';
```

SurrealKit outputs this as `pass ${MY_VAR} literally` without substitution.

## Which commands apply substitution

Template Variables are substituted when applying schema to a database. They are not substituted in commands that only read or plan:

| Command | Substitution applied |
|---|---|
| `sync` | Yes |
| `seed` | Yes |
| `rollout start` | Yes |
| `rollout complete` | Yes |
| `rollout rollback` | Yes |
| `rollout plan` | No |
| `rollout baseline` | No |
| `rollout status` | No |
| `rollout lint` | No |

## Known limitations

**Hash-based re-sync:** SurrealKit tracks files by content hash. Changing a variable value without editing the file will not trigger a re-sync. Touch the file to force re-application:

```bash
touch database/schema/tables.surql
surrealkit sync --user root --pass secret
```

**Watch mode:** Variables in `surrealkit.toml` are resolved once at startup. If you edit `surrealkit.toml` while `--watch` is running, restart SurrealKit for the new values to take effect. Variables passed via `--var` or environment variables are re-read on each sync cycle.

**Catalog snapshots:** Entity names containing `${VAR}` appear literally (without substitution) in `catalog_snapshot.json`. This is cosmetic and does not affect functionality.

**String literals:** Substitution is purely textual. `${VAR}` inside a SurrealQL string is replaced with the variable's value, which may or may not be the intended behaviour. Test carefully when embedding variables inside string literals.
