Skip to main content

!literal

The !literal Atmos YAML function preserves values exactly as written, bypassing all template processing. Use it to pass template-like syntax (e.g., {{...}} or ${...}) to downstream tools like Terraform, Helm, or ArgoCD without Atmos attempting to evaluate them.

Availability and evaluation​

Supported locations:

  • CLI configuration (atmos.yaml, atmos.d, and profiles): during file loading.
  • Stack manifests: during file loading, before inheritance and merging.
  • Workflow manifests: during manifest loading.
  • Scaffold manifests: during manifest loading.

Stack scalar values retain protection through templates and YAML-function processing. Step execution honors only the literal-aware fields documented below.

Automatic evaluation requires native YAML tags from edition 2026-10-20, including unpinned projects. Quoted function strings remain literal; earlier editions retain legacy string-form behavior.

See YAML function scope for field restrictions, import timing, and native tags versus quoted strings.

Usage​

# Preserve template syntax for downstream tools
value: !literal "{{external.email}}"

# In lists
db_users:
- !literal "{{external.email}}"
- !literal "{{external.admin}}"

# Inline array syntax
users: [!literal "{{user1}}", !literal "{{user2}}"]

# Multiline values
script: !literal |
#!/bin/bash
echo "Hello ${USER}"
export VAR={{value}}

Arguments​

value (required)

The string value to preserve. Can be quoted, unquoted, or use YAML multiline syntax. The value is passed through exactly as written, without any template processing.

Examples​

Terraform templatefile() Variables​

Pass variables to Terraform templates without Atmos processing them:

components:
terraform:
ec2-instance:
vars:
user_data_template: !literal "#!/bin/bash\necho ${hostname}"
config_template: !literal "${var.environment}-config.json"

Helm Values​

Pass Helm template expressions that should be processed by Helm, not Atmos:

components:
terraform:
helm-release:
vars:
ingress_annotations: !literal "{{ .Values.ingress.class }}"
service_name: !literal "{{ .Release.Name }}-api"

ArgoCD and External Templating Systems​

Preserve template syntax for external tools like ArgoCD, Jsonnet, or Kustomize:

components:
terraform:
argocd-app:
vars:
config_url: !literal "{{external.config_url}}"
sync_policy: !literal "{{argocd.sync.policy}}"

Documentation and Examples​

Include template examples in your configuration without evaluation:

metadata:
example_usage: !literal "Use {{component}} to reference components"
template_syntax: !literal "Variables use ${var.name} syntax"

Regex Patterns​

Preserve patterns containing brace-like syntax:

vars:
filename_pattern: !literal "user_{id}_{timestamp}.log"
validation_regex: !literal "^[a-z]+\\d{3}$"

Inline Arrays​

Use !literal in inline array syntax for compact configuration:

vars:
db_users: [!literal "{{external.email}}", !literal "{{external.admin}}", regular_user]
allowed_patterns: [!literal "${prefix}*", !literal "*${suffix}"]

Nested Structures​

Use !literal within deeply nested configurations:

components:
terraform:
application:
vars:
templates:
helm:
annotations: !literal "{{ .Values.ingress.class }}"
terraform:
user_data: !literal "#!/bin/bash\necho ${hostname}"
argocd:
config: !literal "{{external.config}}"

Step Definitions and atmos.yaml​

!literal works in atmos.yaml and in the step definitions of custom commands, workflows, and hooks. Atmos renders step fields as Go templates when a step runs, so a Starlark script or shell command that contains {{ }} text would fail with a template error. Tag the field with !literal and Atmos runs it exactly as written.

commands:
- name: report
description: Print a summary
steps:
- name: summary
type: script
interpreter: starlark
# The braces below are Starlark, not Atmos templates.
script: !literal |
rows = [{"name": "vpc", "status": "ok"}]
for row in rows:
print("{} is {}".format(row["name"], row["status"]))
print("Atmos templates look like {{ .vars.stage }}")
- name: echo
command: !literal echo "Atmos templates look like {{ .vars.stage }}"

The same tag works on steps in a workflow manifest, including steps nested in parallel and matrix groups, and on the steps of a step or steps hook.

These step fields honor !literal:

script
The body of a script step, in every step context.
command
The command of a shell step, and the string command of a custom command step.
interpreter
The interpreter of a script step.
working_directory
The working directory of a step.
timeout
The timeout of a step.
env values

Each value in a step's env map, tagged on its own, such as GREETING: !literal "{{ not a template }}". This covers the env of a parallel or matrix step too, and the command-level env of a custom command.

A step written as a plain string works as well: - !literal 'echo "{{ not a template }}"' is a command step whose text Atmos does not render.

A !literal tag on any other field of a step fails when the configuration loads. The error names the field and the step and lists the supported fields: !literal is not supported on field "type" of step "build"; it is supported on script, command, interpreter, working_directory, timeout, and on individual env values. Atmos performs this check for the steps of custom commands.

A script or command loaded with !include.raw is used exactly as written, with no Go template rendering, so it needs no !literal tag. A script loaded with !include is still rendered as a template. When a rendering error comes from an included script that contains {{, the error hint tells you to move that text into a load()ed module or to include the file with !include.raw.

Other fields of the same step keep rendering as templates, so you can combine a literal script with a templated env value. Only a field that carries the tag directly is literal: tagging a whole env map or steps list has no effect on the entries inside it.

!literal on scalar stack values in vars, settings, env, and similar data protects the value through inheritance, merging, template rendering, and YAML-function processing. Final descriptions and generated configuration contain the original ordinary string.

Why !literal is Needed​

Atmos processes Go templates and Gomplate expressions in stack configurations. When your configuration contains {{...}} syntax intended for downstream tools, Atmos can attempt to evaluate those expressions, causing errors or unexpected behavior. ${...} alone is not an Atmos Go-template expression.

The Problem​

Without !literal, these configurations fail or produce incorrect results:

# This fails - Atmos tries to evaluate {{external.email}}
db_users:
- "{{external.email}}"

# This fails - Atmos tries to evaluate ${hostname}
user_data: "echo ${hostname}"

Previous Workarounds​

Before !literal, users had to use awkward escaping:

# Workaround 1: Double braces (fragile, hard to read)
db_users:
- "{{'{{external.email}}'}}"

# Workaround 2: Template escaping (verbose)
db_users:
- "{{ `{{external.email}}` }}"

The Solution​

!literal provides a clean, self-documenting solution:

# Clear intent, preserves value exactly
db_users:
- !literal "{{external.email}}"

Comparison with Other Functions​

FunctionPurposeTemplate Processing
!literalPreserve value exactlyBypassed
!templateEvaluate Go templates and convert JSON to YAML typesEnabled
!execExecute shell commandsCommand may contain templates
!envRead environment variablesNo template processing

Common Use Cases​

  • Terraform: Pass ${var.name} or templatefile() syntax
  • Helm: Pass {{ .Values.* }} template expressions
  • ArgoCD: Pass {{external.*}} application set parameters
  • Kustomize: Pass patch placeholders
  • Documentation: Include template syntax examples
  • Regex/Patterns: Preserve brace patterns in strings
When to Use !literal

Use !literal whenever you need to pass {{...}}, ${...}, or similar template syntax to a downstream tool. If Atmos is trying to evaluate something it shouldn't, !literal is the solution.