---
title: Resolver functions
description: A comprehensive reference of all available function resolvers in varlock
---

You may use _resolver functions_ instead of static values within both config items and decorator values.

Functions can be composed together to create more complex value resolution logic.
```env-spec
ITEM=fn(arg1, arg2)
COMPOSITION=fn1(fn1Arg1, fn2(fn2Arg1, fn2Arg2))
```


Note that many built-in utility functions have _expansion_ equivalents and often it will be more clear to use them that way. For example:
```env-spec
EXPANSION_EQUIVALENT="pre-${OTHER}-post"
USING_FN_CALLS=concat("pre-", ref(OTHER), "-post")

# mixed example
CONFIG=exec(`aws ssm get-parameter --name "/config/${APP_ENV}" --with-decryption`)
```


There are built-in utility functions, encryption functions for device-local secrets, and plugin-provided resolver functions that can fetch data from external providers. See the [Plugins guide](/guides/plugins/) for more information on plugin-provided functions.

## Core
<div class="reference-docs">

<div>
### `ref()`

References another config item (env var) - which is useful when composing multiple functions together.

Expansion equivalent: `ref(OTHER_VARL)` === `${OTHER_VAR}` (and also `$OTHER_VAR`)

We recommend using the bracketed version within string templates, and the simpler version when referencing an item directly.

```env-spec "ref"
API_URL=https://api.example.com
USERS_API_URL=${API_URL}/users
USERS_API_URL2=concat(ref("API_URL"), "/users") # without using expansion
```
</div>

<div>
### `concat()`

Concatenates multiple values into a single string.

Expansion uses `concat()` to combine multiple parts of strings when they include multiple parts.

```env-spec "concat"
PATH=concat("base/", ref("APP_ENV"), "/config.json")
PATH2=`base/${APP_ENV}/config.json` # equivalent using expansion
```
</div>

<div>
### `exec()`

Executes a CLI command and uses its output as the value. This is particularly useful for integrating with external tools and services.

NOTE - many CLI tools output an additional newline. `exec()` will trim this automatically.

Expansion equivalent: `exec(command)` === `$(command)`

```env-spec "exec"
# Using 1Password CLI
API_KEY=exec(`op read "op://dev test/service x/api key"`)
# Using AWS CLI
AWS_CREDENTIALS=exec(`aws sts get-session-token --profile prod`)
```
</div>

<div>
### `fallback()`

Returns the first non-empty value in a list of possible values.

```env-spec "fallback"
POSSIBLY_EMPTY=
ANOTHER=
EXAMPLE=fallback(ref(POSSIBLY_EMPTY), ref(ANOTHER), "default-val")
```
</div>

<div>
### `remap()`

Maps a value to a new value based on a set of lookup pairs. This is useful for translating one value, often provided by an external platform, into another.

- The first argument is the value to remap (often a `ref()` to another variable).
- All following arguments are pairs of `(matchValue, resultValue)`.
- An optional trailing default value can be added as the last argument (when the total number of remaining args is odd).
- Match values can be a string, `undefined`, or a [regex-like string](/reference/functions#regex-like-strings) (`/pattern/`).
- If no match is found and there is no default, the original value is returned.

```env-spec "remap"
# env var that is set by CI/platform
CI_BRANCH=

# @type=enum(development, preview, production)
APP_ENV=remap($CI_BRANCH, "main", production, /.*/, preview, undefined, development)
```

:::caution[Quoting path-like values]
An unquoted match value that looks like a valid regex (i.e., `/something/` with optional flags) will be treated as a regex pattern. If you need to match a literal string containing slashes (like a file path), wrap it in quotes.
```env-spec
# /usr/local/ looks like a valid regex — use quotes to match it literally
ITEM=remap($PATH_VAR, "/usr/local/", found, default)
```
:::

:::note[Deprecated syntax]
The old key=value syntax (`result=match`) is still supported but deprecated. Use positional pairs instead.
```env-spec
# deprecated - key is the result, value is what to match (backwards and limited by key naming)
APP_ENV=remap($CI_BRANCH, production="main", preview=/.*/, development=undefined)
```
:::
</div>

</div>

## Utilities
<div class="reference-docs">

<div>
### `ifs()`

Evaluates a series of condition/value pairs, returning the value for the first truthy condition. Similar to Excel's `IFS` function.

- Arguments are pairs of `(condition, value)`.
- An optional trailing default value can be added as the last argument (when the total number of args is odd).
- If no condition is truthy and there is no default, returns `undefined`.

```env-spec "ifs"
ENV=staging

# returns the value matching the first truthy condition
API_URL=ifs(
  eq($ENV, production), https://api.example.com,
  eq($ENV, staging), https://staging-api.example.com,
  http://localhost:3000
)
```
</div>

<div>
### Regex-like strings

Certain functions like `remap()` and type options like `matches` support regex pattern matching. You can use JavaScript-style regex syntax (`/pattern/flags`) as an unquoted value — these will be automatically detected and treated as regular expressions.

A string is treated as a regex when it:
- Starts and ends with `/` (with optional flags like `i`, `g`, `m`, `s`, `u`, `y` after the closing `/`)
- Is **not** wrapped in quotes

```env-spec
# regex pattern in remap — matches case-insensitively
ENV_TYPE=remap($APP_ENV, /^dev.*/i, dev, "production", prod)

# regex pattern in type options
# @type=string(matches=/^sk-[a-zA-Z0-9]+$/)
API_KEY=

# @type=url(matches=/^https:\/\/api\./)
API_URL=
```

:::caution[Paths vs regex ambiguity]
Since `/something/` looks like a valid regex, values like `/usr/lib/` will be treated as regex patterns in contexts that support them (like `remap()` match values). To use a literal string containing slashes, wrap it in quotes:
```env-spec
# unquoted — treated as regex pattern matching "usr/lib"
ITEM=remap($VAR, /usr/lib/, matched)

# quoted — treated as the literal string "/usr/lib/"
ITEM=remap($VAR, "/usr/lib/", matched)
```
Note that as a top-level config value (e.g., `MY_PATH=/usr/local/bin`), slash-containing strings are always treated as plain strings.
:::

:::note[`regex()` function]
The older `regex("pattern")` function wrapper is still supported but the `/pattern/` literal syntax is preferred — it's more concise and supports flags.

```env-spec
# older style - still works
ENV_TYPE=remap($APP_ENV, regex("^dev.*"), dev, "production", prod)
```
:::
</div>

<div>
### `forEnv()`

Resolves to a boolean, if the current [environment](/reference/root-decorators/#currentenv) matches any in the
list passed in as args.

**Requirements:**
- Requires an [`@currentEnv`](/reference/root-decorators/#currentenv) to be set in your `.env.schema` file
- Takes one or more environment names as arguments

```env-spec /forEnv\\(.*\\)/
# @currentEnv=$APP_ENV @defaultRequired=false
# @disable=forEnv(test)  # entire file will be disabled if env is test
# ---
APP_ENV=staging

# Required only in development
# @required=forEnv(development)
DEV_API_KEY=

# Required in staging and production
# @required=forEnv(staging, production)
PROD_API_KEY=
```
</div>


<div>
### `eq()`

Checks if 2 values are equal and resolves to a boolean.

```env-spec "regex"
IS_STAGING_DEPLOYMENT=eq($GIT_BRANCH, "staging")
```
</div>

<div>
### `if()`

Checks a boolean to return a true/false option

```env-spec "regex"
API_URL=if(eq($GIT_BRANCH, "main"), api.example.com, staging-api.example.com)
```
</div>

<div>
### `not()`

Negates a value and returns a boolean. Falsy values are - `false`, `""`, `0`, `undefined`, and will be negated to `true`. Otherwise will return `false`.

```env-spec /(not)\\(/
# Negate the result of another function
SHOULD_DISABLE_FEATURE=not(forEnv(production))
```
</div>

<div>
### `isEmpty()`

Returns `true` if the value is `undefined` or an empty string, `false` otherwise.

```env-spec "isEmpty"
# Check if a value is empty
HAS_API_KEY=not(isEmpty($API_KEY))

# Use with conditional logic
API_URL=if(isEmpty($CUSTOM_API_URL), "https://api.default.com", $CUSTOM_API_URL)
```
</div>

</div>

## Encryption
<div class="reference-docs">

<div>
### `varlock()`

Decrypts a locally encrypted value, or prompts for a new secret to encrypt. This is the built-in resolver for varlock's [device-local encryption](/guides/local-encryption/) feature.

**Decrypt mode** — pass an encrypted payload to decrypt at load time:
```env-spec "varlock"
# @sensitive
API_KEY=varlock("local:<encrypted-payload>")
```

**Prompt mode** — prompts the user to enter a secret, encrypts it, and writes the encrypted value back to the source file:
```env-spec "varlock"
# @sensitive
API_KEY=varlock(prompt)
# also valid as a key=value param:
API_KEY=varlock(prompt=1)
```

On first run with `prompt` mode, you'll be asked to enter the secret value. Once entered, the file is automatically updated with the encrypted payload. On macOS with Secure Enclave, a native dialog with biometric authentication is used.

Values are encrypted using the best available backend on your platform — see the [Local encryption guide](/guides/local-encryption/) for details.

Encrypted payload lifecycle:
- Store encrypted payloads (`varlock("local:...")`) in local override files (typically `.env.local`)
- Decryption happens at runtime during `varlock load` / `varlock run`
- Use [`varlock reveal`](/reference/cli-commands/#reveal) when you need to inspect a decrypted value interactively

</div>

<div>
### `keychain()`

Reads a secret from the **macOS Keychain**. This built-in resolver communicates through Varlock's native Swift daemon, enforcing biometric (Touch ID) authentication and per-session access control. See the [macOS Keychain page](/plugins/macos-keychain/) for full documentation.

**Array args:**
- `service` (optional): Service name of the keychain item (positional shorthand)
- `prompt` (optional): Enter interactive picker mode

**Key/value args:**
- `service` (optional): Service name of the keychain item
- `account` (optional): Account identifier for the keychain item
- `keychain` (optional): Name of a specific keychain to search (e.g., `"System"`)
- `field` (optional): Specific field to extract from the keychain item
- `prompt` (optional): If set, opens a native picker dialog for interactive selection

```env-spec /keychain\\(.*\\)/
# Positional shorthand
DATABASE_PASSWORD=keychain("com.company.database")

# Named service with account
ADMIN_PW=keychain("com.company.db", account="admin")

# Interactive picker mode — writes back resolved reference
NEW_SECRET=keychain(prompt)
```

:::caution
`keychain()` is only available on macOS. For cross-platform local encryption, use [`varlock()`](#varlock) instead.
:::
</div>

</div>
