Skip to content

Config Item @decorators

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).

# @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.

These are the item decorators built into Varlock. Plugins can extend the DSL with additional decorators.

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.

💡 Use the forEnv() function to set required based on the current environment.

# @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=

Value type: boolean

Opposite of @required. Equivalent to writing @required=false.

# @defaultRequired=true
# ---
# @optional
OPTIONAL_ITEM=

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

Sensitivity may also be implied by the item’s data type. For example, plugin “secret-zero” credential types (like a 1Password opServiceAccountToken) 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 for best practices on handling sensitive values, and how to use plugins to fetch them from secret management platforms.

# @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, 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.
# @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=

Value type: boolean

Opposite of @sensitive. Equivalent to writing @sensitive=false.

# @defaultSensitive=true
# ---
# @public
PUBLIC_API_URL=https://api.example.com

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() or string expansion), but they are excluded from everything that reaches your app: the injected env vars, the serialized graph blob, and generated types. Framework integrations (Vite, Next.js, Astro, Cloudflare) inherit this exclusion too, since they all source their config from the same CLI output.

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.

# 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 or other secrets-manager credential authenticates varlock but is rarely needed in app code. You can opt back in with @internal=false:

# @type=opServiceAccountToken @internal=false
OP_TOKEN=

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 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 there for local debugging.

Value type: data type (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 for more details.

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

# @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

Value type: string

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

# @example="sk-abc123"
SECRET_KEY=

Arg types: [ url: string ] | [ description: string, url: string ]

URL of documentation related to the item. Will be included in generated types. Can be called multiple times.

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

example of docs() in generated typesexample of docs() info in generated types / IntelliSense

Arg types: [ tag: string, ... ]

Attaches one or more tags to the item. Tags don’t affect resolution or validation; they’re used to select items with the --filter CLI flag on varlock load/varlock run, and with the filter= arg on @generate* code-generation decorators (e.g. --filter="#billing", @generateTsTypes(filter=#billing)). Can be called multiple times; tags from every call accumulate (duplicates collapse).

Tag names must start with a letter or number, followed by letters, numbers, _, or -. This keeps every tag selectable with a #tagname filter, which reserves characters like ,, !, and *. An invalid tag name is a schema error.

# @tag(billing)
# @tag(prod, critical)
STRIPE_SECRET_KEY=
Terminal window
varlock load --filter="#billing"

Value type: string

URL of documentation related to the item.

Use @docs() instead, which supports multiple docs entries with optional descriptions.

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

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.

# @icon=mdi:key
SERVICE_X_API_KEY=

Value type: boolean

Suppresses “unused in schema” warnings from varlock audit for this item. Useful for items that are only consumed by external tools and won’t appear in your application code.

# @auditIgnore
# used by CI tooling, not referenced in code
CI_DEPLOY_TOKEN=