Terraform version manager like tfenv but written in Go. Now supports Opentofu!
WARNING: This is my first project written in Go to learn it. It is inspired by
tfenv, but is written without inspecting the source, only documentation is used.
tfenvgo manages both Terraform and OpenTofu (tofu) side-by-side. Use the --flavor flag or the flavor command to switch between them.
Here are the reasons:
- Distributed as a single binary, easy to install.
min-requiredandlatest-alloweddon't have limitations astfenv:tfenvgouses real Go regex.- Ability to work with pre-release Terraform versions (see
--include-prereleaseflag). tfenvgois faster by around 50%.- Supports opentofu out of the box
Currently, tfenvgo supports the following OS and archs:
- Linux
- AMD64
- ARM64
- macOS
- AMD64
- ARM64
- Windows - Not supported and will not be
# Set OpenTofu as the persistent default
tfenvgo flavor tofu
# Install and activate the latest OpenTofu release
tfenvgo install latest
tfenvgo use latest
# Now ~/.tfenvgo/bin/tofu points to the installed binary
tofu version
# Override flavor for a single command without changing the default
tfenvgo install latest --flavor terraform
tfenvgo list --flavor terraformBoth flavors are fully isolated — installed versions live under separate directories and have independent active-version symlinks:
~/.tfenvgo/
├── flavor # persisted default: "tofu" or "terraform"
├── bin/
│ ├── terraform -> ../versions/terraform/1.5.7/terraform
│ └── tofu -> ../versions/tofu/1.8.0/tofu
└── versions/
├── terraform/1.5.7/terraform
└── tofu/1.8.0/tofu
--flavor <value>flag (highest priority)TFENVGO_FLAVORenvironment variable~/.tfenvgo/flavorfile (written bytfenvgo flavor <value>)terraform(built-in default)
Get or set the default binary flavor.
# Print the currently resolved flavor and where it comes from
tfenvgo flavor
# Persist "tofu" as the default for all future invocations
tfenvgo flavor tofu
# Switch back to terraform
tfenvgo flavor terraform- Get the latest release:
ARCH=$(uname -m); ARCH=${ARCH/x86_64/amd64}; curl -sSL "https://github.com/dmakeienko/tfenvgo/releases/download/$(curl -s "https://api.github.com/repos/dmakeienko/tfenvgo/releases" | jq -r '.[].tag_name' | head -1)/tfenvgo-$(curl -s "https://api.github.com/repos/dmakeienko/tfenvgo/releases" | jq -r '.[].tag_name' | head -1)-$(uname -s)-$ARCH.tar.gz" | tar xzf -OR
1.1 Download specific version:
VERSION="vX.Y.Z"
PLATFORM=$(uname -s)
ARCH=$(uname -m); ARCH=${ARCH/x86_64/amd64}
curl -LO https://github.com/dmakeienko/tfenvgo/releases/download/$VERSION/tfenvgo-$VERSION-$PLATFORM-$ARCH.tar.gz1.2 Then unarchive it:
tar -xvzf tfenvgo-$VERSION-$PLATFORM-$ARCH.tar.gz- Install
tfenvgointo any location that is in yourPATH:
sudo mv tfenvgo /usr/local/bin- Update your shell profile:
Add the following line to your shell config file:
export PATH=$PATH:$HOME/.tfenvgo/binOptionally, run:
tfenvgo initThis command will precreate the $HOME/.tfenvgo/bin folder structure.
Install a specific version of Terraform. If no parameter is passed, the version to install is resolved automatically via the TFENVGO_TERRAFORM_VERSION environment variable or .terraform-version file, in that order of precedence. If no argument is provided, it will default to the latest.
Available options:
x.y.z- Semver 2.0.0 string specifying the exact version to install.latest- Syntax to install the latest available stable version.latest-allowed- Syntax to scan your Terraform files to detect which version is maximally allowed.min-required- Syntax to scan your Terraform files to detect which version is minimally required.latest "regex"- Syntax to install the latest version matching the regex.
NOTE: because some symbols interpreted by shell as commands, use quotes (" or ') to specify regex. NOTE:
latest "regex"does not work with prerelease versions
Available flags:
--include-prerelease- Include prerelease versions when specifyinglatest, e.g., 1.12.0-alpha20250213, 0.12.0-rc1, etc.
Environment variables:
TFENVGO_ARCH- Specify to install the binary for a different architecture than your own.TFENVGO_OS_TYPE- Specify to install the binary for a different OS type than your own.
Switch to a specific version to use. If no parameter is passed, the version to use is resolved automatically via the TFENVGO_TERRAFORM_VERSION environment variable or .terraform-version file, in that order of precedence, defaulting to latest if none are found.
Available options:
x.y.z- Semver 2.0.0 string specifying the exact version to use.latest- Syntax to use the latest installed stable version.min-required- Syntax to scan your Terraform files to detect which version is minimally required.latest-allowed- Syntax to scan your Terraform files to detect which version is the latest allowed.latest "regex"- Syntax to install the latest version matching the regex.
NOTE: because some symbols interpreted by shell as commands, use quotes (" or ') to specify regex. NOTE:
latest "regex"does not work with prerelease versions
Uninstall a specific version of Terraform.
Available options:
x.y.z- Semver 2.0.0 string specifying the exact version to uninstall.latest- Syntax to uninstall the latest present version.latest "regex"- Syntax to install the latest version matching the regex.
NOTE: because some symbols interpreted by shell as commands, use quotes (" or ') to specify regex. NOTE:
latest "regex"does not work with prerelease versions
Available flags:
--include-prerelease- Include prerelease versions when specifyinglatest, e.g., 1.12.0-alpha20250213, 0.12.0-rc1, etc.
List all available Terraform versions installed locally. By default, it fetches only stable versions.
Available flags:
--include-prerelease- Include prerelease versions, e.g., 1.12.0-alpha20250213, 0.12.0-rc1, etc.
Get all available versions of Terraform from the Hashicorp release page. By default, it fetches only stable versions.
Available flags:
--include-prerelease- Include prerelease versions, e.g., 1.12.0-alpha20250213, 0.12.0-rc1, etc.
Write the current Terraform version set by tfenvgo to the .terraform-version file.
Display the current Terraform version set by tfenvgo.
TFENVGO_ARCH- Specifies the architecture. The default architecture is defined during compilation. Override to download the Terraform binary for another architecture.TFENVGO_OS_TYPE- Specifies the OS type. The default OS type is defined during compilation. Override to download the Terraform binary for another OS.TFENVGO_TERRAFORM_VERSION- If not an empty string, this variable overrides the Terraform version provided by the.terraform-versionfile and commandstfenvgo install,tfenvgo use.
If you put a .terraform-version file in your project root, tfenvgo detects it and uses the version written in it. If the version is latest or latest: "regex", the latest matching version will be selected.
NOTE: The
TFENVGO_TERRAFORM_VERSIONenvironment variable can be used to override the version specified by the.terraform-versionfile.
For tfenvgo to be able to detect the .terraform-version file, add the provided shell hook to your shell config (.zshrc or .bashrc):
cd() {
builtin cd "$@" || return
if [ -f ".terraform-version" ]; then
tfenvgo use
fi
}tfenvgo uses SemVer package to parse, sort and evaluate constraints.
There are multiple methods to handle ranges and the first is hyphens ranges. These look like:
1.2 - 1.4.5 which is equivalent to >= 1.2 <= 1.4.5
2.3.4 - 4.5 which is equivalent to >= 2.3.4 <= 4.5NOTE: 1.2-1.4.5 without whitespace is parsed completely differently; it's parsed as a single constraint 1.2.0 with prerelease 1.4.5.
The x, X, and * characters can be used as a wildcard character. This works for all comparison operators. When used on the = operator it falls back to the patch level comparison (see tilde below). For example,
1.2.x is equivalent to >= 1.2.0, < 1.3.0
>= 1.2.x is equivalent to >= 1.2.0
<= 2.x is equivalent to < 3
* is equivalent to >= 0.0.0The tilde (~) comparison operator is for patch level ranges when a minor version is specified and major level changes when the minor number is missing. For example,
~1.2.3 is equivalent to >= 1.2.3, < 1.3.0
~1 is equivalent to >= 1, < 2
~2.3 is equivalent to >= 2.3, < 2.4
~1.2.x is equivalent to >= 1.2.0, < 1.3.0
~1.x is equivalent to >= 1, < 2The caret (^) comparison operator is for major level changes once a stable (1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts as the API stability level. This is useful when comparisons of API versions as a major change is API breaking. For example,
^1.2.3 is equivalent to >= 1.2.3, < 2.0.0
^1.2.x is equivalent to >= 1.2.0, < 2.0.0
^2.3 is equivalent to >= 2.3, < 3
^2.x is equivalent to >= 2.0.0, < 3
^0.2.3 is equivalent to >=0.2.3 <0.3.0
^0.2 is equivalent to >=0.2.0 <0.3.0
^0.0.3 is equivalent to >=0.0.3 <0.0.4
^0.0 is equivalent to >=0.0.0 <0.1.0
^0 is equivalent to >=0.0.0 <1.0.0