---
title: Schema
description: Using the schema to manage your environment variables
---
One of the core features of Varlock is its schema-driven approach to environment variables, which is best when shared with your team and committed to version control. We recommend creating a new `.env.schema` file to hold schema info set by [config item decorators](/reference/item-decorators/), non-sensitive default values, and [root decorators](/reference/root-decorators/) to specify global settings that affect the `varlock` CLI itself.

This schema should include all of the environment variables that your application depends on, along with comments and documentation about them, and decorators which affect coercion, validation, and generated types / documentation.

The more complete your schema is, the more validation and coercion `varlock` can perform, and the more it can help you catch errors earlier in your development cycle.

:::note
Running [`varlock init`](/reference/cli-commands/#init) will attempt to convert an existing `.env.example` file into a `.env.schema` file. It must be reviewed, but it should be a good starting point.
:::


## Root Decorators
The _header_ section of a `.env` file is any comment block(s) at the beginning of the file, before the first config item. Within this header, you can use [root decorators](/reference/root-decorators/) to specify global settings and default behavior for all config items.

```env-spec title=".env.schema"
# This is the header, and may contain root decorators
# @currentEnv=$APP_ENV
# @defaultSensitive=false @defaultRequired=false
# @generateTsTypes(path=env.d.ts)
# ---

# This is a config item comment block and may contain decorators which affect only the item
# @required @type=enum(dev, test, staging, prod)
APP_ENV=dev
```

More details:
- [Root decorators reference](/reference/root-decorators/)

## Config Items

Config items are the environment variables that your application depends on. Like normal `.env` syntax, each item is a key-value pair of the form `KEY=value`. The key is the name of the environment variable, and a value may be specified or not.

While simply enumerating all of them in your `.env.schema` is useful (like a `.env.example` file), [@env-spec](/env-spec/overview/) allows us to attach additional comments and [item decorators](/reference/item-decorators/), making our schema much more capable.


### Item Values
Values may be static, or set using [functions](/reference/functions/), which can facilitate loading values from external sources without exposing any sensitive values.

**Quote rules:**
- Static values can be wrapped in quotes or not -- all quotes styles (<code>\`</code>, `"`, `'`) are supported
- Values wrapped in single quotes do not support [expansion](#ref-expansion)
- Single line values may not contain newlines, but `\n` will be converted to an actual newline except in single quotes
- Multiline values can be wrapped in <code>```</code>, `"""`. Also supported is `"` and `'` but not recommended.
- Unquoted values will be parsed as a number/boolean/undefined where possible (`ITEM=foo` -> `"foo"`, while `ITEM=true` -> `true`), however data-types may further coerce values
- No value (undefined) and empty string ("") are distinct

```env-spec title=".env.schema"
NO_VALUE= # will resolve to undefined
EMPTY_STRING_VALUE="" # will resolve to empty string
STATIC_VALUE_UNQUOTED=quotes are optional # but are recommended!
STATIC_VALUE_QUOTED="#hashtag" # and are necessary in some cases
BOOLEAN_VALUE=true
NUMERIC_VALUE=123.456
FUNCTION_VALUE=op(op://api-config/item/credential)
EXPANSION_VALUE=${OTHER_VAR}-suffix
MULTILINE_VALUE="""
multiple
lines
"""
```

### Item comments
Comments are used to attach additional documentation and metadata to config items using [item decorators](/reference/item-decorators). This additional metadata is used by varlock to perform validation, coercion, and generate types / documentation.

Multiple comment lines _directly_ preceding an item will be attached to that item. A blank line or a divider (e.g., `# ---`) breaks a comment block and detaches it from the following config item.
Any comment block before the first item is still part of the document header until it is ended by a blank line, a divider, or the end of the file.
Comment lines can either contain regular comments or [item decorators](/reference/item-decorators). Standalone comments only count as decorator comments when the comment content starts with `@`.

```env-spec
# description of item can be multiple lines
# this @decorator will be ignored because the line does not start with @
# @sensitive=false @required # decorator lines can end with a comment
# @type=string(startsWith=pk-) # multiple lines of decorators are allowed
SERVICE_X_PUBLISHABLE_KEY=pk-abc123
```

More details:
- [Item decorators reference](/reference/item-decorators)
- [@type data types reference](/reference/data-types)
- [Functions reference](/reference/functions)

## Resolver Functions

You may use [resolver functions](/reference/functions/) instead of static values within both config items and decorator values.

Functions may be composed together to create more complex value resolution logic.

```env-spec
# @required=forEnv(prod)
API_DOMAIN=if(eq(ref(APP_ENV), prod), api.myapp.com, staging-api.myapp.com)
```


### Referencing other values ||ref-expansion||

Within values and function args, you often need to reference other env vars within your schema.

You may use [`ref()`](/reference/functions/#ref) but we support _expansion_ syntax (like many other .env tools) for convenience.

Both `$ITEM` and `${ITEM}` are equivalent to `ref(ITEM)`.

We recommend using the bracket version only when used within a larger string.

```env-spec /\\$\\{[^\\}]+\\}/ /\\$[A-Z]+/
WITH_BRACKETS=op(op://${OP_VAULT_NAME}/service/api-key)
NO_BRACKETS=fallback($OTHERVAR, foo)
```

Read more about string expansion in the [@env-spec reference](/env-spec/reference/#expansion).

## Decorator details

### Functions vs single use
Most decorators take a single value (e.g., `@sensitive`, `@currentEnv`) and may be used only once per item (or file in the case of a root decorator). Some decorators however, are function calls (e.g., `@docs()`, `@import()`) and may be called multiple times.

```env-spec
# @sensitive=true
# @docs(https://xyzapi.com/docs/auth)
# @docs(https://xyzapi.com/manage-api-keys)
XYZ_API_KEY=
```

### Value resolution
Values passed to decorators will be resolved, meaning if a decorator is expecting a boolean, either a static `true`/`false` or a [resolver function](/reference/functions) that resolves to a boolean may be used.

```env-spec
# @required=false
NEVER_REQUIRED=

# @required=forEnv(prod) # resolves to true/false depending on the current environment
REQUIRED_FOR_PROD=
```



