Skip to main content

All Insights

5 Suggestions to Upgrade your OpenTofu/Terraform & AWS Development Experience

Tools and scripts to help you reclaim your focus and speed up your workflow.

Share To

February 18, 2026

What if the best tools for your workflow are the ones you build yourself? This article presents five practical suggestions that demonstrate a powerful habit: investing time to automate tasks when friction becomes repetitive. From simple grep aliases that took minutes to create, to custom prompt configurations that display critical context at a glance, these examples show how small investments compound into hours saved every week. You'll see both off-the-shelf tools worth adopting and custom scripts you can adapt to your needs.

Author: Craig Reeder, Sr. Cloud Engineer

Over the years of working with OpenTofu, Terraform, and AWS CLI, I've tried to optimize my tooling and developer experience. Since I am a consultant and use AWS CLI and OpenTofu or Terraform on a daily basis, it's important to me that I have low friction between me and the work I need to perform. I often work with several different environments and clients in a given day.

The following is a collection of tools and scripts that I use and recommend to my coworkers and clients (and anyone else that will listen!). Some were found by looking for solutions, and others were created by me to solve friction I encountered on a regular basis.

Some technical notes:

  • Focus: This article covers OpenTofu and Terraform primarily, AWS secondarily. Most recommendations are cloud-neutral, though one is AWS-specific.
  • Platform: I develop on MacOS. All suggestions should work on Windows, though some may require translation to PowerShell, Git Bash, or WSL.

None of these tools are complex or groundbreaking, but they demonstrate a valuable habit: when you encounter the same problem repeatedly, invest time to automate it. Use these suggestions as inspiration to build your own toolbox.

1. Easily swap between OpenTofu/Terraform versions

tenv is the most valuable helper application in my toolbox. A natural successor to tfenv, this version helper supports OpenTofu, Terraform, and Terragrunt.

This eliminates the need to manually install or swap versions. In each root module, define an .opentofu-version or .terraform-version file with a valid HCL version string, and that version will be used every time!

Generally, my .opentofu-version file contains latest-allowed and then I specify a major and minor version in my terraform block's required_version, like this:

terraform {
 required_version = "~> 1.11.0" # OpenTofu
}

f you utilize the tf command that tenv installs, the version file is required to select the proper tool (OpenTofu or Terraform) and version for your projects.

2. Easily summarize OpenTofu/Terraform plans using grep

Through some simple usage of grep, you can get a suprisingly good summary of a plan action.

All plans boil down to strings that include "will" or "must" followed by "be". When dealing with a larger plan, it's useful to sometimes break this down into a summary.

grep -E "(will|must) be"

This can be used in an alias to make it easy to use when needed. Just put the following in your .bashrc or .zshrc:

alias tfsum='tf plan | grep -E "(will|must) be"'

You can see an example of the output in this image:

Note: This is not a replacement for reviewing a full plan, but is a good for a spot check.

3. Lint your code for common errors or bad practices

As of January 2026, the standard linting tool for OpenTofu/Terraform is tflint. In the future there may be a need for separate tools, as some newer OpenTofu-specific features may trigger errors in tflint.

While tflint provides a solid foundation, enabling additional plugins significantly enhances its capabilities, so make sure you enable the plugin for your relevant cloud platform.

To do that, you'll need to set some additional configuration in your home folder. You can also change the configuration to disable any rules that don't match your organization's standards.

What I recommend is to enable all rules and tune from there. I include the AWS plugin, but you can remove or swap that.

Create a file named .tflint.hcl in your home folder, and run tflint --init:

config {
  call_module_type = "all" # Inspect child modules, as well
}
# See Terraform Ruleset here:
# https://github.com/terraform-linters/tflint-ruleset-terraform/tree/main/docs/rules/
plugin "terraform" {
  enabled = true
  preset  = "all"
}
# See AWS Ruleset here:
# https://github.com/terraform-linters/tflint-ruleset-aws/tree/master/docs/rules
plugin "aws" {
  enabled = true
  version = "0.45.0" # This version needs updated periodically
  source  = "github.com/terraform-linters/tflint-ruleset-aws"
}

Note: You can also have custom .tflint.hcl files in projects or modules that you want custom configuration for. I recommend setting up this strict default in your home folder, and perhaps more lenient rules in a project if needed.

4. Easily switch between AWS Profiles

This one is AWS specific, but it's my favorite and the one I use the most as a consultant. When you need to work on multiple AWS environments or accounts, you will find yourself switching profiles on the AWS CLI often (or passing a profile flag to every command).

Thankfully, the AWS SDK and CLI support profile selection through environment variable. As a result, a tool like awsp can parse the AWS CLI config, and export an environment variable based on an interactive selection (AWS_PROFILE).

Once you have configured the tool, run awsp to get a selection of AWS profiles.

5. Show your Git Branch, OpenTofu/Terraform Workspace, and AWS Profile in your prompt

This requires a bit of customization and work depending on your environment setup, but the improvement it provides is invaluable.

See the following example of my Prompt in bash:

If you are using Zsh and Oh My Zsh, similar functionality is available through usage of the git, terraform, and awsplugins. This is the quick and easy route.

If you are using bash, you may need to build your own. Some pointers:

  • You can get your AWS Profile from AWS_PROFILE environment variable. See my aws-prompt.shhere.
  • You can get Git details from a helper script, thankfully included with the git project itself: See git-prompt.shhere. This one has lots of useful configuration options to show more than just current branch.
  • You can see the current OpenTofu/Terraform Workspace by just looking at what's in .terraform/environment, if it exists. See terraform-prompt.sh here.
  • You can combine all the above together into a script which you source in your .bashrc: See set-prompt.shhere

Bonus Suggestion: Automate bulk operations with Task

When you manage multiple OpenTofu/Terraform projects or work on monorepos with dozens of root modules, running the same commands across all of them becomes tedious. Task, sometimes called "go-task", provides a simple, cross-platform way to define and run tasks. It is a modern alternative to Make, with better syntax and built-in features.

Unlike shell scripts, Taskfiles are declarative definition files for Task that support features like dependency management, variable interpolation, and dry-run modes out of the box.

Simple Examples

Here's a basic Taskfile that wraps common Terraform operations:

version: "3"
tasks:
 fmt:
   desc: "Format all Terraform files"
   cmds:
     - tf fmt -recursive
 lint:
   desc: "Run tflint on the current module"
   cmds:
     - tflint --init
     - tflint

Run `task fmt` to format your code, or `task --list` to see all available tasks.

Advanced Example: Bulk Plan Summary

When working with multiple modules, I often need to know which ones have pending changes. Here's a task that runs tf plan across all modules and provides a consolidated summary:

version: "3"
set: [e, u, pipefail]
tasks:
 plan-summary:
   desc: "Run tf plan on all modules and summarize directories with changes"
   dir: '{{.USER_WORKING_DIR}}'
   cmds:
     - |
       echo "Finding Tf projects..."
       TF_DIRS=$(find . -type d -path '*/.terraform' -prune -o -type f -name '*.tf' -exec dirname {} \; | sort -u)
       if [ -z "$TF_DIRS" ]; then
         echo "❌ No matching directories found."
         exit 0
       fi
       CHANGED_DIRS=()
       ROOT_DIR=$(pwd)
       for dir in $TF_DIRS; do
         if ! cd "$dir"; then
           echo "Failed to cd into $dir"
           exit 1
         fi
         if ! tf init -input=false -no-color >/dev/null; then
           echo "❌ tf init failed in $dir"
           exit 1
         fi
         PLAN_OUTPUT=$(tf plan -input=false -no-color 2>&1)
         PLAN_EXIT=$?
         SUMMARY_LINE=$(echo "$PLAN_OUTPUT" | grep -E '^Plan: [0-9]+ to add, [0-9]+ to change, [0-9]+ to destroy\.' || true)
         OUTPUT_CHANGE=$(echo "$PLAN_OUTPUT" | grep -i -E '^\s*Changes to outputs:' || true)
         HAS_CHANGES=false
         HAS_OUTPUT_CHANGES=false
         if [ -n "$SUMMARY_LINE" ] && echo "$SUMMARY_LINE" | grep -qv 'Plan: 0 to add, 0 to change, 0 to destroy\.'; then
           HAS_CHANGES=true
         elif [ -n "$OUTPUT_CHANGE" ]; then
           HAS_OUTPUT_CHANGES=true
         fi
         if [ "$HAS_CHANGES" = true ]; then
           echo "$dir: 🚨 ${SUMMARY_LINE:-Changes detected}"
           CHANGED_DIRS+=("$dir")
         elif [ "$HAS_OUTPUT_CHANGES" = true ]; then
           echo "$dir: ⚠️ Output-only change detected"
           CHANGED_DIRS+=("$dir (outputs only)")
         else
           echo "$dir: ✅ No changes"
         fi
         cd "$ROOT_DIR" || exit 1
       done
       echo ""
       echo "========== Summary =========="
       if [ ${#CHANGED_DIRS[@]} -eq 0 ]; then
         echo "✅ No changes in any module"
       else
         echo "🚨 Changes detected in:"
         for d in "${CHANGED_DIRS[@]}"; do
           echo " - $d"
         done
       fi
   silent: true

Running task plan-summary gives you output like:

./environments/dev: ✅ No changes
./environments/staging: 🚨 Plan: 2 to add, 1 to change, 0 to destroy.
./environments/prod: ⚠️ Output-only change detected
========== Summary ==========
🚨 Changes detected in:
- ./environments/staging
- ./environments/prod (outputs only)

This saves enormous amounts of time when reviewing changes across multiple environments or when preparing for a deployment.

Closing Thoughts: Build Your Own Toolbox

The suggestions in this article share a common thread: automate repetitive or tedious tasks and frustrations. Each tool saves seconds or minutes per use, but those savings compound into hours over weeks and months.

The specific tools matter less than the habit. Each time you encounter the same problem or pattern, ask whether a shell alias, function, script, or tool could solve it permanently. The tfsum alias took minutes to create but saves time on every large plan review. The Taskfile plan-summary took an hour to build but now checks dozens of modules in seconds.

Your toolkit will evolve differently based on your workflow. Pay attention to where you feel friction, and chip away at it. Whether it's a two-line shell alias or a sophisticated Taskfile, every improvement compounds over time. Start small and build from there. I hope these suggestions gave you some new ideas or inspiration to improve your own experience.

About the Author

Craig is a Senior Cloud Engineer with over a decade of experience experience conjuring up scalable, secure cloud infrastructure. At UTurn Data Solutions, he leads the development of infrastructure-as-code and engineering best practices that power reliable, enterprise-grade systems. Outside of work, Craig is a hobby magician, bringing the same precision and creativity to sleight of hand that he brings to architecture. Whether orchestrating clouds or card tricks, he's always in pursuit of that perfect balance between technical rigor and a touch of magic.

Additional Insights