# Lifecycle Hooks

A lifecycle hook runs a check or action automatically before or after an Atmos
component operation. For example, a hook on `before.terraform.plan` can require
an owner in the component configuration before allowing the plan to start.

Hooks make checks part of the operation your team already runs. Callers do not
need to remember a separate validation command. Your script receives the resolved
component configuration, so the check can use inherited settings and variables
directly. After-hooks can report results or start follow-up work.

This guide uses the [owner-check example](/examples/starlark-hooks). Install
Atmos and Terraform and put them on your `PATH`. The example includes the Atmos
configuration and a Terraform module with no providers or resources; it needs
no cloud credentials.

## Add a check before planning

This stack defines an `api` component and a hook requiring it to have an owner:

The hook selects `before.terraform.plan` and uses `kind: step` with `type: script`
to run one script step. Its `with` block configures that step, including
`interpreter: starlark` for the Atmos Automation Language.

`on_failure: fail` makes a failed check stop the operation. The script reads
`ctx.component.vars`, calls `fail()` if the owner is absent, and otherwise prints
a success message with `ui.success()`.

The component is named `api` in the stack; its implementation directory is
`service`. `ctx.component.name` retains the component name used by the caller,
so messages identify `api`.

## Run the passing case

Run from the example's directory:

```shell
atmos terraform plan api -s dev
```

The hook prints:

```text
Owner check passed: api belongs to platform (dev).
```

Terraform then reports no changes.

## Stop an invalid operation

The `unowned` stack imports the same configuration and clears the owner:

Run the same operation against that stack:

```shell
atmos terraform plan api -s unowned
```

The command fails with `Set an owner before planning api`. Because the check runs
before the plan and has a failing policy, the Terraform plan does not start.
The inherited hook protects both stacks using the same logic.

## Work with lifecycle context

Hook scripts receive read-only objects describing their invocation:

| Object | Use it for |
| --- | --- |
| `ctx.component` | Component name, stack, implementation path, resolved variables, settings, and metadata |
| `ctx.hook` | Hook name and the canonical event that triggered it |
| `ctx.operation` | Parent command and the operation outcome supplied to an after-hook |

A before-hook has no operation outcome yet: status, exit code, and error are
`None`. After-hooks expose the supplied outcome. Ordinary lifecycle hooks do not
capture the parent command's stdout or stderr, and Terraform outputs are not
automatically attached to the component context.

## Choose events and failure behavior

Declare the events your hook handles explicitly. Use before-events for checks
that must pass first and after-events for follow-up work. Keep a hook's failure
policy visible alongside its event so the effect on the parent command is clear.

See the [hooks reference](/stacks/hooks) for supported events, kinds, inheritance,
and failure policies. The
[lifecycle context reference](/steps/type/script#lifecycle-hook-context)
lists script fields and their behavior, including hooks without an individual
component binding. Browse the [runnable example](/examples/starlark-hooks) for the
complete project used in this guide.
