# commands

A command's `commands` field nests subcommands beneath it. Each entry has the same structure as a top-level [`command`](/cli/configuration/commands/command), so you can group related commands (for example, `atmos list stacks` and `atmos list components`) under a shared parent.

```yaml
commands:
  - name: list
    description: Execute 'atmos list' commands
    # nested subcommands
    commands:
      - name: stacks
        description: List all Atmos stacks
        steps:
          - atmos describe stacks --process-templates=false --sections none | grep -e "^\S" | sed s/://g
```

Run a nested subcommand by chaining the names:

```shell
atmos list stacks
```

## Advanced Examples

### Define a New Terraform Command

```yaml
# Custom CLI commands
commands:
  - name: terraform
    description: Execute 'terraform' commands
    # subcommands
    commands:
      - name: provision
        description: This command provisions terraform components
        arguments:
          - name: component
            description: Name of the component
        flags:
          - name: stack
            shorthand: s
            description: Name of the stack
            required: true
        # ENV var values support Go templates
        env:
          - key: ATMOS_COMPONENT
            value: "{{ .Arguments.component }}"
          - key: ATMOS_STACK
            value: "{{ .Flags.stack }}"
        steps:
          - atmos terraform plan $ATMOS_COMPONENT -s $ATMOS_STACK
          - atmos terraform apply $ATMOS_COMPONENT -s $ATMOS_STACK
```

### Override an Existing Terraform Command

```yaml
# Custom CLI commands
commands:
  - name: terraform
    description: Execute 'terraform' commands
    # subcommands
    commands:
      - name: apply
        description: This command executes 'terraform apply -auto-approve' on terraform components
        arguments:
          - name: component
            description: Name of the component
        flags:
          - name: stack
            shorthand: s
            description: Name of the stack
            required: true
        steps:
          - atmos terraform apply {{ .Arguments.component }} -s {{ .Flags.stack }} -auto-approve
```

### Show Component Info

```yaml
# Custom CLI commands
commands:
  - name: show
    description: Execute 'show' commands
    # subcommands
    commands:
      - name: component
        description: Execute 'show component' command
        arguments:
          - name: component
            description: Name of the component
        flags:
          - name: stack
            shorthand: s
            description: Name of the stack
            required: true
        # ENV var values support Go templates and have access to {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables
        env:
          - key: ATMOS_COMPONENT
            value: "{{ .Arguments.component }}"
          - key: ATMOS_STACK
            value: "{{ .Flags.stack }}"
          - key: ATMOS_TENANT
            value: "{{ .ComponentConfig.vars.tenant }}"
          - key: ATMOS_STAGE
            value: "{{ .ComponentConfig.vars.stage }}"
          - key: ATMOS_ENVIRONMENT
            value: "{{ .ComponentConfig.vars.environment }}"
        # If a custom command defines 'component_config' section with 'component' and 'stack', 'atmos' generates the config for the component in the stack
        # and makes it available in {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables,
        # exposing all the component sections (which are also shown by 'atmos describe component' command)
        component_config:
          component: "{{ .Arguments.component }}"
          stack: "{{ .Flags.stack }}"
        # Steps support using Go templates and can access all configuration settings (e.g. {{ .ComponentConfig.xxx.yyy.zzz }})
        # Steps also have access to the ENV vars defined in the 'env' section of the 'command'
        steps:
          - 'echo Atmos component from argument: "{{ .Arguments.component }}"'
          - 'echo ATMOS_COMPONENT: "$ATMOS_COMPONENT"'
          - 'echo Atmos stack: "{{ .Flags.stack }}"'
          - 'echo Terraform component: "{{ .ComponentConfig.component }}"'
          - 'echo Backend S3 bucket: "{{ .ComponentConfig.backend.bucket }}"'
          - 'echo Terraform workspace: "{{ .ComponentConfig.workspace }}"'
          - 'echo Namespace: "{{ .ComponentConfig.vars.namespace }}"'
          - 'echo Tenant: "{{ .ComponentConfig.vars.tenant }}"'
          - 'echo Environment: "{{ .ComponentConfig.vars.environment }}"'
          - 'echo Stage: "{{ .ComponentConfig.vars.stage }}"'
          - 'echo Dependencies: "{{ .ComponentConfig.deps }}"'
```

### List Stacks and Components

```yaml
# Custom CLI commands
commands:
  - name: list
    description: Execute 'atmos list' commands
    # subcommands
    commands:
      - name: stacks
        description: |
          List all Atmos stacks.
        steps:
          - >
            atmos describe stacks --process-templates=false --sections none | grep -e "^\S" | sed s/://g
      - name: components
        description: |
          List all Atmos components in all stacks or in a single stack.

          Example usage:
            atmos list components
            atmos list components -s tenant1-ue1-dev
            atmos list components --stack tenant2-uw2-prod
        flags:
          - name: stack
            shorthand: s
            description: Name of the stack
            required: false
        steps:
          - >
            {{ if .Flags.stack }}
            atmos describe stacks --stack {{ .Flags.stack }} --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
            {{ else }}
            atmos describe stacks --format json --sections none | jq ".[].components.terraform" | jq -s add | jq -r "keys[]"
            {{ end }}
```

### Set EKS Cluster

This top-level command combines `component_config`, `env`, and multiple steps:

```yaml
# Custom CLI commands
commands:
  - name: set-eks-cluster
    description: |
      Download 'kubeconfig' and set EKS cluster.

      Example usage:
        atmos set-eks-cluster eks/cluster -s plat-ue1-dev -r admin
        atmos set-eks-cluster eks/cluster -s plat-uw2-prod --role reader
    verbose: false  # Set to `true` to see verbose outputs
    arguments:
      - name: component
        description: Name of the component
    flags:
      - name: stack
        shorthand: s
        description: Name of the stack
        required: true
      - name: role
        shorthand: r
        description: IAM role to use
        required: true
    # If a custom command defines 'component_config' section with 'component' and 'stack',
    # Atmos generates the config for the component in the stack
    # and makes it available in {{ .ComponentConfig.xxx.yyy.zzz }} Go template variables,
    # exposing all the component sections (which are also shown by 'atmos describe component' command)
    component_config:
      component: "{{ .Arguments.component }}"
      stack: "{{ .Flags.stack }}"
    env:
      - key: KUBECONFIG
        value: /dev/shm/kubecfg.{{ .Flags.stack }}-{{ .Flags.role }}
    steps:
      - >
        aws
        --profile {{ .ComponentConfig.vars.namespace }}-{{ .ComponentConfig.vars.tenant }}-gbl-{{ .ComponentConfig.vars.stage }}-{{ .Flags.role }}
        --region {{ .ComponentConfig.vars.region }}
        eks update-kubeconfig
        --name={{ .ComponentConfig.vars.namespace }}-{{ .Flags.stack }}-eks-cluster
        --kubeconfig="${KUBECONFIG}"
        > /dev/null
      - chmod 600 ${KUBECONFIG}
      - echo ${KUBECONFIG}
```
