Skip to main content
api-reference.md11.5 KB
View on GitHub

Atmos Automation Language API Reference

Everything below is predeclared; there is nothing to import. The published function reference documents each function in more depth. If a name is not listed here, check that page before concluding it does not exist.

Context and inputs

  • ctx.args: immutable list of raw script arguments. Standalone scripts get the tokens after the script name; Git hooks get the arguments Git passes to the hook. It is empty elsewhere.
  • ctx.flags, ctx.arguments: immutable parsed inputs for script steps. Custom command string, bool, and type: int flags keep their types; workflow flags are strings and always include stack. In standalone scripts both are empty; use the cli.command callback instead.
  • ctx.script: .path and .directory of the physical file. Set for standalone scripts and for script steps included through a local !include; None for inline step scripts.
  • ctx.component, ctx.hook, ctx.operation: see the entry-point table in SKILL.md.
  • env: immutable dict of the step's explicit env inputs.

Standalone command line

  • cli.command(run, name=, description=, args=, flags=, validate=), cli.arg(...), cli.flag(...): see standalone-scripts.md. Standalone main thread only.

Processes

  • exec.run(argv, working_directory=, env={...}, output="stream", check=True): argv-based child process; returns a result with .stdout, .stderr, .exit_code, and .data (stdout decoded as JSON on first access; reading it on non-JSON stdout fails). timeout="30s" bounds the whole call, and retry={"max_attempts": 3, "initial_delay": "1s", "conditions": [regex, ...]} retries ordinary nonzero exits (conditions match the failed attempt's output). It raises on failure by default, with the last stderr lines in the error. Use check=False to assert an expected nonzero exit. Start failures (command not found, bad directory), cancellation, signals, and transport errors always raise. output="stream" (default) shows output live and also captures it; output="capture" captures without showing; output="viewport" shows live output in a bounded viewport (streams without a TTY or in parallel tasks). A check=True failure that reaches the top exits Atmos with the child's exit code. It inherits the effective execution environment without changing the global working directory or environment. Relative working_directory resolves against the step working directory.
  • exec.which(name): absolute path of the executable exec.run would start for name, or None. Searches the same PATH as exec.run (including dependencies.tools directories); a name with a path separator resolves relative to the working directory. Use it for prerequisite checks instead of running a tool just to see whether it exists.
  • component.exec(argv, working_directory=, env={...}, output=, check=): same, but runs in the component's physical directory and uses the component env (then command, step, and per-call overrides). Use the handle rather than inferring a path from a logical name.

Atmos commands

  • atmos.<command>(*positional, flags={}, args=[], working_directory=, env=, output=, check=) for every registered command, including custom commands and aliases (print(dir(atmos))). Examples: atmos.version(), atmos.list("components"), atmos.vendor("pull", flags={"stack": "dev"}), atmos.describe("component", "api", flags={"stack": "dev", "format": "json"}, output="capture"), atmos.scaffold("generate", "template", "target"), atmos.config("get", args=["base_path"]). The atmos.list, atmos.describe, atmos.config("get"), atmos.stack("get"), and atmos.stack("config", "get") wrappers default to JSON and captured output and expose .data.
  • atmos.run(argv, working_directory=, env=, output=, check=): invoke the current Atmos binary with a full argument list. Use it for hyphenated custom command names that cannot be attributes: atmos.run(["my-command", "--flag=value"]).
  • atmos.terraform(command, component, stack, flags={}, args=[], working_directory=, env=, output=, check=) and atmos.helm(...): structured component arguments. atmos.tf is atmos.terraform (same keyword component=/stack= signature and detailed-exitcode tolerance). Pass the stack as the stack argument, not as a flags entry. Prefer deploy over apply in non-interactive scripts.
  • atmos.toolchain(command, tool=, flags=, args=, ...): explicit toolchain commands, for example atmos.toolchain("install", "jqlang/jq@1.7.1"). It behaves like the CLI and pins the tool in the project's .tool-versions. Commands use installed pins; automatic installation depends on toolchain.install (always installs all pins on every run). It does not change the script's PATH; use dependencies.tools for a script-scoped pin.
  • Flag mapping: bare keys become --name; an explicit dash prefix preserves native tool spelling ("-detailed-exitcode"). Values are strings, ints, bools, or lists (a list repeats the flag). True emits a bare flag; False emits --name=false. detailed-exitcode on terraform plan uses a single dash and accepts exit code 2 without raising.
  • All wrappers return process results (.stdout, .stderr, .exit_code, .data). .data parses captured stdout as JSON. The query wrappers listed above default to JSON and output="capture"; other wrappers default to output="stream". Default check is True, and the default working directory is where Atmos was invoked. Parent CLI-only flags are not replayed automatically.

Stack configuration

  • components.get(name, stack, type): resolved component handle in standalone scripts (with an Atmos project), and in custom command, workflow, and hook script steps and their parallel/matrix children. Results are cached per run. The handle exposes name, stack, type, implementation, path, vars, settings, metadata, env, config (read-only), and exec.

Concurrency

  • steps.parallel(functions=[fn, ...] | tasks=[...], max_concurrency=4, fail_fast=False): runs zero-argument functions or tasks; returns results in input order.
  • steps.task(name, function, args=[], kwargs={}, retry=None, timeout=""): deferred task descriptor for steps.parallel(tasks=[...]). retry keys: max_attempts, initial_delay, backoff_strategy, max_delay.

Cleanup

  • defer(fn, *args, **kwargs): registers a call to run when the enclosing script or steps.parallel task finishes, last in first out, after a normal return, fail(), or cancellation (then with a 30 s grace context so exec.run/atmos.* still work). Arguments are captured at registration. The body error stays primary; a failing deferred call is reported after it. This is the finally / trap EXIT equivalent; when: always is the YAML-step counterpart. Never write cleanup after a fail() and expect it to run.

Step library

  • steps.run(type, **fields) and steps.<type>(**fields) (for example steps.input, steps.choose, steps.join, steps.http) execute any registered step handler immediately and return its result. See steps.run.

Data helpers

  • json.encode(value), json.decode(text): structured data without shell quoting. Use json.indent(text, prefix=, indent=) to pretty-print JSON text, and json.encode_indent(value) to encode and format in one call.
  • fs.read_file(path): read a local file as a string (relative to the step working directory, also inside loaded functions; absolute paths accepted; a leading ~ expands to the home directory in every fs.* call). There is no write API. Use fs.glob(pattern), fs.stat(path), fs.exists(path), and fs.readlink(path) to inspect the filesystem. fs.resolve(path) returns the absolute path (tilde expanded, relative paths joined to the working directory, cleaned) without touching the filesystem, so use it instead of hand-rolled ~ and absolute-path checks.
  • digest.sha256(data), digest.sha512(data), digest.sha1(data), digest.md5(data): lowercase hex digest of a string. Strings are bytes, so digest.sha256(fs.read_file(path)) fingerprints a binary file exactly. There is no incremental API; sha1 and md5 exist for interoperability (Git ids, S3 ETags), not security.
  • errors.build(message): error builder with .with_title, .with_explanation, .with_hint, .with_example, .with_context, .with_exit_code, and a final .fail().
  • regex.search(pattern, text): boolean match anywhere. regex.findall(pattern, text): list of full matches. regex.replace(pattern, replacement, text): replace all matches with literal text. Go/RE2 syntax, including inline flags; no lookaround, backreferences, or replacement capture expansion. Use ordinary string methods for fixed text.

Output

  • print(...): stdout (data).
  • ui.info(message) (▶), ui.success(message) (✓), ui.warning(message) (⚠): stderr.
  • log.trace/debug/info/warn/error(message, **fields): Atmos logger. Field names must be identifiers. step and task fields are added automatically. Never the step value.

CI

  • ci.context: read-only struct, resolved on first access: provider, local (no CI provider detected; the generic provider renders locally), event, sha, branch, repo, actor, run_id, run_url, elevated (pull_request_target/workflow_run), and pr (number, head, base, url) or None. ci.base(): the affected-detection base (ref, sha, head_sha, target_branch, source) or None.
  • Writes, one call each, with a local rendering on stderr when no provider is detected: ci.summary(markdown), ci.output(name, value), ci.env(name, value), ci.path(dir), ci.mask(value) (registers with Atmos masking at once; ::add-mask:: in CI), ci.annotate(level, message, file="", line=0, end_line=0, title="") (error|warning|notice), ci.comment(body, key="", behavior="upsert", pr=0) → struct id, url, created (a key makes later runs update the same comment; locally a preview, never posted), ci.check(name, state="pending", description="", url="") → handle with name, state, id, url, and update(state, description="", url="") (a commit status on GitHub; no body), ci.group(title, fn) → fn()'s result inside a collapsible log group, and ci.sarif(path, category="").
  • In CI each write honors the same switches as native reporting (ci.enabled plus ci.summary.enabled, ci.output.enabled (also env/path), ci.annotations.enabled, ci.results.enabled, ci.checks.enabled, ci.comments.enabled, ci.groups.mode). A gated-off call renders locally and warns with the disabled flag; local rendering errors can still fail the script. ci.mask registers the secret with Atmos masking without a gate warning when ci.enabled is disabled. Comments and checks are held on elevated events unless ci.allow_unsafe_fork_execution is set.
  • Distinct from atmos.ci(...), which runs the atmos ci CLI command group as a subprocess. Reference: ci.

Toolchain

  • dependencies.tools(name, version): install and pin a tool for the invocation. Main thread only, before steps.parallel.

Language dialect

Top-level if, for, and while; set(); and recursion are enabled. Globals can be assigned once. There are no classes, exceptions, or import; use load("path.star", "name") for local modules and fail("message") to abort.