# Atmos Automation Language

Write your build, test, and deployment process in the Atmos Automation Language,
a Python-like language based on Starlark. Compose Atmos capabilities with your
own functions and run the same automation locally and in CI, for applications
and infrastructure.

Atmos executes your code as a standalone `.star` program or as a script step
in a custom command, workflow, or lifecycle hook. Run a file with
`atmos ./my-tool.star`. For an inline YAML script step, set
`type: script` and `interpreter: starlark`. The interpreter and built-in functions
ship with Atmos.

This page introduces the language and how Atmos runs it. For complete syntax
and data types, see the [language reference](/automation/reference).

## Why Starlark?

Starlark provides functions, loops, conditions, and structured data with
Python-like syntax. You can pass a component's configuration between functions,
inspect a command result, and test a calculation without converting everything
to shell text. Shared functions let your release process grow without copying
logic between Bash scripts and CI jobs.

Its smaller feature set gives teams fewer language features to learn when
writing and reviewing automation. It is a separate language:
Atmos scripts do not run arbitrary Python code or import Python packages.

Atmos supplies functions for reading files, running commands, and working with
component configuration. These built-ins use the same interfaces in standalone
scripts, workflow steps, custom commands, and hooks. Scripts that use only the
built-ins need no separate Python or Node.js installation; commands they launch
still need their own tools and credentials.

Calculations using only their supplied inputs produce repeatable results.
Values shared with parallel tasks are frozen so those tasks cannot change shared
state. File reads and subprocess results still depend on the environment, so an
entire automation script is not necessarily deterministic. The interpreter is not
a security boundary for untrusted scripts.

See Starlark's [design principles](https://github.com/bazelbuild/starlark#design-principles)
for the language's design rationale.

## 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
[`sum()`](/automation/reference/builtin-functions#sum) to total numbers and
[`round()`](/automation/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 CLI app](/automation/standalone-cli-apps) | `cli.command` parses declarations and calls `main(args, flags)`; `ctx.args` provides raw script arguments. |
| [Custom Atmos command](/automation/custom-commands) | `ctx.flags` and `ctx.arguments` contain parsed inputs from the command's YAML declarations. |
| [Workflow step](/automation/workflows) | `env` contains explicitly declared step inputs; the workflow supplies its execution environment. |
| [Lifecycle hook](/automation/lifecycle-hooks) | `ctx.component`, `ctx.hook`, and `ctx.operation` describe the component and operation. |

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

## Built-in helpers

| Helper | Purpose |
| --- | --- |
| [`cli.command`](/functions/automation/cli.command), [`cli.arg`](/functions/automation/cli.arg), [`cli.flag`](/functions/automation/cli.flag) | Declare a standalone program's interface, validate inputs, and invoke its callback. |
| [`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. |
| [`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. |
| [`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](/automation/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](/automation/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](/automation/testing) for a runnable suite.

## Build with the language

- [Custom CLI apps](/automation/standalone-cli-apps): declare your own executable's interface.
- [Custom commands](/automation/custom-commands): add project-specific subcommands to Atmos.
- [Workflows](/automation/workflows): combine programs and other step types into a runbook.
- [Lifecycle hooks](/automation/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.
