env0/terratag
env0/terratag has 1,058 GitHub stars and 50 forks. GitHot measured 0 stars in 24 hours. Last checked 2026-11-09 11:22 UTC. Last push 2026-11-02.
Terratag is a CLI tool that enables users of Terraform to automatically create and maintain tags across their entire set of AWS, Azure, and GCP resources
Measured star growth
- in 24h
- 0
- in 7 days
- Update delayed
- in 15 days
- Update delayed
- in 1 month
- Update delayed
Net star changes over overlapping periods, not daily totals. Missing measurements are left blank. Stars measure attention, not software quality.
README.md
OriginalTerratag is brought to you with ❤️ by
Let your team manage their own environment in AWS, Azure and Google.
Governed by your policies and with complete visibility and cost management.
What?
Terratag is a CLI tool allowing for tags or labels to be applied across an entire set of OpenTofu/Terraform files. Terratag will apply tags or labels to any AWS, GCP and Azure resources.
Terratag in action

Why?
Maintaining tags across your application is hard, especially when done manually. Terratag enables you to easily add tags to your existing IaC and benefit from some cross-resource tag applications you wish you had thought of when you had just started writing your OpenTofu/Terraform, saving you tons of time and making future updates easy. Read more on why tagging is important.
How?
Prerequisites
- OpenTofu 1.x or Terraform 0.12 through 1.x.
Usage
Install from homebrew:
brew install env0/terratag/terratagOr download the latest release binary .
Initialize Opentofu/Terraform modules to get provider schema and pull child modules:
tofu initterraform initRun Terratag
terratag -dir=foo/bar -tags={\"environment_id\": \"prod\"}or
terratag -dir=foo/bar -tags="environment_id=prod,some-tag=value"
Example Output
Before Terratag
|- aws.tf
|- gcp.tf
# aws.tf
provider "aws" {
version = "~> 2.0"
region = "us-east-1"
}
resource "aws_s3_bucket" "b" {
bucket = "my-tf-test-bucket"
acl = "private"
tags {
Name = "My bucket"
}
}
#gcp.tf
resource "google_storage_bucket" "static-site" {
name = "image-store.com"
location = "EU"
force_destroy = true
bucket_policy_only = true
website {
main_page_suffix = "index.html"
not_found_page = "404.html"
}
cors {
origin = ["http://image-store.com"]
method = ["GET", "HEAD", "PUT", "POST", "DELETE"]
response_header = ["*"]
max_age_seconds = 3600
}
labels = {
"foo" = "bar"
}
}
After Terratag
Running terratag -tags={\"env0_environment_id\":\"dev\",\"env0_project_id\":\"clientA\"} will output:
|- aws.terratag.tf
|- gcp.terratag.tf
|- aws.tf.bak
|- gcp.tf.bak
# aws.terratag.tf
provider "aws" {
version = "~> 2.0"
region = "us-east-1"
}
resource "aws_s3_bucket" "b" {
bucket = "my-tf-test-bucket"
acl = "private"
tags = merge( map("Name", "My bucket" ), local.terratag_added_main)
}
locals {
terratag_added_main = {"env0_environment_id"="dev","env0_project_id"="clientA"}
}
# gcp.terratag.tf
resource "google_storage_bucket" "static-site" {
name = "image-store.com"
location = "EU"
force_destroy = true
bucket_policy_only = true
website {
main_page_suffix = "index.html"
not_found_page = "404.html"
}
cors {
origin = ["http://image-store.com"]
method = ["GET", "HEAD", "PUT", "POST", "DELETE"]
response_header = ["*"]
max_age_seconds = 3600
}
labels = merge( map("foo" , "bar"), local.terratag_added_main)
}
locals {
terratag_added_main = {"env0_environment_id"="dev","env0_project_id"="clientA"}
}
Optional CLI flags
-dir=<path>- defaults to.. Sets the opentofu/terraform folder to tag.tfand.tofufiles in-skipTerratagFiles=false- Dont skip processing*.terratag.tfand*.terratag.tofufiles (when running terratag a second time for the same directory)-rename=false- Instead of replacing files named<basename>.tf(or.tofu) with<basename>.terratag.tf(or.terratag.tofu), keep the original filename-filter=<regular expression>- defaults to.*. Only apply tags to the resource types matched by the regular expression-skip=<regular expression>- defaults to empty (no exclusion). Exclude the resource types matched by the regular expression from tagging. Applied after-filter.-type=<terraform, terragrunt, or terragrunt-run-all>- defaults toterraform(andopentofu). Ifterragruntis used, tags the files under.terragrunt-cachefolder. Note: if Terragrunt does not create a.terragrunt-cachefolder, use the default or omit.-verbose- Turn on verbose logging-default-to-terraformBy default uses OpenTofu (if installed), if set will use Terraform even when Opentofu is installed--keep-existing-tags- When set, existing tags will be preserved when merging tags (by default, new tags override existing ones)
Setting options via environment variables is also supported. CLI flags have a precedence over environment variables.
TERRATAG_TAGS
TERRATAG_DIR
TERRATAG_SKIPTERRATAGFILES
TERRATAG_FILTER
TERRATAG_SKIP
TERRATAG_VERBOSE
TERRATAG_RENAME
TERRATAG_TYPE
TERRATAG_DEFAULT_TO_TERRAFORM
TERRATAG_KEEP_EXISTING_TAGS
Filtering resource types
Include only S3 and DynamoDB resources:
terratag -tags='{"env":"prod"}' -filter='aws_s3_bucket|aws_dynamodb_table'
Tag everything except IAM resources:
terratag -tags='{"env":"prod"}' -skip='^aws_iam_'
Combine both — tag all aws_* resources but skip IAM:
terratag -tags='{"env":"prod"}' -filter='^aws_' -skip='^aws_iam_'
See more samples here
Notes
- Resources already having the exact same tag as the one being appended will be overridden
- Supported providers
awsgoogleazurermazurestackazapi
Usage with Terragrunt
To use terratag with Terragrunt:
- Use
-type=terragruntfor a standard unit - Use
-type=terragrunt-run-allfor implicit stacks
Note: Explicit stacks are not explicitly supported. If you are working with an explicit stack, you may run terratag on each unit individually by using
-type=terragruntand-dir=<unit_path>. If your generated stack is similar to an implicit stack, you may use-type=terragrunt-run-allfrom the generated stack directory (.terragrunt-stackby default). Remember to initialize the units in the stack by either runningterragrunt stack run init, or runningterragrunt initin each unit beforehand.
If issues arise with new Terragrunt versions, please open an issue.
Develop
Issues and Pull Requests are very welcome!
Prerequisites
- Go ≥ 1.24.9
Build
git clone https://github.com/env0/terratag
cd terratag
go mod tidy
go build ./cmd/terratag
Test
Structure
The test cases are located under test/tests
Each test case placed there should have the following directory structure:
my_test
|+ input
... // any depth under /input
|- main.tf // this is where we will run all terraform/terratag commands
|- expected
inputis where you should place the terraform files of your test. All commands will be executed wherever down the hierarchy wheremain.tfis located. We do that to allow cases where complex nested submodule resolution may take place, and one would like to test how a directory higher up the hierarchy gets resolved.expectedis a directory in which all.terratag.tffiles will be matched with the output directory
Each terraform version has it's own config file containing the list of test suites to run.
The config file is under test/fixtures/terraform_xx/config.yaml where xx is the terraform version.
What's being tested?
Each test will run:
terraform initterratagterraform validate
And finally, will compare the results in out with the expected directory
Running Tests
Tests can only run on a specific Terraform version -
go test -run TestTerraformXX
We use tfenv to switch between versions. The exact versions used in the CI tests can be found under test/tfenvconf.
Release
- Create and push a tag locally, in semver format -
git tag v0.1.32 && git push origin --tags - Goto Github Releases and edit the draft created by Release Drafter Bot - it should contain the change log for the release (if not press on Auto-generate release notes). Make sure it's pointing at the tag you created in the previous step and publish the release.
- Binaries will be automatically generated by the Github action defined in
.github/workflows/release.yml - NPM will automatically pick up on the new version.
Explore related projects
codecrafters-io/build-your-own-x
Master programming by recreating your favorite technologies from scratch.
561,350 starspublic-apis/public-apis
A collective list of free APIs
497,601 starsmorluto/rea
Reverse engineer anything with agents, from app behavior down to native binaries.
446,856 starsopenclaw/openclaw
The AI that really does things. Any OS. Any Platform. The lobster way. 🦞
394,253 stars