Skip to content

pluggy upgrade

Replace the running pluggy binary with the latest GitHub release.

Usage

pluggy upgrade [options]

Flags

FlagDefaultNotes
--print-onlyoffSkip the download and print manual install instructions instead.
--forceoffSelf-update even when pluggy was installed via Homebrew or Scoop. Not recommended; corrupts the package manager’s tracking.

What it does

  1. Queries https://api.github.com/repos/pluggy-sh/pluggy/releases/latest.

  2. Maps process.platform × process.arch to a release asset name:

    PlatformArchAsset
    darwinarm64pluggy-darwin-arm64
    darwinx64pluggy-darwin-amd64
    linuxarm64pluggy-linux-arm64
    linuxx64pluggy-linux-amd64
    win32x64pluggy-windows-amd64.exe
  3. Downloads the asset to <tmp>/pluggy-upgrade-<rand>/pluggy-new and chmod +x on POSIX.

  4. Renames the current binary to <current>.old, then renames the staged new binary into place. On Windows this works because Node’s rename will swap an open executable.

  5. If the second rename fails, the .old backup is restored atomically.

Without an asset mapped for your platform, pluggy prints the manual install instructions and exits clean.

Human output

$ pluggy upgrade
Upgrading to: v0.2.0
downloading https://github.com/pluggy-sh/pluggy/releases/download/v0.2.0/pluggy-darwin-arm64
✓ pluggy v0.2.0 installed at ~/.pluggy/bin/pluggy (previous binary backed up to ~/.pluggy/bin/pluggy.old)

With --print-only:

Latest release: v0.2.0
Published: 2026-03-01T12:00:00Z
URL: https://github.com/pluggy-sh/pluggy/releases/tag/v0.2.0
Install manually:
Unix: curl -fsSL https://pluggy.sh/install.sh | sh
Windows: irm https://pluggy.sh/install.ps1 | iex

Managed installs (Homebrew, Scoop)

pluggy upgrade refuses to run when it detects that the binary is owned by a package manager. Overwriting it would leave the package manager’s manifest pointing at a file it didn’t install. Run the package manager’s own upgrade instead:

$ pluggy upgrade
✖ pluggy was installed via Homebrew. Don't self-update; that would corrupt the package manager's tracking.
Run this instead:
$ brew upgrade pluggy

The same guard fires for Scoop, suggesting scoop update pluggy. Pass --force to override (the upgrade will succeed but leave the package manager confused).

Detection looks at process.execPath:

Install methodDetected by path containing
Homebrew/Cellar/pluggy/
Scoop/scoop/apps/pluggy/
Install script/.pluggy/bin/ or /Programs/pluggy/

Unrecognised paths are treated as self-updateable.

Permissions

pluggy uses the path Node reports as process.execPath. The install scripts drop the binary somewhere writable by the current user, so no sudo is needed for upgrades:

  • macOS/Linux: ~/.pluggy/bin/pluggy (override with PLUGGY_HOME).
  • Windows: %LOCALAPPDATA%\Programs\pluggy\pluggy.exe.

If pluggy is currently installed in a system-owned path (for example a legacy /usr/local/bin/pluggy install), pluggy upgrade detects this and prints recovery instructions: either re-run with sudo, or reinstall via the install script (which will land in ~/.pluggy/bin) and remove the old system binary so it doesn’t shadow the new one.

Update notification

When pluggy starts, it reads a small state file (<state>/update-check.json, in the state directory so pluggy cache clean doesn’t reset it) and, at most once per 24 hours, fetches the latest release tag in the background. If the cache shows that you are out of date, you’ll see a one-line notice on stderr after the command finishes:

✦ pluggy 0.3.0 available, you have 0.2.0. Run pluggy upgrade.

The notice is suppressed when:

  • --json is set on the current command.
  • CI is set to a non-empty truthy value.
  • stderr isn’t a TTY (for example piped output).
  • PLUGGY_NO_UPDATE_CHECK=1 is set in the environment.
  • The running build is the dev sentinel (0.0.0).

Run pluggy doctor to see the same information inline.

Error cases

TriggerMessage
GitHub API errorFailed to fetch latest release: <status> <statusText>
GitHub rate-limitGitHub API error: API rate limit exceeded ...
Asset download failsfailed to download <url>: <status> <statusText>
Empty assetdownloaded asset from <url> is empty
Rename-in-place failsfailed to install new binary at <path>; restored previous version: <errno>

See also