---
title: "Config Item @decorators"
description: A reference page of available env-spec decorators for items
---
import Decorator from '@/components/decorator-doc-entry.astro'
import docsImg from '@/assets/docs/multiple-docs-intellisense.png'

Decorators in a comment block _directly_ preceding a config item will be attached to that item.
Multiple decorators can be specified on the same line.
A comment block is broken by either an empty line or a divider (`# ---` is optional, but often used for clarity).

```env-spec
# @required @sensitive @type=string(startsWith=sk-)
# @docs(https://docs.servicex.com/api-keys)
SERVICE_X_API_KEY=
```

More details of the minutiae of decorator handling can be found in the [@env-spec reference](/env-spec/reference/#comments-and-decorators).

## Built-in item decorators

These are the item decorators built into Varlock. [Plugins](/guides/plugins/) can extend the DSL with additional decorators.

<div class="reference-docs">
<div>
### `@required`
**Value type:** `boolean`

Sets whether an item is _required_ - meaning validation will fail if the value resolves to `undefined` or an empty string.

Default behavior for all items within the same file can be toggled using the [`@defaultRequired` root decorator](/reference/root-decorators/#defaultrequired).

💡 Use the [`forEnv()` function](/reference/functions/#forenv) to set required based on the current environment.

```env-spec
# @defaultRequired=false
# ---
# @required # same as @required=true
REQUIRED_ITEM=

# @required=forEnv(prod)
REQUIRED_FOR_PROD_ITEM=

# @required=eq($OTHER, foo)
REQUIRED_IF_OTHER_IS_FOO=
```
</div>

<div>
### `@optional`
**Value type:** `boolean`

Opposite of [`@required`](#required). Equivalent to writing `@required=false`.

```env-spec
# @defaultRequired=true
# ---
# @optional
OPTIONAL_ITEM=
```
</div>

<div>
### `@sensitive`
**Value type:** `boolean`

Sets whether the item should be considered _sensitive_ - meaning it cannot be exposed to the public. The value will be always be redacted in CLI output, and client integrations can take further action to prevent leaks.

Default behavior for all items can be set using the [`@defaultSensitive` root decorator](/reference/root-decorators/#defaultsensitive)

Sensitivity may also be implied by the item's [data type](/reference/data-types). For example, plugin "secret-zero" credential types (like a [1Password `opServiceAccountToken`](/plugins/1password/)) are sensitive by default, so you don't need to add `@sensitive` explicitly (use `@public` or `@sensitive=false` to override). An explicit `@sensitive` on the item always wins.

📖 See the [secrets management guide](/guides/secrets/) for best practices on handling sensitive values, and how to use plugins to fetch them from secret management platforms.

```env-spec
# @sensitive
SERVICE_X_PRIVATE_KEY=
# @sensitive=false
SERVICE_X_CLIENT_ID=
```

**Per-item options:** pass an object value to tune protection for a single sensitive item:

- `enabled` (`boolean`, default `true`): whether the item is sensitive. Lets you keep options while toggling sensitivity, including dynamically via a function (e.g. `enabled=forEnv(production)`). `@sensitive={enabled=false}` is equivalent to `@sensitive=false`.
- `preventLeaks` (`boolean`, default `true`): when `false`, this item's value is excluded from [leak detection](/reference/root-decorators/#preventleaks), so it will _not_ trigger an error if it appears in a response. Useful when an endpoint legitimately returns a secret to another system. The value is still redacted in logs.

```env-spec
# @sensitive={preventLeaks=false}
TOKEN_FORWARDED_TO_PARTNER=

# sensitive only in production, and allowed to leave the system
# @sensitive={enabled=forEnv(production), preventLeaks=false}
PARTNER_TOKEN=
```

:::caution[Use `preventLeaks=false` sparingly]
Leak detection is a safety net that stops a secret from accidentally being sent in a response. Setting `preventLeaks=false` removes that net for this item, so only use it when a secret is _deliberately_ meant to leave the system (e.g. an endpoint forwarding a token to another service), never just to silence a leak-detection error. Prefer disabling it for a single item like this over turning off [`@preventLeaks`](/reference/root-decorators/#preventleaks) globally.
:::
</div>

<div>
### `@public`
**Value type:** `boolean`

Opposite of [`@sensitive`](#sensitive). Equivalent to writing `@sensitive=false`.

```env-spec
# @defaultSensitive=true
# ---
# @public
PUBLIC_API_URL=https://api.example.com
```
</div>

<div>
### `@internal`
**Value type:** `boolean`

Marks an item as used **only internally by varlock**, not by your application. Internal items are still resolved and can be referenced by other items (e.g. via [`ref()`](/reference/functions/#ref) or string expansion), but they are **excluded** from everything that reaches your app: the injected env vars, the [serialized graph](/reference/reserved-variables/#__varlock_env) blob, and generated types.

The most common use is a "secret zero": a credential used only to fetch _other_ secrets (for example a vault/secrets-manager token). Your application never needs it, and keeping it out of the process environment reduces your attack surface.

```env-spec
# the token below is only used to resolve the secrets that follow it
# @internal @sensitive
OP_TOKEN=

# resolved using OP_TOKEN, but only DATABASE_URL is injected into the app
# @sensitive
DATABASE_URL=exec(`op read "op://app/db/url"`)
```

Some plugin data types are **internal by default**. For example, a [1Password `opServiceAccountToken`](/plugins/1password/) or other secrets-manager credential authenticates varlock but is rarely needed in app code. You can opt back in with `@internal=false`:

```env-spec
# @type=opServiceAccountToken @internal=false
OP_TOKEN=
```

:::caution[Marking something internal stops injecting it]
Because internal items still resolve and validate, marking a variable internal does **not** produce an error if your application actually reads it. The value simply won't be in the environment at runtime. If your app uses one of these credentials directly (e.g. to write secrets back, renew Vault leases, or fetch more secrets at runtime), set `@internal=false` so it keeps being injected.
:::

:::note
`@internal` controls what varlock _injects_, not what it shows. Internal items still appear (redacted) in inspection output (the `varlock load` summary and `varlock load --agent`), so they can be set and debugged.
:::

`varlock run` strips internal items from the child process environment **even if they were set in the ambient environment** (e.g. `OP_TOKEN=xxx varlock run ...`), so a secret-zero token never leaks into your app. If a _nested_ `varlock run` needs the internal value for its own resolution, pass [`--include-internal`](/reference/cli-commands/#run) to keep it in the child env.

`varlock load --format json-full` excludes internal items by default too, since that format is commonly consumed programmatically (framework integrations shell out to this exact command to get their injected config) - pass [`--include-internal`](/reference/cli-commands/#load) there for local debugging.
</div>

<div>
### `@type`
**Value type:** [`data type`](/reference/data-types) (name only or function call)

Sets the data type of the item - which affects validation, coercion, and generated types.
Note that some data types take additional arguments. See [data types reference](/reference/data-types) for more details.

If not specified, a data type will be inferred when possible, or default to `string` otherwise.

```env-spec
# @type=url # name only
SOME_URL=

# @type=string(startsWith=abc) # function call with options
EXAMPLE_WITH_TYPE_OPTIONS=

INFER_NUMBER=123 # data type of `number` will be inferred from the value
```
</div>

<div>
### `@example`
**Value type:** `string`

Provides an example value for the item. This lets you avoid setting placeholder values that are not meant to be used.

```env-spec
# @example="sk-abc123"
SECRET_KEY=
```
</div>

<div>
### `@docs()`
**Arg types:** `[ url: string ] | [ description: string, url: string ]`

URL of documentation related to the item. Will be included in [generated types](/reference/root-decorators/#code-generation). _Can be called multiple times._

```env-spec
# @docs(https://xyz.com/docs/api-keys)
# @docs("Authentication guide", https://xyz.com/docs/auth-guide)
XYZ_API_KEY=
```

<img src={docsImg.src} alt="example of docs() in generated types" style="max-width:280px"/>_example of `docs()` info in generated types / IntelliSense_
</div>

<div>
### `@docsUrl` (deprecated) ||docsurl||
**Value type:** `string`

URL of documentation related to the item.

Use [`@docs()`](#docs) instead, which supports multiple docs entries with optional descriptions.

`@docsUrl=https://example.com` -> `@docs(https://example.com)`
</div>

<div>
### `@icon`
**Value type:** `string`

Attaches an icon identifier to the item, using iconify ids `collection-name:icon-name`. This icon will be included in autogenerated types.

See https://icones.js.org/ to browse available icons.

Useful for generated docs and UI surfaces that show schema metadata.

```env-spec
# @icon=mdi:key
SERVICE_X_API_KEY=
```
</div>

<div>
### `@auditIgnore`
**Value type:** `boolean`

Suppresses "unused in schema" warnings from [`varlock audit`](/reference/cli-commands/#audit) for this item. Useful for items that are only consumed by external tools and won't appear in your application code.

```env-spec
# @auditIgnore
# used by CI tooling, not referenced in code
CI_DEPLOY_TOKEN=
```
</div>
</div>
