Skip to main content

atmos lint stacks

Use this command to analyze Atmos stack YAML configurations for anti-patterns, optimization opportunities, and structural issues.

Configure Lint Settings

Learn how to configure lint rule thresholds and severity overrides in atmos.yaml.

Usage​

Execute the lint stacks command like this:

atmos lint stacks

This command is distinct from atmos validate stacks:

  • validate stacks — checks correctness (YAML syntax, JSON schema, import resolution)
  • lint stacks — checks quality (DRY-ness, best practices, anti-patterns)

Flags​

--stack, -s
Scope linting to a specific stack name or partial match (optional).
--rule
Comma-separated list of rule IDs to run (e.g., L-02,L-07). Runs all rules by default.
--format
Output format: text (default) or json.
--severity
Minimum severity to report: info (default), warning, or error.

Examples​

# Lint all stacks with default settings
atmos lint stacks

# Output as JSON for downstream tooling
atmos lint stacks --format json

# Run only specific rules
atmos lint stacks --rule L-09,L-04

# Only report errors (suppress warnings and info)
atmos lint stacks --severity error

# Scope to a specific stack
atmos lint stacks --stack plat-ue2-prod

Rules​

IDNameSeverityAuto-fixable
L-01Dead Var Detectionwarningno
L-02Redundant No-Op Overridewarningyes
L-03Import Depth Warningwarningno
L-04Abstract Component Leakerrorno
L-05Catalog File Cohesioninfono
L-06DRY Extraction Opportunityinfono
L-07Orphaned Catalog File Detectionwarningno
L-08Sensitive Var at Global Scopewarningno
L-09Inheritance Cycle Detectionerrorno
L-10Env Var Shadowingwarningno

L-01 — Dead Var Detection​

Detects top-level vars: keys declared in a stack manifest that are not consumed by any component in the stack.

L-02 — Redundant No-Op Override​

Detects component vars that override a value with the exact same value the parent component would have provided via metadata.inherits. These overrides are no-ops and can be safely removed.

L-03 — Import Depth Warning​

Warns when the import chain depth for any stack file exceeds the configured threshold (default: 3). Configurable via lint.max_import_depth in atmos.yaml.

L-04 — Abstract Component Leak​

Finds metadata.type: abstract components present in a deployable stack that have no concrete inheritor. These components are silently skipped at deploy time.

L-05 — Catalog File Cohesion​

Flags catalog files that define components whose names span more than the configured number of inferred concern groups (default: 3). Uses the component name prefix as a heuristic for concern group detection.

L-06 — DRY Extraction Opportunity​

After resolving all logical stacks, identifies variable values repeated across many stacks. If the same value appears in ≥ N% of stacks (default: 80%), suggests extracting it to a shared catalog base component.

L-07 — Orphaned Catalog File Detection​

Enumerates all YAML files under the stacks base path and identifies files that are not referenced in any import chain.

L-08 — Sensitive Var at Global Scope​

Warns when variable names matching sensitive patterns (*password*, *secret*, *token*, *key*, *arn*, *account_id*, *role*) appear at global stack scope. These should be moved to component scope. Add custom patterns via lint.sensitive_var_patterns in atmos.yaml.

L-09 — Inheritance Cycle Detection​

Builds a directed graph of metadata.inherits relationships across all components and runs DFS cycle detection. Reports cycles with the full path.

L-10 — Env Var Shadowing​

Detects environment variables that appear at both stack-level env: and component-level env: with different values.

Configuration​

Add a lint.stacks: section to atmos.yaml to customize rule behavior:

lint:
stacks:
max_import_depth: 3 # L-03 threshold (default: 3)
dry_threshold_pct: 80 # L-06 trigger percentage (default: 80)
sensitive_var_patterns: # L-08 patterns (merged with defaults)
- "*api_key*"
- "*webhook_secret*"
rules:
L-01: warning
L-02: warning
L-03: error # override to error for strict enforcement
L-04: error
L-05: info
L-06: info
L-07: warning
L-08: warning
L-09: error
L-10: warning

JSON Output​

Use --format json to get structured output suitable for piping to jq or downstream tools:

{
"findings": [
{
"rule_id": "L-09",
"severity": "error",
"message": "Inheritance cycle detected: eks-blue → eks-base → eks-blue",
"component": "eks-blue",
"fix_hint": "Break the cycle by removing one of the inherits entries"
}
],
"summary": {
"errors": 1,
"warnings": 4,
"info": 2
}
}

Exit Codes​

CodeMeaning
0No error-severity findings
1One or more error-severity findings (or command error)

Why Go Instead of Rego​

The lint rules are implemented in Go rather than OPA/Rego for the following reasons:

No additional runtime dependency — Rego requires the OPA runtime or the go-opa SDK to be available. Go rules ship inside the atmos binary with zero extra dependencies.

Richer data structures — The lint rules work against deeply nested map[string]any trees (fully resolved logical stacks). Go's type system and reflection make graph traversal (e.g., DFS cycle detection in L-09) and pattern matching (e.g., glob matching in L-08) natural. Expressing the same logic in Rego requires significant boilerplate for comparable traversal.

Performance — Go rules execute in microseconds for typical stack sizes. OPA policy evaluation incurs per-query compilation overhead that adds noticeable latency when linting hundreds of stacks.

Simpler contribution model — Most Atmos contributors know Go. Adding a new lint rule follows the same patterns as the rest of the codebase (interfaces, constants, tests). Learning Rego introduces a separate language, toolchain, and test framework.

Validation already uses OPA — atmos validate stacks already delegates JSON Schema validation to OPA/Rego via the pkg/validate package. Lint rules are intentionally separate: they check quality rather than correctness, and keeping them in Go avoids layering two policy evaluation systems on top of each other.

For policy-based correctness validation (e.g., enforcing naming conventions with custom rules), use atmos validate stacks with OPA policies.