# atmos terraform plan-diff

The `atmos terraform plan-diff` command compares two Terraform plans and shows the differences between them.

# terraform plan-diff

The `atmos terraform plan-diff` command compares two Terraform plans and shows the differences between them.

It takes an original plan file (`--orig`) and optionally a new plan file (`--new`). If the new plan file is not provided, it will generate one by running `terraform plan` with the current configuration.

The command shows differences in variables, resources, and outputs between the two plans.

:::info
[Data sources](https://opentofu.org/docs/language/data-sources/) are automatically skipped during comparison and will not appear in the diff.
:::

## Usage

```shell
atmos terraform plan-diff <component> -s <stack> --orig=<original-plan-file> [--new=<new-plan-file>] [options]
```

## Arguments

- **`component` (required)**
  The name of the component to run the command against.

## Flags

- **`-s` / `--stack` (required)**
  The stack name to use.
- **`--orig` (required)**
  Path to the original Terraform plan file.
- **`--new` (optional)**
  Path to the new Terraform plan file.
- **`--skip-init` (optional)**
  Skip running 
  `terraform init`
   before executing the command.

You can also pass any additional flags and arguments that are supported by the `terraform plan` command when generating a new plan.

## Ignoring attribute changes

Configure `components.terraform.plan_diff.ignore_changes` in `atmos.yaml` to exclude resource
attributes that are expected to vary between plans. These exclusions apply to both
`atmos terraform plan-diff` and plan verification during `atmos terraform deploy`.

For example, an RDS instance's computed `latest_restorable_time` can change between plans
even when its configuration has not changed:

```yaml title="atmos.yaml"
components:
  terraform:
    plan_diff:
      ignore_changes:
        - aws_db_instance.latest_restorable_time
```

Each entry must be an exact `resource_type.attribute` name. The rule applies to every instance
of that resource type, including instances inside modules. Only top-level attributes are supported;
bare attribute names, wildcards, resource addresses, and nested attribute paths are invalid.
Malformed entries cause a configuration error before Terraform runs. When an entry is well formed
but matches no attribute on the resources of that type present in the plans, which usually means a
resource address or a typo was configured, Atmos prints a warning and leaves the comparison unchanged.
Values that become known only after apply are shown as `(known after apply)` rather than as removed
or added attributes.

No resource attributes are excluded from comparison by default.

Exclusions affect both the displayed diff and the comparison verdict. If the plans differ only
in excluded attributes, `plan-diff` exits with code `0`, and deployment plan verification passes.
Other attribute changes, resource additions and removals, lifecycle action changes, and replacement
metadata still count as differences. Variables and outputs are compared independently: exporting
an ignored resource attribute as an output does not exclude that output from comparison.

:::note
This setting controls Atmos's comparison of two plans. It does not modify Terraform plans, state,
or resource updates, and it does not configure Terraform's `lifecycle.ignore_changes`.
:::

### Edition compatibility

Starting with the `2026-10-13` [edition](/cli/configuration/edition), Atmos displays differences in
`response_body_base64`, `content_base64sha256`, `content_base64sha512`, `content_md5`,
`content_sha1`, `content_sha256`, and `content_sha512`. Unpinned projects get this behavior too.

Earlier editions retain the historical display-only suppression of these seven attributes.
Their differences still cause `plan-diff` to exit with code `2` and deployment verification to fail,
just as before; a resource heading can appear without an attribute diff. Pin an earlier date,
such as `edition: "2026-10-12"`, to preserve that display behavior.

Explicit `ignore_changes` entries exclude attributes from both comparison and display under
**every** edition. To tolerate a content hash change, add its qualified attribute explicitly,
for example `local_file.content_sha256`. Computed attributes and content hashes can represent
real changes and are not automatically safe to ignore.

## Examples

### Compare an existing plan with a new plan generated with current configuration

```shell
atmos terraform plan-diff myapp -s dev --orig=orig.plan
```

### Compare two existing plan files

```shell
atmos terraform plan-diff myapp -s dev --orig=orig.plan --new=new.plan
```

### Example with data resources

When your Terraform configuration includes data sources, they will be automatically filtered out of the diff:

```shell
# Your plan might include data sources like:
# data.aws_ami.example
# data.aws_vpc.main
# aws_instance.web_server
# aws_s3_bucket.storage

# The diff will only show managed resources:
atmos terraform plan-diff myapp -s dev --orig=orig.plan
```

**Output:**

```text
Resources:
-----------
+ aws_instance.web_server
~ aws_s3_bucket.storage
  ~ versioning.enabled: false => true
```

## Output Format

When there are no differences between the two plan files:

```text
The planfiles are identical
```

When there are differences between the two plan files:

```text
Diff Output
=========

Variables:
----------
+ added_var: "new value"
- removed_var: "old value"
~ changed_var: "old value" => "new value"

Resources:
-----------
+ aws_s3_bucket.new_bucket
- aws_instance.removed_instance
~ aws_security_group.modified_group
  ~ ingress.cidr_blocks: ["10.0.0.0/16"] => ["10.0.0.0/8"]
  + egress.port: 443

Outputs:
--------
+ new_output: "value"
- removed_output: "value"
~ changed_output: "old" => "new"
```

## Exit Codes

| Exit Code | Description                               |
| --------- | ----------------------------------------- |
| 0         | Success - no differences found            |
| 1         | Error occurred during execution           |
| 2         | Success - differences found between plans |

## Use Cases

The `plan-diff` command is useful for:

1. **Validating changes**: Compare a previously saved plan with the current state to see what has changed.
2. **Reviewing variable impacts**: See how changing variables affects the infrastructure plan.
3. **CI/CD workflows**: Use the exit code to determine if changes are expected or unexpected.
4. **Documentation**: Generate human-readable diffs for change management and approvals.

## How It Works

The command:

1. Runs `terraform init` in the component directory
2. If `--new` is not specified, runs a plan and captures the output
3. Runs `terraform show -json` for each plan to get the JSON representation
4. Sorts the JSON for consistent comparison
5. Creates a diff between the two plans
6. Handles sensitive values properly by displaying `(sensitive value)`
7. Returns appropriate exit code based on whether differences were found
