# Atmos Automation Language

The Atmos Automation Language is based on Starlark, a Python-like language for
scripts. Its interpreter and built-in functions ship with Atmos.

Use scripts in workflows, custom commands, lifecycle hooks, scaffold hooks, and
Git hooks. Scripts can also run as [standalone apps](/scripting/standalone-cli-apps)
with an Atmos shebang. For complete syntax and data types, see the
[language reference](/scripting/reference).

## Syntax and values

Write functions, conditions, loops, lists, and dictionaries using familiar
Python-like syntax:

```python
def capacity(replicas, workers_per_replica):
    if replicas < 1:
        fail("replicas must be positive")
    return replicas * workers_per_replica

print("Total workers: {}".format(capacity(3, 4)))
```

This prints `Total workers: 12`. Use `fail(message)` to stop a script with an
error. Atmos reports the source location and traceback. Use
[`defer(fn)`](/functions/automation/defer) to register cleanup that runs when the
script finishes, even after a failure. Use
[`sum()`](/scripting/reference/builtin-functions#sum) to total numbers and
[`round()`](/scripting/reference/builtin-functions#round) to round a result.

The runtime supports top-level conditionals and loops, `while`, `set()`, and
recursive functions. It does not run arbitrary Python programs or import Python
packages. Use the built-in modules below and `load()` for shared Starlark code.

Module-level names cannot be reassigned. Compute a changing value inside a
function or mutate a list or dictionary before dispatching parallel work.
Values reachable by parallel tasks become immutable when dispatched. See the
[detailed language behavior](/steps/type/script#language-features).

## Inputs depend on the entry point

| Where the program runs | How it receives inputs |
| --- | --- |
| [Custom Atmos command](/scripting/custom-commands) | `ctx.flags` and `ctx.arguments` contain parsed inputs from the command's YAML declarations. |
| [Workflow step](/scripting/workflows) | `ctx.flags` contains available workflow flags. `ctx.arguments` is empty for YAML workflows, including parallel and matrix children. `env` contains explicitly declared step inputs. |
| [Component lifecycle hook](/scripting/lifecycle-hooks) | `ctx.component`, `ctx.hook`, and `ctx.operation` describe the component and parent operation. |
| [Scaffold hook](/scripting/lifecycle-hooks#scaffold-hooks) | Template values such as `.Answers` and `.TargetPath`, passed through the script step's `env`. |
| [Git hook](/scripting/lifecycle-hooks#git-hooks) | Git's positional arguments in `ctx.args`; stdin follows the Git hook's input contract. |
| [Custom CLI app](/scripting/standalone-cli-apps) | `cli.command` calls `main(args, flags)` with parsed inputs; scripts without it read raw `ctx.args`. |

`ctx.flags` and `ctx.arguments` are read-only dictionaries. Use parsed inputs
directly instead of interpolating them into script source or mapping each flag
to an environment variable.

## Why Starlark?

Starlark provides functions, loops, and structured data without a separate Python
or Node.js installation. It does not run Python packages. Module globals are
assigned once, and values shared with parallel tasks are frozen.

Pure calculations are repeatable; file reads and external commands still depend
on their environment. The interpreter is not a sandbox for untrusted scripts.
See Starlark's [design principles](https://github.com/bazelbuild/starlark#design-principles).

## Built-in helpers

| Helper | Purpose |
| --- | --- |
| [`cli.command`](/functions/automation/cli.command), [`cli.arg`](/functions/automation/cli.arg), [`cli.flag`](/functions/automation/cli.flag) | Declare arguments, flags, and help; validate inputs and run the app. |
| [`atmos.run`](/functions/automation/atmos.run), [`atmos.terraform`](/functions/automation/atmos.terraform), [`atmos.helm`](/functions/automation/atmos.helm), [`atmos.toolchain`](/functions/automation/atmos.toolchain), and one wrapper per command, such as [`atmos.vendor`](/functions/automation/atmos.vendor) | Invoke registered Atmos commands, including Terraform, Helm, and project commands through `atmos.run`. |
| [`components.get`](/functions/automation/components.get) | Resolve component configuration for a named component and stack. |
| [`exec.run`](/functions/automation/exec.run) | Run an external program with an argument list and capture its result. |
| [`steps.task`](/functions/automation/steps.task), [`steps.parallel`](/functions/automation/steps.parallel) | Describe function calls, execute concurrent work, and apply retries and timeouts. |
| [`defer`](/functions/automation/defer) | Register cleanup that runs when the script or task finishes, even after a failure or cancellation. |
| [`fs.read_file`](/functions/automation/fs.read_file) | Read a local file as text. |
| [`json.encode`](/functions/automation/json.encode), [`json.decode`](/functions/automation/json.decode) | Convert between structured values and JSON text. |
| [`regex.search`](/functions/automation/regex.search), [`regex.findall`](/functions/automation/regex.findall), [`regex.replace`](/functions/automation/regex.replace) | Match and transform text using regular expressions. |
| [`digest.sha256`](/functions/automation/digest.sha256), [`digest.sha512`](/functions/automation/digest.sha512), [`digest.sha1`](/functions/automation/digest.sha1), [`digest.md5`](/functions/automation/digest.md5) | Compute digests of strings and file contents. |
| [`exec.which`](/functions/automation/exec.which) | Find the executable that `exec.run` would start. |
| [`dependencies.tools`](/functions/automation/dependencies.tools) | Request tools through Atmos's toolchain integration. |
| [`ui.info`](/functions/automation/ui.info), [`ui.success`](/functions/automation/ui.success), [`ui.warning`](/functions/automation/ui.warning) | Write status messages for the person running the program. |
| [`errors.build`](/functions/automation/errors.build) | Raise actionable errors with Atmos's explanations, hints, examples, context, and exit codes. |
| [`log.trace`](/functions/automation/log.trace), [`log.debug`](/functions/automation/log.debug), [`log.info`](/functions/automation/log.info), [`log.warn`](/functions/automation/log.warn), [`log.error`](/functions/automation/log.error) | Emit diagnostics at the configured Atmos log level. |

The [automation functions reference](/functions/automation) documents every helper
and built-in value with its signature, arguments, return value, and examples. The
[script API reference](/steps/type/script#parameterized-tasks-retries-and-timeouts)
also details call signatures, return values, and failure behavior. The
[Atmos command reference](/steps/type/script#calling-atmos-commands)
explains command arguments and flags.

## Data, status, and diagnostics

Use `print()` for data on stdout, `ui.info()`, `ui.success()`, and `ui.warning()`
for status on stderr, and `log.debug()` or other log levels for diagnostics.

Assign the top-level `output` variable to return a step value. Strings are used
as written; other values must be JSON-encodable. Without `output`, a script
step uses captured stdout as its value. Status and diagnostic output do not
become the step value.

Output streams while the program runs. When masking is enabled, Atmos masks
registered secrets and matches for configured masking patterns in displayed
output. Log messages respect the configured log level and can include structured fields.
See [output and logging](/steps/type/script#step-output).

Use [`errors.build`](/functions/automation/errors.build) to give failures the same
presentation as Atmos's own errors. Add an explanation, recovery hints, and an
example before calling `.fail()`. These errors follow Atmos's normal reporting
path, including Sentry when configured.

Call the [step library](/functions/automation/steps.run) directly from scripts:
`steps.input(prompt = "Service?", default = "api").value` returns an input value.
The same module exposes choice and confirmation prompts, HTTP requests, container
operations, archives, and the other registered step handlers. Calls return values,
metadata, and named outputs that you can pass to the next operation.

You can also combine YAML prompts and script steps in a workflow or custom command.
See [prompts and step outputs](/scripting/workflows#collect-input-and-pass-results-between-steps).

## Files and shared code

Use `load("helpers.star", "function_name")` to load reusable functions. For a
program read from a file, module paths resolve relative to that file. For an
inline YAML script, they resolve relative to the step's working directory.

`fs.read_file` and `exec.run` use the step's working directory. A component's
`exec` method defaults to the component directory. See
[file resolution](/steps/type/script#loading-files) for YAML includes,
symlinks, and source paths.

## Execution controls

Use `steps.task` to attach arguments, retries, and a timeout to a function call.
Use `steps.parallel` to run a collection of tasks with a concurrency limit.
Results retain input order. A retry runs the entire function again, so use it
for operations that are safe to repeat.

Workflow dry runs parse embedded script steps without executing their code,
starting child processes, or installing tools. The embedded interpreter runs
inside Atmos; script steps using `interpreter: starlark` cannot run inside an
enabled container. See [workflow integration](/scripting/workflows) and
[execution restrictions](/steps/type/script#containers-and-dry-runs).

## Test program behavior

Use conditions and `fail()` to express assertions in the same language as your
automation. With `exec.run(..., check=False, output="capture")`, inspect a
command's exit code, stdout, and stderr before deciding whether it met the
expectation. A process that cannot start still raises an error.

Put these checks in a `test` step to collect results and display failures. See
[testing automation](/scripting/testing) for a runnable suite.

## Build with the language

- [Custom CLI apps](/scripting/standalone-cli-apps): declare arguments, flags, and help for an executable.
- [Custom commands](/scripting/custom-commands): add project-specific subcommands to Atmos.
- [Workflows](/scripting/workflows): combine programs and other step types into a runbook.
- [Lifecycle hooks](/scripting/lifecycle-hooks): attach checks and actions to component operations.

## Compute stack configuration

Use [`!starlark`](/functions/yaml/starlark) in stack manifests to compute typed
values from the merged component context. These blocks use `return` and a
read-only `ctx` object; see the YAML function reference for the available
builtins and evaluation order.
