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.
Built-in item decorators
Section titled “Built-in item decorators”These are the item decorators built into Varlock. Plugins can extend the DSL with additional decorators.
@required
Section titled “@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.
💡 Use the forEnv() function to set required based on the current environment.
# @defaultRequired=false# ---# @required # same as @required=trueREQUIRED_ITEM=
# @required=forEnv(prod)REQUIRED_FOR_PROD_ITEM=
# @required=eq($OTHER, foo)REQUIRED_IF_OTHER_IS_FOO=@optional
Section titled “@optional”Value type: boolean
Opposite of @required. Equivalent to writing @required=false.
# @defaultRequired=true# ---# @optionalOPTIONAL_ITEM=@sensitive
Section titled “@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
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.
# @sensitiveSERVICE_X_PRIVATE_KEY=# @sensitive=falseSERVICE_X_CLIENT_ID=Per-item options: pass an object value to tune protection for a single sensitive item:
enabled(boolean, defaulttrue): 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, defaulttrue): whenfalse, 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=@public
Section titled “@public”Value type: boolean
Opposite of @sensitive. Equivalent to writing @sensitive=false.
# @defaultSensitive=true# ---# @publicPUBLIC_API_URL=https://api.example.com@internal
Section titled “@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() 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 @sensitiveOP_TOKEN=
# resolved using OP_TOKEN, but only DATABASE_URL is injected into the app# @sensitiveDATABASE_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=falseOP_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 onlySOME_URL=
# @type=string(startsWith=abc) # function call with optionsEXAMPLE_WITH_TYPE_OPTIONS=
INFER_NUMBER=123 # data type of `number` will be inferred from the value@example
Section titled “@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.
# @example="sk-abc123"SECRET_KEY=@docs()
Section titled “@docs()”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() info in generated types / IntelliSense
@tag()
Section titled “@tag()”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=varlock load --filter="#billing"@docsUrl (deprecated)
Section titled “@docsUrl (deprecated)”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:keySERVICE_X_API_KEY=@auditIgnore
Section titled “@auditIgnore”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 codeCI_DEPLOY_TOKEN=