cloudposse/atmos/atmos-starlark

Trust tier 3
  • community
  • ext:[{"type":"hook","description":"Pre/post lifecycle hooks"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

Write Atmos Automation Language scripts (Python-like, embedded Starlark): standalone executable tools (`atmos ./deploy.star`, `#!/usr/bin/env atmos`, typed flags via `cli.command`), `type: script` steps in workflows, custom commands, and hooks, parallel tasks, retries, and migration of Bash/Python glue. Reach for it when a task needs Atmos capabilities (deploy components, build and push containers, pin tools with dependencies.tools, use atmos.yaml auth identities, read resolved stack config with components.get) instead of Bash or Python. Use atmos-steps for the YAML step catalog and atmos-custom-commands for YAML command declarations.

Install

npx vskill@latest install cloudposse/atmos/atmos-starlark

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

Atmos Automation Language

Atmos Automation Language embeds Python-like Starlark in Atmos, with no Python or Bash installation. Scripts call Atmos directly, sharing its stacks, components, identities, and toolchain.

Use it for tasks that need Atmos capabilities:

  • Deploy components and run any Atmos command: atmos.terraform("deploy", "vpc", "dev"),

or atmos.container("build", "web", flags={"stack": "dev"}) (then "push") to build and push container images.

  • Read resolved stack configuration: components.get("vpc", "dev", "terraform").vars.
  • Pin tools without a manual install: dependencies.tools("jqlang/jq", "1.7.1").
  • Use identities and credentials configured under auth in atmos.yaml; the scripts

inherit them like any other Atmos command.

  • Fan out work safely with steps.parallel, retries, and per-task timeouts.

Keep simple one-command automation in YAML (atmos-workflows, atmos-custom-commands, atmos-steps). Use a script when the logic needs loops, conditionals, data shaping, or concurrency. Declarations of project commands and component bindings stay in YAML. The script step configuration is type: script with interpreter: starlark. To run a script file, set source: scripts/check.star instead of script:; Atmos infers starlark from the .star extension, and load() resolves relative to that file.

Documentation: Language reference, Custom CLI apps, function reference, and the script step.

Choose the entry point

Entry pointRun withInputs the script reads
Standalone scriptatmos ./deploy.star args..., atmos deploy.star, or ./deploy with an Atmos shebangcli.command callback args and flags dicts; raw ctx.args. ctx.flags, ctx.arguments, and env are empty.
Custom command stepatmos <name> (command declared in atmos.yaml)ctx.flags (string, bool, and int types preserved), ctx.arguments (an omitted optional argument is ""). ctx.args is empty; arguments after -- are not exposed to scripts.
Workflow stepatmos workflow <name>ctx.flags (string map). env holds only the step's declared env.
Hook steplifecycle event (kind: step, kind: steps, type: test)ctx.component, ctx.hook, ctx.operation.
Git hook stepgit.hooks.<name>.steps run by the installed Git shimctx.args holds the hook's arguments from Git, such as the commit message path for commit-msg. Shell steps get "$@" and ATMOS_GIT_HOOK_ARGS; ATMOS_GIT_HOOK_STDIN is a temp-file path for hooks that receive stdin.

Details for each entry point:

Minimal examples

Standalone tool with typed inputs:

python
#!/usr/bin/env atmos
def main(args, flags):
dependencies.tools("jqlang/jq", "1.7.1")
for stack in flags["stack"]:
atmos.terraform("deploy", args["component"], stack)
ui.success("deployed " + args["component"] + " to " + stack)
cli.command(
run = main,
description = "Deploy a component to one or more stacks",
args = [cli.arg("component", description="Component name")],
flags = [cli.flag("stack", type="string_list", shorthand="s", required=True)],
)

Run it with ./deploy.star vpc --stack=dev --stack=prod.

Workflow step reading its flags, with live subprocess output:

yaml
workflows:
smoke:
steps:
- name: check
type: script
interpreter: starlark
script: |
comp = components.get("api", ctx.flags["stack"], "terraform")
exec.run(["./smoke-test", comp.vars["url"]], working_directory=comp.path)

Language rules

  • Dialect: top-level if/for/while, set(), and recursion are allowed. A recursion

depth limit (10,000 frames) stops runaway recursion with a clean "recursion depth exceeded" error and a collapsed traceback.

  • Globals are assigned once: x = 1 then x = 2, n += 1 at the top level, or assigning

output in both branches of an if/else fails with cannot reassign global. Use output = a if cond else b, or def main(): ... return v then output = main(). Mutate a dict (state["n"] += 1) before steps.parallel, which freezes shared state.

  • env: immutable explicit step inputs (the step's declared env). The ambient process

environment is not copied into it. Child processes from exec.run and atmos.* still inherit the effective process environment; read it with os.getenv(name, default=None) and pass env={...} to add per-call overrides. Missing variables return the default; empty values stay empty.

  • os.platform and os.arch are read-only executable platform/architecture strings. os.getcwd() reads

the script directory; os.environ() returns a frozen environment snapshot. os.setenv(name, value) and os.chdir(path) change invocation-local defaults only from the main thread. Parallel tasks inherit those defaults and use per-call overrides; host process state stays unchanged.

  • ctx.flags and ctx.arguments: immutable parsed command inputs, preserving host types

in custom commands. Read these directly; do not map flags through env or template values into script source.

  • Atmos renders step script bodies as Go templates before Starlark runs. Valid {{ ... }} actions

are rendered; malformed or unresolved actions can fail. Write script: !literal | when braces must remain literal. A script loaded with !include.raw is also used as written; one loaded with !include is still rendered (move the braces into a load()ed module, or use !include.raw). !literal also works on command, interpreter, working_directory, timeout, and single env values; on any other step field it fails config load.

  • Output channels: print writes data to stdout. ui.info (▶), ui.success (✓), and

ui.warning (⚠) write human status to stderr. Bare email addresses render once; explicit Markdown links retain their destination. log.trace/debug/info/warn/error(message, **fields) writes diagnostics through the Atmos logger with step (and, in parallel tasks, task) fields; it honors ATMOS_LOGS_LEVEL, --logs-level, and logs.file, and masks secrets. ci.summary, ci.comment, ci.annotate, ci.output, ci.env, ci.path, ci.mask, ci.check, ci.group, and ci.sarif report into the CI provider running the script and render locally on stderr when none is detected; ci.context describes the run. In CI they honor the ci.*.enabled switches and warn (naming the flag) instead of failing when one is off. Use ci.*, never exec.run(["gh", ...]) or hand-written $GITHUB_ENV appends; see references/api-reference.md.

  • Top-level output: a string is emitted raw, any other value is JSON-encoded, and a value

that cannot be encoded (such as a function) fails the script. Without output, captured stdout is the step value.

  • steps.run(type, **fields) and the steps.<type>(...) library call any registered step

handler (see steps.run); they exist, and steps.input and steps.choose prompt. Also available: fs.read_file, fs.write_file(path, content, overwrite=False, mode=0o600), fs.glob, fs.stat, fs.exists, fs.readlink, fs.resolve (absolute path; every fs.* call accepts a leading ~), exec.which (path or None), defer(fn, *args) (cleanup that runs when the script or task finishes, even after fail(); there is no try/finally), digest.sha256/digest.sha512/digest.sha1/digest.md5 (hex digest of a string or file contents), errors.build(...) (a builder ending in .fail()), json.indent, json.encode_indent, and the ci module (ci.context, ci.summary, ci.comment, ci.annotate, ci.output, ci.env, ci.path, ci.mask, ci.check, ci.group, ci.sarif, ci.base; distinct from the atmos.ci(...) command wrapper). yaml.decode reads one YAML data document; yaml.validate checks syntax across all documents without evaluating tags. git.sandbox provides isolated Git checkouts and safe unstaged fix reconciliation; see the API reference. Never invent components.list, commands.run, direct secret, store, or Terraform state/output builtins. They do not exist. Resolved YAML inputs and component configuration can carry values from those services.

  • Starlark-specific failures include the traceback; unhandled script errors propagate to

Atmos's configured error reporting.

Calling Atmos from a script

  • atmos.<command>(...) exists for every registered Atmos command, including custom

commands and aliases. Run print(dir(atmos)) to list them. Positional arguments are literal CLI arguments; keyword-only options are flags, args, working_directory, env, output, check, and stdin. output is "stream" (default), "capture", or "viewport" (falls back to streaming without a TTY or in parallel tasks); exec.run and component.exec take the same modes. A failed check=True call that reaches the top of the script exits Atmos with the child's exit code. --profile and --identity reach nested atmos.* calls in every script context. Example: atmos.describe("component", "api", flags={"stack": "dev"}).

  • Names that are not valid identifiers (hyphenated command names) are called through

atmos.run(["my-command", "arg"]).

  • atmos.terraform(command, component, stack, flags=, args=, working_directory=, env=, output=, check=, stdin=None)

and atmos.helm(...) take structured component arguments; atmos.tf is atmos.terraform with the same signature (keyword component=, stack=, detailed-exitcode tolerance). Prefer deploy over apply in non-interactive scripts.

  • Wrappers run the current Atmos binary as a subprocess and return a process result

(.stdout, .stderr, .exit_code, and .data, the lazily decoded JSON of stdout). The atmos.list, atmos.describe, atmos.config("get"), atmos.stack("get"), and atmos.stack("config", "get") wrappers default to JSON and captured output, so read .data directly. For other wrappers, pass --format=json flags and read .data or json.decode(result.stdout).

  • The initial default working directory is the directory Atmos was invoked from. os.chdir changes

that default for subsequent Atmos calls; relative per-call directories resolve against the current default.

Hook context

Component lifecycle hooks expose ctx.component, ctx.hook, and ctx.operation. Aggregate or unbound hooks have ctx.component == None: guard it before reading ctx.component.settings or calling ctx.component.exec in shared handlers. Component settings are read-only; exec runs in the component directory. Outside hooks, ctx.hook and ctx.operation are None; guard them in scripts shared with other callers. For examples, event outcomes, environment precedence, recursion limits, and stdout precautions, read Hook context.

Parallel functions

Use steps.parallel with named steps.task calls for concurrent work. Pass functions, not their evaluated results; return branch-local values instead of mutating shared state. See parallel functions for the complete example, retry and timeout rules, cancellation, and output behavior.

Toolchain dependencies

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Extension points

  • hookPre/post lifecycle hooks

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/cloudposse/atmos/atmos-starlark/badge)](https://verified-skill.com/skills/cloudposse/atmos/atmos-starlark)

Something wrong with this skill or its page? Tell us.