NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Go modules · #2348 by repository stars
Last release 10 days ago
28 Sep 2026
Release timing varies
gaps range from 8 days to 2 months
Nearly every release is documented
notes for 60 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
5 years old
147 releases · first in 2022
One column per quarter.
Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.10.2...v1.10.3
gup pin TOOL@VERSION with more than one @, such as gup pin tool@v1@v1.2.3, is rejected with specify the version once, the error gup pin tool@v1 v1.2.3 already gave. Only the last @ split the argument, so the target became tool@v1 and the command failed with 'tool@v1' is not managed by gup, which does not name the mistake.multiple.intoto.jsonl), which slsa-verifier verify-artifact checks against a downloaded archive, verifying its signature against the Sigstore transparency log. The release run verifies every published archive against it before finishing. The GitHub attestation checked by gh attestation verify is still published.Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.10.1...v1.10.2
gup update no longer lowers the Go a binary is built with. It ran go install with the local go command, so a binary built with go1.26.6 and updated on a machine with go1.26.4 came back built with go1.26.4, losing the fixes of the newer Go. gup now asks the go command for at least the Go the binary was built with (GOTOOLCHAIN=<that version>+auto), which the go command downloads like any toolchain a module requires. This covers every reinstall: a new module version, a Go-only rebuild, a pinned version and gup migrate. When GOTOOLCHAIN rules out downloads (local, path or a fixed version), gup keeps that setting and prints a warning that the Go went down. When that Go cannot be downloaded, or the go command's toolchain setting cannot be read, the package fails with an error instead of being rebuilt with the older Go.gup update reinstalls from its latest, main or master channel, the Go version it reports, in the line and in installed_go_version with --json, is now read from the rebuilt binary. gup printed the local Go version, so a binary the go command built with a newer toolchain because its module requires one was shown as built with the older local Go, e.g. go1.26.8 to go1.26.4 for a binary still built with go1.26.8.Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.10.0...v1.10.1
gup pin accepted any string that was not empty or a channel keyword, so gup pin tool v1, gup pin tool v1.2, a branch name such as release, a commit hash, or a query such as >=v1.2.0 was saved, and every later gup update ran go install <path>@<that>, which the go command resolves to whatever it points at that day: a pin to v1 installed the newest v1.x.y. gup pin and every command that reads or writes gup.json (so a hand-edited file cannot bypass it) now accept only a canonical Go module version, checked with golang.org/x/mod: a full vMAJOR.MINOR.PATCH, optionally with a prerelease, +incompatible for major version 2 or later, or a well-formed pseudo-version, which is how to pin a commit. The check is still syntactic and offline, so it needs neither the network nor the go command. An existing gup.json with such a pin now makes update, import, check and the other readers fail with the file, the tool, the value and the fix (set the entry's version to a full version or pseudo-version, or its channel to latest to unpin it), instead of installing it; gup never falls back to @latest or unpins on its own.Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.9.4...v1.10.0
gup update --exclude ... on a machine with no Go binaries exits 0, the same first-run success it is without --exclude, and excluding every installed binary is reported as nothing to update (exit 0) rather than a usage error (#422). --exclude is a filter: it only takes binaries away, so what it leaves cannot be the user's mistake. The exit 1 mattered most to Topgrade, which passes the user's gup_exclude list on every machine and reports the whole Go step as failed on a non-zero exit, so a fresh machine with gup installed from a package manager and an exclude list failed every run. Naming a binary that is not installed as a positional target is still a usage error.gup import of a gup.json with no packages succeeds as a no-op and names the file it read, instead of failing with unable to import package: no package information. That is the file gup export writes on an empty $GOBIN, so the export/import round trip now holds there too (#422). Thanks to @pentaoa, who proposed this fix first in #477.not found 'lazygti' ...; did you mean 'lazygit'? for update and check targets, and --exclude 'lazygti' matches no installed binary; did you mean 'lazygit'? on STDERR for update --exclude, where a typo would otherwise update the very tool it meant to hold back. An excluded name with nothing close stays silent, so an exclude list shared between machines does not warn on every run.Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.9.3...v1.9.4
go 1.26.0, and Go 1.26 and 1.27 are the two releases the Go team still supports. Prebuilt binaries and packages are unaffected.Nothing published for this version
Nothing published for this version
Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.9.2...v1.9.3
gup update --dry-run and gup import --dry-run remove their temporary directory again when $GOBIN is unset, instead of failing at the end with temporary directory for dry run remains: unlinkat ...: permission denied and leaving a whole module cache behind in $TMPDIR (#488). Without $GOBIN, a dry run points $GOPATH at the temporary directory so nothing is installed into the real one, which also puts the module cache there, and the go command extracts every module read-only. os.RemoveAll cannot unlink an entry of a read-only directory, so the removal stopped at the first module. gup now restores the owner's write bits across that tree first, the way go clean -modcache does, without following symbolic links out of it. A shared GOMODCACHE or a set $GOBIN never put the cache there, which is why the end-to-end suite, which sets both, never saw it; it now has a scenario with neither.Nothing published for this version
Nothing published for this version
Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.9.1...v1.9.2
gup remove <tool> < /dev/null refuses up front and names --force, instead of printing the confirmation prompt and then failing on the EOF that comes straight back. Whether a confirmation may be asked for was decided from stdin's file mode, and /dev/null carries the same ModeDevice|ModeCharDevice bits a terminal does, so the guard added for a non-TTY stdin never fired for it. The distinction between a terminal and any other character device exists only in the kernel, and gup now asks it. A redirect from a regular file or a pipe was already refused correctly; a device file was the one shape that reached the prompt.scoop bucket add nao1215 https://github.com/nao1215/gup no longer has anything to install. It reached nobody: a bucket hosted in its own repository is not in Scoop's known-bucket list, so scoop search gup never found it, and getting to it meant reading gup's README, already using Scoop, and preferring it to winget. Meanwhile Windows users were being served without it — v1.8.1's Windows archives were downloaded 113 times while the bucket held no gup manifest at all, because the first one only shipped with v1.9.1. Against that, it was the only publishing step a release could not finish on its own, and it is what failed v1.9.0 partway through, costing that tag the build provenance it can never be given now. winget install --id nao1215.gup and the release archives are unaffected, and anyone who added the bucket can drop it with scoop bucket rm nao1215.Nothing published for this version
Nothing published for this version
Nothing published for this version
Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.9.0...v1.9.1
checksums.txt and its cosign signature verify as always, and the SBOMs are attached - but the attestation step never ran, so gh attestation verify has nothing to check against for that tag and the release notes' promise of build provenance does not hold for it. Provenance is a claim the workflow run that produced an artifact makes about it, and that run has ended, so v1.9.0's binaries cannot be given one that says anything about how they were built. v1.9.1 builds the same code again and attests that.bucket/gup.json was committed straight to main, which is protected with admin enforcement, so v1.9.0's release job was refused with "Changes must be made through a pull request" — after the release itself had published, and before the step that attests build provenance, which therefore never ran. The Scoop bucket had been added since the previous tag, so v1.9.0 was the first release to exercise it. The manifest now arrives as a scoop-gup-<version> pull request, opened by a personal access token rather than the workflow's own: GitHub starts no workflow runs for events that token causes, so a pull request it opened would have every required check reported as never-run and could not be merged by anyone.Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.8.1...v1.9.0
update, import, export, remove, migrate, pin, unpin — now take a lock on every resource the operation involves, so a second gup refuses to start rather than interleaving with the first and losing one of the two results. That includes resources a command only reads when what it writes is derived from them: export and pin lock the $GOBIN they describe, and migrate locks BEFORE_PATH as well as AFTER_PATH, because a gup remove running halfway through the scan would otherwise produce a result describing a tool set that never existed. Locks are scoped to the resource (a $GOBIN, a gup.json) rather than to the config directory, so processes started from different config directories still serialize over a shared $GOBIN or a shared --file. Read-only commands and --dry-run runs take no lock and never wait.flock on Linux and macOS, LockFileEx on Windows — held on a file gup keeps open for as long as it holds the resource. It is therefore released by the kernel the moment the holding process ends, however it ends: a gup killed with kill -9, a machine that lost power mid-update, or a lock file copied from another machine blocks nothing, and there is never a stale lock for anyone to delete by hand. gup leaves the empty .gup.lock / gup.json.lock file in place between runs on purpose — deleting a file another gup may already have opened is what would let two processes lock two different files at one path.gup completion --install sets up PowerShell completion on Windows instead of refusing and printing three manual steps. PowerShell has no completion directory the way bash, fish and zsh do, so gup writes gup.completion.ps1 beside your profile and dot-sources it from one marked block in the profile itself. Nothing outside the markers is touched, a re-run replaces the block in place rather than appending a second copy, and the dot-source is guarded so a profile copied to a machine without gup still opens a working shell. Which profile it is matters more than it looks: PowerShell 5.1 and 7 read different paths, so gup honors an exported $PROFILE, otherwise prefers whichever standard location already has one (including a OneDrive-redirected Documents), and creates the PowerShell 7 path only when there is nothing to prefer.gup remove .gup.lock --force no longer deletes gup's own lock file. .gup.lock is now a reserved name that gup remove refuses on every platform. Removing it did not free the running command's lock — that lives on an open descriptor — but it freed the name, so the next gup created its own file there and locked that instead, and two commands rewrote one $GOBIN each believing it had exclusive access.gup.json.lock pointing at any file gup can write — used to empty that file, with the command reporting success. The lock path is now opened with the operating system's own no-follow open (O_NOFOLLOW on Linux and macOS, FILE_FLAG_OPEN_REPARSE_POINT on Windows), which refuses the link inside the open rather than after a check something could race, and the file kind is read back from the descriptor so a FIFO or a device at the lock path is refused too.gup.json.lock made a second name for gup.json lands on an ordinary regular file, passes every check a symlink fails, and gup then truncates it to record who holds the lock — emptying the user's config, writing owner JSON over it, and reporting success. It also left the lock held on the config file's own inode, which the next atomic rewrite of gup.json orphans, so the lock stopped naming the resource it guarded. gup now refuses a lock path whose file has more than one name (st_nlink on Linux and macOS, NumberOfLinks on Windows, both read from the open descriptor rather than from the path), because a lock file gup created has exactly one. Two spellings that reach one file — a symlinked directory, a $GOBIN capitalized differently — are still one lock, not a refusal.gup remove refuses gup's lock file by the file it reaches, not only by the name typed. The name check was a string comparison, and a name reaches a file in ways a string comparison does not cover: Windows strips trailing dots and spaces before the filesystem sees the name (so .gup.lock. is .gup.lock, and $GOEXE=. made gup compose that spelling itself), NTFS answers to an 8.3 alias, and a hard link is a second name by construction. The last question asked before the delete is now whether the file is the lock file. The name check also folds trailing dots and spaces on every platform, so the refusal reads the same everywhere.gup migrate BEFORE AFTER with AFTER a symlink to BEFORE — or a $GOBIN spelled two ways on the case-insensitive filesystems macOS and Windows use — put the same file in the set twice: gup took the kernel lock, asked for the same file again on a second descriptor, waited out the whole timeout and reported itself as another gup process, so the command could never succeed. A lock is now identified by the filesystem's identity for the file (st_dev/st_ino, the volume serial and file index on Windows) rather than by its path, and a set of them is taken in the order of those identities — the one order every gup agrees on however each of them spelled the paths. Ordering by the sorted paths only held while two processes spelled them alike: a $GOBIN reached as /home/you/go/bin by one and through a symlinked home by another sorted the pair in opposite orders, so each took the resource the other was waiting for and both ended in a busy error over a contention that was theirs alone.gup.json follows the file, not the spelling of --file. The lock is a neighboring file named after the resource, so the name gup was given decided which file the lock was — and one file answers to many names. On Windows, NTFS keeps an 8.3 alias for every long name (GUP~1.JSO, whose lock would be GUP~1.JSO.lock), and Win32 strips trailing dots and spaces before the filesystem sees a name, so --file gup.json. wrote gup.json while locking gup.json..lock, which has no trailing dot to strip and is a different file. Either way two gups rewrote one configuration, each holding a lock the other could not see, and one of the two results was lost with nothing left to see. --file is now resolved to the single name the operating system agrees the file has (GetFinalPathNameByHandle on Windows) before the lock is derived from it. A hard link is the one alias with no such name — the two are equally real — so a --file whose file has a second name is refused rather than locked at a name that only sometimes means it; gup could not have rewritten it correctly either, because the atomic rename that replaces gup.json breaks the link.$GOBIN. That is now an error. A path that can never be a directory (a regular file where $GOBIN or AFTER_PATH should be) is still left to the command, which reports it better than a lock error would and writes nothing either way.gup.json on Windows is replaced in place rather than moved aside. gup's readers take no lock, on the promise that a write is an atomic rename - gup check, gup list and gup import see either the whole previous file or the whole next one. The fallback for a destination that refuses to be replaced moved the old file away first, so gup.json did not exist in between and an unlocked reader landing there read it as "no config". The read-only bit is now cleared for the length of one rename and put back on the file that replaces it, so the file is continuously present and the read-only intent survives the write instead of being silently dropped.gup check and gup update no longer treat a Go toolchain suffix as a version difference. -X:nodwarf5 and -X:jsonv2 are toolchain metadata rather than part of the Go release version, and reading them as SemVer prerelease identifiers reported binaries as out of date and rebuilt them for nothing. (#447)brew install gup from homebrew-core alongside the tap, and the AUR packages (gup, gup-bin) and the nixpkgs gogup attribute. (#453)Nothing published for this version
Nothing published for this version
Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.8.0...v1.8.1
nao1215.gup already existed in the community repository, but a third-party bot submitted the manifests on its own schedule and missed v1.5.1, v1.6.0, and v1.7.0 outright; v1.8.0 arrived five days after the tag carrying v1.7.1's release notes. A tagged release now generates the manifests and opens the pull request against microsoft/winget-pkgs itself, so winget install --id nao1215.gup tracks the release page. The identifier is unchanged, so nothing changes for anyone who already installed gup that way. (#445)Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.7.1...v1.8.0
gup --help now prints the documentation and GitHub Sponsors links. (#433)gup migrate completes its positional arguments: directories while BEFORE_PATH and AFTER_PATH are being typed, then the binaries that actually live under the given BEFORE_PATH. (#438, #439)go and gofmt are skipped by their cmd/... import path, not only by their missing main module. Installing Go through mise and similar tools places them in $GOBIN, where gup used to try to reinstall them with go install cmd/go@latest. (#206, #413)gup pin and gup unpin complete a binary name only where one can still be accepted: not for pin's VERSION, and not past unpin's single argument. (#438)--timeout no longer completes file names; a duration is not a path. (#438, #439)actions/attest-build-provenance from 4.1.0 to 4.1.1, golangci/golangci-lint-action from 9.2.1 to 9.3.0, goreleaser/goreleaser-action from 7.2.2 to 7.2.3, actions/setup-go from 6.5.0 to 7.0.0, reviewdog/action-actionlint from 1.72.0 to 1.73.0, actions/checkout from 7.0.0 to 7.0.1, k1LoW/octocov-action from 1.5.1 to 1.5.2, actions/configure-pages from 5 to 6, actions/deploy-pages from 4 to 5, and actions/upload-pages-artifact from 3 to 5.Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.7.0...v1.7.1
gup export now preserves channels saved under an alternate config file (--output) instead of dropping them when exporting back to a non-default gup.json. (#411)gup validates an auto-detected gup.json on otherwise empty environments so a malformed config fails fast rather than being silently ignored. (#410)$GOBIN directory is treated as an empty environment instead of an error. (#409)gup import rejects directory paths explicitly instead of failing later with an opaque error. (#406)gup bug-report browser launch no longer reports false success when the browser open times out. (#405)gup.json (writing through the link rather than replacing it), and completion-file writes preserve dangling symlinks; completion files and .zshrc are written atomically. (#402, #403, #404)XDG_* and ZDOTDIR paths rather than resolving them against the wrong base. (#401)--ignore-go-update. (#400)gup fails fast when an auto-detected gup.json is a directory. (#399)gup list, gup export, and gup pin no longer require the go command for local-only work.gup migrate --dry-run validates that AFTER_PATH is creatable so a dry run surfaces the same failure a real run would.gup remove treats a failed confirmation read as an error instead of a silent cancel.Printer serializes writes across parallel workers so concurrent output is no longer interleaved. (#393)gup.json persists the version for the effective channel when merging packages.Printer through all commands and inject it via Cobra's SetOut/SetErr instead of redirecting os.Stdout, and inject update/check operations and other dependencies instead of mutating global seams. No user-visible behavior change. (#393)cmd, goutil, configstate, and completion (shared empty-environment and progress-rendering helpers, centralized Cobra flag-registration panics, version-display separation, per-shell completion sync, and a split of the monolithic configstate file). No user-visible behavior change.sigstore/cosign-installer from 3.9.1 to 4.1.2.Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.6.0...v1.7.0
gup pin <tool> <version> (also gup pin <tool>@<version>) records a tool in gup.json under a new pinned channel with a concrete version, and gup unpin <tool> clears it. gup update installs a pinned tool at its exact version with go install <import_path>@<version> (never @latest), keeps it there, and reinstalls it only when the installed version differs or the Go toolchain changed (suppressible with --ignore-go-update), while unpinned tools still update in parallel. gup check reports pinned/pin-mismatch without querying @latest, and --json gains a pinned_version field and the pinned/pin-mismatch statuses. Pinned state is preserved across export/import. (#384)gup.json now uses schema_version 2 only when a package is pinned and otherwise stays at 1, so older gup releases keep reading pin-free configs; channels are parsed strictly so an unknown channel, a pinned entry without a concrete version, or channel: "pinned" under schema_version: 1 fails fast instead of being silently downgraded to @latest. (#384)internal/goutil monolith into concern-focused files and reuse internal/parallel.Run for package-information collection. No user-visible behavior change. (#380)update/check flag parsing into parseUpdateFlags/parseCheckFlags so a flag error is handled in one place. No user-visible behavior change. (#381)SECURITY.md to fit gup, split the go tool comparison into its own section, fold the benchmark result into the feature-comparison table, and mirror the version-pinning documentation across all translated READMEs. (#383, #384)Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.5.1...v1.6.0
gup update and gup check now turn the Go toolchain's failure output into a short, actionable next-step hint printed on STDERR right after the error (and exposed as a per-package hint field in --json output). Hints cover module renames/major-version moves, relocated commands, go.mod replace directives, binaries not installed via go install, missing branch/tag for the selected channel, unresolvable/private/deleted repositories, SSH/auth and network/proxy errors, and an out-of-date Go toolchain. gup stays silent when it has nothing reliable to add (e.g. a timeout, whose message already names the remedy). (#378)gup update and gup check no longer mislabel a binary that exists in $GOBIN but whose build info cannot be read (or that was not installed by go install) as "not found": such a binary is reported as unreadable, not missing. The "not found" notice is now derived from the installed binary paths rather than the resolved packages. (#378)gup update no longer prints two "not found" notices for the same name when it is supplied both as a positional target and in --main/--master/--latest; the duplicate channel-flag notice is suppressed once the name has already been reported. (#378)cmd/ layer into new reusable internal/pkgselect, internal/vercache, and internal/parallel packages, keeping cmd/ a thin wiring/output shell. No user-visible behavior change. (#377)github.com/pkg/errors dependency with the standard library errors/fmt. No user-visible behavior change. (#376)Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.5.0...v1.5.1
gup check, gup update, and gup list --json now fail fast when the resolved gup.json is malformed or has an unsupported schema_version, instead of silently falling back to @latest, and reject a directory passed where a gup.json file is expected instead of clobbering it. (#370)--json output for the parallel commands (check/update/import/migrate) is now emitted in the original input order, making machine-readable output deterministic across runs without changing exit codes, status values, or error semantics. (#371)gup completion --install now honors XDG_DATA_HOME (bash), XDG_CONFIG_HOME (fish), and ZDOTDIR (zsh) when choosing where to write completion files and the .zshrc snippet. (#372)gup completion --install now repairs a deleted, stale, or hand-broken zsh .zshrc fpath block on re-install instead of leaving zsh completion broken; an already-correct block is left byte-for-byte unchanged. (#373)gup update: persisting gup.json after a binary rename that kept the same import_path could drop the package from the saved config entirely. (#374)cmd/ commands into a new internal/configstate package (config-path resolution, update-channel resolution/merge, and persistence) and unify binary-name matching in internal/binname, so update/check/list/export interpret the same gup.json entry through one consistent package-identity model. No user-visible behavior change. (#374)Nothing published for this version
Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.4.0...v1.5.0
--file/-f flag to check and update to select which gup.json to read saved update channels from (and write back to, for update), consistent with import/export. (#342)go install yet) as a normal first-run condition rather than an error: list, check, export, and update now exit 0. list/check/update print an informational note (or emit a valid empty [] in --json mode), and export writes an empty gup.json. Naming a non-existent binary or excluding everything is still treated as a usage error (exit 1). (#350)gup update --main and check now fall back from @main to @master only when the main branch does not exist. Build, network, proxy, authentication, timeout, and cancellation failures on @main are surfaced as-is instead of silently installing @master. (#340)gup export now preserves each package's saved update channel (latest/main/master) regardless of --file/--output. Channels are always resolved from the canonical user-level gup.json, matched by import_path first (with Windows .exe name differences normalized), so exporting to a new destination no longer resets channels to latest. (#341)gup check and gup update now fail fast when both the user-level gup.json and ./gup.json exist and --file is omitted, instead of silently picking one — matching the existing gup import behavior. (#342)gup completion --install now exits non-zero when a completion file cannot be written (previously it could print an error but still exit 0), and fails fast with a clear message when HOME is unset instead of writing completion files into relative paths under the current directory. (#343)gup man now creates the target man1 directory when it does not exist (e.g. for a valid custom MANPATH) instead of failing, and reports a clear error for unwritable targets. (#344)gup bug-report no longer pre-fills a generic placeholder issue title (so reports are less likely to be filed with an empty/placeholder title), now includes the OS alongside the gup version in the generated body, and its help text no longer claims to include broader system information than is actually present. The bug-report issue template is aligned with the command. (#345)gup update --file <path> now persists update channels and rename bookkeeping to the explicitly named file even when it does not exist yet, instead of silently writing them to the user-level gup.json. The export-side saved-channel matching also normalizes the .exe/.EXE suffix case-insensitively so hand-edited or upper-cased config entries keep their channel. (#358)brew install nao1215/tap/gup, and rewrite the feature-comparison table so the force-reinstall row is command-scoped (update never reinstalls up-to-date binaries; migrate --force reinstalls when the target already exists), removing the previously misleading row. (#349)doc/{ja,ru,zh-cn,ko,es,fr}): Quiet output (--quiet/-q), machine-readable JSON output (--json), disable-colorized output (NO_COLOR/--no-color), and the feature-comparison table; remove the stale v1.0.0 breaking-change note. doc_sync_test.go now guards these sections so future drift fails CI. (#339)import/check/update fail-fast on an ambiguous gup.json, and export always resolving saved channels from the canonical user-level config), the empty-environment behavior, man honoring MANPATH, and completion --install requiring HOME. (#359)e2e/ that exercises the real gup binary in an isolated temp HOME/XDG_CONFIG_HOME/GOBIN, with no network access. It covers list, export --output, import --file, migrate, and non-TTY remove. Run it with make e2e; it also runs in CI (.github/workflows/e2e.yml). (#346)check and update flows through the actual go toolchain against a self-contained local module proxy (e2e/testproxy): up-to-date vs. update-available, installing a newer version, --main success, @main→@master fallback only on branch-not-found, and no fallback when @main exists but fails to build. (#347)MANPATH and HOME payloads verbatim across every translation, and extend the E2E suite to cover update --file persisting the channel to a not-yet-existing destination and the multiple-gup.json ambiguity fail-fast. (#359)scripts/smoke_artifacts.sh (extracted archive runs gup --version, every archive ships the completion files, and the Linux .deb installs and runs) before the real goreleaser release, so a packaging regression blocks publication. A Release Smoke workflow runs the same check on every PR. (#348)Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.3.1...v1.4.0
--version/-V flag in addition to the existing gup version subcommand. (#326)--quiet/-q output mode to check and update that hides the up-to-date lines and prints only changed/updatable binaries, failures, and a one-line summary. Errors still go to STDERR. (#290)NO_COLOR environment variable and add a --no-color flag to disable colorized output. (#309)gup remove now fails fast with a clear message in non-interactive execution (when stdin is not a TTY, e.g. CI or a pipe) instead of blocking on stdin or surfacing a raw EOF. --force still skips confirmation. (#323)unknown/(devel)/empty binary version to latest before persisting it to gup.json, so later gup update runs resolve the package correctly. (#300)--version flag, the non-TTY remove behavior, and the --json/--quiet precedence in the README.goExe-based subprocess calls, plus property-based tests for version comparison, name normalization, and config round-trip. (#301, #305)config_file rename injectable and cover the backup-swap restore-failure worst case. (#302)gup remove. (#303)Short punctuation, example indentation) and give the non-interactive remove error a labeled STDERR message.Fast parallel updater and manager for binaries installed with go install .
Fast parallel updater and manager for binaries installed with go install.
Install or upgrade, then see the grouped highlights below. Every artifact is
signed and ships with an SBOM and build provenance — see
Verifying release integrity.
Full changelog: v1.3.0...v1.3.1
--timeout added in v1.3.0 is now opt-in and disabled by default (default 0), so a slow but healthy go install is no longer killed as a timeout; this restores the pre-v1.3.0 behavior. Pass --timeout 5m (or any duration) to re-enable a bound. (#318)--timeout bound is hit, the error now names the exact command to rerun (go install <path>@<version> or go list -m <module>@<ref>) and hints at --timeout, so a slow build is easy to diagnose. (#318)gup update now decides whether to skip a package using its resolved update channel, so binaries tracked on @main/@master are no longer skipped or updated based on @latest. (#292)gup update --json keeps STDOUT valid JSON when --exclude is used, instead of leaking a human-readable "Exclude ..." line that broke machine-readable output. (#291)GOBIN/GOPATH fails, and runs cleanup via defer so it is panic-safe. (#297)go install/go list subprocess that writes nothing to stderr now reports a cause (e.g. signal: killed) instead of an empty error message. (#298)8cf97fc Merge pull request #263 from nao1215/dependabot/github_actions/actions/checkout-7
--timeout to update, check, import, and migrate so a stuck go subprocess fails instead of hanging forever (default 5m; --timeout 0 disables). Signal-based cancellation still aborts in-flight work, and timeouts are reported distinctly from cancellations.gup import now fails with a clear error when both the user-level gup.json and ./gup.json exist and --file is omitted, instead of silently picking one.gup version, gup help, gup completion <shell>) no longer create notification asset files under the user profile at startup; icons are deployed lazily only when a desktop notification is actually sent.gup completion --install now returns a clear error on Windows (where it was a silent no-op) and points users to gup completion powershell for stdout generation.list, export, and migrate no longer run the go version subprocess they never used, cutting their package scan by up to ~97% on small $GOBIN sets.go list -m, which was slower than the existing parallel resolution).update, check, import, and migrate, shrinking the command files without changing behavior.gup with go-global-update and a sequential go install loop, and replaced the v1.0.0 breaking-change note with it.gup update example and gup list screenshot with VHS-recorded GIFs.golangci-lint baseline (goconst/nolintlint/govet) and made golangci-lint an enforced CI gate; aligned the module with its declared go1.25 policy by dropping a go1.26-constrained dependency.internal/completion, internal/assets, and internal/notify packages.Add gup migrate BEFORE_PATH AFTER_PATH [BINARY...] subcommand to reinstall go install binaries from one $GOBIN directory into another
gup migrate BEFORE_PATH AFTER_PATH [BINARY...] subcommand to reinstall go install binaries from one $GOBIN directory into another
import path@version recorded in each binary's build info (no implicit upgrade to @latest)AFTER_PATH, skips binaries that already exist there unless --force is givenBEFORE_PATH and AFTER_PATH resolve to the same directory, and never mutates the filesystem on a validation failurecommand-line-arguments builds, and devel/(devel) versions instead of upgrading them--dry-run, --notify, --jobs, and --force (parallelized like import/update)mise changes the real path of $GOBIN per Go versiongup update GIF recorded via VHS and document the gup migrate use case (including mise)github.com/hashicorp/go-version from 1.8.0 to 1.9.0github.com/mattn/go-colorable from 0.1.14 to 0.1.15gitleaks/gitleaks-action from 2 to 3migrate covering path validation, add-only/force semantics, binary filtering, skip conditions, module-path-mismatch retry, dry-run, and --jobs boundariesNothing published for this version
Bump minimum Go version from 1.24 to 1.25
github.com/fatih/color from 1.18.0 to 1.19.0Harden browser launch behavior in bug-report with command timeout/wait handling
bug-report with command timeout/wait handlingremove target validation and normalization (including Windows-specific suffix handling)man generation success logging and config swap error reporting in failure recovery pathsremove regression test expectation and resolve -race failure in bug-report fallback output testgoreleaser/goreleaser-action from v6 to v7Treat equal custom Go toolchain versions (e.g. go1.26.0-X:nodwarf5) as up-to-date in check and update
go1.26.0-X:nodwarf5) as up-to-date in check and updateinternal/goutil, check, and update, including output color behaviorMake config writes atomic and harden replacement flow to avoid data loss on failed updates
GOEXE is unsetupdate with case-insensitive name handlingremove behavior on Windows when GOEXE is empty and handle .exe suffix checks robustlygo install / go list subprocessesAdd PowerShell completion generation via gup completion powershell
gup completion powershellcompletions/gup.ps1 in scripts/completions.shcompletion --install targets bash/fish/zsh onlyos.Stdout and verifying PowerShell header outputConfig format changed from plain-text gup.conf ( = ) to JSON gup.json with versioned schema
gup.conf (<name> = <import-path>) to JSON gup.json with versioned schemagup import now installs the exact version recorded in gup.jsongup import flag changed from --input to --filegup export flag changed from --output to --filelatest / main / master) in gup.json$XDG_CONFIG_HOME/gup/gup.json first, then ./gup.json)--file option to both import and exportremoveOldBinaryIfRenamed to prevent path traversalgup.json is corrupt during updategup.json parse errors during update--main/--master/--latest flag resolution for WindowsreplaceImportPathPrefix--exclude package names--install for completion file writesgup.conf lines early (legacy format migration)GetLatestVer calls and parallelize binary info collectiongolang.org/x/exp/slices with standard slices packageshouldPersistChannelsFix bug fixes and CI improvements #230 (nao1215)
docs: add mise alternate installation instructions (en/fr) and fix shell quoting in README #222 (jylenhof)
Use MANPATH when installing man pages and fix lints #211 (nao1215)
Nothing published for this version
Nothing published for this version
Add --ignore-go-update flag and refine updater error handling #201 (iTrooz)
Nothing published for this version
Nothing published for this version
docs: add README translations (es, fr, ko, ru, zh-cn) #195 (nao1215)
Bump golang.org/x/sync from 0.11.0 to 0.12.0 #185 ([dependabot[bot]](https://github.com/apps/dependabot))
Add Go 1.24 to CI and fix unit tests #182 (nao1215)
Bump github.com/mattn/go-colorable from 0.1.13 to 0.1.14 #180 ([dependabot[bot]](https://github.com/apps/dependabot))
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fix: check sub command prints incorrect path #172 (nao1215)
Nothing published for this version
Feat: Integrate completions into Homebrew formula (Issue #168) #169 (nao1215)
Your coding agent can read these notes before it upgrades. Set up the MCP server →