Skip to content

Conversation

@osterman
Copy link
Member

@osterman osterman commented Nov 17, 2025

what

  • Implement reusable renderer pipeline infrastructure for list commands (filter, sort, column selection, format)
  • Apply renderer pipeline to all list commands: stacks, components, instances, metadata, vendor, workflows
  • Add configurable column output via atmos.yaml and --columns CLI flag with Go template support
  • Add tree-view visualization with --format=tree and --provenance flags for import hierarchy display
  • Add comprehensive test coverage for list infrastructure packages

why

  • Enable users to customize list command output with template-based columns (e.g., --columns "Name={{ .component }}")
  • Provide consistent filtering, sorting, and formatting across all list commands
  • Support multiple output formats (JSON, YAML, CSV, TSV, table, tree) for different use cases
  • Improve developer experience with smart TTY detection and automatic color degradation
  • Achieve high test coverage (>88%) for reliability and maintainability

references

Key Features

Configurable Columns

# atmos.yaml
stacks:
  list:
    columns:
      - name: Stack
        value: "{{ .stack }}"
      - name: Component  
        value: "{{ .component }}"

CLI Flags

  • --columns - Custom column definitions with Go templates
  • --format - Output format (table, json, yaml, csv, tsv, tree)
  • --sort - Sort specification (e.g., Stack:asc,Component:desc)
  • --provenance - Show import hierarchy in tree format

Test Coverage

Package Coverage
pkg/list/column 88.5%
pkg/list/filter 96.8%
pkg/list/sort 96.2%
pkg/list/output 100%
pkg/list/renderer 91.5%
pkg/list/list_metadata.go 100% (unit functions)
pkg/list/list_instances.go 100% (unit functions)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Enhanced list commands: filtering, tri-state enabled/locked flags, sorting, and custom column selection via CLI or atmos.yaml.
    • Multiple output formats including JSON, YAML, CSV, TSV, Table and a provenance-aware Tree view.
    • Dynamic tab-completion for --columns across list commands.
    • Improved tree rendering showing import/provenance relationships.
  • Documentation

    • New and expanded docs and guides for configurable list output, custom columns, and CLI usage.
  • UX

    • Informational UI messages for no-results scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

…ipeline

- Implement reusable renderer pipeline (filter, sort, column, format, output)
- Create 5 pkg/list packages with >88% test coverage each
- Add extraction functions for components, stacks, vendor
- Update Priority Tier 1 commands: components (DEV-2805), stacks, vendor (DEV-2806)
- Add schema support for List config in Stacks and Components
- Create 17 standardized flag wrappers using With* naming convention
- Enable universal filtering, sorting, column selection, and format options

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@osterman osterman requested a review from a team as a code owner November 17, 2025 06:27
@github-actions github-actions bot added the size/xl Extra large size PR label Nov 17, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 17, 2025

📝 Walkthrough

Walkthrough

Refactors Atmos "list" commands into a unified, pipeline-driven system: new column templates, filters, sorters, renderer, provenance-driven import resolution, dynamic flag wrappers, and extensive tests/docs supporting configurable, multi-format list outputs.

Changes

Cohort / File(s) Summary
Core list infra: column & templates
pkg/list/column/column.go, pkg/list/column/column_test.go
New column Selector, template func map, per-row template evaluation, headers/rows extraction and tests.
Core list infra: filtering
pkg/list/filter/filter.go, pkg/list/filter/filter_test.go
New composable Filter interface with GlobFilter, ColumnValueFilter, BoolFilter and Chain plus tests.
Core list infra: sorting
pkg/list/sort/sort.go, pkg/list/sort/sort_test.go
New Sorter/MultiSorter, type-aware comparisons, ParseSortSpec and tests.
Core list infra: renderer & output
pkg/list/renderer/renderer.go, pkg/list/renderer/*.test.go, pkg/list/output/output.go, pkg/list/output/output_test.go
Renderer orchestrating filter→extract→sort→format→write; output Manager; formatters and tests.
Table & tree formatting
pkg/list/format/table.go, pkg/list/format/table_test.go, pkg/list/format/tree_*.go, pkg/list/format/tree_*.test.go, pkg/list/format/tree_utils.go
Enhanced table layout, styling, inline markdown, ErrTableTooWide; tree renderers for instances/stacks and tests.
Data extractors
pkg/list/extract/*.go, pkg/list/extract/*_test.go (components, instances, metadata, stacks, vendor, workflows)
New extractors converting internal structures to []map[string]any for rendering, plus tests.
Import resolver & provenance
pkg/list/importresolver/resolver.go, pkg/list/importresolver/provenance.go, pkg/list/importresolver/*_test.go
Import tree resolution (heuristic + provenance), cycle detection, caching and tests.
Command flag wrappers & parser
cmd/list/flag_wrappers.go, cmd/list/flag_wrappers_test.go, docs
New WithXFlag wrappers and NewListParser factory with tests and docs.
Commands: components/stacks/instances/metadata/vendor/workflows/values/settings
cmd/list/components.go, cmd/list/stacks.go, cmd/list/instances.go, cmd/list/metadata.go, cmd/list/vendor.go, cmd/list/workflows.go, cmd/list/values.go, cmd/list/settings.go and tests
Commands reworked to use pipeline: new Options fields (Columns, Sort, Format, Enabled/Locked tri-state, Provenance, etc.), dynamic --columns completion, Viper binding via NewListParser, and adapter functions delegating to pkg/list renderer/extractors.
List package adapters & cmd-level callers
pkg/list/list_instances.go, pkg/list/list_metadata.go, pkg/list/list_vendor.go, pkg/list/list_vendor_format.go, pkg/list/list_*_test.go
New InstancesCommandOptions / MetadataOptions, column parsing, sorter/filter builders, and migration of vendor flows to extract.VendorInfo.
Schema & errors
pkg/schema/schema.go, errors/errors.go
Added List fields to schema components and new error sentinels (ErrTemplateEvaluation, ErrInvalidConfig, ErrNoStacksFound).
Internal exec / provenance plumbing
internal/exec/stack_processor_utils.go, internal/exec/stack_processor_template_test.go, internal/exec/utils.go
ProcessYAMLConfigFileWithContext now returns MergeContext; provenance propagation and GetAllMergeContexts; ClearFindStacksMapCache added.
CLI root / terminal integration
cmd/root.go, cmd/root_test.go
Terminal color-profile detection wired early; chdir parsing refactor for testability.
Docs, examples & tests
website/docs/cli/commands/list/*.mdx, website/blog/*.mdx, docs/prd/*.md, docs/list-*.md, examples/*, tests/snapshots/*, pre-commit & scripts
Extensive docs and examples for configurable list output, PRDs, new tests, example atmos.yaml, snapshot updates, pre-commit hook and helper scripts.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as CLI Command
    participant Parser as Flag Parser
    participant Extract as Extractor
    participant Filters as Filter Chain
    participant Selector as Column Selector
    participant Sorter as Sorters
    participant Renderer as Renderer
    participant Formatter as Formatter
    participant Output as Output Manager
    User->>CLI: run "atmos list instances --columns Stack,Comp --sort stack:asc"
    CLI->>Parser: parse flags (NewListParser)
    CLI->>Extract: extract instances (extract.Instances)
    Extract-->>CLI: []map[string]any
    CLI->>Filters: build/apply filters
    Filters-->>CLI: filtered data
    CLI->>Selector: select columns & compile templates
    Selector-->>CLI: headers, rows
    CLI->>Sorter: sort rows
    Sorter-->>CLI: sorted rows
    CLI->>Renderer: render(format)
    Renderer->>Formatter: format(headers, rows)
    Formatter-->>Renderer: formatted string
    Renderer->>Output: write(formatted)
    Output-->>User: stdout
Loading
sequenceDiagram
    participant StackProc as ProcessYAMLConfigFileWithContext
    participant MergeCtx as MergeContext
    participant ProvResolver as ResolveImportTreeFromProvenance
    participant ImportBuilder as buildImportTreeFromChain
    participant Renderer as RenderStacksTree
    StackProc->>MergeCtx: create and populate provenance data
    StackProc-->>StackProc: return MergeContext
    ProvResolver->>MergeCtx: read all merge contexts
    ProvResolver->>ImportBuilder: build import tree per chain
    ImportBuilder-->>ProvResolver: ImportNode trees
    ProvResolver-->>Renderer: per-stack import trees
    Renderer->>Renderer: render styled tree output
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Key areas that need careful review:

  • pkg/list/renderer/renderer.go — full pipeline, error wrapping, format branching, TTY vs non-TTY logic
  • pkg/list/importresolver/provenance.go & resolver.go — provenance merging, path resolution, cycle detection, caching
  • pkg/list/column/column.go — template parsing, func map, evaluation errors and performance
  • internal/exec/stack_processor_utils.go — changed ProcessYAMLConfigFileWithContext signature and MergeContext propagation
  • cmd/list/flag_wrappers.go and per-command wiring — Viper binding, completion registration, tri-state flag handling
  • pkg/list/format/table.go — layout and width calculations (ErrTableTooWide implications)
  • Tests/snapshots — snapshot changes and removal/addition of tests (metadata tests removed, many new tests added)

Possibly related PRs

Suggested reviewers

  • osterman

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 67.98% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Implement configurable output for list commands' accurately describes the primary feature added - a configurable renderer pipeline for list commands with column selection, sorting, filtering, and multiple output formats.
Linked Issues check ✅ Passed The PR comprehensively addresses both DEV-2805 and DEV-2806 requirements: configurable columns via atmos.yaml [DEV-2805, DEV-2806], --columns CLI flag, template support, filtering (--type, --enabled, --locked) [DEV-2805], semantic styling (disabled gray, locked orange) [DEV-2805], multi-format output (json/yaml/csv/tsv/table/tree) [DEV-2805, DEV-2806], TTY detection with auto-downgrade [DEV-2805, DEV-2806], and tree view with --provenance flag.
Out of Scope Changes check ✅ Passed All changes directly support the list command configurable output objectives. Infrastructure additions (column/filter/sort/renderer/extract/importresolver packages), cmd/list enhancements, configuration schema updates, and documentation are all in-scope. Minor adjacent changes (root.go terminal integration, stack_processor provenance tracking) support tree rendering with provenance.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch osterman/list-ui-overhaul

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mergify
Copy link

mergify bot commented Nov 17, 2025

Warning

This PR exceeds the recommended limit of 1,000 lines.

Large PRs are difficult to review and may be rejected due to their size.

Please verify that this PR does not address multiple issues.
Consider refactoring it into smaller, more focused PRs to facilitate a smoother review process.

@github-actions
Copy link

github-actions bot commented Nov 17, 2025

Dependency Review

✅ No vulnerabilities or license issues found.

Scanned Files

None

Claude (via Conductor) and others added 6 commits November 17, 2025 00:38
Migrate workflows, values, and instances commands to use the new renderer
pipeline and flag wrapper pattern for consistent flag handling.

## Changes

### cmd/list/workflows.go
- Migrate to full renderer pipeline (filter → column → sort → format)
- Replace custom flag parsing with NewListParser flag wrappers
- Add buildWorkflowFilters(), getWorkflowColumns(), buildWorkflowSorters()
- Update return type from string to error
- Add support for --columns and --sort flags
- Maintain backward compatibility with --file filter
- Use static errors from errors/errors.go

### pkg/list/extract_workflows.go (NEW)
- Create ExtractWorkflows() to transform workflow manifests into []map[string]any
- Extract workflow data with file, workflow name, description, and step count
- Support file filtering via --file flag
- Handle workflow directory traversal and YAML parsing
- Use static errors (ErrParseFile, ErrWorkflowDirectoryDoesNotExist)

### pkg/list/extract_workflows_test.go (NEW)
- Add comprehensive tests for workflow extraction
- Test empty workflows, single workflow, multiple workflows
- Test nil workflows handling

### cmd/list/values.go
- Replace newCommonListParser with NewListParser using flag wrappers
- Use WithFormatFlag, WithDelimiterFlag, WithStackFlag, WithQueryFlag
- Use WithMaxColumnsFlag, WithAbstractFlag, WithProcessTemplatesFlag
- Use WithProcessFunctionsFlag
- Maintain existing FilterAndListValues logic (already using reusables)
- Update both valuesCmd and varsCmd parsers

### cmd/list/instances.go
- Replace newCommonListParser with NewListParser using flag wrappers
- Use WithFormatFlag, WithDelimiterFlag, WithMaxColumnsFlag
- Use WithStackFlag, WithQueryFlag, WithUploadFlag
- Maintain existing ExecuteListInstancesCmd logic

## Testing

All tests pass:
- go test ./cmd/list/... ./pkg/list/... ✓
- All flag wrapper tests pass ✓
- All extraction tests pass ✓

## Impact

- Workflows command now supports universal --columns and --sort flags
- Values and instances commands use consistent flag wrapper pattern
- All Tier 2 commands follow same architectural pattern as Tier 1
- Maintains backward compatibility with existing flags

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Fix critical bug where empty format string caused "unsupported format:" error
when running list commands without explicit --format flag.

## Changes

### pkg/list/renderer/renderer.go
- Add default handling in formatTable() to use table format when empty
- Prevents "unsupported format:" error on commands like `atmos list stacks`

### pkg/list/renderer/renderer_integration_test.go (NEW)
- Add comprehensive integration tests for all format types
- Test empty format string (should default to table)
- Test invalid format string (should error)
- Test rendering with sorting
- Test rendering with empty data
- All tests initialize I/O context properly

## Testing

- All renderer tests pass (91.8% coverage)
- Fixed user-reported issue: `atmos list stacks` now works
- Test all formats: table, json, yaml, csv, tsv, empty

## Impact

- Fixes critical regression where basic list commands failed
- Empty format now correctly defaults to table format
- Maintains backward compatibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
- Replace thick bordered table with clean header-only underline
- Use simple local styles (bold header, plain cells) like version list
- Change border to gray (color 8) for consistency
- Remove unused theme import

This gives list commands the same polished look as atmos version list.
…support

- Add ExtractInstances() to convert schema.Instance to renderer format
- Add getInstanceColumns() to read column config from atmos.yaml
- Update ExecuteListInstancesCmd to use renderer pipeline
- Remove obsolete formatInstances() function and related tests
- Add custom column configuration to quick-start-advanced example
- Support all output formats (table, json, yaml, csv, tsv)

Custom columns configured in atmos.yaml (components.list.columns):
- Component, Stack, Tenant, Environment, Stage, Region

All existing list instances tests pass with renderer migration.
- Move Component column to the end for better readability
- Add Description column from metadata.description field
- Add description metadata to vpc and vpc-flow-logs-bucket components

Column order: Stack → Tenant → Environment → Stage → Region → Description → Component

This makes the output more readable by grouping organizational fields (tenant,
environment, stage, region) before the descriptive and component fields.
…data to renderer pipeline

This change fixes an anti-pattern where list commands were using log.Info()
for user-facing messages instead of proper UI output methods. It also migrates
the list metadata command to use the renderer pipeline for consistent table
output with customizable columns.

## Changes

### Anti-pattern fixes
- **cmd/list/settings.go**: Replace `log.Info()` with `ui.Info()` for "No settings found" messages
- **cmd/list/values.go**: Replace `log.Info()` with `ui.Info()` for "No vars/values found" messages
- **pkg/list/list_metadata.go**: Remove `log.Error()` calls; errors are now properly returned
- **cmd/list/settings_test.go**: Update tests for renamed function `displayNoSettingsFoundMessage()`
- **cmd/list/values_test.go**: Update tests for renamed function `displayNoValuesFoundMessage()`

### List metadata migration to renderer pipeline
- **cmd/list/metadata.go**: Migrate to renderer pipeline (91 lines, down from 161)
- **cmd/list/metadata_test.go**: Delete obsolete tests for old flag structure
- **pkg/list/extract_metadata.go**: Create metadata extractor for renderer
- **pkg/list/extract_metadata_test.go**: Add comprehensive tests (5 test cases)
- **pkg/list/list_metadata.go**: Implement renderer integration with default columns

### Documentation updates
- **website/docs/cli/commands/list/list-metadata.mdx**: Complete rewrite for table view with column configuration examples
- **website/docs/cli/commands/list/list-instances.mdx**: New comprehensive documentation
- **website/docs/cli/commands/list/list-vendor.mdx**: New comprehensive documentation
- **website/docs/cli/commands/list/list-components.mdx**: Enhanced with column examples
- **website/docs/cli/commands/list/list-stacks.mdx**: Add column configuration
- **website/docs/cli/commands/list/list-workflows.mdx**: Fix duplicate sections
- **website/blog/2025-11-17-customizable-list-command-output.mdx**: Feature announcement blog post

### Breaking changes for list metadata
- Removed `--query` flag (use `--filter` with YQ syntax instead)
- Removed `--max-columns` flag (use renderer table formatting)
- Removed `--delimiter` flag (renderer handles formatting)
- Removed positional component argument (use `--filter` for filtering)

## Resolution

Fixes issue where `atmos list metadata` displayed "INFO No metadata found"
instead of proper UI output. Now uses `ui.Info()` for user-facing messages
and renderer pipeline for consistent table formatting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
@mergify
Copy link

mergify bot commented Nov 17, 2025

Important

Cloud Posse Engineering Team Review Required

This pull request modifies files that require Cloud Posse's review. Please be patient, and a core maintainer will review your changes.

To expedite this process, reach out to us on Slack in the #pr-reviews channel.

Apply theme-aware color styling to table cells based on content type:
- Booleans: Green (Success) for 'true', Red (Error) for 'false'
- Numbers: Cyan (Info) for numeric values
- Placeholders: Darker gray (Muted) for {...} and [...] placeholders
- Default text: No color styling (uses base table cell style)

Implementation details:
- Add detectContentType() to identify cell content (boolean, number, placeholder)
- Add getCellStyle() to apply appropriate theme style based on content type
- Update CreateStyledTable() StyleFunc to apply semantic styling
- Use theme.GetCurrentStyles() for theme-aware color consistency
- Add regex pattern matching for placeholder detection ({...}, [...])
- Pass baseStyle by pointer to avoid copying heavy struct (552 bytes)

This enhances readability by visually distinguishing different data types
in list command table output (instances, metadata, workflows, etc.)
Claude (via Conductor) added 2 commits November 17, 2025 08:28
Tables now expand arrays of scalar values (strings, numbers, booleans)
into multi-row cells with one value per line, making array data readable
without needing to expand placeholders.

Changes:
- Add tryExpandScalarArray() to detect and expand scalar arrays
- Arrays with non-scalar elements still show placeholder format
- Add joinItems() helper to join array items with newlines
- Respect MaxColumnWidth for individual array items
- Maps continue to show {...} (N keys) placeholder format

Benefits:
- availability_zones: us-east-1a, us-east-1b, us-east-1c (multi-line)
- Complex arrays: [...] (N items) (placeholder for non-scalar)
- Improves readability for common scalar array fields

Tests:
- Add comprehensive tests for scalar array expansion
- Test mixed types, nested arrays, empty arrays
- Verify placeholder fallback for complex structures
Replace byte-based len() with lipgloss.Width() for proper handling of:
- ANSI escape codes (colors, styles)
- Multi-byte Unicode characters
- Multi-line cell content (expanded arrays)

Changes:
- Replace len() with lipgloss.Width() in width calculations
- Add getMaxLineWidth() to handle multi-line cells correctly
- Add splitLines() helper for line-by-line width calculation
- Update calculateMaxKeyWidth() to use visual width
- Update calculateStackColumnWidth() to use visual width
- Update getMaxValueWidth() to find widest line in multi-line values

Benefits:
- Tables now size columns based on actual visual width
- Colored text no longer causes incorrect column sizing
- Multi-line array expansions properly measured
- More efficient use of terminal space

Tests:
- Add tests for getMaxLineWidth with ANSI codes
- Add tests for splitLines with various inputs
- Verify ANSI-aware width calculation
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

♻️ Duplicate comments (1)
cmd/list/vendor.go (1)

145-171: --columns for vendor shares the same stub implementation

getVendorColumns also calls parseColumnsFlag(columnsFlag) when --columns is set, but that helper is currently a TODO that always returns default columns. So for vendor:

  • --columns / ATMOS_LIST_COLUMNS do not actually influence the output today.

Once parseColumnsFlag is implemented for components, it would be good to hook vendor into the same real implementation so behavior is consistent.

🧹 Nitpick comments (20)
CLAUDE.md (1)

39-74: Good addition - consider fixing the markdownlint issue.

This section provides clear guidance on when to consult specialized agents. The examples and rationale are helpful.

One minor issue: The fenced code block at line 57 is missing a language identifier. Consider adding one for proper syntax highlighting:

-```
+```text
 Task(
   subagent_type: "flag-handler",
   prompt: "Help design named wrapper functions for list command flags"
 )

</blockquote></details>
<details>
<summary>website/docs/cli/commands/list/list-vendor.mdx (1)</summary><blockquote>

`24-37`: **Minor style nit in description paragraph**

The “Target destination path” / “Vendor configuration file” bullets read a bit abruptly after “information about:”. If you care about polish, consider making the last bullet a full phrase like “Vendor configuration file path.” or similar, but the content is otherwise clear.

</blockquote></details>
<details>
<summary>cmd/list/instances.go (1)</summary><blockquote>

`15-26`: **InstancesOptions is built but not used downstream**

`InstancesOptions` (including the new `Filter` and `Sort` fields) is populated in `RunE` and passed into `executeListInstancesCmd`, but `executeListInstancesCmd` ignores `opts` and just calls `list.ExecuteListInstancesCmd(&configAndStacksInfo, cmd, args)`.

If the list package is still reading values directly from Cobra/Viper, this options struct isn’t buying you anything right now and may confuse future readers. I’d either:

- Wire `opts` through into `list.ExecuteListInstancesCmd` (if you’re moving instances onto the same options-based renderer pipeline as other list commands), or
- Drop `InstancesOptions` / the `opts` parameter for now and reintroduce it when instances actually consume these fields.




Also applies to: 47-57, 85-95

</blockquote></details>
<details>
<summary>cmd/list/settings.go (1)</summary><blockquote>

`116-123`: **Consider handling ui.Info errors.**

The error returns from `ui.Info` are discarded. While this may be acceptable for informational messages, consider whether these errors should be logged or returned, especially if UI output failures could impact user experience.



```diff
 func displayNoSettingsFoundMessage(componentFilter string) {
 	if componentFilter != "" {
-		_ = ui.Info("No settings found for component: " + componentFilter)
+		if err := ui.Info("No settings found for component: " + componentFilter); err != nil {
+			log.Debug("Failed to display no settings message", "error", err)
+		}
 	} else {
-		_ = ui.Info("No settings found")
+		if err := ui.Info("No settings found"); err != nil {
+			log.Debug("Failed to display no settings message", "error", err)
+		}
 	}
 }
pkg/list/extract_metadata.go (1)

34-50: Simplify string concatenation with strings.Join.

The manual string building for inherits can be streamlined using strings.Join, making the code more concise and idiomatic.

 		if val, ok := instance.Metadata["inherits"].([]interface{}); ok {
-			// Convert []interface{} to comma-separated string.
 			inheritsSlice := make([]string, 0, len(val))
 			for _, v := range val {
 				if str, ok := v.(string); ok {
 					inheritsSlice = append(inheritsSlice, str)
 				}
 			}
-			if len(inheritsSlice) > 0 {
-				for i, s := range inheritsSlice {
-					if i > 0 {
-						inherits += ", "
-					}
-					inherits += s
-				}
-			}
+			inherits = strings.Join(inheritsSlice, ", ")
 		}

Don't forget to import strings if not already imported.

pkg/list/list_metadata.go (1)

48-85: Consider adding filter and sort support.

The renderer is created with nil filters and sorters (line 77), but other list commands support filtering and sorting via CLI flags. Consider whether metadata listing should also support these features for consistency.

If filtering and sorting are needed, you could add flags and build filters/sorters similar to other list commands:

 func ExecuteListMetadataCmd(info *schema.ConfigAndStacksInfo, cmd *cobra.Command, args []string) error {
 	// Initialize CLI config.
 	atmosConfig, err := cfg.InitCliConfig(*info, true)
 	if err != nil {
 		return errors.Join(errUtils.ErrFailedToInitConfig, err)
 	}
 
-	// Get flags.
+	// Get flags
 	formatFlag, _ := cmd.Flags().GetString("format")
+	filterFlag, _ := cmd.Flags().GetString("filter")
+	sortFlag, _ := cmd.Flags().GetString("sort")
 
 	// Process instances (same as list instances, but we'll extract metadata).
 	instances, err := processInstances(&atmosConfig)
 	if err != nil {
 		return errors.Join(errUtils.ErrProcessInstances, err)
 	}
 
 	// Extract metadata into renderer-compatible format.
 	data := ExtractMetadata(instances)
 
 	// Get column configuration.
 	columns := getMetadataColumns(&atmosConfig)
+
+	// Build filters and sorters
+	filters := buildMetadataFilters(filterFlag)
+	sorters := buildMetadataSorters(sortFlag)
 
 	// Create column selector.
 	selector, err := column.NewSelector(columns, column.BuildColumnFuncMap())
 	if err != nil {
 		return fmt.Errorf("failed to create column selector: %w", err)
 	}
 
 	// Create renderer.
-	r := renderer.New(nil, selector, nil, format.Format(formatFlag))
+	r := renderer.New(filters, selector, sorters, format.Format(formatFlag))
 
 	// Render output.
 	if err := r.Render(data); err != nil {
 		return fmt.Errorf("failed to render metadata: %w", err)
 	}
 
 	return nil
 }
cmd/list/flag_wrappers_test.go (1)

377-414: Tighten env var binding test or drop unused envVarName

TestFlagEnvironmentVariableBinding currently only asserts that BindToViper succeeds; the envVarName field is never used, so the test doesn’t actually confirm the binding name.

Either:

  • Use envVarName (e.g., t.Setenv(tt.envVarName, "x"), call BindToViper, then assert v.GetString(tt.flagName) == "x"), or
  • Remove envVarName from the table to avoid implying stronger coverage than is present.
pkg/list/extract_stacks.go (1)

9-73: Consider whether deterministic stack ordering is needed

Both extractors iterate over stacksMap directly, so the output order is whatever Go’s map iteration yields. If the downstream renderer doesn’t always apply an explicit sort (e.g., default sort by stack), CLI output may appear in a non‑deterministic order between runs.

If you want stable default ordering, consider sorting the stack names (or ensure callers always run the sort pipeline on these results). Otherwise, the current implementation is straightforward and matches the tests.

pkg/list/renderer/renderer_test.go (1)

38-237: Consider factoring I/O initialization into a helper

Most tests duplicate the NewContext/InitWriter/InitFormatter setup. Extracting a small helper like initTestRendererIO(t) would cut repetition and make future tweaks to the IO/UI wiring cheaper.

pkg/list/extract_components.go (1)

9-17: Unused exported ComponentData struct

ComponentData isn’t used in this file. If there’s no external consumer yet, consider either wiring it into the API (e.g., returning strongly‑typed slices instead of []map[string]any) or dropping it for now to avoid a “blessed but unused” public type.

pkg/list/extract_components_test.go (1)

11-245: Nice coverage; consider asserting component_type semantics explicitly

The tests do a good job exercising success and failure paths. To lock in the intended meaning of metadata fields, you might add a couple of assertions that:

  • For an abstract component (like ingress in TestExtractComponents), comp["component_type"] == "abstract".
  • For a normal TF component, comp["type"] == "terraform" and comp["component_type"] == "real".

That would make future refactors around .type vs .component_type safer.

cmd/list/stacks.go (1)

29-31: Columns flag type vs parsing helper may not line up

StacksOptions.Columns is a string populated via v.GetString("columns"), but WithColumnsFlag registers columns as a StringSlice flag. Depending on how StandardParser binds to Viper, GetString("columns") may see something like "[stack,component]" rather than the raw stack,component string that parseColumnsFlag expects.

If the intent is “comma‑separated single value”, you might either:

  • Change the flag to a simple string flag; or
  • Keep it as a slice and update StacksOptions + parseColumnsFlag to work with []string.

Worth a quick manual check of --columns stack,component and the env var form to confirm the value that reaches parseColumnsFlag.

Also applies to: 150-154

website/docs/cli/commands/list/list-stacks.mdx (1)

119-142: Clarify that the listed template functions are a subset of what’s available

The “Available functions” list here is a subset of what BuildColumnFuncMap exposes (pad, get, getOr, has, split, toInt, toBool, etc. are also supported). To avoid confusing folks who read the code, consider either:

  • Renaming this to “Common functions” and noting it’s not exhaustive, or
  • Expanding the list to match the actual func map.
pkg/list/renderer/renderer.go (1)

151-159: Use a CSV/TSV writer to handle escaping correctly

formatDelimited currently does a raw strings.Join for CSV/TSV. That means fields containing the delimiter, quotes, or newlines won’t be escaped and can break consumers.

Consider switching to Go’s encoding/csv (with the delimiter configurable for TSV) so quoting and escaping are handled correctly, e.g., by writing into a bytes.Buffer and returning the buffer string.

cmd/list/components.go (1)

142-177: Revisit interaction between type and abstract filters

buildComponentFilters currently combines:

  • Type flag → filter.NewColumnFilter("type", opts.Type) (default "real" from WithTypeFlag), and
  • Abstract flag → when !opts.Abstract, always adds filter.NewColumnFilter("component_type", "real").

This can make it hard to express some combinations:

  • With no flags you filter on both type=real and component_type=real.
  • With --abstract but no explicit --type, you still filter type=real, so abstract-only components may never show.
  • With --type=all but --abstract omitted, you still filter component_type to real, so “all” doesn’t actually include abstract.

Might be worth clarifying which field (type vs component_type) is the canonical “real/abstract/all” dimension and simplifying defaults around that (e.g., let Type default to "" and derive the “real-only by default” behavior solely from Abstract).

cmd/list/vendor.go (2)

130-143: Confirm intent of using --stack to glob on the component field

buildVendorFilters treats the --stack flag as a glob on the "component" field:

globFilter, err := filter.NewGlobFilter("component", opts.Stack)

Given WithStackFlag’s help text (“Filter by stack pattern”) this is a bit surprising. If vendor rows don’t have a stack field and the goal is to filter by component name, it might be clearer to either:

  • Introduce a dedicated --component filter for vendor, or
  • Rename/update the --stack help text for this command.

At minimum, worth double-checking that this aligns with how users expect to filter vendor entries.


185-256: Unused home-dir obfuscation helpers after renderer refactor

After switching vendor listing to the renderer pipeline, obfuscateHomeDirInOutput, shouldReplaceHomeDir, and isPathChar are no longer used in this file.

If the renderer-based output is intentionally allowed to show absolute paths now, these helpers can probably be removed. If you still want to avoid leaking $HOME in vendor paths, you may want to integrate this behavior into the data extraction step or the renderer instead.

pkg/list/sort/sort.go (1)

110-133: Numeric and multi-column sort behavior is good; tighten comments around edge cases

The type-aware sorting and stable multi-column precedence look solid. Two small nits:

  • compareNumeric’s comment says “Non-numeric values sort last”, but when both values are non-numeric you fall back to strings.Compare(a, b). That’s fine behavior, just worth reflecting in the comment so future readers don’t assume “always last”.
  • In Sorter.Sort, rows where colIdx >= len(row) are effectively treated as “equal” to everything else (you always return false from the comparator). That’s a reasonable choice; consider documenting that missing-column rows preserve original order and don’t participate in the sort.

No functional changes required; this is just about making the behavior explicit.

Also applies to: 161-185

pkg/list/filter/filter.go (1)

39-86: Filter primitives and chaining look solid

The glob/column/boolean filters and the Chain combinator are straightforward and type-safe, with good validation and error messages. The permissive string handling in BoolFilter (treating non-true strings as false) is fine for the intended enabled/locked use cases; if you later apply it to arbitrary fields you might want stricter validation, but nothing blocking here.

Nice foundation for composing filters into the renderer pipeline.

Also applies to: 119-160, 167-178

pkg/list/column/column.go (1)

27-47: TemplateContext struct is unused; current implementation relies on a generic map-based context

Right now, templates are evaluated against the map[string]any produced by buildTemplateContext, and the TemplateContext struct isn’t used anywhere. That’s not wrong, but it’s a bit misleading for readers who might assume templates see a strongly-typed context with the JSON-tagged field names.

You can either:

  • Remove TemplateContext until you actually switch to using it, or
  • Update buildTemplateContext to construct and return a TemplateContext (plus maybe embed Raw separately) so the declared API matches the real context shape.

Low priority, but it’ll reduce cognitive overhead for anyone extending the column templating later.

Also applies to: 190-272

Claude (via Conductor) added 2 commits November 17, 2025 08:35
Tables now expand maps with scalar values (like tags) into readable
multi-line format with one key-value pair per line.

Before:
  tags    {...} (7 keys)

After:
  tags    Environment: production
          Name: vpc
          Team: platform
          ...

Implementation:
- Add tryExpandScalarMap() to detect and expand scalar maps
- Sort keys alphabetically for consistent ordering
- Format as 'key: value' pairs, one per line
- Maps with non-scalar values still show {...} (N keys) placeholder
- Shares joinItems() helper with array expansion

Behavior:
- Scalar maps (string, number, bool values) → Expanded multi-line
- Complex maps (nested objects, arrays) → Placeholder {...} (N keys)
- Empty maps → Empty string
- Keys sorted alphabetically for consistency

Benefits:
- Tags and metadata now readable without expanding
- Consistent with array expansion behavior
- Maintains compact placeholder for complex structures

Tests:
- Add comprehensive tests for scalar map expansion
- Test mixed scalar types, empty maps
- Verify placeholder fallback for nested structures
- Update existing tests to match new behavior
Prevent scalar arrays and maps from being expanded if their items
exceed a reasonable width threshold. This avoids creating impossibly
wide tables that trigger "table too wide" errors.

Problem:
- Expanding arrays/maps with long values caused tables to exceed terminal width
- Users saw: "Error: the table is too wide to display properly (width: 418 > 185)"
- No fallback to compact placeholder format for wide values

Solution:
- Track maximum item width during expansion
- Reject expansion if any item exceeds maxReasonableItemWidth (20 chars)
- Fall back to compact placeholder format: [...] (N items) or {...} (N keys)
- Threshold set to ~1/3 of MaxColumnWidth for reasonable table display

Changes:
- Add width tracking to tryExpandScalarArray()
- Add width tracking to tryExpandScalarMap()
- Use lipgloss.Width() for ANSI-aware measurement
- Set maxReasonableItemWidth constant to 20 characters

Benefits:
- Tables stay within terminal width limits
- Short values still expand (availability_zones, tags with short values)
- Long values gracefully degrade to placeholders
- No more "table too wide" errors from expansion

Tests:
- Add test for arrays with very long strings
- Add test for maps with very long values
- Verify both fall back to placeholder format
- Add renderInlineMarkdown() function to render markdown in table cells
- Uses glamour library with theme-aware styling for terminals
- Automatically detects color support and degrades gracefully
- Collapses multi-line markdown into single line for table cells
- Applies to Description column specifically when present in headers
- Preserves inline markdown (bold, italic, code) while removing blocks
- Includes comprehensive tests for markdown rendering edge cases

Resolves markdown rendering for description fields in metadata tables.
…data

**Enhancement 1: Style <no value> in Dark Gray**
- Add contentTypeNoValue enum to cell content type detection
- Update detectContentType() to identify <no value> from Go templates
- Apply styles.Muted (dark gray) styling to <no value> cells
- Consistent with placeholder styling ({...}, [...])
- Theme-aware and zero-config

**Enhancement 2: Support Vars in List Metadata**
- Expose vars, settings, and env in ExtractMetadata()
- Enables column templates to access component variables
- Users can now use {{ .vars.region }}, {{ .vars.environment }}, etc.
- Follows same pattern as ExtractInstances()

**Testing:**
- Add TestDetectContentType_NoValue with comprehensive test cases
- Add TestExtractMetadata_IncludesVarsSettingsEnv to verify exposure
- Update existing metadata tests to include new fields
- All tests passing

**Impact:**
- list metadata now displays actual var values instead of <no value>
- Improves readability with dark gray styling for missing values
- Enables custom column configuration using vars/settings/env

Closes user request for dark gray <no value> styling and vars support.
Add perf.Track instrumentation to all helper functions in vendor command
and list extract packages to satisfy repository performance tracking policy.

Changes:
- cmd/list/vendor.go: Add perf tracking to columnsCompletionForVendor,
  listVendorWithOptions, buildVendorFilters, getVendorColumns, and
  buildVendorSorters functions
- pkg/list/extract/components.go: Add perf tracking to buildBaseComponent,
  extractMetadataFields, setDefaultMetadataFields, getBoolWithDefault,
  and getStringWithDefault helper functions
- pkg/list/extract/workflows.go: Fix cleanPath usage to ensure normalized
  path is used consistently for all file operations and error messages
- pkg/list/importresolver/provenance.go: Add perf tracking to stripBasePath
  function

All functions now have defer perf.Track(nil, "package.functionName")()
as the first statement, matching the repository's mandatory performance
tracking pattern.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
The stripBasePath function was removing file extensions before converting
path separators to forward slashes, which caused inconsistent behavior
across different operating systems.

Changes:
- Reorder operations to convert to forward slashes first (via filepath.ToSlash)
- Then remove .yaml/.yml extensions using string literals instead of constants
- This ensures consistent relative, extensionless paths regardless of OS

The fix ensures that stripBasePath returns paths like "catalog/base" rather
than OS-specific separator formats, making the import tree rendering consistent
across Windows, macOS, and Linux.

All tests now pass, including TestStripBasePath which validates:
- Simple paths
- Paths with trailing slashes
- Both .yaml and .yml extensions
- Relative paths
- Nested directory structures

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 24, 2025
osterman and others added 2 commits November 23, 2025 20:27
…omponent

- Replace outdated `:::note Purpose` pattern in CLAUDE.md documentation template with modern `<Intro>` component
- Add Intro import to template example
- Update terminology from "purpose note" to "intro" for consistency
- Improve list-stacks intro to describe specific user actions (filtering, format options, understanding inheritance) instead of generic "list stacks"
- Follows pattern from auth commands: concrete actions users can accomplish

This fixes the root cause of documentation hallucinations where new docs were being written with deprecated :::note syntax.

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Replace deprecated `:::note Purpose` admonitions with modern `<Intro>` component across all list command documentation files. Update intros to describe specific user actions and benefits following pattern from auth commands.

Changes:
- list-components.mdx: Add Intro describing filtering and output formats
- list-instances.mdx: Add Intro explaining component-stack combinations and Atmos Pro upload
- list-metadata.mdx: Add Intro about filtering and sorting metadata fields
- list-vendor.mdx: Add Intro describing vendor sources and dependencies
- themes.mdx: Add Intro about color schemes and syntax highlighting
- list-workflows.mdx: Add Intro, Screengrab, and description field
- list-settings.mdx: Add Intro about cross-stack comparison tables
- list-values.mdx: Add Intro about configuration value comparison
- list-vars.mdx: Add Intro about Terraform variable comparison

All intros now:
- Use action-oriented language (what users can accomplish)
- Describe specific capabilities (filtering, formats, comparison)
- Follow modern documentation pattern with <Intro> component
- Include Screengrab components where missing

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
pkg/list/extract/workflows.go (1)

72-78: Consider extracting path construction helper

The logic here duplicates lines 55-59. Both blocks check IsPathAbsolute and construct paths accordingly. A small helper function could reduce repetition:

func buildWorkflowPath(atmosConfig *schema.AtmosConfiguration, relPath string) string {
    if utils.IsPathAbsolute(atmosConfig.Workflows.BasePath) {
        return filepath.Join(atmosConfig.Workflows.BasePath, relPath)
    }
    return filepath.Join(atmosConfig.BasePath, atmosConfig.Workflows.BasePath, relPath)
}

Then both call sites become simpler. Optional cleanup—the current approach works fine.

pkg/list/importresolver/provenance.go (1)

346-371: Consider tracing YAML read/parse failures in resolveImportFileImports

Right now, any error from readImportsFromYAMLFile is silently treated as “no imports”, which can make it harder to debug missing branches in the provenance tree when a path is wrong or a file is malformed. A low-noise Trace log would help operators understand why parts of the tree disappear without impacting normal runs.

For example:

 func resolveImportFileImports(
   importFilePath string,
   atmosConfig *schema.AtmosConfiguration,
   visited map[string]bool,
   cache map[string][]string,
 ) []*tree.ImportNode {
@@
-  // Read imports from the file.
-  imports, err := readImportsFromYAMLFile(importFilePath)
-  if err != nil {
-    // File can't be read or has no imports.
-    return nil
-  }
+  // Read imports from the file.
+  imports, err := readImportsFromYAMLFile(importFilePath)
+  if err != nil {
+    // Trace-level log so provenance debugging can see why a branch is missing.
+    log.Trace("Failed to read imports from YAML file", "file", importFilePath, "error", err)
+    return nil
+  }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between be74995 and 82ed911.

📒 Files selected for processing (5)
  • CLAUDE.md (4 hunks)
  • cmd/list/vendor.go (1 hunks)
  • pkg/list/extract/components.go (1 hunks)
  • pkg/list/extract/workflows.go (1 hunks)
  • pkg/list/importresolver/provenance.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/list/extract/components.go
🧰 Additional context used
🧠 Learnings (41)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-02T15:35:09.958Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 759
File: internal/exec/terraform.go:366-368
Timestamp: 2024-11-02T15:35:09.958Z
Learning: In `internal/exec/terraform.go`, the workspace cleaning code under both the general execution path and within the `case "init":` block is intentionally duplicated because the code execution paths are different. The `.terraform/environment` file should be deleted before executing `terraform init` in both scenarios to ensure a clean state.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2025-04-26T15:54:10.506Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1195
File: internal/exec/terraform_clean.go:99-99
Timestamp: 2025-04-26T15:54:10.506Z
Learning: The error variable `ErrRelPath` is defined in `internal/exec/terraform_clean_util.go` and is used across files in the `exec` package, including in `terraform_clean.go`. This is part of an approach to standardize error handling in the codebase.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-10-27T04:41:49.199Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:215-223
Timestamp: 2024-10-27T04:41:49.199Z
Learning: In `internal/exec/terraform_clean.go`, the function `determineCleanPath` is necessary and should not be removed.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-12-25T20:28:47.526Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/stack_processor_utils.go:380-380
Timestamp: 2024-12-25T20:28:47.526Z
Learning: Windows path handling often requires `filepath.Join` to ensure correct separators and comparisons. Insufficient tests can break cross-platform compatibility, so migrating from `path.Join` to `filepath.Join` needs thorough testing on Windows before merging.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-12-25T20:28:19.618Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/workflow_utils.go:167-169
Timestamp: 2024-12-25T20:28:19.618Z
Learning: The user plans to revert the change from `path.Join` to `filepath.Join` in this PR due to testing gaps and will open a new PR to safely handle the migration without breaking `main`.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-11-12T03:16:02.910Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 775
File: internal/exec/template_funcs_component.go:157-159
Timestamp: 2024-11-12T03:16:02.910Z
Learning: In the Go code for `componentFunc` in `internal/exec/template_funcs_component.go`, the function `cleanTerraformWorkspace` does not return errors, and it's acceptable if the file does not exist. Therefore, error handling for `cleanTerraformWorkspace` is not needed.

Applied to files:

  • pkg/list/extract/workflows.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • pkg/list/extract/workflows.go
  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-11-07T14:52:55.217Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1761
File: docs/prd/claude-agent-architecture.md:331-439
Timestamp: 2025-11-07T14:52:55.217Z
Learning: In the cloudposse/atmos repository, Claude agents are used as interactive tools, not in automated/headless CI/CD contexts. Agent documentation and patterns should assume synchronous human interaction.

Applied to files:

  • CLAUDE.md
📚 Learning: 2024-10-31T19:25:41.298Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:233-235
Timestamp: 2024-10-31T19:25:41.298Z
Learning: When specifying color values in functions like `confirmDeleteTerraformLocal` in `internal/exec/terraform_clean.go`, avoid hardcoding color values. Instead, use predefined color constants or allow customization through configuration settings to improve accessibility and user experience across different terminals and themes.

Applied to files:

  • CLAUDE.md
📚 Learning: 2024-11-10T19:28:17.365Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 768
File: internal/exec/vendor_utils.go:0-0
Timestamp: 2024-11-10T19:28:17.365Z
Learning: When TTY is not supported, log the downgrade message at the Warn level using `u.LogWarning(cliConfig, ...)` instead of `fmt.Println`.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • CLAUDE.md
📚 Learning: 2024-11-01T14:45:32.417Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 757
File: cmd/docs.go:52-54
Timestamp: 2024-11-01T14:45:32.417Z
Learning: In `cmd/docs.go`, capping the terminal width at 120 columns is considered acceptable and preferred after testing.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-10-11T19:11:58.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:0-0
Timestamp: 2025-10-11T19:11:58.965Z
Learning: For terraform apply interactivity checks in Atmos (internal/exec/terraform.go), use stdin TTY detection (e.g., `IsTTYSupportForStdin()` or checking `os.Stdin`) to determine if user prompts are possible. This is distinct from stdout/stderr TTY checks used for output display (like TUI rendering). User input requires stdin to be a TTY; output display requires stdout/stderr to be a TTY.

Applied to files:

  • CLAUDE.md
📚 Learning: 2024-11-10T18:37:10.032Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 768
File: internal/exec/vendor_component_utils.go:354-360
Timestamp: 2024-11-10T18:37:10.032Z
Learning: In the vendoring process, a TTY can exist without being interactive. If the process does not prompt the user, we should not require interactive mode to display the TUI. The `CheckTTYSupport` function should check TTY support on stdout rather than stdin.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-10-14T01:54:48.410Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-completion--help.html:2-7
Timestamp: 2025-10-14T01:54:48.410Z
Learning: Screengrab HTML files in website/src/components/Screengrabs/ are generated from actual Atmos CLI output converted to HTML. The ANSI-art headers and formatting in these files are intentional and reflect the real CLI user experience, so they should not be suggested for removal or modification.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-09-13T16:39:20.007Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-10-02T19:17:51.630Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1504
File: pkg/profiler/profiler.go:20-31
Timestamp: 2025-10-02T19:17:51.630Z
Learning: In pkg/profiler/profiler.go, profiler-specific errors (ErrUnsupportedProfileType, ErrStartCPUProfile, ErrStartTraceProfile, ErrCreateProfileFile) must remain local and cannot be moved to errors/errors.go due to an import cycle: pkg/profiler → errors → pkg/schema → pkg/profiler. This is a valid exception to the centralized errors policy.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-09-10T21:17:55.273Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/http_client_test.go:3-10
Timestamp: 2025-09-10T21:17:55.273Z
Learning: In the cloudposse/atmos repository, imports should never be changed as per samtholiya's coding guidelines.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.

Applied to files:

  • pkg/list/importresolver/provenance.go
  • cmd/list/vendor.go
📚 Learning: 2025-09-24T20:45:40.401Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: tests/fixtures/scenarios/atmos-auth/stacks/deploy/nonprod.yaml:3-4
Timestamp: 2025-09-24T20:45:40.401Z
Learning: In Atmos stack files, the correct syntax for importing other stack files is `import:` (singular), not `imports:` (plural). All stack files in the Atmos codebase consistently use `import:` followed by a list of paths to import.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-11-22T12:38:33.132Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 768
File: internal/exec/vendor_utils.go:496-513
Timestamp: 2024-11-22T12:38:33.132Z
Learning: In the Atmos project, continue to flag path traversal issues in code reviews but acknowledge when they are expected and acceptable in specific cases.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-01-17T00:18:57.769Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 944
File: go.mod:206-206
Timestamp: 2025-01-17T00:18:57.769Z
Learning: For indirect dependencies with license compliance issues in the cloudposse/atmos repository, the team prefers to handle them in follow-up PRs rather than blocking the current changes, as these issues often require deeper investigation of the dependency tree.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2025-10-16T05:26:31.892Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1639
File: pkg/merge/merge.go:392-430
Timestamp: 2025-10-16T05:26:31.892Z
Learning: In Atmos merge operations (pkg/merge/merge.go), context.Positions is a PositionMap (map[string]*schema.Position) keyed by JSONPath strings, not a slice indexed by input array position. Position lookups are path-based, making them independent of input array reorganization or filtering. This design allows filtering empty inputs without affecting provenance tracking correctness.

Applied to files:

  • pkg/list/importresolver/provenance.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-12-07T16:19:01.683Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 825
File: internal/exec/terraform.go:30-30
Timestamp: 2024-12-07T16:19:01.683Z
Learning: In `internal/exec/terraform.go`, skipping stack validation when help flags are present is not necessary.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-12-08T14:26:16.972Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 828
File: pkg/schema/schema.go:98-100
Timestamp: 2024-12-08T14:26:16.972Z
Learning: The `ListConfig` columns array in the `Components` struct can be empty.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2024-10-22T23:00:20.627Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:131-141
Timestamp: 2024-10-22T23:00:20.627Z
Learning: In the `ReadAndProcessVendorConfigFile` function in `internal/exec/vendor_utils.go`, the existence of the vendor config file is already checked, so additional file existence checks may be unnecessary.

Applied to files:

  • cmd/list/vendor.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • cmd/list/vendor.go
🧬 Code graph analysis (1)
cmd/list/vendor.go (11)
pkg/flags/standard_parser.go (1)
  • StandardParser (18-22)
pkg/flags/global_registry.go (1)
  • ParseGlobalFlags (33-74)
pkg/schema/schema.go (3)
  • ConfigAndStacksInfo (624-718)
  • Vendor (936-941)
  • AtmosConfiguration (53-94)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
pkg/list/extract/vendor.go (1)
  • Vendor (24-44)
cmd/list/flag_wrappers.go (2)
  • NewListParser (304-315)
  • WithFormatFlag (32-40)
pkg/list/list_vendor.go (1)
  • GetVendorInfos (128-156)
pkg/list/column/column.go (2)
  • NewSelector (52-79)
  • Config (13-17)
pkg/list/renderer/renderer.go (1)
  • New (31-46)
pkg/list/output/output.go (1)
  • New (14-16)
pkg/list/sort/sort.go (4)
  • Sorter (35-39)
  • NewSorter (48-54)
  • Ascending (17-17)
  • ParseSortSpec (195-237)
🪛 LanguageTool
CLAUDE.md

[typographical] ~40-~40: Consider using a typographic close quote here.
Context: ...i-expert(terminal UI). Use Task tool:Task(subagent_type: "flag-handler", prompt: "...")`. Prevents incorrect patterns and ensu...

(EN_QUOTES)

⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Acceptance Tests (macos)
  • GitHub Check: Acceptance Tests (linux)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (20)
CLAUDE.md (3)

39-40: Specialized Agents guidance is clear and actionable.

The new mandatory pattern for consulting specialized agents via the Task tool provides concrete direction. The specific mention of flag-handler aligns well with the PR's list command refactoring and prevents duplicated effort.


767-790: Intro component integration strengthens documentation consistency.

The addition of Intro component usage in the documentation template aligns the guidance with the PR's UI/messaging improvements across list commands. The example clearly shows the intended pattern, and the section ordering (Intro → Screengrab → Usage → Examples) reads naturally.


206-206: Benefits consolidation maintains substance while improving clarity.

Replacing the multi-block rationale with a single concise line ("Auto color/width degradation, TTY detection, secret masking, ...") preserves the key benefits without sacrificing readability. This is especially valuable in a document this size.

pkg/list/extract/workflows.go (2)

3-26: Clean structure and imports

The imports are correct, perf tracking is in place, and the linter suppressions are justified for the file handling complexity. Good start.


97-120: Solid extraction logic

The function is well-structured with perf tracking, nil-checking, and clear mapping from manifest to output format. Works as intended.

pkg/list/importresolver/provenance.go (9)

33-101: Provenance tree assembly and perf instrumentation look solid

The aggregation over merge contexts into map[stackName]map[componentName][]*tree.ImportNode is coherent, and the use of extractComponentFolders to attach ComponentFolder on the first node per component keeps rendering concerns nicely separated. perf.Track is wired in as per policy and there are no obvious correctness issues here.


107-187: Stack/file matching logic in findStacksForFilePath is thorough

The normalization plus multiple match strategies (absolute, relative, and extensionless) give this a good chance of matching atmos_stack_file values across common variants without overcomplicating things. The function is defensive around type assertions and keeps logging at Trace, which is appropriate.


191-238: Component folder derivation aligns with components/{type}/{folder} convention

Using metadata.component when present and falling back to the component name, then composing components/{type}/{folder}, matches Atmos’ component folder semantics and gives renderers the path they need without exposing the full stack structure.


241-271: extractComponentsFromStackData is a simple, reusable helper

This helper cleanly extracts component names across all types and is defensive on shapes. It’s a reasonable internal/test utility to keep component enumeration logic in one place.


273-315: ImportChain → tree conversion is cycle-safe and cached

buildImportTreeFromChain correctly skips the root stack entry, normalizes display paths via stripBasePath, and uses a visited set plus importCache to avoid infinite recursion and redundant file reads. The backtracking of visited per branch looks correct.


319-344: stripBasePath normalization and extension stripping are well-behaved

The combination of filepath.Rel with a TrimPrefix fallback, plus filepath.ToSlash and .yaml/.yml stripping, gives consistent, cross-platform, extensionless display paths. The added perf.Track keeps it aligned with repo profiling rules.


373-409: Child-node Path values intentionally preserve original import strings

Top-level nodes are normalized via stripBasePath, while child nodes use the raw importPath from YAML for Path. That gives users what they actually wrote in nested imports, at the expense of inconsistent normalization between levels. If that’s the intended UX for --provenance output, this implementation supports it cleanly.


411-439: Import path resolution correctly handles relative vs base-path imports

The split between ./..-prefixed paths resolved against parentFilePath and other imports resolved against StacksBaseAbsolutePath matches expected stack import semantics and keeps cycle detection keyed on absolute paths. Path cleaning and extension handling look correct, and directory traversal for legitimate .. imports is preserved as intended.
Based on learnings, directory traversal in stack imports is acceptable here.


441-492: YAML import extraction is flexible and defensive

readImportsFromYAMLFile plus extractImportStringsHelper handle both import and imports, and accept either a single string or a slice, returning an empty slice instead of nil when no imports are found. That makes the callers simpler and keeps provenance resolution tolerant of optional import fields. The perf tracking is in place on both helpers.

cmd/list/vendor.go (6)

68-91: LGTM!

Dynamic completion properly loads config and extracts vendor column names. Performance tracking is in place and error handling is graceful.


93-117: Clean flag setup with modular wrappers.

Flag configuration uses composable wrappers and properly registers completions and Viper bindings. Follows established patterns.


119-173: Solid renderer pipeline implementation.

The flow is clean: config → vendor data → filters/columns/sorters → renderer → output. Format fallback from config and graceful handling of empty vendors are good touches. Error handling is comprehensive.


175-191: Filter implementation correctly targets component field.

The filter logic and inline comment clearly document that --stack is applied to the "component" field (vendor rows don't contain stack context). This design was reviewed in past comments and accepted.


193-222: Column configuration properly preserves width settings.

Flag precedence is correct (flag → config → defaults), and the Width field is now carried through from atmos.yaml configuration as intended. Default columns align with vendor data structure.


224-236: Sorter configuration with sensible defaults.

Default sort by Component ascending is appropriate, and the implementation delegates to the shared ParseSortSpec validation. Clean and correct.

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 24, 2025
Merged main branch changes including:
- Authentication/identity support for list commands
- Metadata inheritance feature (StacksInherit)
- Devcontainer support
- Various bug fixes and improvements

Resolved conflicts by:
- Keeping new list UI infrastructure (renderer, column selector, filters)
- Integrating auth manager support via createAuthManagerForList helper
- Merging Stacks schema to include both List and Inherit fields
- Combining documentation flags from both branches

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Remove the third argument (nil authManager) from all test calls since
the function signature was simplified during the merge conflict resolution.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…ommands

During the merge conflict resolution, the authManager parameter was
accidentally removed from processInstances and processInstancesWithDeps
functions. This regression broke authentication support that was added
on main branch.

Changes:
- Restore auth.AuthManager parameter to processInstancesWithDeps()
- Restore auth.AuthManager parameter to processInstances()
- Add AuthManager field to InstancesCommandOptions struct
- Add AuthManager field to MetadataOptions struct
- Update cmd/list/instances.go to create and pass authManager
- Update cmd/list/metadata.go to create and pass authManager
- Update ExecuteListInstancesCmd to use opts.AuthManager
- Pass authManager to ExecuteDescribeStacks calls for both tree and
  non-tree formats
- Update all tests to match new function signatures

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
…nance

The second ExecuteDescribeStacks call in listStacksWithOptions was
passing nil instead of authManager when re-processing stacks with
provenance tracking enabled. This would cause authentication to fail
for stacks using YAML template functions that require authentication.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Add tests for all ListCommandProvider getter methods which were at 0%
coverage. This increases cmd/list package coverage from 43.9% to 44.6%.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (1)
cmd/list/components.go (1)

279-293: parseColumnsFlag remains a stub - --columns flag is effectively ignored.

Past review noted this issue and marked it as "addressed in commit c8f61af", but the implementation still returns default columns regardless of input. Users passing --columns will see no effect.

If this is intentionally deferred, consider either:

  1. Documenting the deferral more explicitly (e.g., link to tracking issue)
  2. Emitting a warning when --columns is used but not yet implemented

This prevents user confusion when the flag appears functional but isn't.

🧹 Nitpick comments (5)
cmd/list/instances.go (1)

72-97: Missing perf.Track in columnsCompletionForInstances.

Unlike columnsCompletionForComponents which has defer perf.Track(nil, "list.components.columnsCompletionForComponents")(), this function lacks performance tracking. Per repo policy, non-trivial functions should include it.

 func columnsCompletionForInstances(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+	defer perf.Track(nil, "list.instances.columnsCompletionForInstances")()
+
 	// Load atmos configuration.

Add the perf import if not present.

cmd/list/metadata.go (1)

63-88: Missing perf.Track in columnsCompletionForMetadata.

Same issue as instances.go. This function lacks performance tracking.

 func columnsCompletionForMetadata(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+	defer perf.Track(nil, "list.metadata.columnsCompletionForMetadata")()
+
 	// Load atmos configuration.
cmd/list/values.go (1)

3-23: Import organization needs correction.

The log import (line 7) is placed between stdlib (errors, fmt) and 3rd-party imports. It should be in the Atmos packages group since it's github.com/cloudposse/atmos/pkg/logger.

 import (
 	"errors"
 	"fmt"

-	log "github.com/cloudposse/atmos/pkg/logger"
 	pkgerrors "github.com/pkg/errors"
 	"github.com/spf13/cobra"
 	"github.com/spf13/viper"

 	e "github.com/cloudposse/atmos/internal/exec"
 	"github.com/cloudposse/atmos/pkg/config"
 	"github.com/cloudposse/atmos/pkg/flags"
 	"github.com/cloudposse/atmos/pkg/flags/global"
 	l "github.com/cloudposse/atmos/pkg/list"
 	listerrors "github.com/cloudposse/atmos/pkg/list/errors"
 	f "github.com/cloudposse/atmos/pkg/list/format"
 	listutils "github.com/cloudposse/atmos/pkg/list/utils"
+	log "github.com/cloudposse/atmos/pkg/logger"
 	"github.com/cloudposse/atmos/pkg/schema"
 	"github.com/cloudposse/atmos/pkg/ui"
 	u "github.com/cloudposse/atmos/pkg/utils"
 )
cmd/list/stacks.go (2)

70-95: Dynamic --columns completion is correct; consider prefix-filtering

The completion helper correctly loads atmosConfig via ProcessCommandLineArgs + InitCliConfig and surfaces configured stacks.list.columns names, which is exactly what users need.

If you want to polish UX a bit, you could optionally filter on toComplete before returning, so shells don’t have to handle very long suggestion lists:

var columnNames []string
for _, col := range atmosConfig.Stacks.List.Columns {
    if toComplete == "" || strings.HasPrefix(col.Name, toComplete) {
        columnNames = append(columnNames, col.Name)
    }
}

You’d need a strings import if you go this route.


121-160: Consider aligning new user-facing errors with the ErrorBuilder pattern

The new error paths here (invalid --provenance usage, CLI config initialization, ExecuteDescribeStacks failure, sort spec parsing) currently use fmt.Errorf directly, sometimes wrapping sentinels like errUtils.ErrInvalidFlag or errUtils.ErrInitializingCLIConfig.

To better match the repo’s error-handling conventions, you might want to transition these to the central ErrorBuilder API so you can attach causes, hints, and explanations consistently. For example, the provenance validation could become something along the lines of:

return errUtils.
    NewInvalidFlagError().
    WithExplanation("--provenance flag only works with --format=tree").
    Error()

(Adjusted to whatever concrete builder helpers exist.)

Not urgent for correctness, but it will make CLI error reporting and downstream handling more consistent with the rest of the codebase.

Also applies to: 247-257

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 82ed911 and db8d0e4.

📒 Files selected for processing (12)
  • cmd/list/components.go (1 hunks)
  • cmd/list/instances.go (4 hunks)
  • cmd/list/metadata.go (1 hunks)
  • cmd/list/settings.go (4 hunks)
  • cmd/list/stacks.go (1 hunks)
  • cmd/list/values.go (5 hunks)
  • cmd/root.go (4 hunks)
  • cmd/root_test.go (1 hunks)
  • errors/errors.go (2 hunks)
  • internal/exec/stack_processor_utils.go (31 hunks)
  • internal/exec/utils.go (1 hunks)
  • internal/exec/validate_stacks.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/exec/validate_stacks.go
  • errors/errors.go
🧰 Additional context used
📓 Path-based instructions (4)
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: All comments must end with periods (enforced by godot linter)
Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig param
Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit
Use sentinel errors from errors/errors.go with ErrorBuilder for all user-facing errors. Use errors.Is() for checking errors, never string comparison. WithCause() preserves underlying error messages, WithExplanation() adds context, WithHint() provides guidance, WithContext() adds key-value pairs
Use context.Context as first parameter for: cancellation signals (prop...

Files:

  • internal/exec/utils.go
  • cmd/list/settings.go
  • cmd/list/stacks.go
  • cmd/list/metadata.go
  • cmd/root.go
  • cmd/list/instances.go
  • cmd/list/values.go
  • cmd/root_test.go
  • cmd/list/components.go
  • internal/exec/stack_processor_utils.go
cmd/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under cmd/ directory
Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands

cmd/**/*.go: CLI command files must be thin wrappers that only handle CLI concerns (flags, arguments, command registration). All business logic must be delegated to pkg/ packages
Use flags.NewStandardParser() for command-specific flag parsing. NEVER call viper.BindEnv() or viper.BindPFlag() directly - use the unified pkg/flags/ infrastructure instead. Register flags with Cobra command and bind to Viper for precedence handling
All CLI commands MUST implement the CommandProvider interface and register via command registry pattern in cmd/internal/registry.go
Embed examples from cmd/markdown/*_usage.md using //go:embed. Render with utils.PrintfMarkdown()

Files:

  • cmd/list/settings.go
  • cmd/list/stacks.go
  • cmd/list/metadata.go
  • cmd/root.go
  • cmd/list/instances.go
  • cmd/list/values.go
  • cmd/root_test.go
  • cmd/list/components.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Use assert.ErrorIs(t, err, ErrSentinel) for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER use assert.Contains(err.Error(), ...) for error checking. ALWAYS use assert.ErrorIs() instead. NEVER use string comparison: err.Error() == "..." or strings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid os.Exit, CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks. Pattern: //go:generate go run go.uber.org/mock/mockgen@latest -source=filename.go -destination=mock_filename_test.go
Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)

Files:

  • cmd/root_test.go
cmd/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS use cmd.NewTestKit(t) for cmd tests. This auto-cleans RootCmd state (flags, args) and is required for any test touching RootCmd

Files:

  • cmd/root_test.go
🧠 Learnings (89)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 as a special value to display unlimited columns in table outputs.
📚 Learning: 2025-10-08T06:48:07.499Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1602
File: internal/exec/stack_processor_utils.go:968-1003
Timestamp: 2025-10-08T06:48:07.499Z
Learning: The `FindComponentDependenciesLegacy` function in `internal/exec/stack_processor_utils.go` is legacy code that is not actively used and is kept only for backward compatibility purposes.

Applied to files:

  • internal/exec/utils.go
📚 Learning: 2024-11-13T21:37:07.852Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 764
File: internal/exec/describe_stacks.go:289-295
Timestamp: 2024-11-13T21:37:07.852Z
Learning: In the `internal/exec/describe_stacks.go` file of the `atmos` project written in Go, avoid extracting the stack name handling logic into a helper function within the `ExecuteDescribeStacks` method, even if the logic appears duplicated.

Applied to files:

  • internal/exec/utils.go
  • cmd/list/stacks.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-09-13T18:06:07.674Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: toolchain/list.go:39-42
Timestamp: 2025-09-13T18:06:07.674Z
Learning: In the cloudposse/atmos repository, for UI messages in the toolchain package, use utils.PrintfMessageToTUI instead of log.Error or fmt.Fprintln(os.Stderr, ...). Import pkg/utils with alias "u" to follow the established pattern.

Applied to files:

  • cmd/list/settings.go
  • cmd/root.go
  • cmd/list/values.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-01-18T15:15:41.645Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/terraform.go:37-46
Timestamp: 2025-01-18T15:15:41.645Z
Learning: In the atmos CLI, error handling is intentionally structured to use LogErrorAndExit for consistent error display, avoiding Cobra's default error handling to prevent duplicate error messages.

Applied to files:

  • cmd/list/settings.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Use Viper for managing configuration, environment variables, and flags in CLI commands

Applied to files:

  • cmd/list/settings.go
  • cmd/list/instances.go
  • cmd/list/values.go
📚 Learning: 2024-10-23T21:36:40.262Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 740
File: cmd/cmd_utils.go:340-359
Timestamp: 2024-10-23T21:36:40.262Z
Learning: In the Go codebase for Atmos, when reviewing functions like `checkAtmosConfig` in `cmd/cmd_utils.go`, avoid suggesting refactoring to return errors instead of calling `os.Exit` if such changes would significantly increase the scope due to the need to update multiple call sites.

Applied to files:

  • cmd/list/settings.go
  • cmd/list/stacks.go
  • cmd/list/metadata.go
  • cmd/root.go
  • cmd/list/instances.go
  • cmd/list/values.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases: `cfg`, `log`, `u`, `errUtils`

Applied to files:

  • cmd/list/settings.go
  • cmd/root.go
  • cmd/list/instances.go
  • cmd/list/values.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-08-29T20:57:35.423Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1433
File: cmd/theme_list.go:33-36
Timestamp: 2025-08-29T20:57:35.423Z
Learning: In the Atmos codebase, avoid using viper.SetEnvPrefix("ATMOS") with viper.AutomaticEnv() because canonical environment variable names are not exclusive to Atmos and could cause conflicts. Instead, use selective environment variable binding through the setEnv function in pkg/config/load.go with bindEnv(v, "config.key", "ENV_VAR_NAME") for specific environment variables.

Applied to files:

  • cmd/list/settings.go
📚 Learning: 2024-12-11T18:40:12.808Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/helmfile.go:37-37
Timestamp: 2024-12-11T18:40:12.808Z
Learning: In the atmos project, `cliConfig` is initialized within the `cmd` package in `root.go` and can be used in other command files.

Applied to files:

  • cmd/list/settings.go
  • cmd/list/instances.go
  • cmd/list/values.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Use `viper.BindEnv("ATMOS_VAR", "ATMOS_VAR", "FALLBACK")` for environment variables - ATMOS_ prefix required. Configuration loading precedence: CLI flags → ENV vars → config files → defaults

Applied to files:

  • cmd/list/settings.go
  • cmd/list/values.go
📚 Learning: 2025-07-05T20:59:02.914Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1363
File: internal/exec/template_utils.go:18-18
Timestamp: 2025-07-05T20:59:02.914Z
Learning: In the Atmos project, gomplate v4 is imported with a blank import (`_ "github.com/hairyhenderson/gomplate/v4"`) alongside v3 imports to resolve AWS SDK version conflicts. V3 uses older AWS SDK versions that conflict with newer AWS modules used by Atmos. A full migration to v4 requires extensive refactoring due to API changes and should be handled in a separate PR.

Applied to files:

  • cmd/list/settings.go
  • cmd/root.go
  • cmd/list/values.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-10-22T14:55:44.014Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1695
File: pkg/auth/manager.go:169-171
Timestamp: 2025-10-22T14:55:44.014Z
Learning: Go 1.20+ supports multiple %w verbs in fmt.Errorf, which returns an error implementing Unwrap() []error. This is valid and does not panic. Atmos uses Go 1.24.8 and configures errorlint with errorf-multi: true to validate this pattern.

Applied to files:

  • cmd/list/settings.go
  • cmd/list/values.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-12-05T22:33:54.807Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_stacks.go:55-56
Timestamp: 2024-12-05T22:33:54.807Z
Learning: In the atmos project, the `u.LogErrorAndExit` function logs the error and exits the command execution appropriately within flag completion functions.

Applied to files:

  • cmd/list/settings.go
📚 Learning: 2024-10-28T01:51:30.811Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:329-332
Timestamp: 2024-10-28T01:51:30.811Z
Learning: In the Atmos Go code, when deleting directories or handling file paths (e.g., in `terraform_clean.go`), always resolve the absolute path using `filepath.Abs` and use the logger `u.LogWarning` for logging messages instead of using `fmt.Printf`.

Applied to files:

  • cmd/list/settings.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-12-05T22:33:40.955Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 820
File: cmd/list_components.go:53-54
Timestamp: 2024-12-05T22:33:40.955Z
Learning: In the Atmos CLI Go codebase, using `u.LogErrorAndExit` within completion functions is acceptable because it logs the error and exits the command execution.

Applied to files:

  • cmd/list/settings.go
📚 Learning: 2025-02-21T20:56:05.539Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1077
File: pkg/downloader/custom_github_detector.go:0-0
Timestamp: 2025-02-21T20:56:05.539Z
Learning: The `github.com/charmbracelet/log` package should be imported with the alias `log` according to the project's import alias configuration.

Applied to files:

  • cmd/list/settings.go
📚 Learning: 2025-02-21T20:56:20.761Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1077
File: pkg/downloader/custom_github_detector_test.go:0-0
Timestamp: 2025-02-21T20:56:20.761Z
Learning: The `github.com/charmbracelet/log` package should be imported with the alias `log`, not `clog`.

Applied to files:

  • cmd/list/settings.go
📚 Learning: 2024-12-07T16:16:13.038Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 825
File: internal/exec/helmfile_generate_varfile.go:28-31
Timestamp: 2024-12-07T16:16:13.038Z
Learning: In `internal/exec/helmfile_generate_varfile.go`, the `--help` command (`./atmos helmfile generate varfile --help`) works correctly without requiring stack configurations, and the only change needed was to make `ProcessCommandLineArgs` exportable by capitalizing its name.

Applied to files:

  • cmd/list/stacks.go
  • cmd/list/metadata.go
  • cmd/list/components.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-01-09T22:27:25.538Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/validate_stacks.go:20-23
Timestamp: 2025-01-09T22:27:25.538Z
Learning: The validate commands in Atmos can have different help handling implementations. Specifically, validate_component.go and validate_stacks.go are designed to handle help requests differently, with validate_stacks.go including positional argument checks while validate_component.go does not.

Applied to files:

  • cmd/list/stacks.go
📚 Learning: 2024-12-07T16:19:01.683Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 825
File: internal/exec/terraform.go:30-30
Timestamp: 2024-12-07T16:19:01.683Z
Learning: In `internal/exec/terraform.go`, skipping stack validation when help flags are present is not necessary.

Applied to files:

  • cmd/list/stacks.go
📚 Learning: 2024-12-02T21:26:32.337Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 808
File: pkg/config/config.go:478-483
Timestamp: 2024-12-02T21:26:32.337Z
Learning: In the 'atmos' project, when reviewing Go code like `pkg/config/config.go`, avoid suggesting file size checks after downloading remote configs if such checks aren't implemented elsewhere in the codebase.

Applied to files:

  • cmd/list/stacks.go
  • cmd/list/metadata.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-10-10T23:51:36.597Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1599
File: internal/exec/terraform.go:394-402
Timestamp: 2025-10-10T23:51:36.597Z
Learning: In Atmos (internal/exec/terraform.go), when adding OpenTofu-specific flags like `--var-file` for `init`, do not gate them based on command name (e.g., checking if `info.Command == "tofu"` or `info.Command == "opentofu"`) because command names don't reliably indicate the actual binary being executed (symlinks, aliases). Instead, document the OpenTofu requirement in code comments and documentation, trusting users who enable the feature (e.g., `PassVars`) to ensure their terraform command points to an OpenTofu binary.

Applied to files:

  • cmd/list/stacks.go
  • cmd/list/metadata.go
  • cmd/list/instances.go
  • cmd/list/components.go
📚 Learning: 2024-12-13T15:28:13.630Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 844
File: cmd/version.go:34-44
Timestamp: 2024-12-13T15:28:13.630Z
Learning: In `cmd/version.go`, when handling the `--check` flag in the `versionCmd`, avoid using `CheckForAtmosUpdateAndPrintMessage(cliConfig)` as it updates the cache timestamp, which may not be desired in this context.

Applied to files:

  • cmd/list/stacks.go
📚 Learning: 2025-11-08T19:56:18.660Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1697
File: internal/exec/oci_utils.go:0-0
Timestamp: 2025-11-08T19:56:18.660Z
Learning: In the Atmos codebase, when a function receives an `*schema.AtmosConfiguration` parameter, it should read configuration values from `atmosConfig.Settings` fields rather than using direct `os.Getenv()` or `viper.GetString()` calls. The Atmos pattern is: viper.BindEnv in cmd/root.go binds environment variables → Viper unmarshals into atmosConfig.Settings via mapstructure → business logic reads from the Settings struct. This provides centralized config management, respects precedence, and enables testability. Example: `atmosConfig.Settings.AtmosGithubToken` instead of `os.Getenv("ATMOS_GITHUB_TOKEN")` in functions like `getGHCRAuth` in internal/exec/oci_utils.go.

Applied to files:

  • cmd/list/stacks.go
  • cmd/list/instances.go
📚 Learning: 2025-04-04T02:03:23.676Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1185
File: internal/exec/yaml_func_store.go:26-26
Timestamp: 2025-04-04T02:03:23.676Z
Learning: The Atmos codebase currently uses `log.Fatal` for error handling in multiple places. The maintainers are aware this isn't an ideal pattern (should only be used in main() or init() functions) and plan to address it comprehensively in a separate PR. CodeRabbit should not flag these issues or push for immediate changes until that refactoring is complete.

Applied to files:

  • cmd/list/stacks.go
📚 Learning: 2025-01-19T15:49:15.593Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.

Applied to files:

  • cmd/list/stacks.go
📚 Learning: 2025-09-29T02:20:11.636Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1540
File: internal/exec/validate_component.go:117-118
Timestamp: 2025-09-29T02:20:11.636Z
Learning: The ValidateComponent function in internal/exec/validate_component.go had its componentSection parameter type refined from `any` to `map[string]any` without adding new parameters. This is a type safety improvement, not a signature change requiring call site updates.

Applied to files:

  • cmd/list/stacks.go
  • cmd/list/components.go
📚 Learning: 2025-01-09T22:37:01.004Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 914
File: cmd/terraform_commands.go:260-265
Timestamp: 2025-01-09T22:37:01.004Z
Learning: In the terraform commands implementation (cmd/terraform_commands.go), the direct use of `os.Args[2:]` for argument handling is intentionally preserved to avoid extensive refactoring. While it could be improved to use cobra's argument parsing, such changes should be handled in a dedicated PR to maintain focus and minimize risk.

Applied to files:

  • cmd/list/stacks.go
  • cmd/list/metadata.go
  • cmd/list/instances.go
  • cmd/root_test.go
  • cmd/list/components.go
📚 Learning: 2025-05-22T15:42:10.906Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1261
File: internal/exec/utils.go:639-640
Timestamp: 2025-05-22T15:42:10.906Z
Learning: In the Atmos codebase, when appending slices with `args := append(configAndStacksInfo.CliArgs, configAndStacksInfo.AdditionalArgsAndFlags...)`, it's intentional that the result is not stored back in the original slice. This pattern is used when the merged result serves a different purpose than the original slices, such as when creating a filtered version for component section assignments.

Applied to files:

  • cmd/list/stacks.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-08-16T23:32:40.412Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1405
File: internal/exec/describe_dependents_test.go:455-456
Timestamp: 2025-08-16T23:32:40.412Z
Learning: In the cloudposse/atmos Go codebase, `InitCliConfig` returns a `schema.AtmosConfiguration` value (not a pointer), while `ExecuteDescribeDependents` expects a `*schema.AtmosConfiguration` pointer parameter. Therefore, when passing the result of `InitCliConfig` to `ExecuteDescribeDependents`, use `&atmosConfig` to pass the address of the value.

Applied to files:

  • cmd/list/stacks.go
  • cmd/list/instances.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions

Applied to files:

  • cmd/list/metadata.go
  • cmd/root.go
  • cmd/list/components.go
📚 Learning: 2025-10-07T00:25:16.333Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.

Applied to files:

  • cmd/list/metadata.go
📚 Learning: 2025-06-23T02:14:30.937Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1327
File: cmd/terraform.go:111-117
Timestamp: 2025-06-23T02:14:30.937Z
Learning: In cmd/terraform.go, flags for the DescribeAffected function are added dynamically at runtime when info.Affected is true. This is intentional to avoid exposing internal flags like "file", "format", "verbose", "include-spacelift-admin-stacks", "include-settings", and "upload" in the terraform command interface, while still providing them for the shared DescribeAffected function used by both `atmos describe affected` and `atmos terraform apply --affected`.

Applied to files:

  • cmd/list/metadata.go
  • cmd/list/instances.go
📚 Learning: 2025-01-30T19:30:59.120Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 959
File: cmd/workflow.go:74-74
Timestamp: 2025-01-30T19:30:59.120Z
Learning: Error handling for `cmd.Usage()` is not required in the Atmos CLI codebase, as confirmed by the maintainer.

Applied to files:

  • cmd/list/metadata.go
📚 Learning: 2025-04-11T22:06:46.999Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1147
File: internal/exec/validate_schema.go:42-57
Timestamp: 2025-04-11T22:06:46.999Z
Learning: The "ExecuteAtmosValidateSchemaCmd" function in internal/exec/validate_schema.go has been reviewed and confirmed to have acceptable cognitive complexity despite static analysis warnings. The function uses a clean structure with only three if statements for error handling and delegates complex operations to helper methods.

Applied to files:

  • cmd/list/metadata.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-09-05T14:57:37.360Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 1448
File: cmd/ansible.go:26-28
Timestamp: 2025-09-05T14:57:37.360Z
Learning: The Atmos codebase uses a consistent pattern for commands that delegate to external tools: `PersistentFlags().Bool("", false, doubleDashHint)` where doubleDashHint provides help text about using double dashes to separate Atmos options from native command arguments. This pattern is used across terraform, packer, helmfile, atlantis, aws, and ansible commands.

Applied to files:

  • cmd/list/metadata.go
  • cmd/list/instances.go
  • cmd/list/values.go
📚 Learning: 2024-10-31T19:25:41.298Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:233-235
Timestamp: 2024-10-31T19:25:41.298Z
Learning: When specifying color values in functions like `confirmDeleteTerraformLocal` in `internal/exec/terraform_clean.go`, avoid hardcoding color values. Instead, use predefined color constants or allow customization through configuration settings to improve accessibility and user experience across different terminals and themes.

Applied to files:

  • cmd/root.go
  • cmd/list/values.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Use colors from `pkg/ui/theme/colors.go` for consistent theming throughout the codebase

Applied to files:

  • cmd/root.go
  • cmd/list/values.go
📚 Learning: 2025-06-07T19:27:40.807Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1266
File: pkg/utils/highlight_utils.go:0-0
Timestamp: 2025-06-07T19:27:40.807Z
Learning: In pkg/utils/highlight_utils.go, the global variable `isTermPresent` that caches terminal detection at package initialization is an intentional design choice and should not be changed to per-call detection.

Applied to files:

  • cmd/root.go
📚 Learning: 2024-11-01T14:45:32.417Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 757
File: cmd/docs.go:52-54
Timestamp: 2024-11-01T14:45:32.417Z
Learning: In `cmd/docs.go`, capping the terminal width at 120 columns is considered acceptable and preferred after testing.

Applied to files:

  • cmd/root.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • cmd/root.go
  • cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to pkg/io/**/*.go : Use I/O layer (`pkg/io/`) for stream access (stdout/stderr/stdin), terminal capabilities, masking. Use UI layer (`pkg/ui/`) for formatting (colors, styles, markdown rendering). Never use `fmt.Fprintf(os.Stdout/Stderr, ...)`, `fmt.Println()`, or direct stream access

Applied to files:

  • cmd/root.go
  • cmd/list/values.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands

Applied to files:

  • cmd/root.go
  • cmd/list/values.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to tests/**/*_test.go : NEVER use pipe redirection (`2>&1`, `| head`, `| tail`) when running tests. Piping breaks TTY detection → ASCII fallback → wrong snapshots. NEVER manually edit golden snapshot files - always use `-regenerate-snapshots` flag. Snapshots capture exact output including invisible formatting (lipgloss padding, ANSI codes, trailing whitespace)

Applied to files:

  • cmd/root.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Add `defer perf.Track(atmosConfig, "pkg.FuncName")()` + blank line to all public functions. Use `nil` if no atmosConfig param

Applied to files:

  • cmd/root.go
  • cmd/list/values.go
  • cmd/list/components.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-11-09T19:06:58.470Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1752
File: pkg/profile/list/formatter_table.go:27-29
Timestamp: 2025-11-09T19:06:58.470Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` is enforced on all functions via linting, including high-frequency utility functions, formatters, and renderers. This is a repository-wide policy to maintain consistency and avoid making case-by-case judgment calls about which functions should have profiling.

Applied to files:

  • cmd/root.go
  • cmd/list/components.go
  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : For output: Pipeable data → `data.*` (stdout), Plain UI → `ui.Write*()` (stderr), Status messages → `ui.Success/Error/Warning/Info()` (stderr), Formatted docs → `ui.Markdown*()`. Use `data.Write()`, `data.Writef()`, `data.Writeln()`, `data.WriteJSON()`, `data.WriteYAML()` for data output

Applied to files:

  • cmd/root.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands (values, settings, metadata) supports -1 as a special value to display unlimited columns in table outputs. The default is 10 columns if not specified.

Applied to files:

  • cmd/list/instances.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands (values, settings, metadata) supports -1 as a special value to display unlimited columns in table outputs, with a default of 10 columns.

Applied to files:

  • cmd/list/instances.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.

Applied to files:

  • cmd/list/instances.go
📚 Learning: 2025-02-20T13:57:36.326Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 as a special value to display unlimited columns in table outputs.

Applied to files:

  • cmd/list/instances.go
📚 Learning: 2025-11-10T03:03:31.505Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 0
File: :0-0
Timestamp: 2025-11-10T03:03:31.505Z
Learning: In the Atmos codebase, commands using the `StandardParser` flag pattern (from pkg/flags) do NOT need explicit `viper.BindPFlag()` calls in their code. The StandardParser encapsulates flag binding internally: flags are registered via `parser.RegisterFlags(cmd)` in init(), and bound via `parser.BindFlagsToViper(cmd, v)` in RunE, which internally calls viper.BindPFlag for each flag. This pattern is used throughout Atmos (e.g., cmd/toolchain/get.go, cmd/toolchain/info.go, cmd/toolchain/install.go, cmd/toolchain/path.go). Do not flag missing viper.BindPFlag calls when StandardParser is used.

Applied to files:

  • cmd/list/instances.go
  • cmd/list/values.go
  • cmd/list/components.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to cmd/**/*.go : Use `flags.NewStandardParser()` for command-specific flag parsing. NEVER call `viper.BindEnv()` or `viper.BindPFlag()` directly - use the unified `pkg/flags/` infrastructure instead. Register flags with Cobra command and bind to Viper for precedence handling

Applied to files:

  • cmd/list/instances.go
  • cmd/list/values.go
  • cmd/list/components.go
📚 Learning: 2024-11-25T17:17:15.703Z
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.

Applied to files:

  • cmd/list/values.go
📚 Learning: 2025-02-18T13:18:53.146Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: cmd/vendor_pull.go:31-31
Timestamp: 2025-02-18T13:18:53.146Z
Learning: Error checking is not required for cobra.Command.RegisterFlagCompletionFunc calls as these are static configurations done at init time.

Applied to files:

  • cmd/list/values.go
  • cmd/list/components.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: The atmos codebase has a custom extension to *testing.T that provides a Chdir method, allowing test functions to call t.Chdir() to change working directories during tests. This is used consistently across test files in the codebase.

Applied to files:

  • cmd/root_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests. This is implemented through custom testing framework extensions and is used consistently throughout the test suite.

Applied to files:

  • cmd/root_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method that can be called on *testing.T objects. This functionality is implemented through custom testing framework extensions and is used consistently throughout the test suite for changing working directories during tests.

Applied to files:

  • cmd/root_test.go
📚 Learning: 2025-05-23T19:51:47.091Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1255
File: cmd/describe_affected_test.go:15-15
Timestamp: 2025-05-23T19:51:47.091Z
Learning: In the atmos codebase, t.Chdir() is a valid method call on *testing.T objects and works correctly for changing directories in tests.

Applied to files:

  • cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to tests/**/*.go : Use `cmd.NewTestKit(t)` for any test touching RootCmd. This auto-cleans RootCmd state. Tests skip gracefully with helpers from `tests/test_preconditions.go`

Applied to files:

  • cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid `os.Exit`, `CheckErrorPrintAndExit`, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios

Applied to files:

  • cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to cmd/**/*_test.go : ALWAYS use `cmd.NewTestKit(t)` for cmd tests. This auto-cleans RootCmd state (flags, args) and is required for any test touching RootCmd

Applied to files:

  • cmd/root_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Use table-driven tests for testing multiple scenarios in Go

Applied to files:

  • cmd/root_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)

Applied to files:

  • cmd/root_test.go
📚 Learning: 2024-12-25T20:28:47.526Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 887
File: internal/exec/stack_processor_utils.go:380-380
Timestamp: 2024-12-25T20:28:47.526Z
Learning: Windows path handling often requires `filepath.Join` to ensure correct separators and comparisons. Insufficient tests can break cross-platform compatibility, so migrating from `path.Join` to `filepath.Join` needs thorough testing on Windows before merging.

Applied to files:

  • cmd/root_test.go
📚 Learning: 2024-12-08T14:26:16.972Z
Learnt from: pkbhowmick
Repo: cloudposse/atmos PR: 828
File: pkg/schema/schema.go:98-100
Timestamp: 2024-12-08T14:26:16.972Z
Learning: The `ListConfig` columns array in the `Components` struct can be empty.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Use functional options pattern for configuration instead of many parameters. Provide defaults and extensibility without breaking changes. Pattern: `type Option func(*Config)`, `func WithName(val) Option { return func(c *Config) { c.Name = val } }`, `func New(opts ...Option) { cfg := &Config{/*defaults*/}; for _, opt := range opts { opt(cfg) }; return &Client{config: cfg} }`

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-01-07T20:38:09.618Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 896
File: cmd/editor_config.go:37-40
Timestamp: 2025-01-07T20:38:09.618Z
Learning: Error handling suggestion for `cmd.Help()` in `cmd/editor_config.go` was deferred as the code is planned for future modifications.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-06-07T19:28:21.289Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1266
File: cmd/describe_affected.go:0-0
Timestamp: 2025-06-07T19:28:21.289Z
Learning: In the Atmos codebase, using panic for unsupported flag types in flag processing functions like setDescribeAffectedFlagValueInCliArgs is the expected behavior rather than returning errors. This pattern is preferred for developer errors when unsupported types are added to the flagsKeyValue map.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-02-19T05:50:35.853Z
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_apply_--help.stdout.golden:0-0
Timestamp: 2025-02-19T05:50:35.853Z
Learning: Backtick formatting should only be applied to flag descriptions in Go source files, not in golden test files (test snapshots) as they are meant to capture the raw command output.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-11-30T04:16:24.155Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:34-48
Timestamp: 2025-11-30T04:16:24.155Z
Learning: In the cloudposse/atmos repository, the `defer perf.Track()` guideline applies to functions that perform meaningful work (I/O, computation, external calls), but explicitly excludes trivial accessors/mutators (e.g., simple getters, setters with single integer increments, string joins, or map appends) where the tracking overhead would exceed the actual method cost and provide no actionable performance data. Hot-path methods called in tight loops should especially avoid perf.Track() if they perform only trivial operations.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-11-30T04:16:01.899Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1821
File: pkg/merge/deferred.go:50-59
Timestamp: 2025-11-30T04:16:01.899Z
Learning: In the cloudposse/atmos repository, performance tracking with `defer perf.Track()` should NOT be added to trivial O(1) getter methods that only return field references or check map lengths (e.g., `GetDeferredValues()`, `HasDeferredValues()`). The guideline to add perf tracking to "all public functions" applies to functions that do meaningful work (I/O, computation, external calls), not to trivial accessors where the tracking overhead would exceed the operation time and pollute performance reports.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2025-10-13T18:13:54.020Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1622
File: pkg/perf/perf.go:140-184
Timestamp: 2025-10-13T18:13:54.020Z
Learning: In pkg/perf/perf.go, the `trackWithSimpleStack` function intentionally skips ownership checks at call stack depth > 1 to avoid expensive `getGoroutineID()` calls on every nested function. This is a performance optimization for the common single-goroutine execution case (most Atmos commands), accepting the rare edge case of potential metric corruption if multi-goroutine execution occurs at depth > 1. The ~19× performance improvement justifies this trade-off.

Applied to files:

  • cmd/list/components.go
📚 Learning: 2024-11-19T23:00:45.899Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 795
File: internal/exec/stack_processor_utils.go:378-386
Timestamp: 2024-11-19T23:00:45.899Z
Learning: In the `ProcessYAMLConfigFile` function within `internal/exec/stack_processor_utils.go`, directory traversal in stack imports is acceptable and should not be restricted.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-10-31T07:09:31.983Z
Learnt from: Cerebrovinny
Repo: cloudposse/atmos PR: 737
File: internal/exec/vendor_utils.go:181-182
Timestamp: 2024-10-31T07:09:31.983Z
Learning: In `internal/exec/vendor_utils.go`, the variables `mergedSources` and `mergedImports` are declared and used later in the code. Do not suggest removing them as unused variables.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : New configs support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`. Implement template functions in `internal/exec/template_funcs.go`, register them, add tests, and update documentation

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to pkg/**/*.go : Create focused purpose-built packages in `pkg/` for new functionality, each with clear responsibility. DO NOT add new functions to `pkg/utils/` or `internal/exec/`. Each package should have focused business logic with tests

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Before implementing new functionality, search `internal/exec/` and `pkg/` for existing code. Extend, don't duplicate

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*.go : Document complex logic with inline comments in Go code

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-10-30T13:25:45.965Z
Learnt from: osterman
Repo: cloudposse/atmos PR: 727
File: internal/exec/terraform_clean.go:405-412
Timestamp: 2024-10-30T13:25:45.965Z
Learning: In `internal/exec/terraform_clean.go`, when appending `stackFolders` to `folders` in the `handleCleanSubCommand` function, it's unnecessary to check if `stackFolders` is nil before appending, because in Go, appending a nil slice is safe and does not cause a panic.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : NEVER use `assert.Contains(err.Error(), ...)` for error checking. ALWAYS use `assert.ErrorIs()` instead. NEVER use string comparison: `err.Error() == "..."` or `strings.Contains(err.Error(), ...)`

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use `//revive:disable:file-length-limit`

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-02-06T13:38:07.216Z
Learnt from: Listener430
Repo: cloudposse/atmos PR: 984
File: internal/exec/copy_glob.go:0-0
Timestamp: 2025-02-06T13:38:07.216Z
Learning: The `u.LogTrace` function in the `cloudposse/atmos` repository accepts `atmosConfig` as its first parameter, followed by the message string.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-10-16T05:26:31.892Z
Learnt from: aknysh
Repo: cloudposse/atmos PR: 1639
File: pkg/merge/merge.go:392-430
Timestamp: 2025-10-16T05:26:31.892Z
Learning: In Atmos merge operations (pkg/merge/merge.go), context.Positions is a PositionMap (map[string]*schema.Position) keyed by JSONPath strings, not a slice indexed by input array position. Position lookups are path-based, making them independent of input array reorganization or filtering. This design allows filtering empty inputs without affecting provenance tracking correctness.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-09-10T22:38:42.212Z
Learnt from: Benbentwo
Repo: cloudposse/atmos PR: 1475
File: pkg/auth/identities/aws/user.go:141-145
Timestamp: 2025-09-10T22:38:42.212Z
Learning: ErrWrappingFormat is correctly defined as "%w: %w" in the errors package and is used throughout the codebase to wrap two error types together. The usage fmt.Errorf(errUtils.ErrWrappingFormat, errUtils.ErrAuthAwsFileManagerFailed, err) is the correct pattern when both arguments are error types.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2024-10-20T00:57:53.500Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 731
File: internal/exec/validate_stacks.go:0-0
Timestamp: 2024-10-20T00:57:53.500Z
Learning: In `internal/exec/validate_stacks.go`, when downloading the Atmos JSON Schema file to the temp directory, the temporary file is overwritten each time, so explicit removal is not necessary.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-03-17T18:41:08.831Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1085
File: pkg/config/imports.go:68-75
Timestamp: 2025-03-17T18:41:08.831Z
Learning: In the Atmos configuration import system, errors during config file merging are logged at debug level and the process continues with other imports rather than failing completely, prioritizing resilience over strict correctness.

Applied to files:

  • internal/exec/stack_processor_utils.go
📚 Learning: 2025-04-03T10:57:04.602Z
Learnt from: haitham911
Repo: cloudposse/atmos PR: 1091
File: pkg/config/load_config_args.go:61-82
Timestamp: 2025-04-03T10:57:04.602Z
Learning: In the Atmos configuration system, errors in `mergeDefaultImports` and `mergeImports` functions are intentionally only logged as debug messages without returning errors, as they are considered non-critical. Only errors in critical functions like `mergeConfigFile` are returned to halt execution.

Applied to files:

  • internal/exec/stack_processor_utils.go
🧬 Code graph analysis (5)
internal/exec/utils.go (2)
pkg/perf/perf.go (1)
  • Track (121-138)
pkg/logger/log.go (1)
  • Trace (14-16)
cmd/list/settings.go (1)
pkg/list/errors/types.go (1)
  • NoValuesFoundError (9-12)
cmd/list/metadata.go (3)
internal/exec/cli_utils.go (1)
  • ProcessCommandLineArgs (80-201)
pkg/config/config.go (1)
  • InitCliConfig (28-67)
cmd/list/flag_wrappers.go (6)
  • NewListParser (304-315)
  • WithFormatFlag (32-40)
  • WithStackFlag (126-133)
  • WithMetadataColumnsFlag (68-75)
  • WithSortFlag (149-156)
  • WithFilterFlag (137-144)
cmd/root.go (2)
pkg/terminal/terminal.go (6)
  • New (150-190)
  • ColorProfile (89-89)
  • ColorNone (92-92)
  • Color16 (93-93)
  • Color256 (94-94)
  • ColorTrue (95-95)
pkg/ui/formatter.go (1)
  • SetColorProfile (121-123)
cmd/list/values.go (2)
pkg/list/errors/types.go (1)
  • NoValuesFoundError (9-12)
cmd/list/flag_wrappers.go (5)
  • NewListParser (304-315)
  • WithFormatFlag (32-40)
  • WithDelimiterFlag (44-51)
  • WithStackFlag (126-133)
  • WithQueryFlag (230-237)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary

Comment on lines +206 to +212
// Stack filter (glob pattern).
if opts.Stack != "" {
globFilter, err := filter.NewGlobFilter("stack", opts.Stack)
if err == nil {
filters = append(filters, globFilter)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Silently swallowing glob pattern errors could confuse users.

If NewGlobFilter returns an error (e.g., invalid pattern), the filter isn't added but no feedback is provided. Users might think their --stack pattern is being applied when it's silently ignored.

Consider logging a warning or returning the error:

 	if opts.Stack != "" {
 		globFilter, err := filter.NewGlobFilter("stack", opts.Stack)
-		if err == nil {
+		if err != nil {
+			return nil // or log warning and continue
+		}
+		if globFilter != nil {
 			filters = append(filters, globFilter)
 		}
 	}

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 3 to 25
import (
"fmt"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/viper"

errUtils "github.com/cloudposse/atmos/errors"
e "github.com/cloudposse/atmos/internal/exec"
"github.com/cloudposse/atmos/pkg/config"
"github.com/cloudposse/atmos/pkg/flags"
"github.com/cloudposse/atmos/pkg/flags/global"
l "github.com/cloudposse/atmos/pkg/list"
"github.com/cloudposse/atmos/pkg/list/column"
"github.com/cloudposse/atmos/pkg/list/extract"
"github.com/cloudposse/atmos/pkg/list/filter"
"github.com/cloudposse/atmos/pkg/list/format"
"github.com/cloudposse/atmos/pkg/list/importresolver"
"github.com/cloudposse/atmos/pkg/list/renderer"
listSort "github.com/cloudposse/atmos/pkg/list/sort"
"github.com/cloudposse/atmos/pkg/list/tree"
log "github.com/cloudposse/atmos/pkg/logger"
"github.com/cloudposse/atmos/pkg/schema"
"github.com/cloudposse/atmos/pkg/ui"
"github.com/cloudposse/atmos/pkg/ui/theme"
u "github.com/cloudposse/atmos/pkg/utils"
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid fmt.Println for output; route through data.* instead

Per the project’s I/O guidelines, list output shouldn’t go directly to stdout via fmt.Println; it should go through the data helpers so it stays consistently pipeable and benefits from any future central behavior changes.

You can keep semantics and just swap to data.Writeln (or data.Write) and wire in the import:

-import (
-	"fmt"
+import (
+	"fmt"
@@
-	"github.com/cloudposse/atmos/pkg/list/tree"
+	"github.com/cloudposse/atmos/pkg/list/tree"
+	"github.com/cloudposse/atmos/pkg/data"
@@
-		// Render the tree.
-		// Use showImports from --provenance flag.
-		output := format.RenderStacksTree(importTrees, opts.Provenance)
-		fmt.Println(output)
+		// Render the tree.
+		// Use showImports from --provenance flag.
+		output := format.RenderStacksTree(importTrees, opts.Provenance)
+		data.Writeln(output)

This keeps behavior the same while aligning with the global output abstraction.

Also applies to: 228-231

🤖 Prompt for AI Agents
In cmd/list/stacks.go around lines 3-25 (and also update occurrences at
228-231), the code uses fmt.Println to write list output directly to stdout;
replace those direct fmt outputs with the project data helpers (e.g.,
data.Writeln or data.Write) and add the required import for the data package so
output is routed through the central I/O abstraction. Update each fmt.Println
call to the appropriate data.* call preserving the string/format semantics and
ensure the data package is imported at the top of the file.

Comment on lines +121 to +123
//nolint:gocognit,revive,cyclop,funlen // Complexity and length from necessary validation and format branching.
func listStacksWithOptions(cmd *cobra.Command, args []string, opts *StacksOptions) error {
// Early validation: --provenance only works with --format=tree.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

New nolint directives conflict with repo linting guidance

You’ve added:

  • //nolint:gocognit,revive,cyclop,funlen on listStacksWithOptions.
  • //nolint:nestif in the tree-format branch.

Project guidelines explicitly call out avoiding nolint for gocognit/cyclomatic complexity/nestif and preferring refactors instead, and also ask for explicit approval before adding new nolint comments.

A straightforward way to drop most of these would be to extract the tree-specific logic into a focused helper:

-func listStacksWithOptions(cmd *cobra.Command, args []string, opts *StacksOptions) error {
-    ...
-    //nolint:nestif // Nesting required for tree format handling.
-    if opts.Format == "tree" {
-        // provenance + tree rendering
-    }
-    ...
-}
+func listStacksWithOptions(cmd *cobra.Command, args []string, opts *StacksOptions) error {
+    ...
+    if opts.Format == string(format.FormatTree) {
+        return renderStacksTree(cmd, args, opts, stacks, stacksMap, &atmosConfig, authManager)
+    }
+    ...
+}
+
+func renderStacksTree(
+    cmd *cobra.Command,
+    args []string,
+    opts *StacksOptions,
+    stacks []map[string]any,
+    stacksMap map[string]any,
+    atmosConfig *schema.AtmosConfiguration,
+    authManager AuthManagerType, // adjust to actual type
+) error {
+    // existing tree/provenance logic moved here.
+}

That should bring cyclomatic complexity and length down enough to remove most of the nolints while keeping behavior identical.

If you intentionally want to keep the lint suppressions as-is, can you confirm that’s acceptable for this repo so they’re clearly an intentional exception?

Also applies to: 181-182

Comment on lines +1056 to 1087
//nolint:nestif // Nesting required for provenance tracking.
// Store merge context for imported files if provenance tracking is enabled.
if atmosConfig != nil && atmosConfig.TrackProvenance {
switch {
case result.mergeContext == nil:
log.Trace("Import has nil merge context", "import", result.importRelativePathWithoutExt)
case !result.mergeContext.IsProvenanceEnabled():
log.Trace("Import has merge context but provenance not enabled", "import", result.importRelativePathWithoutExt)
default:
log.Trace("Storing merge context for import", "import", result.importRelativePathWithoutExt, "chain_length", len(result.mergeContext.ImportChain))
SetMergeContextForStack(result.importRelativePathWithoutExt, result.mergeContext)

// Add imported files to parent merge context's import chain.
// The imported file's chain includes its own imports, so we take all files from it.
for _, importedFile := range result.mergeContext.ImportChain {
// Skip the first file if it's the same as the result's own file path (to avoid duplicates).
if len(result.mergeContext.ImportChain) > 0 && importedFile == result.mergeContext.ImportChain[0] {
// This is the imported file itself, add it only once.
if !u.SliceContainsString(mergeContext.ImportChain, importedFile) {
mergeContext.ImportChain = append(mergeContext.ImportChain, importedFile)
log.Trace("Added import to parent import chain", "file", importedFile)
}
} else {
// This is a nested import from the imported file.
if !u.SliceContainsString(mergeContext.ImportChain, importedFile) {
mergeContext.ImportChain = append(mergeContext.ImportChain, importedFile)
log.Trace("Added nested import to parent import chain", "file", importedFile)
}
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Refactor to eliminate nolint:nestif directive.

The coding guidelines explicitly forbid using nolint for nestif complexity: "NEVER add nolint for gocognit, cyclomatic complexity, magic numbers, or nestif - refactor instead." The provenance tracking logic at lines 1056-1087 should be extracted into a helper function to reduce nesting.

Consider extracting the provenance tracking and import chain propagation into a dedicated helper function:

// propagateImportChainToParent adds imported files from the result's merge context
// to the parent merge context's import chain, avoiding duplicates.
func propagateImportChainToParent(parentContext, resultContext *m.MergeContext, importPath string) {
    if resultContext == nil || !resultContext.IsProvenanceEnabled() {
        log.Trace("Import has nil or disabled merge context", "import", importPath)
        return
    }
    
    log.Trace("Storing merge context for import", "import", importPath, "chain_length", len(resultContext.ImportChain))
    SetMergeContextForStack(importPath, resultContext)
    
    // Add imported files to parent's import chain.
    for _, importedFile := range resultContext.ImportChain {
        if !u.SliceContainsString(parentContext.ImportChain, importedFile) {
            parentContext.ImportChain = append(parentContext.ImportChain, importedFile)
            
            // Log with context about whether this is the direct import or nested.
            if len(resultContext.ImportChain) > 0 && importedFile == resultContext.ImportChain[0] {
                log.Trace("Added import to parent import chain", "file", importedFile)
            } else {
                log.Trace("Added nested import to parent import chain", "file", importedFile)
            }
        }
    }
}

Then call it from line 1058:

if atmosConfig != nil && atmosConfig.TrackProvenance {
    propagateImportChainToParent(mergeContext, result.mergeContext, result.importRelativePathWithoutExt)
}
🤖 Prompt for AI Agents
internal/exec/stack_processor_utils.go lines 1056-1087: refactor the provenance
tracking block (which currently uses //nolint:nestif) into a small helper that
handles nil/disabled contexts, stores the merge context, and appends imported
files to the parent import chain without duplicates; remove the nolint comment,
add a function (e.g., propagateImportChainToParent) that accepts the parent
mergeContext, result.mergeContext and import path, move the
logging/SetMergeContextForStack and loop logic into it, and replace the original
nested if/switch with a single call to that helper when atmosConfig != nil &&
atmosConfig.TrackProvenance.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
errors/errors.go (1)

49-49: Consider more specific naming if ambiguity arises.

ErrInvalidConfig is intentionally generic for reusability across the rendering pipeline, but the file already has several specific config errors (ErrInvalidStackConfiguration, ErrInvalidBackendConfig, ErrInvalidAuthConfig). If you find callers wrapping this with similar context repeatedly, consider splitting into more specific sentinels like ErrInvalidColumnConfig or ErrInvalidFilterConfig.

cmd/list/list_test.go (1)

247-280: Interface contract test looks good.

The test correctly verifies that ListCommandProvider implements the CommandProvider interface with expected values. Using require.NotNil before accessing cmd.Use is appropriate defensive practice.

Consider verifying additional command properties if it adds value:

 t.Run("GetCommand returns listCmd", func(t *testing.T) {
   cmd := provider.GetCommand()
   require.NotNil(t, cmd)
   assert.Equal(t, "list", cmd.Use)
+  assert.NotEmpty(t, cmd.Commands(), "Expected list command to have subcommands")
 })

However, the current focused interface contract test is perfectly acceptable for the command registry pattern.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between db8d0e4 and deb451a.

📒 Files selected for processing (2)
  • cmd/list/list_test.go (2 hunks)
  • errors/errors.go (2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
cmd/**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

cmd/**/*.go: Use Cobra's recommended command structure with a root command and subcommands, implementing each command in a separate file under cmd/ directory
Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions
Provide meaningful feedback to users and include progress indicators for long-running operations in CLI commands

cmd/**/*.go: CLI command files must be thin wrappers that only handle CLI concerns (flags, arguments, command registration). All business logic must be delegated to pkg/ packages
Use flags.NewStandardParser() for command-specific flag parsing. NEVER call viper.BindEnv() or viper.BindPFlag() directly - use the unified pkg/flags/ infrastructure instead. Register flags with Cobra command and bind to Viper for precedence handling
All CLI commands MUST implement the CommandProvider interface and register via command registry pattern in cmd/internal/registry.go
Embed examples from cmd/markdown/*_usage.md using //go:embed. Render with utils.PrintfMarkdown()

Files:

  • cmd/list/list_test.go
**/*.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*.go: Use Viper for managing configuration, environment variables, and flags in CLI commands
Use interfaces for external dependencies to facilitate mocking and consider using testify/mock for creating mock implementations
All code must pass golangci-lint checks
Follow Go's error handling idioms: use meaningful error messages, wrap errors with context using fmt.Errorf("context: %w", err), and consider using custom error types for domain-specific errors
Follow standard Go coding style: use gofmt and goimports to format code, prefer short descriptive variable names, use kebab-case for command-line flags, and snake_case for environment variables
Document all exported functions, types, and methods following Go's documentation conventions
Document complex logic with inline comments in Go code
Support configuration via files, environment variables, and flags following the precedence order: flags > environment variables > config file > defaults
Provide clear error messages to users, include troubleshooting hints when appropriate, and log detailed errors for debugging

**/*.go: All comments must end with periods (enforced by godot linter)
Import organization: three groups separated by blank lines, sorted alphabetically: 1) Go stdlib, 2) 3rd-party (NOT cloudposse/atmos), 3) Atmos packages. Maintain aliases: cfg, log, u, errUtils
Add defer perf.Track(atmosConfig, "pkg.FuncName")() + blank line to all public functions. Use nil if no atmosConfig param
Keep files small and focused (<600 lines). One cmd/impl per file. Co-locate tests. Never use //revive:disable:file-length-limit
Use sentinel errors from errors/errors.go with ErrorBuilder for all user-facing errors. Use errors.Is() for checking errors, never string comparison. WithCause() preserves underlying error messages, WithExplanation() adds context, WithHint() provides guidance, WithContext() adds key-value pairs
Use context.Context as first parameter for: cancellation signals (prop...

Files:

  • cmd/list/list_test.go
  • errors/errors.go
**/*_test.go

📄 CodeRabbit inference engine (.cursor/rules/atmos-rules.mdc)

**/*_test.go: Every new feature must include comprehensive unit tests targeting >80% code coverage for all packages
Use table-driven tests for testing multiple scenarios in Go
Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

**/*_test.go: Use assert.ErrorIs(t, err, ErrSentinel) for checking our own errors and stdlib errors. Only use string matching for third-party errors
NEVER use assert.Contains(err.Error(), ...) for error checking. ALWAYS use assert.ErrorIs() instead. NEVER use string comparison: err.Error() == "..." or strings.Contains(err.Error(), ...)
Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid os.Exit, CheckErrorPrintAndExit, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios
Use go.uber.org/mock/mockgen with //go:generate directives for mock generation. Never create manual mocks. Pattern: //go:generate go run go.uber.org/mock/mockgen@latest -source=filename.go -destination=mock_filename_test.go
Use table-driven tests for comprehensive coverage. Tests must call actual production code, never duplicate logic. Target >80% test coverage (enforced by CodeCov)

Files:

  • cmd/list/list_test.go
cmd/**/*_test.go

📄 CodeRabbit inference engine (CLAUDE.md)

ALWAYS use cmd.NewTestKit(t) for cmd tests. This auto-cleans RootCmd state (flags, args) and is required for any test touching RootCmd

Files:

  • cmd/list/list_test.go
🧠 Learnings (11)
📓 Common learnings
Learnt from: Listener430
Repo: cloudposse/atmos PR: 934
File: tests/fixtures/scenarios/docs-generate/README.md.gotmpl:99-118
Timestamp: 2025-01-25T03:51:57.689Z
Learning: For the cloudposse/atmos repository, changes to template contents should be handled in dedicated PRs and are typically considered out of scope for PRs focused on other objectives.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1466
File: cmd/markdown/atmos_toolchain_aliases.md:2-4
Timestamp: 2025-09-13T16:39:20.007Z
Learning: In the cloudposse/atmos repository, CLI documentation files in cmd/markdown/ follow a specific format that uses " $ atmos command" (with leading space and dollar sign prompt) in code blocks. This is the established project convention and should not be changed to comply with standard markdownlint rules MD040 and MD014.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1533
File: pkg/config/load.go:585-637
Timestamp: 2025-09-27T20:50:20.564Z
Learning: In the cloudposse/atmos repository, command merging prioritizes precedence over display ordering. Help commands are displayed lexicographically regardless of internal array order, so the mergeCommandArrays function focuses on ensuring the correct precedence chain (top-level file wins) rather than maintaining specific display order.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 for unlimited width, which bypasses terminal width restrictions and may require horizontal scrolling. The default is 10 columns if not specified.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands supports -1 as a special value to display unlimited columns in table outputs.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands (values, settings, metadata) supports -1 as a special value to display unlimited columns in table outputs, with a default of 10 columns.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1036
File: cmd/list_settings.go:46-50
Timestamp: 2025-02-20T13:57:36.326Z
Learning: The max-columns flag in Atmos list commands (values, settings, metadata) supports -1 as a special value to display unlimited columns in table outputs. The default is 10 columns if not specified.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 1068
File: tests/snapshots/TestCLICommands_atmos_terraform_help.stdout.golden:59-64
Timestamp: 2025-02-18T13:13:11.497Z
Learning: For Atmos CLI help text, angle brackets in command examples and flag descriptions should be escaped using HTML entities (e.g., `&lt;component&gt;`) rather than converted to backticks or other markdown formatting.
Learnt from: samtholiya
Repo: cloudposse/atmos PR: 955
File: tests/snapshots/TestCLICommands_atmos_validate_editorconfig_--help.stdout.golden:0-0
Timestamp: 2025-01-19T15:49:15.593Z
Learning: In future commits, the help text for Atmos CLI commands should be limited to only show component and stack parameters for commands that actually use them. This applies to the example usage section in command help text.
Learnt from: RoseSecurity
Repo: cloudposse/atmos PR: 797
File: pkg/list/atmos.yaml:213-214
Timestamp: 2024-11-25T17:17:15.703Z
Learning: The file `pkg/list/atmos.yaml` is primarily intended for testing purposes.
Learnt from: osterman
Repo: cloudposse/atmos PR: 1498
File: website/src/components/Screengrabs/atmos-terraform-metadata--help.html:25-55
Timestamp: 2025-10-07T00:25:16.333Z
Learning: In Atmos CLI, subcommands inherit flags from their parent commands via Cobra's command inheritance. For example, `atmos terraform metadata --help` shows `--affected` and related flags inherited from the parent `terraform` command (defined in cmd/terraform.go), even though the metadata subcommand doesn't explicitly define these flags. This is expected Cobra behavior and auto-generated help screengrabs accurately reflect this inheritance.
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to **/*_test.go : Include integration tests for command flows and test CLI end-to-end when possible with test fixtures

Applied to files:

  • cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to cmd/**/*.go : All CLI commands MUST implement the CommandProvider interface and register via command registry pattern in `cmd/internal/registry.go`

Applied to files:

  • cmd/list/list_test.go
📚 Learning: 2025-11-24T17:35:37.209Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: .cursor/rules/atmos-rules.mdc:0-0
Timestamp: 2025-11-24T17:35:37.209Z
Learning: Applies to cmd/**/*.go : Provide comprehensive help text for all commands and flags, include examples in command help, and follow Go's documentation conventions in Cobra command definitions

Applied to files:

  • cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Use `assert.ErrorIs(t, err, ErrSentinel)` for checking our own errors and stdlib errors. Only use string matching for third-party errors

Applied to files:

  • cmd/list/list_test.go
  • errors/errors.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : Test behavior, not implementation. Never test stub functions - implement or remove. Avoid tautological tests. Make code testable using dependency injection to avoid `os.Exit`, `CheckErrorPrintAndExit`, external systems. Remove always-skipped tests - fix or delete. Table-driven tests must have real scenarios

Applied to files:

  • cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Use dependency injection and interface-driven design to make code testable - avoid `os.Exit`, `CheckErrorPrintAndExit`, and direct external system calls in testable functions

Applied to files:

  • cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*_test.go : NEVER use `assert.Contains(err.Error(), ...)` for error checking. ALWAYS use `assert.ErrorIs()` instead. NEVER use string comparison: `err.Error() == "..."` or `strings.Contains(err.Error(), ...)`

Applied to files:

  • cmd/list/list_test.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : Use sentinel errors from `errors/errors.go` with ErrorBuilder for all user-facing errors. Use `errors.Is()` for checking errors, never string comparison. `WithCause()` preserves underlying error messages, `WithExplanation()` adds context, `WithHint()` provides guidance, `WithContext()` adds key-value pairs

Applied to files:

  • errors/errors.go
📚 Learning: 2025-12-06T19:24:49.343Z
Learnt from: CR
Repo: cloudposse/atmos PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-06T19:24:49.343Z
Learning: Applies to **/*.go : New configs support Go templating with `FuncMap()` from `internal/exec/template_funcs.go`. Implement template functions in `internal/exec/template_funcs.go`, register them, add tests, and update documentation

Applied to files:

  • errors/errors.go
📚 Learning: 2025-06-02T14:12:02.710Z
Learnt from: milldr
Repo: cloudposse/atmos PR: 1229
File: internal/exec/workflow_test.go:0-0
Timestamp: 2025-06-02T14:12:02.710Z
Learning: In the atmos codebase, workflow error handling was refactored to use `PrintErrorMarkdown` followed by returning specific error variables (like `ErrWorkflowNoSteps`, `ErrInvalidFromStep`, `ErrInvalidWorkflowStepType`, `ErrWorkflowStepFailed`) instead of `PrintErrorMarkdownAndExit`. This pattern allows proper error testing without the function terminating the process with `os.Exit`, enabling unit tests to assert on error conditions while maintaining excellent user-facing error formatting.

Applied to files:

  • errors/errors.go
🧬 Code graph analysis (1)
cmd/list/list_test.go (1)
cmd/list/list.go (1)
  • ListCommandProvider (50-50)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Acceptance Tests (windows)
  • GitHub Check: Summary
🔇 Additional comments (2)
errors/errors.go (1)

48-48: LGTM!

Both ErrTemplateEvaluation and ErrNoStacksFound are well-placed within their respective error categories and have clear, actionable messages. The template error sits naturally with other template-related sentinels, and the stack error fits perfectly in the list package section.

Also applies to: 453-453

cmd/list/list_test.go (1)

8-8: LGTM – Import properly organized.

The require import is correctly placed in the 3rd-party section and used appropriately in the new test for assertions where subsequent code depends on non-nil values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor New features that do not break anything needs-cloudposse Needs Cloud Posse assistance size/xl Extra large size PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants