bin

ID

bin

Home page

https://github.com/marcosnils/bin

Version requirement

>= 0.27

Platforms

🐧 Linux · 🍎 macOS · 🪟 Windows

Operations

installed · upgrade · upgrade_all · remove

purl types

pkg:bin

CLI name

bin

Forced environment

NO_COLOR=1

Issues and PRs

📦 manager: bin

Source

meta_package_manager/managers/bin.toml

bin installs binaries straight from GitHub releases and similar sources (https://github.com/marcosnils/bin).

The package identifier is the absolute path of the installed binary, which is what list reports and what remove and update accept. That choice is forced rather than preferred: bin names a package differently depending on the verb. Installing takes a source spec (github.com/junegunn/fzf, a release-tag URL, goinstall://…, docker://…, a vendor host), while everything afterwards is keyed on the installed path. Handing a source spec back to remove does not resolve, and a bare basename resolves through $PATH first, so a managed binary shadowed by another copy on $PATH fails outright. The absolute path is the only identifier every non-installing operation accepts.

That asymmetry is also why install is not declared: no identifier list reports can be handed to it, so mpm could never install what it had just listed. Installing through bin stays a bin install <spec> the user runs themselves, and mpm reports and maintains the result.

No outdated, though bin can compute it. update --dry-run exits 3 when it finds updates and 0 when it finds none, and prints the listing to stderr while leaving stdout empty. A declarative operation is one argument list whose stdout is parsed on a zero exit, so neither half of that fits: the operation needs a Python class to express. upgrade --all is unaffected.

No search: bin has no registry to search, only sources the user names. No sync: there is no index to refresh. bin prune is left alone too, since it drops configuration entries whose file has vanished rather than cleaning up packages.

NO_COLOR is set because bin colors on its own initiative whenever CI is non-empty, which every GitHub Actions run sets: without it CI would parse ANSI a local run never produces. bin colors its two streams through separate libraries and only one of them honors NO_COLOR, but that one is fatih/color governing the stdout table, which is the only stream anything below parses. The caarlos0/log lines on stderr stay colored under CI and are nobody’s input here, being the payload of the outdated this definition does not declare.

No escalation: bin installs into a directory it picked from $PATH for being writable, and never needs root.

Caution

A bin that has never been configured prompts for its download directory on every command, the listing included, and cannot be driven until someone answers once interactively. mpm sees that as a failed version probe and treats the manager as unavailable, which is the right outcome: an uninitialised bin has no inventory to report, and reporting zero packages would be a lie.

What mpm adds to bin

mpm reaches across every manager at once, not bin alone: mpm installed and mpm outdated cover bin alongside every other manager you run in one table, mpm upgrade --all updates them together, and mpm sbom exports the whole machine as one bill of materials.

Every mpm command also gains --dry-run and --plan previews, cross-scheme version comparison and purl identifiers. See manager augmentations for how each one is built.

Your bin commands, in mpm

You already know bin: each operation maps one-to-one onto mpm, in an interface shared by every manager.

To…

With bin

With mpm

List what’s installed

bin list

mpm --bin installed

Upgrade one package

bin update --yes --continue-on-error <package_id>

mpm --bin upgrade <package_id>

Upgrade everything

bin update --yes --continue-on-error

mpm --bin upgrade --all

Remove a package

bin remove <package_id>

mpm remove pkg:bin/<package_id>

Prefix any command above with --dry-run to simulate the underlying manager calls without touching the system: the safe way to watch what mpm would do before trusting it.

Operations

Operation

Supported

installed

outdated

orphans

search

install

upgrade

upgrade_all

remove

sync

cleanup

doctor

Selecting and configuring bin

Deselect bin for a single run with --no-bin, or persist the choice in your configuration:

[mpm]
bin = false

The arguments and environment variables listed in the box atop this page are forced on every bin call, so runs stay quiet, non-interactive and reproducible: the defaults you would set in CI anyway.

Keep it enabled but tune how mpm drives it with a per-manager override:

[mpm.managers.bin]
timeout = 900

mpm config-template bin prints every overridable attribute as a ready-to-paste block.

Recipes

A few jobs you would otherwise script around bin, one mpm command each:

  • Snapshot and clone a machine: mpm --bin dump bin.toml, then mpm restore bin.toml on the next one.

  • Export a compliance SBOM: mpm --bin sbom (CycloneDX by default, --spdx for SPDX).

Privilege escalation

mpm runs this manager as the current user and never prepends sudo by default. Flip the policy for its privileged operations with --sudo or the per-manager sudo override.

None of its operations needs root.

See privilege escalation for the full policy.

Cooldown

State of bin’s release-age gating, from the cooldown support table:

Status: ❌ None

A cooldown only pays off where a compromised release can be withdrawn while the clock runs, and can only be emulated where the registry dates its releases. From the retraction table:

  • Registry: GitHub release assets

  • Retraction: None: withdrawing a build is the upstream author deleting their own release or tag. Nothing sits between them and the user

  • Publish date: ✅ server-set published_at on each release (REST API)

With --cooldown set, mpm skips this manager’s install and upgrade operations rather than run them unguarded (fail-closed); --allow-unsupported-managers opts back in.

Version probe

The version is probed by running:

$ bin --version
bin version 0.29.1
commit: c24db4aced89c855062fe8e2907ae0deb3fb9f53
built at: 2026-08-02T13:37:10Z
built by: goreleaser

and extracted with:

r"^bin version (?P<version>\S+)"

Reference traces

Raw native outputs captured in the bundled definition: the reference mpm’s parsers were written against. If you know bin well and a transcript below looks wrong, or a newer release changed its output format, report it.

$ bin list
/home/user/.local/bin/fzf         v0.74.2  github.com/junegunn/fzf                                    OK
/home/user/.local/bin/rg          14.1.1   https://github.com/BurntSushi/ripgrep/releases/tag/14.1.1  OK
/home/user/.local/bin/terraform  *1.5.7    releases.hashicorp.com/terraform                           OK

Feed any of these through mpm and the raw output becomes one uniform table, the same shape for every manager: filter it, project columns, or export it (mpm --bin installed --output json, or csv, toml, yaml), each package carrying a purl and a version comparable across managers.

Changelog

  • 7.7.0.dev0 (unreleased)

    • Add the bin binary manager with installed, upgrade and remove support, shipped as a bundled definition. Packages are keyed on the installed binary’s absolute path, the only identifier its non-installing operations accept. It declares no install, since bin installs from a source spec no listing reports back, and no outdated, since update --dry-run signals its findings through an exit code and writes them to stderr.