Skip to content

ishuar/tfskel

Repository files navigation

Test GitHub Release License: MIT Stargazers Go Report Card codecov Go Version

tfskel logo

Simplified and predictable Terraform operations. Scale & Build infrastructure, not overhead!

tfskel

Warning

This project is in early development. APIs, commands, and configurations may introduce breaking changes between releases.

tfskel is a CLI tool that helps you run Terraform without the operational chaos.

It standardizes project structure, reduces drift, and makes plans easier to reason about, so you can spend less time managing Terraform and more time terraforming your infrastructure. No wrappers. No unnecessary abstraction. With tfskel Just well-structured, scalable Terraform that stays maintainable as you grow.

Why tfskel

Terraform itself isn’t hard. Managing it at scale is.

As infrastructure grows, so does the operational overhead — inconsistent folder structures, version drift, massive plan reviews, and environments slowly falling out of sync. Teams end up spending more time maintaining Terraform than actually building infrastructure.

tfskel removes that friction.

It gives you a clean, opinionated foundation that keeps your Terraform projects structured, consistent, and predictable from day one. Instead of reinventing layouts and fixing drift, you can focus on delivering Infrastructure as Code with confidence. No copy-paste cycles. No structural chaos. No hidden abstraction layers. Just well-organized, scalable Terraform — built to grow with your infrastructure.

tfskel is not a Terraform wrapper. It’s an operational discipline tool for Terraform.

Features

  1. Enforce consistent project structure across environments
  2. Scaffold Terraform code using clean, maintainable templates
  3. Upgrade generated files in-place when templates or config change (--upgrade)
  4. Preview changes safely with --dry-run before writing anything
  5. Detect AWS provider and Terraform version drift across the entire repo
  6. Analyze Terraform plans to make reviews easier and safer with custom resources severity
  7. Stay vanilla — no wrappers, no lock-in, just Terraform

Note

⭐️ If you find tfskel useful, consider starring the repo to stay updated and support the project. ⭐️

Demo

👉 Check out this ishuar/tfskel-demo#2 to see how to initialize a new terraform monorepo in just 4 steps and leverage the built-in GitHub Actions workflows:

Installation

Quick Install

  • Install a specific version (recommended)
curl -fsSL https://raw.githubusercontent.com/ishuar/tfskel/main/install.sh | TFSKEL_VERSION=<RELEASED_VERSION> bash
  • Install latest version
curl -fsSL https://raw.githubusercontent.com/ishuar/tfskel/main/install.sh | bash
  • Custom install directory
curl -fsSL https://raw.githubusercontent.com/ishuar/tfskel/main/install.sh | INSTALL_DIR=~/.local/bin bash

Install via Go

go install github.com/ishuar/tfskel@latest ## or released version

Make sure $HOME/go/bin is in your PATH.

Caution

This project is developed with AI assistance. Please review the code carefully and perform your own due diligence. Thank you 🙏

Quick Start

Global Flags

These flags are available on every tfskel command:

Flag Short Default Description
--config -c .tfskel.yaml (current dir) Path to config file; takes precedence over auto-discovery
--verbose -v false Enable verbose/debug output
--dry-run false Show what would happen without writing files
--no-color false Disable colored output (also respects NO_COLOR, FORCE_COLOR, and CI env vars)
--version Print tfskel version, commit, and build info (same output as tfskel version)

tfskel version

Prints the installed tfskel version along with the build commit, OS/arch, and — for official release builds — a link to the GitHub release page.

tfskel version

tfskel init

Initializes a new Terraform monorepo with an environment-and-region-based directory layout (dev/stg/prd) with sensible defaults already in place — .gitignore, .pre-commit-config.yaml, .tflint.hcl, trivy.yaml, .tfskel.yaml, and per-environment .terraform-version files. The same structure, every time, across every project.

If a .tfskel.yaml already exists in the target directory, init reads environments from provider.aws.account_mapping and regions from provider.aws.regions, so your existing configuration drives the scaffold.

With --workflows, also generates the shared GitHub Actions reusable workflow files (lint.yaml, reusable-detect-changes.yaml, reusable-terraform-plan-apply.yaml, reusable-lint.yaml) under .github/workflows/. This can also be enabled via workflows.create: true in .tfskel.yaml.

Flag Short Default Description
--dir -d current directory Directory to initialize
--workflows false Generate shared GitHub Actions reusable workflow files
--upgrade false Re-render init-managed files with latest embedded templates
--force false With --upgrade, overwrite files even without source markers
# Initialize in the current directory
tfskel init

# Initialize in a specific directory
tfskel init --dir /path/to/your/project

# Initialize with an explicit config file
tfskel init --config /path/to/config.yaml

# Also generate shared GitHub Actions workflow files
tfskel init --workflows

# Re-render init files (e.g. .pre-commit-config.yaml, .tflint.hcl) from latest templates
tfskel init --upgrade

# Force overwrite all init files, even those without source markers
tfskel init --upgrade --force

# Preview what init would create/upgrade without writing files
tfskel init --dry-run

tfskel init demo

tfskel scaffold

It accepts any subcommand as an input for target app-dir and creates per-application root module directories with a pre-configured backend.tf (S3 with state locking and encryption) and a versions.tf with pinned Terraform and AWS provider versions. You can extend this with your own .tmpl files — any custom template you place in your templates directory is processed alongside the built-in defaults; if the same filename is provided, the custom template takes precedence.

Flag Short Default Description
--env -e (required) Target environment (e.g. dev, stg, prd)
--region -r (required) AWS region (e.g. us-east-1, eu-central-1)
--templates-dir "" Directory containing custom .tmpl template files
--s3-bucket-name "" S3 bucket name for Terraform state (overrides config)
--upgrade false Re-render existing files from updated templates (only files with source markers)
--force false With --upgrade, overwrite files even without source markers
# Scaffold structure for an app in dev/us-east-1
tfskel scaffold myapp --env dev --region us-east-1

# Scaffold with a custom templates directory
tfskel scaffold myapp --env stg --region eu-central-1 --templates-dir ./templates

# Override S3 bucket name at runtime
tfskel scaffold myapp --env prd --region us-east-1 --s3-bucket-name my-tf-state-bucket

# Scaffold with a custom config file
tfskel scaffold myapp --config ./my-config.yaml --env dev --region us-east-1

# Using the short alias
tfskel sc myapp --env dev --region us-east-1

# Re-render scaffolded files after updating templates or config
tfskel scaffold myapp --env dev --region us-east-1 --upgrade

# Force overwrite all scaffolded files, even without source markers
tfskel scaffold myapp --env dev --region us-east-1 --upgrade --force

# Dry-run: see what scaffold would do without writing
tfskel scaffold myapp --env dev --region us-east-1 --dry-run

tfskel scaffold workflows

Generates a per-environment GitHub Actions Terraform plan/apply caller workflow. Run this once per environment after tfskel init --workflows has created the shared reusable workflow files.

Flag Short Default Description
--env -e (required) Target environment (e.g. dev, stg, prd)
--upgrade false Re-render existing workflow files from updated templates
--force false With --upgrade, overwrite workflow files even without source markers
# Generate a per-env Terraform workflow for dev
tfskel scaffold workflows --env dev

# Generate with a custom config file
tfskel scaffold workflows --env prd --config ./my-config.yaml

# Re-render an existing workflow after config changes
tfskel scaffold workflows --env dev --upgrade

Generated file: .github/workflows/<env>-<name>.yaml

Note

workflows.name is a plain string (Go template syntax is not supported). The environment prefix and .yaml extension are added automatically. Example: with name: "terraform" and --env dev, the file will be dev-terraform.yaml.

tfskel scaffold demo

tfskel validate

Checks whether your project is in sync with .tfskel.yaml by running two validation checks: config drift detection (Terraform/provider version constraints and .terraform-version files) and tool installation status (compared against .mise.toml).

Flag Short Default Description
--skip Comma-separated checks to skip (config, tools)
--format -f table Output format: table, json, csv
--no-color false Disable colored output

Exit codes:

Code Meaning
0 All checks pass
1 Findings detected (drift or tool issues)
2 Execution errors
# Run all checks
tfskel validate

# Skip tool checks
tfskel validate --skip tools

# JSON output for CI/CD pipelines
tfskel validate --format json

# Generate a CSV report without ANSI colors
tfskel validate --format csv --no-color > validate-report.csv

tfskel validate demo

tfskel review plan

Reads a plan.json file, summarizes resource changes, flags high-severity updates based on a configurable list of critical resources, and produces a structured report. Output can be exported as CSV, table, or JSON for reporting.

Flag Short Default Description
--json-file (required) Path to the Terraform plan JSON file
--format -f table Output format: table, json, csv
--no-color false Disable colored output

Exit codes:

Code Meaning
0 No changes — infrastructure is up to date
1 Non-critical changes detected (additions or modifications)
2 Critical changes detected (deletions or replacements)
# Generate and analyze a Terraform plan
terraform plan -out plan.bin
terraform show -json plan.bin > plan.json
tfskel review plan --json-file plan.json

# Export as CSV for reporting
tfskel review plan --json-file plan.json --format csv

# JSON output without colors (suitable for log files)
tfskel review plan --json-file plan.json --format json --no-color

tfskel review plan demo

Upgrading Generated Files

tfskel embeds source markers (e.g. ## tfskel-source: {...}) in every generated file (except .terraform-version). These markers record which template produced the file and its content hash, enabling safe, selective re-rendering with --upgrade. After each scaffold or scaffold workflows run, tfskel prints an operation summary (e.g. 2 files created, 1 file skipped).

Tip

For more details on source markers, metadata tracking, and selective upgrade whitelists, see the tfskel book.

Configuration

Create a .tfskel.yaml in your project root to customize defaults:

Tip

Use .tfskel.example.yaml for a full annotated reference. Configuration precedence: CLI flags → config file → defaults

Template context variables

The following config fields accept Go template syntax: backend.s3.bucket_name, workflows.aws_role_arn, and workflows.aws_role_name.

All placeholders are populated from the tfskel scaffold invocation:

Placeholder Source Description Example value
{{.AppDir}} <app-dir> argument to tfskel scaffold Application directory name. Path separators / are replaced with - in filenames. myapp, base-infra-ecs
{{.Env}} --env / -e flag Target environment. dev, stg, prd
{{.Region}} --region / -r flag Full AWS region name. eu-central-1, us-east-1
{{.ShortRegion}} Derived from --region / -r flag Abbreviated region (e.g. eu-central-1euc1). euc1, use1
{{.AccountID}} provider.aws.account_mapping[.Env] AWS account ID for the target environment. 123456789012
{{.S3BucketName}} backend.s3.bucket_name (post-render) Resolved S3 bucket name after template rendering. my-tfstate-bucket
{{.TerraformVersion}} terraform_version in config Terraform version constraint. ~> 1.13
{{.AWSProviderVersion}} provider.aws.version in config AWS provider version constraint. ~> 6.0
{{.AWSRoleArn}} Resolved from aws_role_arn / aws_role_name Final IAM role ARN used in workflow files. arn:aws:iam::123456789012:role/dev-githubactionsrole
{{.WorkflowFileName}} Auto-generated Rendered workflow filename (used for self-reference in workflow on: triggers). dev-terraform.yaml

Template functions

In addition to the standard Go text/template built-ins, additional template functions are available in all templated config values.

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have any suggestion that would make this project better, feel free to fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement" with your suggestion.

Tip

See CONTRIBUTING.md for guidelines.

  1. Fork the repository on GitHub
  2. Clone your fork and create a new branch
  3. Make your changes
  4. Run tests and checks
  5. Push your branch and open a pull request
git clone https://github.com/<your-username>/tfskel.git
cd tfskel
git checkout -b my-feature-branch
make test   # Run tests
make check  # Run all quality checks

Important

Please keep your pull requests small and focused. This will make it easier to review and merge.

License

Released under MIT LICENSE

Back To Top ⬆️

About

CLI tool to reduce Terraform operational complexity and enable scalable Infrastructure as Code.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Languages