https://github.com/yannlambret/tfs
A lightweight CLI tool for managing multiple Terraform versions
https://github.com/yannlambret/tfs
cli devops golang infrastructure-as-code linux macos terraform tooling version-manager
Last synced: 5 days ago
JSON representation
A lightweight CLI tool for managing multiple Terraform versions
- Host: GitHub
- URL: https://github.com/yannlambret/tfs
- Owner: yannlambret
- License: mit
- Created: 2021-12-20T12:14:14.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2026-01-06T09:20:46.000Z (about 1 month ago)
- Last Synced: 2026-01-12T00:32:53.307Z (28 days ago)
- Topics: cli, devops, golang, infrastructure-as-code, linux, macos, terraform, tooling, version-manager
- Language: Go
- Homepage:
- Size: 240 KB
- Stars: 3
- Watchers: 1
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README

[](https://goreportcard.com/report/github.com/yannlambret/tfs)

[](https://github.com/yannlambret/tfs/releases)
# tfs
`tfs` is a command-line tool that helps you manage multiple versions of Terraform efficiently.\
It was inspired by [this project](https://github.com/warrensbox/terraform-switcher).
`tfs` is simple, lightweight, and follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).
It works out of the box on all GNU/Linux distributions and macOS.
---
## Build & Install
```bash
git clone https://github.com/yannlambret/tfs.git && cd tfs
go mod tidy
go build -o build/tfs
```
Alternatively, you can download a prebuilt binary for your platform from the [Releases page](https://github.com/yannlambret/tfs/releases). \
Then place the resulting binary somewhere in your `PATH`.
---
## Usage
Here are a few examples of how to use the tool (assuming the current directory contains some Terraform manifest files):
### 🔄 Automatically use the appropriate Terraform version
```bash
tfs
```
Note: `tfs` now uses HashiCorp’s `hc-install` library to automatically download and install Terraform.\
It is thus no longer possible to download Terraform from alternative sources.
If no version constraint is detected, `tfs` will activate the most recently downloaded Terraform version.
### 📌 Use a specific Terraform version
If no Terraform version constraint is specified in the configuration, you can manually select
the version to use:
```bash
tfs 1.10.1
```
### 🎯 Respect Terraform version constraints (including `~>`)
When you run `tfs` without specifying a version, it inspects Terraform configuration files
in the current directory to infer which version to activate.
`tfs` understands standard comparison operators (`=`, `!=`, `>`, `>=`, `<`, `<=`) and also
supports the Terraform / HashiCorp pessimistic operator `~>` (sometimes called the "compatible with" operator).
Supported forms and their expansion:
```
~> 1 => >=1.0.0, <2.0.0
~> 1.2 => >=1.2.0, <1.3.0
~> 1.2.3 => >=1.2.3, <1.3.0
```
Multiple constraints are ANDed (`,` separator) and any `||` segments (if present) act as OR, following the semantics of the underlying `hashicorp/go-version` library.
Examples:
```
# Accept any 1.2.x (but not 1.3.0):
required_version = "~> 1.2"
# Accept patch upgrades starting at 1.2.5 (but still < 1.3.0):
required_version = "~> 1.2, >= 1.2.5"
# Accept any 1.x:
required_version = "~> 1"
# Mixed with other operators:
required_version = ">= 1.5.0, ~> 1.6"
```
Invalid uses (e.g. `~> 1.alpha`, `~> 1..2`, `~> ~> 1.2`) are rejected and will cause `tfs` to report an error instead of choosing a wrong version silently.
The `~>` constraints are internally expanded before being passed to the version resolver; this ensures consistent behavior without pulling additional parsing libraries.
> Tip: If no constraint is found, `tfs` simply activates the most recently downloaded Terraform version.
### 📂 List cached versions
```bash
tfs list
```
### 🧹 Clear the entire cache
```bash
tfs prune
```
### 🗑️ Remove versions older than a specific one
```bash
tfs prune-until 1.8.0
```
---
## Caching & Paths
By default, Terraform binaries are stored in `${XDG_CACHE_HOME}/tfs`\
If `XDG_CACHE_HOME` is not set, it defaults to `${HOME}/.cache/tfs`.
A symbolic link to the active Terraform binary is created at `${HOME}/.local/bin/terraform`,\
so make sure this directory is added to your `PATH`.
---
## Configuration
`tfs` supports a configuration file to customize behavior.\
By default, the configuration file is located at:
```
$XDG_CONFIG_HOME/tfs/config.yaml
```
If `XDG_CONFIG_HOME` is not set, it falls back to:
```
$HOME/.config/tfs/config.yaml
```
### Configuration Template
```yaml
# -- Cache Management
# Custom path for the Terraform cache directory.
# Default: "${XDG_CACHE_HOME}/tfs"
# Fallback: "${HOME}/.cache/tfs"
#cache_directory:
# Enable automatic cache cleanup.
cache_auto_clean: true # default value
# Maximum number of releases to keep in the cache (fallback mode).
cache_history: 8 # default value
# Advanced cache management:
# Keep a limited number of releases per minor version,
# and a limited number of patch versions within each minor.
#
# For example, with the config below, you might keep:
# * 1.9.3
# * 1.9.5
# * 1.10.2
# * 1.10.3
# * 1.11.0
#
# When both values are defined, cache_history is ignored.
#cache_minor_version_nb: 3
#cache_patch_version_nb: 2
```
---
## Advanced Cache Behavior
`tfs` tries to preserve the current version in use — even if it would otherwise be cleaned up.
Consider this scenario (using the config above):
```bash
$ tfs prune # The cache is now empty
$ tfs 1.10.2
$ tfs 1.10.3
```
Now the cache contains:
```bash
$ tfs list
1.10.2
1.10.3 (active)
```
Let’s install one more version:
```bash
$ tfs 1.10.4
```
Since you want to keep at most two patch versions, `1.10.2` is removed:
```bash
$ tfs list
1.10.3
1.10.4 (active)
```
Now, suppose you need to work with `1.10.1`:
```bash
$ tfs 1.10.1
```
Even though `1.10.1` falls outside the patch retention window, `tfs` will **not** delete it immediately, because it’s now the **active** version.
```bash
$ tfs list
1.10.1 (active)
1.10.3
1.10.4
```
But as soon as you switch again:
```bash
$ tfs 1.10.4
$ tfs list
1.10.3
1.10.4 (active)
```
Now `1.10.1` is cleaned up, as expected.
---
## License
MIT © [Yann Lambret](https://github.com/yannlambret)