<!-- BADGES -->
<p align="center">
  <a href="https://github.com/tofuutils/tenv/releases"><img src="https://img.shields.io/github/v/release/tofuutils/tenv?style=for-the-badge" alt="Github release"></a>
  <a href="https://github.com/tofuutils/tenv/graphs/contributors"><img src="https://img.shields.io/github/contributors/tofuutils/tenv?style=for-the-badge" alt="Contributors"></a>
  <img src="https://img.shields.io/maintenance/yes/2026.svg?style=for-the-badge" alt="maintenance status">
  <a href="https://goreportcard.com/report/github.com/tofuutils/tenv/"><img src="https://img.shields.io/badge/go%20report-A+-brightgreen.svg?style=for-the-badge" alt="Go report"></a>
  <a href="https://codecov.io/gh/tofuutils/tenv"><img src="https://img.shields.io/codecov/c/github/tofuutils/tenv?token=BDU9X0BAZV&style=for-the-badge" alt="codecov"></a>
</p>


<!-- LOGO -->
<br />
<div align="center">
  <a>
    <img src="assets/logo.png" alt="Logo" width="200" height="200">
  </a>
  <h3 align="center">tenv</h3>
  <p align="center">
    OpenTofu, Terraform, Terragrunt, Terramate and Atmos version manager, written in Go.
    <br />
    ·
    <a href="https://github.com/tofuutils/tenv/issues/new?assignees=&labels=issue%3A+bug&projects=&template=bug_report.md&title=">Report Bug</a>
    ·
    <a href="https://github.com/tofuutils/tenv/issues/new?assignees=&labels=&projects=&template=feature_request.md&title=">Request Feature</a>
    ·
  </p>
</div>

<p align="center">
    <a href="https://devhunt.org/tool/tenv" title="DevHunt - Tool of the Week"><img src="./assets/devhunt-badge.png" width=160 alt="DevHunt - Tool of the Week" /></a>
</p>

<a id="about-the-project"></a>
## About The Project

Welcome to **tenv**, a versatile version manager for [OpenTofu](https://opentofu.org),
[Terraform](https://www.terraform.io/), [Terragrunt](https://terragrunt.gruntwork.io/), [Terramate](https://terramate.io/) and
[Atmos](https://atmos.tools), written in Go. Our tool simplifies the complexity of handling different versions of these powerful tools, ensuring developers and DevOps professionals can focus on what matters most - building and deploying efficiently.

**tenv** is a successor of [tofuenv](https://github.com/tofuutils/tofuenv) and [tfenv](https://github.com/tfutils/tfenv).

<a id="key-features"></a>
### Key Features

- Versatile version management: Easily switch between different versions of OpenTofu,
Terraform, Terragrunt, Terramate and Atmos.
- [Semver 2.0.0](https://semver.org/) Compatibility: Utilizes [go-version](https://github.com/hashicorp/go-version) for semantic versioning and use the [HCL](https://github.com/hashicorp/hcl) parser to extract required version constraint from OpenTofu/Terraform/Terragrunt files (see [required_version](#required_version) and [Terragrunt hcl](#terragrunt-hcl-file)).
- Signature verification: Supports [cosign](https://github.com/sigstore/cosign) (if present on your machine) and PGP (via [gopenpgp](https://github.com/ProtonMail/gopenpgp)), see [signature support](#signature-support).
- Intuitive installation: Simple installation process with Homebrew and manual options.
- Callable as [Go](https://go.dev) module, with a [Semver compatibility promise](https://semver.org/#summary) on [tenvlib](https://github.com/tofuutils/tenv/tree/main/versionmanager/tenvlib) wrapper package (get more information in [TENV_AS_LIB.md](https://github.com/tofuutils/tenv/blob/main/TENV_AS_LIB.md)).

<a id="difference-with-asdf"></a>
### Difference with asdf

[asdf-vm](https://asdf-vm.com/) share the same goals than **tenv** : simplify the usage of several version of tools.

asdf-vm is generic and extensible with a plugin system, key **tenv** differences :
- **tenv** is more specific and has features dedicated to OpenTofu, Terraform, Terragrunt, Terramate 
and Atmos, like [HCL](https://github.com/hashicorp/hcl) parsing based detection (see [Key Features](#key-features)).
- **tenv** is distributed as independent binaries and does not rely on any shell or other CLI executable.
- **tenv** does better in terms of performance and platform compatibility. It works uniformly across all modern operating systems,
including Linux, MacOS, Windows, BSD, and Solaris, whereas asdf-vm natively supports only Linux and MacOS.
- **tenv** checks the sha256 checksum and the signature of the checksum file with [cosign](https://github.com/sigstore/cosign). Check [Signature support](#signature-support) section for getting more information about it.
- **tenv** command compatibility: In nearly all places you can use the exact syntax that works in tfenv / tofuenv.
If you're coming from tfenv/tofuenv and comfortable with that way of working you can almost always use the same syntax with tenv.
- **tenv** performance: It sounds incredibly useful, though it might be tough to get a real apples to apples comparison since the
tools work differently in a lot of ways. The author of asdf did a great writeup of performance problems.

<a id="table-of-contents"></a>
## Table of Contents
<!-- TABLE OF CONTENTS -->
<details markdown="1">
  <summary>Table of Contents</summary>
  <ol>
    <li>
      <a href="#about-the-project">About The Project</a>
      <ul>
        <li><a href="#key-features">Key Features</a></li>
        <li><a href="#difference-with-asdf">Difference with asdf</a></li>
      </ul>
    </li>
    <li>
        <a href="#table-of-contents">Table of contents</a>
    </li>
    <li>
      <a href="#getting-started">Getting Started</a>
      <ul>
        <li><a href="#prerequisites">Prerequisites</a></li>
        <li><a href="#installation">Installation</a></li>
      </ul>
    </li>
    <li><a href="#usage">Usage</a></li>
    <li><a href="#environment-variables">Environment variables</a></li>
    <li><a href="#version-files">Version files</a></li>
    <li><a href="#technical-details">Technical details</a></li>
    <li><a href="#verifying-signature">Verifying tenv Signatures</a></li>
    <li><a href="#contributing">Contributing</a></li>
    <li><a href="#community">Community</a></li>
    <li><a href="#authors">Authors</a></li>
    <li><a href="#licence">Licence</a></li>
  </ol>
</details>


<a id="getting-started"></a>
## Getting Started

<a id="prerequisites"></a>
### Prerequisites
If you need to enable cosign checks, install `cosign` (v.2.0+) tool via one of the following commands:

<details markdown="1"><summary><b>MacOS (Homebrew, MacPorts)</b></summary><br>

Installation via Homebrew:
```sh
brew install cosign
```

Installation via MacPorts:
```sh
sudo port install cosign
```

</details>


<details markdown="1"><summary><b>Windows (go install)</b></summary><br>

```sh
go install github.com/sigstore/cosign/v2/cmd/cosign@latest
```

</details>

<details markdown="1"><summary><b>Alpine Linux</b></summary><br>

```sh
apk add cosign
```

</details>

<details markdown="1"><summary><b>Arch Linux</b></summary><br>

```sh
sudo pacman -S cosign
```

</details>

<details markdown="1"><summary><b>Linux: RPM</b></summary><br>

```sh
LATEST_VERSION=$(curl https://api.github.com/repos/sigstore/cosign/releases/latest | jq -r .tag_name | tr -d "v")
curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign-${LATEST_VERSION}-1.x86_64.rpm"
sudo rpm -ivh cosign-${LATEST_VERSION}-1.x86_64.rpm
```

</details>
<details markdown="1"><summary><b>Linux: dkpg</b></summary><br>

```sh
LATEST_VERSION=$(curl https://api.github.com/repos/sigstore/cosign/releases/latest | jq -r .tag_name | tr -d "v")
curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign_${LATEST_VERSION}_amd64.deb"
sudo dpkg -i cosign_${LATEST_VERSION}_amd64.deb
```

</details>


<a id="installation"></a>
### Installation

<a id="automatic-installation"></a>
#### Automatic Installation
<details markdown="1"><summary><b>Arch Linux (AUR, Nix)</b></summary><br>

This package is available on the Arch Linux User Repository.
It can be installed using the yay AUR helper:
```sh
yay tenv-bin
```

Installation via Nix package manager:
```sh
nix-env -i tenv
```

</details>

<details markdown="1"><summary><b>MacOS (Homebrew, MacPorts, Nix)</b></summary><br>

Installation via Homebrew:
```console
brew install tenv
```

Installation via MacPorts:
```console
sudo port install tenv
```

Installation via Nix package manager:
```console
nix-env -i tenv
```

</details>

<details markdown="1"><summary><b>Windows (Chocolatey, Scoop etc.)</b></summary><br>

Installation via Chocolatey:
```console
choco install tenv
```

Installation via Scoop:
```console
scoop install tenv
```

Installation via Nix package manager:
```console
nix-env -i tenv
```

Installation via WinGet package manager:
```console
winget install Tofuutils.Tenv
```

</details>

<details markdown="1"><summary><b>Linux: Snapcraft</b></summary><br>

```sh
snap install tenv
```

</details>

<details markdown="1"><summary><b>Alpine</b></summary><br>

```sh
apk add tenv --repository=http://dl-cdn.alpinelinux.org/alpine/edge/testing/
```

#### Installation via Cloudsmith Artifact Management platform.

Setup Cloudsmith repository [automatically](https://help.cloudsmith.io/docs/alpine-repository#public-repositories):
```sh
sudo apk add --no-cache bash
curl -1sLf 'https://dl.cloudsmith.io/public/tofuutils/tenv/cfg/setup/bash.alpine.sh' | sudo bash
```
Install via apk:
```sh
apk add tenv
```

</details>

<details markdown="1"><summary><b>Ubuntu</b></summary><br>

#### Install via dpkg

```sh
LATEST_VERSION=$(curl --silent https://api.github.com/repos/tofuutils/tenv/releases/latest | jq -r .tag_name)
curl -O -L "https://github.com/tofuutils/tenv/releases/latest/download/tenv_${LATEST_VERSION}_amd64.deb"
sudo dpkg -i "tenv_${LATEST_VERSION}_amd64.deb"
```

#### Install via Nix
Installation via Nix package manager:
```console
nix-env -i tenv
```

#### Installation via Cloudsmith Artifact Management platform.
Setup Cloudsmith repository [automatically](https://help.cloudsmith.io/docs/debian-repository#public-repositories):
```sh
curl -1sLf 'https://dl.cloudsmith.io/public/tofuutils/tenv/cfg/setup/bash.deb.sh' | sudo bash
```
Install via apt:
```sh
sudo apt install tenv
```

</details>

<details markdown="1"><summary><b>RedHat</b></summary><br>

#### Installation via Cloudsmith Artifact Management platform.
Setup Cloudsmith repository [automatically](https://help.cloudsmith.io/docs/redhat-repository#public-repositories):
```sh
curl -1sLf 'https://dl.cloudsmith.io/public/tofuutils/tenv/cfg/setup/bash.rpm.sh' | sudo bash
```
Install via yum:
```sh
sudo yum install tenv
```

</details>

<details markdown="1"><summary><b>NixOS</b></summary>

#### nix-env

```sh
nix-env -iA nixos.tenv
```

#### NixOS Configuration
Add the following Nix code to your NixOS Configuration, usually located in /etc/nixos/configuration.nix
```console
environment.systemPackages = [
    pkgs.tenv
  ];
```
#### nix-shell

```sh
nix-shell -p tenv
```
</details>

<a id="manual-installation"></a>
#### Manual Installation
Get the most recent packaged binaries (`.deb`, `.rpm`, `.apk`, `pkg.tar.zst `, `.zip` or `.tar.gz` format) by visiting the [release page](https://github.com/tofuutils/tenv/releases). After downloading, unzip the folder and seamlessly integrate it into your system's `PATH`.

<a id="docker-installation"></a>

#### Docker Installation

You can use dockerized version of tenv via the following command:

```sh
docker run -it --rm tofuutils/tenv:latest help
```
The docker container is not meant as a way to run tenv for CI pipelines, for local use, you should use one of the [packaged binaries](#manual-installation).
<a id="usage"></a>

<a id="shell-completion"></a>
### Install shell completion

> [!NOTE]
> If you install tenv via Brew, MacPorts, or Nix, completion will be installed automatically.

<details markdown="1"><summary><b>zsh</b></summary><br>

```console
tenv completion zsh > ~/.tenv.completion.zsh
echo "source \$HOME/.tenv.completion.zsh" >> ~/.zshrc
```
</details>

<details markdown="1"><summary><b>Oh My Zsh</b></summary><br>

```console
tenv completion zsh > ~/.oh-my-zsh/completions/_tenv
```

Make sure the completions folder `~/.oh-my-zsh/completions` is listed under `$fpath`:

```console
print -l $fpath
```
</details>

<details markdown="1"><summary><b>powershell</b></summary><br>

```console
tenv completion powershell | Out-String | Invoke-Expression
```
</details>

<details markdown="1"><summary><b>bash</b></summary><br>

```console
tenv completion bash > ~/.tenv.completion.bash
echo "source \$HOME/.tenv.completion.bash" >> ~/.bashrc
```
</details>

<details markdown="1"><summary><b>fish</b></summary><br>

```console
tenv completion fish > ~/.tenv.completion.fish
echo "source \$HOME/.tenv.completion.fish" >> ~/.config/fish/config.fish
```
</details>

## Usage

**tenv** supports [OpenTofu](https://opentofu.org),
[Terraform](https://www.terraform.io/), [Terragrunt](https://terragrunt.gruntwork.io/), [Terramate](https://terramate.io/) and
[Atmos](https://atmos.tools). To manage each binary you can use `tenv <tool> <command>`. Below is a list of tools and commands that use actual subcommands:

| tool (alias)        | env vars                   | description                                    |
| ------------------- | -------------------------- | ---------------------------------------------- |
| `tofu` (`opentofu`) | [TOFUENV_](#tofu-env-vars) | [OpenTofu](https://opentofu.org)               |
| `tf` (`terraform`)  | [TFENV_](#tf-env-vars)     | [Terraform](https://www.terraform.io/)         |
| `tg` (`terragrunt`) | [TG_](#tg-env-vars)        | [Terragrunt](https://terragrunt.gruntwork.io/) |
| `tm` (`terramate`)  | [TM_](#tm-env-vars)        | [Terramate](https://terramate.io/)             |
| `at` (`atmos`)      | [ATMOS_](#atmos-env-vars)  | [Atmos](https://atmos.tools)                   |


Without subcommand `tenv` display interactive menus to manage tools and their versions.
<p align="center">
  <a href="https://asciinema.org/a/670790">
    <img alt="tenv interactive" src="https://raw.githubusercontent.com/tofuutils/tenv/main/assets/tenv.gif" width="100%">
  </a>
</p>

<details markdown="1"><summary><b>tenv &lt;tool&gt; install [version]</b></summary><br>

Install a requested version of the tool (into `TENV_ROOT` directory from `<TOOL>_REMOTE` url).

Without a parameter, the version to use is resolved automatically (see resolution order in [tools description](#technical-details), with `latest` as default in place of `latest-allowed`).

If a parameter is passed, available options include:

- an exact [Semver 2.0.0](https://semver.org/) version string to install.
- a [version constraint](https://opentofu.org/docs/language/expressions/version-constraints) string (checked against versions available at `<TOOL>_REMOTE` url).
- `latest`, `latest-stable` (old name of `latest`) or `latest-pre` (include unstable version), which are checked against versions available at `<TOOL>_REMOTE` url.
- `latest:<re>` or `min:<re>` to get first version matching with `<re>` as a [regexp](https://github.com/google/re2/wiki/Syntax) after a descending or ascending version sort.
- `latest-allowed` or `min-required` to scan your IAC files to detect which version is maximally allowed or minimally required. See [required_version](#required_version) docs.

```console
tenv tofu install
tenv tofu install 1.6.0-beta5
tenv tf install "~> 1.6.0"
tenv tf install latest-pre
tenv tg install latest
tenv tg install latest-stable
tenv atmos install "~> 1.70"
tenv atmos install latest
tenv <tool> install latest-allowed
tenv <tool> install min-required
```

A complete display :

```console
$ tenv tofu install 1.6.0
Installing OpenTofu 1.6.0
Fetching release information from https://api.github.com/repos/opentofu/opentofu/releases/tags/v1.6.0
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_linux_amd64.zip
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS.sig
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS.pem
Installation of OpenTofu 1.6.0 successful
```

</details>


<details markdown="1"><summary><b>tenv &lt;tool&gt; use  &lt;version&gt;</b></summary><br>

Switch the default tool version to use (set in `TENV_ROOT/<TOOL>/version` file).

`tenv <tool> use` has a `--working-dir`, `-w` flag to write a [version file](#version-files) in working directory.

Available parameter options:

- an exact [Semver 2.0.0](https://semver.org/) version string to use.
- a [version constraint](https://opentofu.org/docs/language/expressions/version-constraints) string (checked against versions available in TENV_ROOT directory).
- `latest`, `latest-stable` (old name of `latest`) or `latest-pre` (include unstable version), which are checked against versions available in TENV_ROOT directory.
- `latest:<re>` or `min:<re>` to get first version matching with `<re>` as a [regexp](https://github.com/google/re2/wiki/Syntax) after a descending or ascending version sort.
- `latest-allowed` or `min-required` to scan your IAC files to detect which version is maximally allowed or minimally required. See [required_version](#required_version) docs.

```console
tenv tofu use v1.6.0-beta5
tenv tf use min-required
tenv tg use latest
tenv atmos use latest
tenv tofu use latest-allowed
```

</details>


<details markdown="1"><summary><b>tenv &lt;tool&gt; detect</b></summary><br>

Detect the used version of tool for the working directory.

```console
$ tenv tofu detect
No version files found for OpenTofu, fallback to latest-allowed strategy
Scan project to find .tf files
No OpenTofu version requirement found in project files, fallback to latest strategy
Found compatible version installed locally : 1.6.1
OpenTofu 1.6.1 will be run from this directory.
$ tenv tg detect -q
Terragrunt 0.55.1 will be run from this directory.
$ tenv atmos detect -q
Atmos 1.72.0 will be run from this directory.
```

</details>


<details markdown="1"><summary><b>tenv &lt;tool&gt; reset</b></summary><br>

Reset used version of tool (remove `TENV_ROOT/<TOOL>/version` file).

```console
$ tenv tofu reset
Removed /home/dvaumoron/.tenv/OpenTofu/version
```

</details>


<details markdown="1"><summary><b>tenv &lt;tool&gt; uninstall [version]</b></summary><br>

Uninstall versions of the tool (remove it from `TENV_ROOT` directory).

Without parameter, display an interactive list to select several versions.

If a parameter is passed, available parameter options:

- an exact [Semver 2.0.0](https://semver.org/) version string to remove (no confirmation required)
- a [version constraint](https://opentofu.org/docs/language/expressions/version-constraints) string
- `all`
- `but-last` (all versions except the highest installed)
- `not-used-for:<duration>`, `<duration>` in days or months, like "14d" or "2m"
- `not-used-since:<date>`, `<date>` format is YYYY-MM-DD, like "2024-06-30"

```console
$ tenv tofu uninstall v1.6.0-alpha4
Uninstallation of OpenTofu 1.6.0-alpha4 successful (directory /home/dvaumoron/.tenv/OpenTofu/1.6.0-alpha4 removed)
```

</details>


<details markdown="1"><summary><b>tenv &lt;tool&gt; list</b></summary><br>

List installed tool versions (located in `TENV_ROOT` directory), sorted in ascending version order.

`tenv <tool> list` has a `--descending`, `-d` flag to sort in descending order.

```console
$ tenv tofu list -v
* 1.6.0 (set by /home/dvaumoron/.tenv/OpenTofu/version)
  1.6.1
found 2 OpenTofu version(s) managed by tenv.
```

</details>


<details markdown="1"><summary><b>tenv &lt;tool&gt; list-remote</b></summary><br>

List installable tool versions (from `<TOOL>_REMOTE` url), sorted in ascending version order.

`tenv <tool> list-remote` has a `--descending`, `-d` flag to sort in descending order.

`tenv <tool> list-remote` has a `--stable`, `-s` flag to display only stable version.

```console
$ tenv tofu list-remote
Fetching all releases information from https://api.github.com/repos/opentofu/opentofu/releases
1.6.0-alpha1
1.6.0-alpha2
1.6.0-alpha3
1.6.0-alpha4
1.6.0-alpha5
1.6.0-beta1
1.6.0-beta2
1.6.0-beta3
1.6.0-beta4
1.6.0-beta5
1.6.0-rc1
1.6.0 (installed)
1.6.1 (installed)
```

</details>


<details markdown="1"><summary><b>tenv &lt;tool&gt; constraint [expression]</b></summary><br>

Set or reset a default constraint expression for the tool.

```console
$ tenv tf constraint "<= 1.5.7"
Written <= 1.5.7 in /home/dvaumoron/.tenv/Terraform/constraint
```

Or without expression :

```console
$ tenv tg constraint
Removed /home/dvaumoron/.tenv/Terragrunt/constraint
```

</details>


<details markdown="1"><summary><b>tenv help [command]</b></summary><br>

Help about any command.

You can use `--help` `-h` flag instead.

```console
$ tenv help tf detect
Display Terraform current version.

Usage:
  tenv tf detect [flags]

Flags:
  -a, --arch string          specify arch for binaries downloading (default "amd64")
  -f, --force-remote         force search on versions available at TFENV_REMOTE url
  -h, --help                 help for detect
  -k, --key-file string      local path to PGP public key file (replace check against remote one)
  -n, --no-install           disable installation of missing version
  -c, --remote-conf string   path to remote configuration file (advanced settings)
  -u, --remote-url string    remote url to install from

Global Flags:
  -q, --quiet              no unnecessary output (and no log)
  -r, --root-path string   local path to install versions of OpenTofu, Terraform and Terragrunt (default "/home/dvaumoron/.tenv")
  -v, --verbose            verbose output (and set log level to Trace)
```

```console
$ tenv tofu use -h
Switch the default OpenTofu version to use (set in TENV_ROOT/OpenTofu/version file)

Available parameter options:
- an exact Semver 2.0.0 version string to use
- a version constraint expression (checked against version available in TENV_ROOT directory)
- latest, latest-stable or latest-pre (checked against version available in TENV_ROOT directory)
- latest-allowed or min-required to scan your OpenTofu files to detect which version is maximally allowed or minimally required.

Usage:
  tenv tofu use version [flags]

Flags:
  -a, --arch string           specify arch for binaries downloading (default "amd64")
  -f, --force-remote          force search on versions available at TOFUENV_REMOTE url
  -t, --github-token string   GitHub token (increases GitHub REST API rate limits)
  -h, --help                  help for use
  -k, --key-file string       local path to PGP public key file (replace check against remote one)
  -n, --no-install            disable installation of missing version
  -c, --remote-conf string    path to remote configuration file (advanced settings)
  -u, --remote-url string     remote url to install from
  -w, --working-dir           create .opentofu-version file in working directory

Global Flags:
  -q, --quiet              no unnecessary output (and no log)
  -r, --root-path string   local path to install versions of OpenTofu, Terraform and Terragrunt (default "/home/dvaumoron/.tenv")
  -v, --verbose            verbose output (and set log level to Trace)
```

</details>


<details markdown="1"><summary><b>tenv update-path</b></summary><br>

Display PATH updated with tenv directory location first. With GITHUB_ACTIONS set to true, write tenv directory location to GITHUB_PATH.

This command can be used when one of the managed tool is already installed on your system and hide the corresponding proxy (in that case `which tenv` and `which <tool>` will indicate different locations). The following shell call should resolve such issues :

```console
export PATH=$(tenv update-path)
```

</details>


<details markdown="1"><summary><b>tenv version</b></summary><br>

Display tenv current version.

```console
$ tenv version
tenv version v1.7.0
```


</details>


<a id="environment-variables"></a>
## Environment variables

**tenv** commands support global environment variables and variables by tool for : [OpenTofu](https://opentofu.org), [Terraform](https://www.terraform.io/), [TerraGrunt](https://terragrunt.gruntwork.io/) and [Atmos](https://atmos.tools).


<a id="tenv-vars"></a>
### Global tenv environment variables

<details markdown="1"><summary><b>TENV_ARCH</b></summary><br>

String (Default: current tenv binaries architecture)

Allow to override the default architecture for binaries downloading during installation.

`tenv <tool>` subcommands `detect`, `install` and `use` support a `--arch`, `-a`  flag version.

</details>


<details markdown="1"><summary><b>TENV_AUTO_INSTALL</b></summary><br>

String (Default: false)

If set to true **tenv** will automatically install missing tool versions needed.

`tenv <tool>` subcommands `detect` and `use` support a `--install`, `-i` enabling flag, and a `--no-install`, `-n` disabling flag.

</details>


<details markdown="1"><summary><b>TENV_FORCE_REMOTE</b></summary><br>

String (Default: false)

If set to true **tenv** detection of needed version will skip local check and verify compatibility on remote list.

`tenv <tool>` subcommands `detect` and `use` support a `--force-remote`, `-f` flag version.

</details>


<details markdown="1"><summary><b>TENV_GITHUB_TOKEN</b></summary><br>

String (Default: "")

Allow to specify a GitHub token to increase [GitHub Rate limits for the REST API](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api). Useful because OpenTofu, Terragrunt and Atmos binaries are downloaded from GitHub repository.

`tenv tofu` and `tenv tg` subcommands `detect`, `install`, `list-remote` and `use` support a `--github-token`, `-t` flag version.

</details>


<details markdown="1"><summary><b>TENV_GITHUB_APP_ID</b></summary><br>

String (Default: "")

The numeric ID of a [GitHub App](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps). When set (and `TENV_GITHUB_TOKEN` is not), **tenv** generates a short-lived installation access token from the App credentials and uses it as the bearer token for GitHub API calls. This is useful in CI systems (e.g. Atlantis) that already authenticate via a GitHub App, and raises the rate limit to 15,000 requests/hour per installation. Requires one of `TENV_GITHUB_APP_PEM` or `TENV_GITHUB_APP_PEM_FILE` to also be set.

</details>


<details markdown="1"><summary><b>TENV_GITHUB_APP_INSTALLATION_ID</b></summary><br>

String (Default: "")

The numeric installation ID of the GitHub App. Optional: when omitted, **tenv** auto-discovers it by querying the App's installations with the App JWT and using the first one returned. Set it explicitly when the App has more than one installation. Only used when `TENV_GITHUB_APP_ID` is set.

</details>


<details markdown="1"><summary><b>TENV_GITHUB_APP_PEM</b></summary><br>

String (Default: "")

The GitHub App's RSA private key as an inline PEM string. Alternative to `TENV_GITHUB_APP_PEM_FILE`; takes precedence over it when both are set. Only used when `TENV_GITHUB_APP_ID` is set.

</details>


<details markdown="1"><summary><b>TENV_GITHUB_APP_PEM_FILE</b></summary><br>

String (Default: "")

Path to a file containing the GitHub App's RSA private key in PEM format. Alternative to `TENV_GITHUB_APP_PEM`. Only used when `TENV_GITHUB_APP_ID` is set.

</details>


<details markdown="1"><summary><b>TENV_QUIET</b></summary><br>

String (Default: false)

If set to true **tenv** disable unnecessary output (including log level forced to off).

`tenv` subcommands support a `--quiet`, `-q` flag version.

</details>


<details markdown="1"><summary><b>TENV_LOG</b></summary><br>

String (Default: "warn")

Set **tenv** log level (possibilities sorted by decreasing verbosity : "trace", "debug", "info", "warn", "error", "off").

`tenv` support a `--verbose`, `-v` flag which set log level to "trace".

</details>


<details markdown="1"><summary><b>TENV_REMOTE_CONF</b></summary><br>

String (Default: `${TENV_ROOT}/remote.yaml`)

The path to a yaml file for [advanced remote configuration](#advanced-remote-configuration) (can be used to call artifact mirror).

`tenv <tool>` subcommands `detect`, `install`, `list-remote` and `use`  support a `--remote-conf`, `-c` flag version.

</details>


<details markdown="1"><summary><b>TENV_ROOT</b></summary><br>

String (Default: `${HOME}/.tenv`)

The path to a directory where the local OpenTofu versions, Terraform versions, Terragrunt versions and tenv configuration files exist.

`tenv` support a `--root-path`, `-r` flag version.

</details>


<details markdown="1"><summary><b>TENV_SKIP_LAST_USE</b></summary><br>

String (Default: false)

If set to true **tenv** disable tracking of last use date for installed versions. It allow to avoid warning message when **tenv** is installed as root user and run with a normal user by skipping the writing of `last-use.txt`. This will lead to misselection with `not-used-for` and `not-used-since` behavior of `tenv uninstall`.

</details>


<details markdown="1"><summary><b>TENV_VALIDATION</b></summary><br>

String (Default: signature)

Set **tenv** validation, known values are "signature" (check SHA256 and its signature, see [signature support](#signature-support)), "sha" (only check SHA256), "none" (no validation).

</details>


<details markdown="1"><summary><b>GITHUB_ACTIONS</b></summary><br>

String (Default: false)

If set to true **tenv** proxies exposes proxied output `stdout`, `stderr`, and `exitcode` by writing them into GITHUB_OUTPUT in [multiline format](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings). GitHub Actions set it (see [default environment variables](https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables)).

</details>


<details markdown="1"><summary><b>GITHUB_OUTPUT</b></summary><br>

String (Default: "")

Needed when GITHUB_ACTIONS is set to true, path to a file to write proxied output.

</details>


<details markdown="1"><summary><b>GITHUB_PATH</b></summary><br>

String (Default: "")

Used by `tenv update-path` when GITHUB_ACTIONS is set to true, path to a file to write tenv directory location.

</details>


<a id="tofu-env-vars"></a>
### OpenTofu environment variables

<details markdown="1"><summary><b>TOFUENV_AGNOSTIC_PROXY</b></summary><br>

String (Default: false)

Switch `tofu` proxy to an agnostic proxy (behave like `tf`, see [resolution order](#project-binaries)).

</details>


<details markdown="1"><summary><b>TOFUENV_ARCH</b></summary><br>

Same as TENV_ARCH (compatibility with [tofuenv](https://github.com/tofuutils/tofuenv)).

</details>


<details markdown="1"><summary><b>TOFUENV_AUTO_INSTALL</b></summary><br>

Same as TENV_AUTO_INSTALL (compatibility with [tofuenv](https://github.com/tofuutils/tofuenv)).

#### Example 1
Use OpenTofu version 1.6.1 that is not installed, and auto installation stay disabled :

```console
$ tenv use 1.6.1
Written 1.6.1 in /home/dvaumoron/.tenv/OpenTofu/version
```

#### Example 2
Use OpenTofu version 1.6.0 that is not installed, and auto installation is enabled :

```console
$ TOFUENV_AUTO_INSTALL=true tenv tofu use 1.6.0
Installing OpenTofu 1.6.0
Fetching release information from https://api.github.com/repos/opentofu/opentofu/releases/tags/v1.6.0
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_linux_amd64.zip
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS.sig
Downloading https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_SHA256SUMS.pem
Installation of OpenTofu 1.6.0 successful
Written 1.6.0 in /home/dvaumoron/.tenv/OpenTofu/version
```

</details>


<details markdown="1"><summary><b>TOFUENV_FORCE_REMOTE</b></summary><br>

Same as TENV_FORCE_REMOTE.

</details>


<details markdown="1"><summary><b>TOFUENV_INSTALL_MODE</b></summary><br>

String (the default depend on TOFUENV_REMOTE, without change on it, it is "api" else it is "direct")

- "api" install mode retrieve download url of OpenTofu from [Github REST API](https://docs.github.com/en/rest?apiVersion=2022-11-28) (TOFUENV_REMOTE must comply with it).
- "direct" install mode generate download url of OpenTofu based on TOFUENV_REMOTE.
- "mirror" install mode generate download url with TOFUENV_URL_TEMPLATE (as specified in [TofuDL mirror specification](https://github.com/opentofu/tofudl/blob/mirror-spec/MIRROR-SPECIFICATION.md))

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TOFUENV_LIST_MODE</b></summary><br>

String (the default depend on TOFUENV_LIST_URL, without change on it, it is "api" else it is "html")

- "api" list mode retrieve information of OpenTofu releases from [Github REST API](https://docs.github.com/en/rest?apiVersion=2022-11-28) (TOFUENV_LIST_URL must comply with it).
- "html" list mode extract information of OpenTofu releases from parsing an html page at TOFUENV_LIST_URL.
- "mirror" list mode retrieve information of OpenTofu releases at TOFUENV_LIST_URL as [TofuDL Mirroring format](https://get.opentofu.org/tofu/api.json)

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TOFUENV_LIST_URL</b></summary><br>

String (Default: copy TOFUENV_REMOTE, default is overloaded by "https://get.opentofu.org/tofu/api.json" when TOFUENV_LIST_MODE is "mirror")

Allow to override the remote url only for the releases listing.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TOFUENV_OPENTOFU_PGP_KEY</b></summary><br>

String (Default: "")

Allow to specify a local file path or URL to OpenTofu PGP public key. If a URL is provided (starting with "http://" or "https://"), the key will be downloaded from that URL. If a local file path is provided, the key will be read from that location. If not set, the key will be downloaded from the default URL (https://get.opentofu.org/opentofu.asc).

`tenv tofu` subcommands `detect`, `ìnstall` and `use` support a `--key-file`, `-k` flag version.

</details>


<details markdown="1"><summary><b>TOFUENV_REMOTE</b></summary><br>

String (Default: https://api.github.com/repos/opentofu/opentofu/releases)

URL to install OpenTofu, when TOFUENV_REMOTE differ from its default value, TOFUENV_INSTALL_MODE is set to "direct" and TOFUENV_LIST_MODE is set to "html" (assume an artifact proxy usage).

`tenv tofu` subcommands `detect`, `install`, `list-remote` and `use` support a `--remote-url`, `-u` flag version.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TOFUENV_REMOTE_PASSWORD</b></summary><br>

String (Default: "")

Could be used with TOFUENV_REMOTE_USER to specify HTTP basic auth when same credential are used with TOFUENV_REMOTE and TOFUENV_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>TOFUENV_REMOTE_USER</b></summary><br>

String (Default: "")

Could be used with TOFUENV_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with TOFUENV_REMOTE and TOFUENV_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>TOFUENV_ROOT</b></summary><br>

Same as TENV_ROOT (compatibility with [tofuenv](https://github.com/tofuutils/tofuenv)).

</details>


<details markdown="1"><summary><b>TOFUENV_URL_TEMPLATE</b></summary><br>

String (Default: `https://github.com/opentofu/opentofu/releases/download/v{{ .Version }}/{{ .Artifact }}`)

Used when TOFUENV_INSTALL_MODE is "mirror" (see [TofuDL mirror specification](https://github.com/opentofu/tofudl/blob/mirror-spec/MIRROR-SPECIFICATION.md)).

</details>


<details markdown="1"><summary><b>TOFUENV_GITHUB_TOKEN</b></summary><br>

Same as TENV_GITHUB_TOKEN (compatibility with [tofuenv](https://github.com/tofuutils/tofuenv)).

</details>


<details markdown="1"><summary><b>TOFUENV_TOFU_DEFAULT_CONSTRAINT</b></summary><br>

String (Default: "")

If not empty string, this variable overrides OpenTofu default constraint, specified in ${TENV_ROOT}/OpenTofu/constraint file.

</details>


<details markdown="1"><summary><b>TOFUENV_TOFU_DEFAULT_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides OpenTofu fallback version, specified in ${TENV_ROOT}/OpenTofu/version file.

</details>


<details markdown="1"><summary><b>TOFUENV_TOFU_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides OpenTofu version, specified in [`.opentofu-version`](#opentofu-version-files) files.

`tenv tofu` subcommands `install` and `detect` also respects this variable.

e.g. with :

```console
$ tofu version
OpenTofu v1.6.1
on linux_amd64
```

then :

```console
$ TOFUENV_TOFU_VERSION=1.6.0 tofu version
OpenTofu v1.6.0
on linux_amd64
```

</details>


<a id="tf-env-vars"></a>
### Terraform environment variables

<details markdown="1"><summary><b>TFENV_AGNOSTIC_PROXY</b></summary><br>

String (Default: false)

Switch `terraform` proxy to an agnostic proxy (behave like `tf`, see [resolution order](#project-binaries)).

</details>


<details markdown="1"><summary><b>TFENV_ARCH</b></summary><br>

Same as TENV_ARCH (compatibility with [tfenv](https://github.com/tfutils/tfenv)).

</details>


<details markdown="1"><summary><b>TFENV_AUTO_INSTALL</b></summary><br>

Same as TENV_AUTO_INSTALL (compatibility with [tfenv](https://github.com/tfutils/tfenv)).

</details>


<details markdown="1"><summary><b>TFENV_FORCE_REMOTE</b></summary><br>

Same as TENV_FORCE_REMOTE.

</details>


<details markdown="1"><summary><b>TFENV_HASHICORP_PGP_KEY</b></summary><br>

Allow to specify a local file path or URL to Hashicorp PGP public key. If a URL is provided (starting with "http://" or "https://"), the key will be downloaded from that URL. If a local file path is provided, the key will be read from that location. If not set, the key will be downloaded from the default URL (https://www.hashicorp.com/.well-known/pgp-key.txt).

`tenv tf` subcommands `detect`, `ìnstall` and `use` support a `--key-file`, `-k` flag version.
</details>


<details markdown="1"><summary><b>TFENV_INSTALL_MODE</b></summary><br>

String (Default: "api")

- "api" install mode retrieve download url of Terraform from [Hashicorp Release API](https://releases.hashicorp.com/docs/api/v1) (TFENV_REMOTE must comply with it).
- "direct" install mode generate download url of Terraform based on TFENV_REMOTE.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TFENV_LIST_MODE</b></summary><br>

String (the default depend on TFENV_LIST_URL, without change on it, it is "api" else it is "html")

- "api" list mode retrieve information of Terraform releases from [Hashicorp Release API](https://releases.hashicorp.com/docs/api/v1) (TFENV_LIST_URL must comply with it).
- "html" list mode extract information of Terraform releases from parsing an html page in TFENV_LIST_URL.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TFENV_LIST_URL</b></summary><br>

String (Default: copy TFENV_REMOTE)

Allow to override the remote url only for the releases listing.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TFENV_REMOTE</b></summary><br>

String (Default: https://releases.hashicorp.com)

URL to install Terraform, changing it assume an artifact proxy use (TFENV_LIST_URL copy it, and if it differ from its default value, TFENV_LIST_MODE is set to "html", because an artifact proxy usage will not disturb the retrieving of index.json for a release, but will freeze the json list of releases).

`tenv tf` subcommands `detect`, `install`, `list-remote` and `use` support a `--remote-url`, `-u` flag version.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TFENV_REMOTE_PASSWORD</b></summary><br>

String (Default: "")

Could be used with TFENV_REMOTE_USER to specify HTTP basic auth when same credential are used with TFENV_REMOTE and TFENV_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>TFENV_REMOTE_USER</b></summary><br>

String (Default: "")

Could be used with TFENV_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with TFENV_REMOTE and TFENV_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>TFENV_ROOT</b></summary><br>

Same as TENV_ROOT (compatibility with [tfenv](https://github.com/tfutils/tfenv)).

</details>


<details markdown="1"><summary><b>TFENV_TERRAFORM_DEFAULT_CONSTRAINT</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terraform default constraint, specified in ${TENV_ROOT}/Terraform/constraint file.

</details>


<details markdown="1"><summary><b>TFENV_TERRAFORM_DEFAULT_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terraform fallback version, specified in ${TENV_ROOT}/Terraform/version file.

</details>


<details markdown="1"><summary><b>TFENV_TERRAFORM_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terraform version, specified in [`.terraform-version`](#terraform-version-files) files.

`tenv tf` subcommands `install` and `detect` also respects this variable.

e.g. with :

```console
$ terraform version
Terraform v1.7.2
on linux_amd64
```

then :

```console
$ TFENV_TERRAFORM_VERSION=1.7.0 terraform version
Terraform v1.7.0
on linux_amd64

Your version of Terraform is out of date! The latest version
is 1.7.2. You can update by downloading from https://www.terraform.io/downloads.html
```

</details>


<a id="tg-env-vars"></a>
### Terragrunt environment variables


<details markdown="1"><summary><b>TG_INSTALL_MODE</b></summary><br>

String (the default depend on TG_REMOTE, without change on it, it is "api" else it is "direct")

- "api" install mode retrieve download url of Terragrunt from [Github REST API](https://docs.github.com/en/rest?apiVersion=2022-11-28) (TG_REMOTE must comply with it).
- "direct" install mode generate download url of Terragrunt based on TG_REMOTE.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TG_LIST_MODE</b></summary><br>

String (the default depend on TG_LIST_URL, without change on it, it is "api" else it is "html")

- "api" list mode retrieve information of Terragrunt releases from [Github REST API](https://docs.github.com/en/rest?apiVersion=2022-11-28) (TG_LIST_URL must comply with it).
- "html" list mode extract information of Terragrunt releases from parsing an html page in TG_LIST_URL.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TG_LIST_URL</b></summary><br>

String (Default: copy TG_REMOTE)

Allow to override the remote url only for the releases listing.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TG_REMOTE</b></summary><br>

String (Default: https://api.github.com/repos/gruntwork-io/terragrunt/releases)

URL to install Terragrunt, when TG_REMOTE differ from its default value, TG_INSTALL_MODE is set to "direct" and TG_LIST_MODE is set to "html" (assume an artifact proxy usage).

`tenv tg` subcommands `detect`, `install`, `list-remote` and `use` support a `--remote-url`, `-u` flag version.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TG_REMOTE_PASSWORD</b></summary><br>

String (Default: "")

Could be used with TG_REMOTE_USER to specify HTTP basic auth when same credential are used with TG_REMOTE and TG_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>TG_REMOTE_USER</b></summary><br>

String (Default: "")

Could be used with TG_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with TG_REMOTE and TG_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>TG_DEFAULT_CONSTRAINT</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terragrunt default constraint, specified in ${TENV_ROOT}/Terragrunt/constraint file.

</details>


<details markdown="1"><summary><b>TG_DEFAULT_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terragrunt fallback version, specified in ${TENV_ROOT}/Terragrunt/version file.

</details>


<details markdown="1"><summary><b>TG_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terragrunt version, specified in [`.terragrunt-version`](#terragrunt-version-files) files.

`tenv tg` subcommands `install` and `detect` also respects this variable.

e.g. with :

```console
$ terragrunt -v
terragrunt version v0.55.1
```

then :

```console
$ TG_VERSION=0.54.1 terragrunt -v
terragrunt version v0.54.1
```

</details>


<a id="tm-env-vars"></a>
### Terramate environment variables


<details markdown="1"><summary><b>TM_INSTALL_MODE</b></summary><br>

String (the default depend on TM_REMOTE, without change on it, it is "api" else it is "direct")

- "api" install mode retrieve download url of Terramate from [Github REST API](https://docs.github.com/en/rest?apiVersion=2022-11-28) (TM_REMOTE must comply with it).
- "direct" install mode generate download url of Terramate based on TM_REMOTE.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TM_LIST_MODE</b></summary><br>

String (the default depend on TM_LIST_URL, without change on it, it is "api" else it is "html")

- "api" list mode retrieve information of Terramate releases from [Github REST API](https://docs.github.com/en/rest?apiVersion=2022-11-28) (TM_LIST_URL must comply with it).
- "html" list mode extract information of Terramate releases from parsing an html page in TM_LIST_URL.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TM_LIST_URL</b></summary><br>

String (Default: copy TM_REMOTE)

Allow to override the remote url only for the releases listing.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TM_REMOTE</b></summary><br>

String (Default: https://api.github.com/repos/terramate-io/terramate/releases)

URL to install Terramate, when TM_REMOTE differ from its default value, TM_INSTALL_MODE is set to "direct" and TM_LIST_MODE is set to "html" (assume an artifact proxy usage).

`tenv tm` subcommands `detect`, `install`, `list-remote` and `use` support a `--remote-url`, `-u` flag version.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>TM_REMOTE_PASSWORD</b></summary><br>

String (Default: "")

Could be used with TM_REMOTE_USER to specify HTTP basic auth when same credential are used with TM_REMOTE and TM_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>TM_REMOTE_USER</b></summary><br>

String (Default: "")

Could be used with TM_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with TM_REMOTE and TM_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>TM_DEFAULT_CONSTRAINT</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terramate default constraint, specified in ${TENV_ROOT}/Terramate/constraint file.

</details>


<details markdown="1"><summary><b>TM_DEFAULT_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terramate fallback version, specified in ${TENV_ROOT}/Terramate/version file.

</details>


<details markdown="1"><summary><b>TM_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Terramate version, specified in [`.terramate-version`](#terramate-version-files) files.

`tenv tm` subcommands `install` and `detect` also respects this variable.

e.g. with :

```console
$ terramate version
0.13.0
```

then :

```console
$ TM_VERSION=0.12.0 terramate version
0.12.0
```

</details>


<a id="atmos-env-vars"></a>
### Atmos environment variables


<details markdown="1"><summary><b>ATMOS_INSTALL_MODE</b></summary><br>

String (the default depend on ATMOS_REMOTE, without change on it, it is "api" else it is "direct")

- "api" install mode retrieve download url of Atmos from [Github REST API](https://docs.github.com/en/rest?apiVersion=2022-11-28) (ATMOS_REMOTE must comply with it).
- "direct" install mode generate download url of Atmos based on ATMOS_REMOTE.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>ATMOS_LIST_MODE</b></summary><br>

String (the default depend on ATMOS_LIST_URL, without change on it, it is "api" else it is "html")

- "api" list mode retrieve information of Atmos releases from [Github REST API](https://docs.github.com/en/rest?apiVersion=2022-11-28) (ATMOS_LIST_URL must comply with it).
- "html" list mode extract information of Atmos releases from parsing an html page in ATMOS_LIST_URL.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>ATMOS_LIST_URL</b></summary><br>

String (Default: copy ATMOS_REMOTE)

Allow to override the remote url only for the releases listing.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>ATMOS_REMOTE</b></summary><br>

String (Default: https://api.github.com/repos/cloudposse/atmos/releases)

URL to install Atmos when ATMOS_REMOTE differ from its default value, ATMOS_INSTALL_MODE is set to "direct" and ATMOS_LIST_MODE is set to "html" (assume an artifact proxy usage).

`tenv atmos` subcommands `detect`, `install`, `list-remote` and `use` support a `--remote-url`, `-u` flag version.

See [advanced remote configuration](#advanced-remote-configuration) for more details.

</details>


<details markdown="1"><summary><b>ATMOS_REMOTE_PASSWORD</b></summary><br>

String (Default: "")

Could be used with ATMOS_REMOTE_USER to specify HTTP basic auth when same credential are used with ATMOS_REMOTE and ATMOS_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>ATMOS_REMOTE_USER</b></summary><br>

String (Default: "")

Could be used with ATMOS_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with ATMOS_REMOTE and ATMOS_LIST_URL (instead of `https://user:password@host.org` URL format).

</details>


<details markdown="1"><summary><b>ATMOS_DEFAULT_CONSTRAINT</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Atmos default constraint, specified in ${TENV_ROOT}/Atmos/constraint file.

</details>


<details markdown="1"><summary><b>ATMOS_DEFAULT_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Atmos fallback version, specified in ${TENV_ROOT}/Atmos/version file.

</details>


<details markdown="1"><summary><b>ATMOS_VERSION</b></summary><br>

String (Default: "")

If not empty string, this variable overrides Atmos version, specified in [`.atmos-version`](#atmos-version-files) files.

`tenv atmos` subcommands `install` and `detect` also respects this variable.

e.g. with :

```console
$ atmos version
👽 Atmos v1.72.0 on linux/amd64

```

then :

```console
$ ATMOS_VERSION=1.70 atmos version
👽 Atmos v1.70.0 on linux/amd64
```

</details>

<a id="version-files"></a>
## version files

<a id="default-version-file"></a>
<details markdown="1"><summary><b>default version file</b></summary><br>

The `TENV_ROOT/<TOOL>/version` file is the tool default version used when no project specific or user specific are found. It can be written with `tenv <tool> use`.

</details>

<a id="opentofu-version-files"></a>
<details markdown="1"><summary><b>opentofu version files</b></summary><br>

If you put a `.opentofu-version` file in the working directory, one of its parent directory, or user home directory, **tenv** detects it and uses the version written in it.
Note, that TOFUENV_TOFU_VERSION can be used to override version specified by `.opentofu-version` file.

Recognize same values as `tenv tofu use` command.

See [required_version](https://opentofu.org/docs/language/settings#specifying-a-required-opentofu-version) docs.

</details>

<a id="terraform-version-files"></a>
<details markdown="1"><summary><b>terraform version files</b></summary><br>

If you put a `.terraform-version` or `.tfswitchrc` file in the working directory, one of its parent directory, or user home directory, **tenv** detects it and uses the version written in it.
Note, that TFENV_TERRAFORM_VERSION can be used to override version specified by those files.

Recognize same values as `tenv tf use` command.

See [required_version](https://developer.hashicorp.com/terraform/language/settings#specifying-a-required-terraform-version) docs.

</details>

<a id="terragrunt-version-files"></a>
<details markdown="1"><summary><b>terragrunt version files</b></summary><br>

If you put a `.terragrunt-version` or a `.tgswitchrc` file in the working directory, one of its parent directory, or user home directory, **tenv** detects it and uses the version written in it. **tenv** also detect a `version` field in a `.tgswitch.toml` in same places.
Note, that TG_VERSION can be used to override version specified by those files.

Recognize same values as `tenv tg use` command.

</details>


<a id="terragrunt-hcl-file"></a>
<details markdown="1"><summary><b>terragrunt.hcl or root.hcl file</b></summary><br>

[Terragrunt now recommends](https://terragrunt.gruntwork.io/docs/migrate/migrating-from-root-terragrunt-hcl/) using `root.hcl` instead of `terragrunt.hcl` as the root configuration file name.

If a `terragrunt.hcl`, `root.hcl`, or their `.json` equivalents exist in the working directory, a parent directory, or the user home directory, **tenv** will read constraints from the `terraform_version_constraint` or `terragrunt_version_constraint` field (depending on proxy or subcommand used).


If both `root.hcl` and `terragrunt.hcl` (or their `.json` versions) are present, `terragrunt.hcl` takes precedence.

</details>

<a id="terramate-version-files"></a>
<details markdown="1"><summary><b>terramate version files</b></summary><br>

If you put a `.terramate-version` file in the working directory, one of its parent directory, or user home directory, **tenv** detects it and uses the version written in it.
Note, that TM_VERSION can be used to override version specified by those files.

Recognize same values as `tenv tm use` command.

</details>

<a id="atmos-version-files"></a>
<details markdown="1"><summary><b>atmos version files</b></summary><br>

If you put a `.atmos-version` file in the working directory, one of its parent directory, or user home directory, **tenv** detects it and uses the version written in it.
Note, that ATMOS_VERSION can be used to override version specified by those files.

Recognize same values as `tenv atmos use` command.

</details>

<a id="required_version"></a>
<details markdown="1"><summary><b>required_version</b></summary><br>

the `latest-allowed` or `min-required` strategies scan through your IAC files (see list in [project binaries](#project-binaries)) and identify a version conforming to the constraint in the relevant files. They fallback to `latest` when no IAC files and no default constraint are found, and can optionally be used with a default constraint as detailed in [project binaries](#project-binaries).

Currently the format for [Terraform required_version](https://developer.hashicorp.com/terraform/language/settings#specifying-a-required-terraform-version) and [OpenTofu required_version](https://opentofu.org/docs/language/settings#specifying-a-required-opentofu-version) are very similar, however this may change over time, always refer to docs for the latest format specification.

example:

```HCL
version = ">= 1.2.0, < 2.0.0"
```

This would identify the latest version at or above 1.2.0 and below 2.0.0

</details>

<a id="technical-details"></a>
## Technical details

<a id="project-binaries"></a>
### Project binaries

All the proxy binaries return the exit code `42` on error happening before proxied command call.


<details markdown="1"><summary><b>tofu</b></summary><br>

The `tofu` command in this project is a proxy to OpenTofu's `tofu` command  managed by **tenv**.

The version resolution order is :

- TOFUENV_TOFU_VERSION environment variable
- `.opentofu-version` file
- `.tool-versions` [file](https://asdf-vm.com/manage/configuration.html#tool-versions)
- `terraform_version_constraint` from `terragrunt.hcl` file
- `terraform_version_constraint` from `terragrunt.hcl.json` file
- `terraform_version_constraint` from `root.hcl` file
- `terraform_version_constraint` from `root.hcl.json` file
- TOFUENV_TOFU_DEFAULT_VERSION environment variable
- `${TENV_ROOT}/OpenTofu/version` file (can be written with `tenv tofu use`)
- `latest-allowed`

The `latest-allowed` strategy rely on [required_version](#required_version) from .tofu, .tofu.json, .tf or .tf.json files with a fallback to `latest` when no constraint are found. Moreover it is possible to add a default constraint with TOFUENV_TOFU_DEFAULT_CONSTRAINT environment variable or `${TENV_ROOT}/OpenTofu/constraint` file (can be written with `tenv tofu constraint`). The default constraint is added while using `latest-allowed`, `min-required` or custom constraint. A default constraint with `latest-allowed` or `min-required` will avoid the fallback to `latest` when there is no .tf or .tf.json files.

</details>

<details markdown="1"><summary><b>terraform</b></summary><br>

The `terraform` command in this project is a proxy to HashiCorp's `terraform` command managed by **tenv**.

The version resolution order is :

- TFENV_TERRAFORM_VERSION environment variable
- `.terraform-version` file
- `.tfswitchrc` file
- `.tool-versions` [file](https://asdf-vm.com/manage/configuration.html#tool-versions)
- `terraform_version_constraint` from `terragrunt.hcl` file
- `terraform_version_constraint` from `terragrunt.hcl.json` file
- `terraform_version_constraint` from `root.hcl` file
- `terraform_version_constraint` from `root.hcl.json` file
- TFENV_TERRAFORM_DEFAULT_VERSION environment variable
- `${TENV_ROOT}/Terraform/version` file (can be written with `tenv tf use`)
- `latest-allowed`

The `latest-allowed` strategy rely on [required_version](#required_version) from .tf or .tf.json files with a fallback to `latest` when no constraint are found. Moreover it is possible to add a default constraint with TFENV_TERRAFORM_DEFAULT_CONSTRAINT environment variable or `${TENV_ROOT}/Terraform/constraint` file (can be written with `tenv tf constraint`). The default constraint is added while using `latest-allowed`, `min-required` or custom constraint. A default constraint with `latest-allowed` or `min-required` will avoid the fallback to `latest` when there is no .tf or .tf.json files.

</details>


<details markdown="1"><summary><b>terragrunt</b></summary><br>

The `terragrunt` command in this project is a proxy to Gruntwork's `terragrunt` command managed by **tenv**.

The version resolution order is :

- TG_VERSION environment variable
- `.terragrunt-version` file
- `.tgswitchrc` file
- `version` from `tgswitch.toml` file
- `.tool-versions` [file](https://asdf-vm.com/manage/configuration.html#tool-versions)
- `terragrunt_version_constraint` from `terragrunt.hcl` file
- `terragrunt_version_constraint` from `terragrunt.hcl.json` file
- `terragrunt_version_constraint` from `root.hcl` file
- `terragrunt_version_constraint` from `root.hcl.json` file
- TG_DEFAULT_VERSION environment variable
- `${TENV_ROOT}/Terragrunt/version` file (can be written with `tenv tg use`)
- `latest-allowed`

The `latest-allowed` strategy has no information for Terragrunt and will fallback to `latest` unless there is default constraint. Adding a default constraint could be done with TG_DEFAULT_CONSTRAINT environment variable or `${TENV_ROOT}/Terragrunt/constraint` file (can be written with `tenv tg constraint`). The default constraint is added while using `latest-allowed`, `min-required` or custom constraint. A default constraint with `latest-allowed` or `min-required` will avoid there fallback to `latest`.

</details>


<details markdown="1"><summary><b>terramate</b></summary><br>

The `terramate` command in this project is a proxy to Terramate's `terramate` command managed by **tenv**.

The version resolution order is :

- TM_VERSION environment variable
- `.terramate-version` file
- TM_DEFAULT_VERSION environment variable
- `${TENV_ROOT}/Terramate/version` file (can be written with `tenv tm use`)
- `latest-allowed`

The `latest-allowed` strategy has no information for Terramate and will fallback to `latest` unless there is default constraint. Adding a default constraint could be done with TM_DEFAULT_CONSTRAINT environment variable or `${TENV_ROOT}/Terramate/constraint` file (can be written with `tenv tm constraint`). The default constraint is added while using `latest-allowed`, `min-required` or custom constraint. A default constraint with `latest-allowed` or `min-required` will avoid there fallback to `latest`.

</details>


<details markdown="1"><summary><b>atmos</b></summary><br>

The `atmos` command in this project is a proxy to Cloudposse's `atmos` command managed by **tenv**.

The version resolution order is :

- ATMOS_VERSION environment variable
- `.atmos-version` file
- `.tool-versions` [file](https://asdf-vm.com/manage/configuration.html#tool-versions)
- ATMOS_DEFAULT_VERSION environment variable
- `${TENV_ROOT}/Atmos/version` file (can be written with `tenv atmos use`)
- `latest-allowed`

The `latest-allowed` strategy has no information for Atmos and will fallback to `latest`
unless there is default constraint. Adding a default constraint could be done with
ATMOS_DEFAULT_CONSTRAINT environment variable or `${TENV_ROOT}/Atmos/constraint` file (can
be written with `tenv atmos constraint`). The default constraint is added while using `latest-allowed`, `min-required` or custom constraint. A default constraint with `latest-allowed` or `min-required` will avoid there fallback to `latest`.

</details>

<details markdown="1"><summary><b>tf</b></summary><br>

The `tf` command is a proxy to `tofu` or `terraform` depending on the version files present in project.

The version resolution order is :

- `.opentofu-version` file (launch `tofu`)
- `tofu` version from `.tool-versions` [file](https://asdf-vm.com/manage/configuration.html#tool-versions)
- `terraform_version_constraint` from `terragrunt.hcl` file (launch `tofu`)
- `terraform_version_constraint` from `terragrunt.hcl.json` file (launch `tofu`)
- `terraform_version_constraint` from `root.hcl` file (launch `tofu`)
- `terraform_version_constraint` from `root.hcl.json` file (launch `tofu`)
- `.terraform-version` file (launch `terraform`)
- `.tfswitchrc` file  (launch `terraform`)
- `terraform` version from `.tool-versions` [file](https://asdf-vm.com/manage/configuration.html#tool-versions)
- fail with a message

</details>


<a id="advanced-remote-configuration"></a>
### Advanced remote configuration

This advanced configuration is meant to call artifact mirror (like [JFrog Artifactory](https://jfrog.com/artifactory)).

The yaml file from TENV_REMOTE_CONF path can have one part for each supported proxy : `tofu`, `terraform`, `terragrunt` and `atmos`.

<details markdown="1"><summary><b>yaml fields description</b></summary><br>

Each part can have the following string field : `install_mode`, `list_mode`, `list_url`, `url`, `new_base_url`, `old_base_url`, `selector` and `part`

With `install_mode` set to "direct", **tenv** skip the release information fetching and generate download url instead of reading them from API (overridden by `<TOOL>_INSTALL_MODE` env var).

With `list_mode` set to "html", **tenv** change the fetching of all releases information from API to parse the parent html page of artifact location, see `selector` and `part` (overridden by `<TOOL>_LIST_MODE` env var).

`url` allows to override the default remote url (overridden by flag or `<TOOL>_REMOTE` env var).

`list_url` allows to override the remote url only for the releases listing (overridden by `<TOOL>_LIST_URL` env var).

`old_base_url` and `new_base_url` are used as url rewrite rule (if an url start with the prefix, it will be changed to use the new base url).

If `old_base_url` and `new_base_url` are empty, **tenv** try to guess right behaviour based on previous fields.

`selector` is used to gather in a list all matching html node and `part` choose on which node part (attribute name or "#text" for inner text) a version will be extracted (selector default to "a" (html link) and part default to "href" (link target))

</details>


<details markdown="1"><summary><b>Examples</b></summary><br>

Those examples assume that a GitHub proxy at https://artifactory.example.com/artifactory/github have the same behavior than [JFrog Artifactory](https://jfrog.com/artifactory) :

- mirror https://github.com/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_linux_amd64.zip at https://artifactory.example.com/artifactory/github/opentofu/opentofu/releases/download/v1.6.0/tofu_1.6.0_linux_amd64.zip.
- have at https://artifactory.example.com/artifactory/github/opentofu/opentofu/releases/download an html page with links on existing sub folder like "v1.6.0/"

Example 1 : Retrieve Terraform binaries and list available releases from the mirror (TFENV_LIST_MODE is optional because TFENV_LIST_URL differ from its default(when TFENV_LIST_URL is not set, it copy TFENV_REMOTE)).

```console
TFENV_REMOTE=https://artifactory.example.com/artifactory/hashicorp
TFENV_LIST_MODE=html
```

Example 2 : Retrieve Terraform binaries from the mirror and list available releases from the Hashicorp releases API.

```console
TFENV_REMOTE=https://artifactory.example.com/artifactory/hashicorp
TFENV_LIST_URL=https://releases.hashicorp.com
```

Example 1 & 2, does not need install mode (by release index.json is figed in mirror without problem), however create a rewrite rule from "https://releases.hashicorp.com" to "https://artifactory.example.com/artifactory/hashicorp" to obtains correct download URLs.

Example 3 : Retrieve OpenTofu binaries and list available releases from the mirror (TOFUENV_INSTALL_MODE and TOFUENV_LIST_MODE are optional because overloading TOFUENV_REMOTE already change them).

```console
TOFUENV_REMOTE=https://artifactory.example.com/artifactory/github
TOFUENV_INSTALL_MODE=direct
TOFUENV_LIST_MODE=html
```

Example 4 : Retrieve OpenTofu binaries from the mirror and list available releases from the GitHub API (TOFUENV_INSTALL_MODE is optional because overloading TOFUENV_REMOTE already set it to "direct").

```console
TOFUENV_REMOTE=https://artifactory.example.com/artifactory/github
TOFUENV_INSTALL_MODE=direct
TOFUENV_LIST_URL=https://api.github.com/repos/opentofu/opentofu/releases
```

Example 3 & 4, does not create a rewrite rule (the direct install mode build correct download URLs).

Example 5 : Install Terragrunt directly from GitHub release downloads, bypassing the GitHub REST API to avoid rate limits without needing a GitHub token.

```console
TG_REMOTE=https://github.com
```

Pointing TG_REMOTE at https://github.com switches TG_INSTALL_MODE to "direct" and TG_LIST_MODE to "html" automatically, so `tenv tg install <version>` resolves the download URL as `https://github.com/gruntwork-io/terragrunt/releases/download/v<version>/terragrunt_<os>_<arch>` directly.

Example 1 & 4 can be merged in a remote.yaml :

```yaml
tofu:
  url: "https://artifactory.example.com/artifactory/github"
  install_mode: "direct"
  list_url: "https://api.github.com/repos/opentofu/opentofu/releases"
terraform:
  url: "https://artifactory.example.com/artifactory/hashicorp"
  list_mode: "html"
```

</details>


<a id="lockfile-support"></a>
### Lockfile support

<details markdown="1"><summary><b>Lockfile behavior</b></summary><br>

**tenv** uses lockfiles to ensure safe concurrent operations when multiple instances are run in parallel. This prevents race conditions during installation, uninstallation, and other operations that modify the local version cache.

**Lock file location and naming:**
- Default location: `${TENV_ROOT}/{tool}.lock` (e.g., `~/.tenv/OpenTofu.lock`)
- Can be customized using the `TENV_LOCK_PATH` environment variable
- Each tool (OpenTofu, Terraform, Terragrunt, Terramate, Atmos) uses its own lock file

**Parallel execution behavior:**
When multiple **tenv** instances attempt to run simultaneously:

1. The first instance creates its lock file successfully and proceeds with the operation
2. Subsequent instances fail to create the lock file (due to exclusive creation) and enter a retry loop
3. The retry mechanism waits 1 second between attempts and logs a warning message
4. Once the first instance completes and releases its lock, the next waiting instance can acquire the lock and proceed

**Example retry behavior:**
```console
$ tenv tofu install 1.6.0 & tenv tofu install 1.6.1
[1] Installing OpenTofu 1.6.0
[2] can not write .lock file, will retry: file already exists
[2] can not write .lock file, will retry: file already exists
[1] Installation of OpenTofu 1.6.0 successful
[2] Installing OpenTofu 1.6.1
[2] Installation of OpenTofu 1.6.1 successful
```

**Lock scope:**
- **Operations that modify versions** (`install`, `uninstall`) use locks to prevent conflicts
- **Read-only operations** (`list`, `list-remote`, `detect`) don't need locks
- **Batch operations** (`InstallMultiple` API) use a single lock for the entire batch
- Locks are automatically cleaned up when operations finish (success or failure)
- Interrupt signals (Ctrl+C) properly release locks to prevent deadlocks

</details>

<a id="signature-support"></a>
### Signature support

<details markdown="1"><summary><b>OpenTofu signature support</b></summary><br>

**tenv** checks the sha256 checksum and the signature of the checksum file with [cosign](https://github.com/sigstore/cosign) (if present on your machine) or PGP (via [gopenpgp](https://github.com/ProtonMail/gopenpgp)). However, unstable OpenTofu versions are signed only with cosign (in this case, if cosign is not found tenv will display a warning).

</details>

<details markdown="1"><summary><b>Terraform signature support</b></summary><br>

**tenv** checks the sha256 checksum and the PGP signature of the checksum file (via [gopenpgp](https://github.com/ProtonMail/gopenpgp), there is no cosign signature available).

</details>

<details markdown="1"><summary><b>Terragrunt signature support</b></summary><br>

**tenv** checks the sha256 checksum (there is no signature available).

</details>

<details markdown="1"><summary><b>Atmos signature support</b></summary><br>

**tenv** checks the sha256 checksum (there is no signature available).

</details>

<a id="verifying-signature"></a>
## Verifying tenv Signatures

You can use `cosign` to verify the signature of `tenv` releases. Below is an example installing the `.rpm` using `dnf` once we've verified the signatures/integrity.

> [!NOTE]
> The example below is a bash script that could be useful if you are wanting to automate installation of `tenv` in a developer environment. Adapt it to fit your specific use case.

```bash
# Get latest release
LATEST_VERSION=$(curl --silent https://api.github.com/repos/tofuutils/tenv/releases/latest | jq -r .tag_name) #v2.6.1

# Get checksum files
curl --silent -OL https://github.com/tofuutils/tenv/releases/download/${LATEST_VERSION}/tenv_${LATEST_VERSION}_checksums.txt
curl --silent -OL https://github.com/tofuutils/tenv/releases/download/${LATEST_VERSION}/tenv_${LATEST_VERSION}_checksums.txt.sig
curl --silent -OL https://github.com/tofuutils/tenv/releases/download/${LATEST_VERSION}/tenv_${LATEST_VERSION}_checksums.txt.pem

# Get RPM files
curl --silent -OL https://github.com/tofuutils/tenv/releases/download/${LATEST_VERSION}/tenv_${LATEST_VERSION}_amd64.rpm
curl --silent -OL https://github.com/tofuutils/tenv/releases/download/${LATEST_VERSION}/tenv_${LATEST_VERSION}_amd64.rpm.sig
curl --silent -OL https://github.com/tofuutils/tenv/releases/download/${LATEST_VERSION}/tenv_${LATEST_VERSION}_amd64.rpm.pem

# Verify signatures
cosign \
    verify-blob \
    --certificate-identity "https://github.com/tofuutils/tenv/.github/workflows/release.yml@refs/tags/${LATEST_VERSION}" \
    --signature "tenv_${LATEST_VERSION}_checksums.txt.sig" \
    --certificate "tenv_${LATEST_VERSION}_checksums.txt.pem" \
    --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
    "tenv_${LATEST_VERSION}_checksums.txt"

TENV_SIG_CHECK=$?

cosign \
    verify-blob \
    --certificate-identity "https://github.com/tofuutils/tenv/.github/workflows/release.yml@refs/tags/${LATEST_VERSION}" \
    --signature "tenv_${LATEST_VERSION}_amd64.rpm.sig" \
    --certificate "tenv_${LATEST_VERSION}_amd64.rpm.pem" \
    --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
    "tenv_${LATEST_VERSION}_amd64.rpm"

TENV_ASSET_CHECK=$?

# Check everything is good before installation
if [ "$TENV_SIG_CHECK" -eq "0" ] && [ "$TENV_ASSET_CHECK" -eq "0" ] && shasum -a 256 -c "tenv_${LATEST_VERSION}_checksums.txt" --ignore-missing
then
  dnf install "tenv_${LATEST_VERSION}_amd64.rpm" -y
  tenv --version
else
  echo "Signature verification and/or checksum checks failed!"
fi
```

<a id="contributing"></a>
## 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**.

Check out our [contributing guide](CONTRIBUTING.md) to get started.

Don't forget to give the project a star! Thanks again!

<a id="community"></a>
## Community
Have questions or suggestions? Reach out to us via:

* [GitHub Issues](LINK_TO_ISSUES)
* User/Developer Group: Join github community to get update of Harbor's news, features, releases, or to provide suggestion and feedback.
* Slack: Join tofuutils's community for discussion and ask questions: OpenTofu, channel: #tofuutils


<a id="authors"></a>
## Authors
tenv is based on [tofuenv](https://github.com/tofuutils/tofuenv) and [gotofuenv](https://github.com/tofuutils/gotofuenv) projects and supported by tofuutils team with help from these awesome contributors:

<!-- markdownlint-disable no-inline-html -->
<a href="https://github.com/tofuutils/tenv/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=tofuutils/tenv" />
</a>


<a href="https://star-history.com/#tofuutils/tenv&Date">
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=tofuutils/tenv&type=Date&theme=dark" />
    <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=tofuutils/tenv&type=Date" />
    <img alt="Star History Chart" src="https://api.star-history.com/svg?repos=tofuutils/pre-commit-opentofu&type=Date" />
  </picture>
</a>

<!-- markdownlint-enable no-inline-html -->

<a id="licence"></a>
## LICENSE
The tenv project is distributed under the Apache 2.0 license. See [LICENSE](LICENSE).
