# dependencies

The `dependencies` field declares tool dependencies that Atmos installs automatically before a command runs, and the named commands and workflows that must complete first. This ensures any CLI tools your command requires are available at the correct version, leveraging Atmos's [toolchain management](/cli/configuration/toolchain/).

## Basic Usage

Specify tool dependencies using the `dependencies.tools` section within your command:

```yaml
commands:
  - name: lint
    description: Run tflint on terraform components
    dependencies:
      tools:
        tflint: "0.54.0"
    arguments:
      - name: component
        description: Component to lint
        required: true
    flags:
      - name: stack
        shorthand: s
        description: Stack name
        required: true
    steps:
      - atmos terraform generate varfile {{ .Arguments.component }} -s {{ .Flags.stack }}
      - tflint --chdir=components/terraform/{{ .Arguments.component }}
```

When you run `atmos lint vpc -s plat-ue2-dev`, Atmos will:

1. Check if tflint 0.54.0 is installed in the toolchain directory
2. Install it from the [toolchain registry](/cli/configuration/toolchain/registries) if missing
3. Execute the command steps with the tool available in PATH

## Multiple Tool Dependencies

Commands can declare multiple tool dependencies:

```yaml
commands:
  - name: security-scan
    description: Run security scans on infrastructure code
    dependencies:
      tools:
        tflint: "0.54.0"
        checkov: "3.0.0"
        tfsec: "1.28.0"
    steps:
      - tflint --chdir=components/terraform
      - checkov -d components/terraform
      - tfsec components/terraform
```

## Version Specification

Tool versions can be specified in several formats:

```yaml
dependencies:
  tools:
    # Exact version
    terraform: "1.9.8"

    # Latest available version
    kubectl: "latest"
```

## Integration with Toolchain Configuration

Tool dependencies in custom commands work with your toolchain configuration in `atmos.yaml`. Tools are installed to the configured `install_path` and resolved using your configured [registries](/cli/configuration/toolchain/registries).

```yaml
# atmos.yaml
toolchain:
  install_path: ".tools"
  registries:
    - name: aqua
      type: aqua
      source: https://github.com/aquaproj/aqua-registry/tree/main/pkgs
      priority: 10

commands:
  - name: lint
    dependencies:
      tools:
        tflint: "0.54.0"  # Installed to .tools/, resolved via aqua registry
    steps:
      - tflint --version
```

:::tip
Use tool dependencies in custom commands to ensure all team members and CI/CD pipelines use consistent tool versions without manual installation steps.
:::

## Using Toolchain Tools

Custom commands automatically have access to tools defined in your project's `.tool-versions` file. The toolchain ensures the correct versions are installed and available in PATH when your command executes.

### Automatic Tool Access

If your project has a `.tool-versions` file:

```
terraform 1.10.0
kubectl 1.32.0
helm 3.16.0
```

Custom commands can use these tools directly:

```yaml
commands:
  - name: deploy
    description: Deploy infrastructure
    steps:
      - terraform init
      - terraform plan
      - kubectl apply -f manifests/
```

When you run `atmos deploy`:

1. Atmos reads `.tool-versions` to identify required tools
2. Missing tools are automatically installed
3. PATH is updated to include toolchain binaries
4. Command steps execute with the correct tool versions

### Declaring Additional Dependencies

Use the `dependencies` field to require additional tools or override versions from `.tool-versions`:

```yaml
commands:
  - name: validate
    description: Validate with specific tool versions
    dependencies:
      tools:
        tflint: "^0.54.0"      # Additional tool not in .tool-versions
        terraform: "1.9.8"     # Override .tool-versions version
    steps:
      - terraform validate
      - tflint --recursive
```

Dependencies declared in the command take precedence over `.tool-versions`.

### Version Constraints

Dependencies support SemVer constraints:

| Constraint | Meaning | Example |
|------------|---------|---------|
| `1.10.3` | Exact version | Only version 1.10.3 |
| `~> 1.10.0` | Pessimistic (patch) | Includes 1.10.x but not 1.11.0 |
| `^1.10.0` | Compatible (minor) | Includes 1.x.x but not 2.0.0 |
| `latest` | Latest available | Most recent version |

:::tip
The combination of `.tool-versions` for project-wide defaults and per-command `dependencies` for overrides gives you flexibility while maintaining consistency across your team.
:::

## Named command and workflow dependencies

`dependencies.commands` and `dependencies.workflows` declare other named custom commands and [workflows](/workflows) that must complete before this command runs its own steps. They resolve and run **concurrently by default** — like go-task's `deps:` — through the same generic DAG scheduler used by [`parallel`](/workflows/steps/type/parallel)/[`matrix`](/workflows/steps/type/matrix) `needs:` and Terraform's `dependencies.components`:

```yaml
commands:
  - name: build
    steps:
      - command: go build ./...

  - name: test
    dependencies:
      commands: [build]
    steps:
      - command: go test ./...

  - name: lint
    dependencies:
      commands: [build]
    steps:
      - command: golangci-lint run ./...

  - name: release
    dependencies:
      commands: [test, lint]
    steps:
      - type: atmos
        command: terraform apply infra -s dev
```

Running `atmos release` resolves the full dependency closure: `build` runs once (even though both `test` and `lint` depend on it — a shared dependency is deduped, not run twice), then `test` and `lint` run concurrently once `build` finishes, then `release`'s own steps run.

- **`commands`**
  List of custom command names. Entries can be a plain string (
  `build`
  ) or an object with 
  `flags`
  /
  `args`
   overrides for a parameterized invocation. Commands run 
  **in-process**
  , reusing the already-registered Cobra command — no subprocess is spawned. Resolved globally: Atmos deep-merges every 
  `atmos.d`
  -imported command definition into one list before any command runs, so there's no file boundary to specify.
- **`workflows`**
  List of workflow names, each as an object with a required 
  `file:`
   — a custom command has no "current workflow file" to default a bare name against, so the file is always explicit, resolved the same way the CLI's 
  `atmos workflow <name> -f <file>`
   resolves it. Workflow dependencies run in-process within 
  `internal/exec`
  .

### Parameterized dependencies

An entry with `flags`/`args` runs the target with those overrides. Two entries with the **same** name and parameters collapse into one execution; entries with **different** parameters are distinct and both run:

```yaml
commands:
  - name: build
    flags:
      - name: env
        default: dev
    steps:
      - command: go build -o bin/{{ .Flags.env }}/handler ./cmd/handler

  - name: release
    dependencies:
      commands:
        - name: build
          flags: { env: dev }
        - name: build
          flags: { env: prod }
    steps:
      - command: ./scripts/publish.sh
```

### Failure propagation

By default (`wait_all`), a failed dependency skips everything that transitively depends on it. `fail` reuses the exact same modes [`parallel`](/workflows/steps/type/parallel#failure-behavior) uses, derived from every direct dependency entry on this command (`best_effort` wins if any sets it, else `fail_fast` if any sets it, else `wait_all`):

```yaml
dependencies:
  commands:
    - name: test
      fail: best_effort   # wait_all (default) | fail_fast | best_effort
```

## Related Documentation

- [Toolchain Configuration](/cli/configuration/toolchain) - Configure tool version management
- [Workflows](/workflows) - Workflows also support toolchain integration
