{"id":36451444,"url":"https://github.com/yannlambret/tfs","last_synced_at":"2026-02-15T23:16:47.079Z","repository":{"id":66992404,"uuid":"440158433","full_name":"yannlambret/tfs","owner":"yannlambret","description":"A lightweight CLI tool for managing multiple Terraform versions","archived":false,"fork":false,"pushed_at":"2026-02-03T18:50:09.000Z","size":253,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-02-04T08:04:52.356Z","etag":null,"topics":["cli","devops","golang","infrastructure-as-code","linux","macos","terraform","tooling","version-manager"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yannlambret.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-12-20T12:14:14.000Z","updated_at":"2026-02-03T18:48:27.000Z","dependencies_parsed_at":null,"dependency_job_id":"f3e29d7e-5a44-4744-986c-868860792b02","html_url":"https://github.com/yannlambret/tfs","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/yannlambret/tfs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannlambret%2Ftfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannlambret%2Ftfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannlambret%2Ftfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannlambret%2Ftfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yannlambret","download_url":"https://codeload.github.com/yannlambret/tfs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yannlambret%2Ftfs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29492045,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-15T19:29:10.908Z","status":"ssl_error","status_checked_at":"2026-02-15T19:29:10.419Z","response_time":118,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","devops","golang","infrastructure-as-code","linux","macos","terraform","tooling","version-manager"],"created_at":"2026-01-11T22:56:48.840Z","updated_at":"2026-02-15T23:16:47.055Z","avatar_url":"https://github.com/yannlambret.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"![go test](https://github.com/yannlambret/tfs/actions/workflows/test.yml/badge.svg)\n[![go report](https://goreportcard.com/badge/github.com/yannlambret/tfs)](https://goreportcard.com/report/github.com/yannlambret/tfs)\n![go version](https://img.shields.io/github/go-mod/go-version/yannlambret/tfs?label=go%20version)\n[![release](https://img.shields.io/github/v/release/yannlambret/tfs?label=release)](https://github.com/yannlambret/tfs/releases)\n\n# tfs\n\n`tfs` is a command-line tool that helps you manage multiple versions of Terraform efficiently.\\\nIt was inspired by [this project](https://github.com/warrensbox/terraform-switcher).\n\n`tfs` is simple, lightweight, and follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).\n\nIt works out of the box on all GNU/Linux distributions and macOS.\n\n---\n\n## Build \u0026 Install\n\n```bash\ngit clone https://github.com/yannlambret/tfs.git \u0026\u0026 cd tfs\ngo mod tidy\ngo build -o build/tfs\n```\nAlternatively, you can download a prebuilt binary for your platform from the [Releases page](https://github.com/yannlambret/tfs/releases). \\\nThen place the resulting binary somewhere in your `PATH`.\n\n---\n\n## Usage\n\nHere are a few examples of how to use the tool (assuming the current directory contains some Terraform manifest files):\n\n### 🔄 Automatically use the appropriate Terraform version\n\n```bash\ntfs\n```\n\nNote: `tfs` now uses HashiCorp’s `hc-install` library to automatically download and install Terraform.\\\nIt is thus no longer possible to download Terraform from alternative sources.\n\nIf no version constraint is detected, `tfs` will activate the most recently downloaded Terraform version.\n\n### 📌 Use a specific Terraform version\nIf no Terraform version constraint is specified in the configuration, you can manually select\nthe version to use:\n\n```bash\ntfs 1.10.1\n```\n\n### 🎯 Respect Terraform version constraints (including `~\u003e`)\n\nWhen you run `tfs` without specifying a version, it inspects Terraform configuration files\nin the current directory to infer which version to activate.\n\n`tfs` understands standard comparison operators (`=`, `!=`, `\u003e`, `\u003e=`, `\u003c`, `\u003c=`) and also\nsupports the Terraform / HashiCorp pessimistic operator `~\u003e` (sometimes called the \"compatible with\" operator).\n\nSupported forms and their expansion:\n\n```\n~\u003e 1        =\u003e \u003e=1.0.0, \u003c2.0.0\n~\u003e 1.2      =\u003e \u003e=1.2.0, \u003c1.3.0\n~\u003e 1.2.3    =\u003e \u003e=1.2.3, \u003c1.3.0\n```\n\nMultiple constraints are ANDed (`,` separator) and any `||` segments (if present) act as OR, following the semantics of the underlying `hashicorp/go-version` library.\n\nExamples:\n\n```\n# Accept any 1.2.x (but not 1.3.0):\nrequired_version = \"~\u003e 1.2\"\n\n# Accept patch upgrades starting at 1.2.5 (but still \u003c 1.3.0):\nrequired_version = \"~\u003e 1.2, \u003e= 1.2.5\"\n\n# Accept any 1.x:\nrequired_version = \"~\u003e 1\"\n\n# Mixed with other operators:\nrequired_version = \"\u003e= 1.5.0, ~\u003e 1.6\"\n```\n\nInvalid uses (e.g. `~\u003e 1.alpha`, `~\u003e 1..2`, `~\u003e ~\u003e 1.2`) are rejected and will cause `tfs` to report an error instead of choosing a wrong version silently.\n\nThe `~\u003e` constraints are internally expanded before being passed to the version resolver; this ensures consistent behavior without pulling additional parsing libraries.\n\n\u003e Tip: If no constraint is found, `tfs` simply activates the most recently downloaded Terraform version.\n\n### 📂 List cached versions\n\n```bash\ntfs list\n```\n\n### 🧹 Clear the entire cache\n\n```bash\ntfs prune\n```\n\n### 🗑️ Remove versions older than a specific one\n\n```bash\ntfs prune-until 1.8.0\n```\n\n---\n\n## Caching \u0026 Paths\n\nBy default, Terraform binaries are stored in `${XDG_CACHE_HOME}/tfs`\\\nIf `XDG_CACHE_HOME` is not set, it defaults to `${HOME}/.cache/tfs`.\n\nA symbolic link to the active Terraform binary is created at `${HOME}/.local/bin/terraform`,\\\nso make sure this directory is added to your `PATH`.\n\n---\n\n## Configuration\n\n`tfs` supports a configuration file to customize behavior.\\\nBy default, the configuration file is located at:\n\n```\n$XDG_CONFIG_HOME/tfs/config.yaml\n```\n\nIf `XDG_CONFIG_HOME` is not set, it falls back to:\n\n```\n$HOME/.config/tfs/config.yaml\n```\n\n### Configuration Template\n\n```yaml\n# -- Cache Management\n\n# Custom path for the Terraform cache directory.\n# Default: \"${XDG_CACHE_HOME}/tfs\"\n# Fallback: \"${HOME}/.cache/tfs\"\n#cache_directory: \u003cCUSTOM_PATH\u003e\n\n# Enable automatic cache cleanup.\ncache_auto_clean: true # default value\n\n# Maximum number of releases to keep in the cache (fallback mode).\ncache_history: 8 # default value\n\n# Advanced cache management:\n# Keep a limited number of releases per minor version,\n# and a limited number of patch versions within each minor.\n#\n# For example, with the config below, you might keep:\n#   * 1.9.3\n#   * 1.9.5\n#   * 1.10.2\n#   * 1.10.3\n#   * 1.11.0\n#\n# When both values are defined, cache_history is ignored.\n#cache_minor_version_nb: 3\n#cache_patch_version_nb: 2\n```\n\n---\n\n## Advanced Cache Behavior\n\n`tfs` tries to preserve the current version in use — even if it would otherwise be cleaned up.\n\nConsider this scenario (using the config above):\n\n```bash\n$ tfs prune  # The cache is now empty\n\n$ tfs 1.10.2\n$ tfs 1.10.3\n```\n\nNow the cache contains:\n\n```bash\n$ tfs list\n1.10.2\n1.10.3 (active)\n```\n\nLet’s install one more version:\n\n```bash\n$ tfs 1.10.4\n```\n\nSince you want to keep at most two patch versions, `1.10.2` is removed:\n\n```bash\n$ tfs list\n1.10.3\n1.10.4 (active)\n```\n\nNow, suppose you need to work with `1.10.1`:\n\n```bash\n$ tfs 1.10.1\n```\n\nEven though `1.10.1` falls outside the patch retention window, `tfs` will **not** delete it immediately, because it’s now the **active** version.\n\n```bash\n$ tfs list\n1.10.1 (active)\n1.10.3\n1.10.4\n```\n\nBut as soon as you switch again:\n\n```bash\n$ tfs 1.10.4\n$ tfs list\n1.10.3\n1.10.4 (active)\n```\n\nNow `1.10.1` is cleaned up, as expected.\n\n---\n\n## License\n\nMIT © [Yann Lambret](https://github.com/yannlambret)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyannlambret%2Ftfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyannlambret%2Ftfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyannlambret%2Ftfs/lists"}