gvm is a per-user Go version manager implemented in Go. It installs and selects Go SDKs, prepares project-specific environments, manages Go tools, and runs binaries with the selected environment.
Supported platforms:
- Linux: amd64, arm64
- macOS: amd64, arm64
- Windows: amd64, arm64
- Install Go SDKs from the official Go download metadata.
- Install the latest stable Go SDK with
gvm install latest. - Verify SDK archives with SHA-256 checksums before installation.
- Select global and project-local Go versions.
- Discover
.gvmrcfiles from the current directory up to the filesystem root. - Use safe dotenv configuration without shell evaluation or command execution.
- Create project virtual environments in
.venv/bin. - Install tools from repeated
GVM_TOOLentries. - Run binaries with deterministic, deduplicated
PATHordering. - List and remove installed SDK versions.
- Update the
gvm,go, andgofmtmanager binaries from GitHub Releases. - Use managed
goandgofmtwrappers with recursive-launch protection.
The installer uses the latest GitHub Release and configures .profile, .bashrc, and .zshrc.
curl --fail --location https://raw.githubusercontent.com/osspkg/gvm/master/install.sh | bashTo use a custom installation directory:
export GVM_HOME="$HOME/tools/gvm"
curl --fail --location https://raw.githubusercontent.com/osspkg/gvm/master/install.sh | bashOpen a new shell, or reload the profile after installation:
source "$HOME/.profile"The installer downloads the latest Windows release, sets the user-level GVM_HOME and PATH, and updates the PowerShell profile.
irm https://raw.githubusercontent.com/osspkg/gvm/master/install.ps1 | iexFor a custom installation directory:
$env:GVM_HOME = Join-Path $HOME "tools\gvm"
irm https://raw.githubusercontent.com/osspkg/gvm/master/install.ps1 | iexStart a new PowerShell session after installation.
Select a global Go version and use it in a project:
gvm default 1.22.0
mkdir -p ~/src/example
cd ~/src/example
gvm local 1.22.0
go versionCreate a project environment with tools:
cat > .gvmrc <<'EOF'
GVM_GO_VERSION=1.22.0
GVM_VENV=true
GVM_TOOL=golang.org/x/tools/gopls@latest
GVM_TOOL=honnef.co/go/tools/cmd/staticcheck@latest
GOPROXY=https://proxy.golang.org
EOF
gvm venv
go version
gvm run gopls versiongvm venv creates .venv/bin, adds .venv/ to .gitignore, and installs the configured tools into the project environment.
For every newly installed SDK, gvm preserves the official executables as bin/go.bin and bin/gofmt.bin, then places the gvm go and gofmt wrappers at bin/go and bin/gofmt. This keeps IDEs that discover the SDK by its GOROOT path inside the managed environment. Existing SDKs are not migrated; the behavior applies only to newly installed SDKs.
The go and gofmt wrappers pass the internal GVM_WRAPPER_ACTIVE=1 marker to the real Go process. If another managed wrapper is invoked from that process, it directly uses the matching GOROOT/bin/<tool>.bin and does not resolve the configuration again.
| Command | Description |
|---|---|
| `gvm install [version | latest]` |
gvm list |
List complete SDKs installed in $GVM_HOME/.cache/src. |
gvm rm <version> |
Remove one installed SDK, for example gvm rm 1.21.0. |
gvm remove-all |
Remove all installed SDKs while preserving tools, module cache, and configuration. |
gvm default <version> |
Install an SDK and configure the global $GVM_HOME/.gvmrc. |
gvm local [version] |
Install an SDK and configure .gvmrc in the current directory. Without a version, infer it from go.work first, then go.mod. |
gvm venv |
Create .venv/bin, enable GVM_VENV=true, and install configured tools. |
gvm run <binary> [args...] |
Run a binary using the active SDK environment. |
gvm update |
Update or repair the gvm, go, and gofmt manager binaries from the latest GitHub Release. |
gvm version |
Print the gvm version. |
go [args...] |
Run the selected Go SDK with the active environment. |
gofmt [args...] |
Run the selected SDK's gofmt with the active environment. |
gvm rm accepts a Go version, not a filesystem path. It does not edit .gvmrc; if the removed version remains selected, the next go invocation may install it again.
gvm install latest queries the official Go metadata and installs the newest stable release available for the current platform.
GVM_HOME selects the per-user installation directory. If it is not set, gvm uses:
$HOME/.gvm
The installers export GVM_HOME and prepend $GVM_HOME/bin to PATH in the supported shell or PowerShell profiles.
.gvmrc is a restricted dotenv file. It is parsed as data and is never sourced by a shell. Shell commands, command substitution, and executable expressions are not evaluated.
Example:
GVM_GO_VERSION=1.22.0
GVM_VENV=true
GVM_TOOL=golang.org/x/tools/gopls@latest
GVM_TOOL=honnef.co/go/tools/cmd/staticcheck@latest
GOPROXY=https://proxy.golang.orgConfiguration resolution works as follows:
- Process environment values have the highest priority.
- The nearest
.gvmrcin the current directory or a parent directory is selected. - If no local
.gvmrcexists,$GVM_HOME/.gvmrcis used. GVM_VENVdefaults tofalseandGVM_TOOLdefaults to empty.GVM_GO_VERSIONis required; there is no implicit Go SDK version for normalgoinvocations.
Repeated GVM_TOOL entries are preserved in order. The legacy plain-text format containing only a version number is invalid and is not migrated automatically.
The former plural key GVM_TOOLS is not migrated; rename it manually to GVM_TOOL in existing .gvmrc files.
When gvm local is called without a version, it searches the current directory and its parents for go.work first, then go.mod. The first valid go directive becomes GVM_GO_VERSION; if both files are available, go.work wins. Passing a version explicitly remains an override.
For the active SDK, gvm computes these variables:
GOROOT=$GVM_HOME/.cache/src/go<version>
GOPATH=$GVM_HOME/.cache
GOMODCACHE=$GVM_HOME/.cache/pkg
GOBIN=$GVM_HOME/.cache/bin
When GVM_VENV=true, GOBIN becomes <project>/.venv/bin.
The managed PATH order is (the active SDK bin is included after the global tool bin):
<project>/.venv/bin # when GVM_VENV=true
$GVM_HOME/.cache/bin
$GVM_HOME/.cache/src/go<version>/bin
$GVM_HOME/bin
inherited PATH without empty entries or duplicates
The path separator is selected for the host platform automatically.
$GVM_HOME/
├── bin/
│ ├── gvm
│ ├── go
│ └── gofmt
└── .cache/
├── bin/ # global tools installed with go install
├── pkg/ # Go module cache
└── src/
└── go<version>/ # installed Go SDK; bin/go and bin/gofmt are gvm wrappers
# bin/go.bin and bin/gofmt.bin are the official SDK executables
Project-local state:
<project>/
├── .gvmrc
├── .gitignore
└── .venv/
└── bin/
gvm venv adds .venv/ to .gitignore idempotently.
gvm run, the go wrapper, and the gofmt wrapper use the same environment construction. Binary lookup order is:
<project>/.venv/bin$GVM_HOME/.cache/bin$GVM_HOME/.cache/src/go<version>/bin$GVM_HOME/bin- The inherited
PATH
Each path is included once, and empty path components are removed.
gvm update retrieves the latest release from github.com/osspkg/gvm, selects the archive for the current operating system and architecture, verifies checksums.txt, and updates or repairs only the manager binaries (gvm, go, and gofmt); if one is missing, the current release is downloaded again. Installed Go SDKs are not modified.
Release archives use these names:
gvm_<version>_<os>_<arch>.tar.gz # Linux and macOS
gvm_<version>_<os>_<arch>.zip # Windows
The release workflow publishes builds for all six supported targets and includes SHA-256 checksums.
Requirements:
- Go 1.26.8 or newer
- Bash for the Unix installer and local CI commands
Run the standard checks:
go fmt ./...
go test ./...
go test -race ./...
go vet ./...
git diff --checkBuild the command binaries:
go build -o bin/gvm ./cmd/gvm
go build -o bin/go ./cmd/go
go build -o bin/gofmt ./cmd/gofmtCross-compile an individual target:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build ./cmd/gvmCI configuration is in .github/workflows/ci.yml, and release packaging is in .github/workflows/release.yml.
Bug reports, feature requests, and pull requests are welcome. Please include the platform, architecture, Go version, command used, and relevant error output when reporting a problem.
gvm is distributed under the BSD 3-Clause License.