getRelease is a Go CLI for downloading GitHub release assets, extracting archives, installing binaries, and tracking what was installed so later upgrades can be automated. It can target a repository by owner and repo name or by full GitHub URL, prefers assets that match the current platform, and falls back to interactive selection when more than one candidate fits.
- Install the latest release or a specific tag from any GitHub repository.
- Target repositories with
--ownerand--repoor a single--url. - Match assets by operating system, architecture, and preferred archive formats.
- Auto-select the best asset when there is a clear winner, otherwise prompt interactively.
- Extract common archive formats including
.tar.gz,.tar.xz,.tar.bz2,.tar, and.zip. - Install one binary or multiple binaries from the selected asset.
- Rename a single installed binary with
--install-as. - Skip installation and keep the downloaded payload with
--download-only. - Track install history for upgrades, version pinning, shell completion, and cleanup workflows.
- Upgrade one installed package or every installed package still present on disk.
- Manage config and history from built-in
configandhistorysubcommands. - Emit machine-readable JSON from the main install flow and list/history/config commands.
- Enforce a release cooldown by default to harden against supply-chain attacks, with per-run and per-owner overrides.
- Download the binary for your preferred platform from the releases page
- Extract the archive. It contains this readme, a copy of the Apache 2.0 license, and the getRelease binary.
- Copy the binary to a directory in your
$PATH. i.e./usr/local/bin
Install the latest release for a repository:
getRelease --owner sharkdp --repo batInstall a specific tagged release:
getRelease --owner junegunn --repo fzf --tag 0.66.0Resolve the repository from a GitHub URL instead of separate flags:
getRelease --url https://github.com/junegunn/fzfDownload an asset without installing it:
getRelease --owner sharkdp --repo fd --download-onlyInstall a single binary under a different name:
getRelease --owner sharkdp --repo bat --install-as bat-previewList recent releases for a repository:
getRelease list --owner JakeTRogers --repo timeBuddyList the assets for a specific release tag:
getRelease list --owner JakeTRogers --repo timeBuddy --tag v2.0.0Preview an upgrade without changing anything:
getRelease upgrade timeBuddy --dry-runUpgrade every installed package that still exists on disk:
getRelease upgrade --allPin an installed package to its current minor line:
getRelease pin timeBuddy --level minorRemove version pinning from an installed package:
getRelease unpin timeBuddypin works on tracked installs from local history. Pin levels mean:
patch: stay on the current exact releaseminor: allow patch updates within the current minor linemajor: allow minor and patch updates within the current major line
When a pinned package has no eligible newer release inside its allowed range, upgrade and upgrade --all report it as unchanged instead of failed.
Inspect tracked installs:
getRelease history listhistory list shows the current pin policy in the PIN column using -, patch, minor, or major.
Prune history records for binaries that are no longer installed:
getRelease history pruneShow the effective configuration:
getRelease config showSet preferred archive formats:
getRelease config set assetPreferences.formats '["tar.gz","zip"]'The CLI stores configuration with Viper precedence rules:
- CLI flags
- Environment variables prefixed with
GETRELEASE_ config.yaml- Built-in defaults
Common environment variable examples:
export GETRELEASE_INSTALLDIR="$HOME/.local/bin"
export GETRELEASE_ASSETPREFERENCES_FORMATS='["tar.gz","zip"]'A freshly published release is the riskiest thing you can install: if a repository is compromised, the malicious release is usually detected and yanked within days. To give the ecosystem that window, getRelease refuses to install releases younger than the cooldown — 10 days by default.
When the latest release is still inside the cooldown, getRelease automatically falls back to the newest release that is old enough:
release v1.4.0 is 2 day(s) old, cooldown is 10 days — falling back to v1.3.2
An explicit --tag request has no fallback and fails instead, and the check also covers the selected asset's upload time — a binary re-uploaded onto an old release (a common tampering pattern) is refused even though the release itself is old enough.
Change the cooldown or opt out:
# one-off: disable (or change) the cooldown for a single run
getRelease --owner sharkdp --repo bat --cooldown 0
# permanently change the window (0 disables it entirely)
getRelease config set cooldown 5
# or via environment variable
export GETRELEASE_COOLDOWN=5
# skip the cooldown for owners you trust (e.g. your own repos); case-insensitive
getRelease config set trustedOwners 'JakeTRogers'API requests are anonymous by default, which is subject to GitHub's 60 requests/hour per-IP rate limit. To authenticate (5,000 requests/hour, plus access to private-repo releases), getRelease uses the first token it finds:
- The
tokenconfig key, or theGETRELEASE_TOKENenvironment variable - The
GH_TOKENenvironment variable - The
GITHUB_TOKENenvironment variable (set automatically in GitHub Codespaces and Actions) - The gh CLI's stored credentials, via
gh auth token
If none are found, requests silently fall back to anonymous. Prefer environment variables or gh over storing a token in config.yaml; config show redacts the token either way.
getRelease targets github.com by default. Targeting a GitHub Enterprise Cloud tenant with data residency (a *.ghe.com host) is always explicit — environment variables like GH_HOST are deliberately ignored so an ambient setting can never silently retarget a command:
# the URL's host is used directly
getRelease --url https://acme.ghe.com/acme/tool
# or name the host explicitly with --owner/--repo
getRelease --owner acme --repo tool --host acme.ghe.comThe host a package was installed from is recorded in install history, so getRelease upgrade, and later --owner/--repo invocations for that same package, target the right host automatically without repeating --host.
getRelease derives the REST API endpoint (https://api.acme.ghe.com) and web URLs from the host, and passes --hostname to gh auth token so the right stored credentials are used. Self-hosted GitHub Enterprise Server (with a customer-owned domain and /api/v3 path) is not supported.
The main commands are:
getRelease: download, extract, and install a release assetgetRelease list: list recent releases or release assetsgetRelease upgrade: upgrade an installed package from recorded historygetRelease pin: pin an installed package to the current patch, minor, or major linegetRelease unpin: remove version pinning from an installed packagegetRelease history: inspect and maintain install historygetRelease config: inspect and change configurationgetRelease version: print version and platform information
getRelease uses Cobra's built-in completion command, so you can install shell completion with the standard Cobra flow:
# Bash
source <(getRelease completion bash)
# Zsh
source <(getRelease completion zsh)
# Fish
getRelease completion fish | source
# PowerShell
getRelease completion powershell | Out-String | Invoke-ExpressionThe completion callbacks are extended to read local install history. That gives you history-backed suggestions for commands such as:
getRelease -o <TAB>
getRelease -o JakeTRogers -r <TAB>
getRelease upgrade <TAB>
getRelease pin <TAB>
getRelease upgrade -o <TAB>upgrade, pin, and unpin target suggestions are limited to binaries that are still installed on disk. The pin --level flag completes patch, minor, and major.
Generate completion scripts explicitly if you prefer to install them into your shell startup files:
getRelease completion bash
getRelease completion zsh
getRelease completion fish
getRelease completion powershell- Asset selection is automatic when there is exactly one match or one clearly preferred match for the current platform.
- When an archive contains multiple binaries, the CLI can install all of them or prompt you to choose one.
- Install history is what powers
upgrade,pin,unpin, owner and repo completion, and installed-target suggestions.
go test ./... -vgo test ./... -coverprofile=coverage.out
go tool cover -html=coverage.outThis project uses pre-commit hooks to ensure code quality. The hooks run:
- go test: Runs all tests with race detection
- go test coverage: Ensures cmd package maintains ≥85% coverage
- golangci-lint: Comprehensive Go linting
- commitizen: Enforces conventional commit messages
To install pre-commit hooks:
# Install pre-commit (if not already installed)
pip install pre-commit
# Install the git hooks
pre-commit install --hook-type pre-commit --hook-type commit-msg
# Run hooks manually on all files
pre-commit run --all-filesThe hooks will automatically run before each commit. To skip hooks temporarily:
git commit --no-verify