b is a binary manager and environment file syncer for development projects. It installs binaries from multiple sources and syncs configuration files from upstream git repositories.
Features:
- 30+ pre-packaged binaries (kubectl, k9s, jq, helm, etc.) with auto-detection
- Install from GitHub, GitLab, Gitea/Forgejo, Go modules, Docker images, and git repos (docs)
- Sync env files from git repos with glob matching and three-way merge
- SSH & HTTPS — use SSH keys (ssh-agent) or tokens for private repos
- Lockfile (
b.lock) for reproducible installations with SHA256 verification - direnv integration for per-project binary management
# Initialise a new project with b.yaml config and direnv
b init
# List all configured binaries and envs
b list
# Install pre-packaged binaries
b install jq kubectl helm
# Install from any supported provider
b install github.com/derailed/k9s
b install gitlab.com/org/tool
b install codeberg.org/user/app@v1.0
b install go://golang.org/x/tools/cmd/goimports
b install docker://alpine/helm
b install docker://docker@cli # tag via @ (e.g. docker:cli image)
b install docker://docker@cli:/usr/local/bin/docker # explicit in-container path
b install oci://ghcr.io/org/img@v1 # daemonless, any OCI registry
b install oci://docker@cli:/usr/local/bin/docker # daemonless docker CLI
b install "git:///home/user/myrepo:.scripts/tool"
b install "git://github.com/org/repo:bin/app@v1.0"
# SSH repos (uses ssh-agent)
b install "git@github.com:org/private-repo:bin/app"
# Install and add to b.yaml
b install --add jq@1.7
# Install with a post-install hook (saved to b.yaml with --add)
b install --add github.com/arg-sh/argsh --on-post 'argsh builtin ${B_EVENT}'
# Install and pin version in b.yaml
b install --fix jq@1.7
# Sync env files from a git repository (SCP-style)
b install github.com/org/infra:/manifests/hetzner/** /hetzner
b install github.com/org/infra@v2.0:/manifests/base/** .
# Update all binaries and envs
b update
# Update with merge strategy (three-way merge on local changes)
b update --strategy=merge
# Update keeping local changes
b update --strategy=client
# Search for available binaries
b search terraform
# Show versions (with remote update check for envs)
b version
b version --local # skip remote checks
b version --check # exit code 0 if up-to-date, 1 if not (CI-friendly)
# Verify installed artifacts against b.lock checksums
b verify
# Manage git cache
b cache clean # remove all cached repos
b cache path # print cache directory
# Request a new binary
b request
b needs one of three things defined to know where to install binaries:
PATH_BINenv, set to the directory where you want to install binaries.PATH_BASEenv, set to the project root directory. All binaries will be installed in the.bindirectory.- If you are in a git repository,
bwill install binaries in the.bindirectory in the root of the repository.
If none of these are set, b will fail.
Create a b.yaml file in the binary directory to declare what to install. Here is an example:
binaries:
jq:
version: jq-1.8.1 # pin version
helm:
enforced: v3.14.0 # strict pin (never auto-upgrade)
kind:
tilt:
envsubst:
alias: renvsubst # alias to renvsubst
kubectl:
file: ../kc # custom path (relative to config)
# Install from any provider by ref (GitHub, GitLab, Gitea, go://, docker://, oci://, git://)
github.com/sharkdp/bat:
version: v0.24.0
# Install from a git repo (local or remote)
git:///home/user/myproject:.scripts/tool:
git://github.com/org/repo:bin/app:
version: v1.0
# Install from an OCI registry (daemonless — works without docker)
oci://ghcr.io/org/img:
version: v1.0
oci://docker:/usr/local/bin/docker:
version: cli
# Post-install hook — runs after install/update when the binary changed
github.com/arg-sh/argsh:
onPost: argsh builtin ${B_EVENT}
envs:
# Sync files from upstream git repos
github.com/org/infra:
version: v2.0 # pin to tag/branch (default: HEAD)
strategy: merge # replace (default) | client | merge
ignore:
- "*.md"
files:
manifests/base/**: # glob pattern
dest: base/ # local destination
manifests/hetzner/**:
dest: hetzner/
# Minimal env entry (sync all files, default settings)
github.com/org/shared-config:Binaries: If you don't specify a version, b will install the latest. Use enforced instead of version to strictly pin a version (prevents auto-upgrade). Custom file paths can be relative (resolved from config location) or absolute.
Envs: Sync configuration files from upstream git repositories. Strategy controls how local changes are handled during updates:
- replace (default): Overwrite with upstream. Interactive prompt on TTY when local changes detected.
- client: Keep local files when modified, skip upstream.
- merge: Three-way merge via
git merge-file. Conflict markers inserted on failure.
Set environment variables to authenticate with providers for higher rate limits or private repositories:
| Variable | Provider |
|---|---|
GITHUB_TOKEN |
GitHub |
GITLAB_TOKEN |
GitLab |
GITEA_TOKEN |
Gitea / Forgejo (Codeberg) |
For oci:// the daemonless client reuses your local registry auth from ~/.docker/config.json (or the DOCKER_CONFIG override) — the same credentials docker login writes.
You can run b using Docker without installing it locally:
# Run b with volume mount to access .bin directory
docker run --rm -v ./.bin:/.bin ghcr.io/fentas/b list
# Install binaries using Docker
docker run --rm -v ./.bin:/.bin ghcr.io/fentas/b install b jq kubectlYou can also copy the b binary into your own Docker images:
FROM alpine:latest
# Copy the b binary from the official image
COPY --from=ghcr.io/fentas/b:latest /b /usr/local/bin/b
# Install binaries during build
ENV PATH_BIN=/usr/local/bin
RUN b install curl jq
# Your application code
COPY . /app
WORKDIR /app
All related documentation, including the source for the website, is located on the docs branch.
If you have Go installed, you can build and install the latest version of b with:
go install github.com/fentas/b/b@latestBinaries built in this way do not have the correct version embedded. Use our prebuilt binaries or check out .goreleaser.yaml to learn how to embed it yourself.
To use this package, you need to import it into your Go project:
import "github.com/fentas/b/pkg/binary"The Binary struct represents a binary file, including its name, file path, version, and other related properties. You can create a Binary struct by providing the binary name and version:
bin := binary.Binary{Name: "mybinary", Version: "1.0.0"}
bin.EnsureBinary(true)Have a look at pkg/binary for more details.
Have a look at pkg/binaries for prepackaged binaries.
- argocd - Declarative Continuous Deployment for Kubernetes
- argsh - Utilities for Bash script quality
b- (Selfupdate) Manage and execute binary files- cilium - Providing, securing, and observing network connectivity between workloads
- clusterctl - Kubernetes cluster lifecycle management
- curl - Command-line tool for transferring data with URL syntax
- docker-compose - Define and run multi-container Docker applications
- gh - GitHub CLI wrapper
- hcloud - Hetzner Cloud CLI wrapper
- hubble - Fully distributed networking and security observability platform
- jq - Command-line JSON processor
- k9s - Kubernetes CLI to manage your clusters
- khelm - A Helm chart templating CLI, kustomize plugin and containerized kustomize/kpt KRM function
- kind - Kubernetes IN Docker
- kubectl - Kubernetes CLI to manage your clusters
- kubectl-cnpg - CloudNativePG kubectl plugin to manage PostgreSQL databases
- kubelogin - int128 - kubectl plugin for Kubernetes OpenID Connect authentication (kubectl oidc-login)
- kubeseal - A Kubernetes controller and tool for one-way encrypted Secrets
- kustomize - Kubernetes native configuration management
- mkcert - Create locally-trusted development certificates
- packer - Packer is a tool for creating machine and container images
- renvsubst - envsubst with some extra features written in Rust
- sops - Secure processing of configuration files
- ssh-to-age - Convert SSH Ed25519 keys to age keys
- stern - Simultaneous log tailing for multiple Kubernetes pods and containers
- tilt - Local Kubernetes development with no stress
- yq - Command-line YAML processor
Feel free to extend this, PRs are welcome.
Using direnv allows you to load required binaries bound to a specific project.
#!/usr/bin/env bash
set -euo pipefail
: "${PATH_BASE:="$(git rev-parse --show-toplevel)"}"
: "${PATH_BIN:="${PATH_BASE}/.bin"}"
export PATH_BASE PATH_BINThis is all you need; alternatively, you can refer to here.
- Windows support (OS/arch detection improvements)
- Advanced configurations (proxy, custom registries)
- Upstream
b.yamldiscovery (auto-detect file groups from repos)
b is released under the MIT license, which grants the following permissions:
- Commercial use
- Distribution
- Modification
- Private use
For more convoluted language, see the LICENSE. Let's build a better Bash experience together.
Thanks to all tools and projects that developing this project made possible. Special thanks to marcosnils/bin for the inspiration and code that helped bootstrap the provider and asset detection logic.
Copyright © 2024-present fentas