Fast, isolated package management for developers. Versioned installs, per-project environments that activate automatically.
Homebrew is easy to start with and hard to maintain. Dependencies pile up invisibly, there is no manifest to version-control, and a clean reinstall means starting over. Nix solves all of this — declarative config, rollback, per-project isolation — but demands you learn a language and debug cryptic build failures. Gale is as easy to use as Homebrew and as predictable as Nix, without the baggage of either.
curl -fsSL https://raw.githubusercontent.com/kelp/gale/main/scripts/install.sh | shOr with Homebrew:
brew install kelp/tap/galeAdd gale to your PATH:
export PATH="$HOME/.gale/current/bin:$PATH"Install a tool:
gale install jqGale fetches a prebuilt binary, verifies its SHA256, and symlinks it into your PATH.
Set up a project manifest:
cd myproject
gale init
gale install go@1.26.1
gale install justThis creates gale.toml with pinned versions and a
lockfile with SHA256 hashes. Commit both. Anyone who
clones the repo runs gale sync and gets identical
tools.
Packages live in ~/.gale/pkg/, one directory per
version, never modified after install. A generation
directory holds symlinks into the store, and
~/.gale/current points to the active generation.
Installing or removing a package builds a new
generation and swaps the current symlink in one
atomic operation. No partial states, no broken PATH.
A project's gale.toml pins the tools it needs:
[packages]
go = "1.26.1"
just = "1.48.0"
golangci-lint = "2.11.4"
[vars]
CGO_ENABLED = "0"With direnv, environments activate on cd:
# One-time setup in ~/.config/direnv/direnvrc
eval "$(gale hook direnv)"Enter the project directory and direnv syncs packages,
adds .gale/current/bin to PATH, and exports
variables from [vars]. Leave the directory and your
global environment returns.
Global and project packages can coexist at different versions. Go 1.24 globally, Go 1.26.1 in the project — direnv handles the switch.
Teams migrating from asdf or mise can keep their
.tool-versions file. Gale reads it as a fallback
when no gale.toml exists.
One gale.toml can describe more than one machine.
Top-level [packages] applies everywhere; per-host
sections add or override entries on a specific
machine:
[packages]
jq = "1.8.1"
ripgrep = "14.1.1"
[hosts.my-mac.packages]
fzf = "0.50"
[hosts.my-server.packages]
htop = "3.0"Gale picks the section that matches hostname (or
GALE_HOST if set). Sync the same file across
machines with chezmoi or git — each machine runs
gale sync and gets its own toolset.
gale add fzf --host current # write to this host's section
ssh server gale sync # remote install — no special command neededSee docs/chezmoi.md and docs/configuration.md for details.
gale install <pkg>[@ver] Install a package
gale remove <pkg> Remove a package
gale sync Install at pinned versions
gale update [pkg...] Update to latest
gale list List packages in manifest
gale info <pkg> Show package metadata
gale outdated Show available updates
gale search <query> Search by name or description
gale which <binary> Find which package owns it
gale doctor Diagnose setup issues
gale gc Clean unused versions + gens
gale generations List and manage generations
gale init Set up a project
gale env Print PATH and vars for shell
gale shell Open shell with project env
gale run <cmd> Run command in project env
gale pin <pkg> Pin version, skip on update
gale unpin <pkg> Unpin a package
gale build <recipe> Build from source
gale lint <recipe> Validate a recipe
gale create-recipe <repo> Generate recipe with AI
gale audit <pkg> Rebuild and compare hashes
gale verify <pkg> Check binary attestation
gale sbom [pkg] Software bill of materials
gale completion <shell> Generate shell completions
See man gale for the full reference.
Recipes are TOML files in gale-recipes. The repository has over 180 recipes today, covering tools like jq, ripgrep, git, terraform, kubectl, and Go. Each recipe defines how to build a package from source. Prebuilt binaries cached in GHCR are an optimization — every recipe can build from source if needed.
gale create-recipe owner/repo generates a recipe
from a GitHub repository using the Anthropic API.
It detects the build system, computes the SHA256,
and produces a valid recipe. Requires an API key
in ~/.gale/config.toml.
[package]
name = "mytool"
version = "1.0.0"
description = "Does the thing"
license = "MIT"
homepage = "https://github.com/owner/mytool"
[source]
repo = "owner/mytool"
url = "https://github.com/owner/mytool/archive/refs/tags/v1.0.0.tar.gz"
sha256 = "..."
[dependencies]
build = ["go"]
[build]
steps = [
"mkdir -p ${PREFIX}/bin",
"go build -o ${PREFIX}/bin/mytool .",
]gh — GitHub CLI.
Used for Sigstore attestation verification during
binary installs, gale verify, and gale audit.
Without it, gale skips attestation checks and
installs proceed normally. gale doctor reports
its availability.
Anthropic API key —
used by gale create-recipe for AI-powered recipe
generation. Configure in ~/.gale/config.toml under
[anthropic]. Not needed for any other functionality.
Requires Go 1.26+ for bootstrapping.
git clone https://github.com/kelp/gale
git clone https://github.com/kelp/gale-recipes
cd gale
just bootstrap
gale sync --recipes ../gale-recipes
direnv allowAfter bootstrap, just install rebuilds gale from
source using gale itself.
just # test + lint
just build # build binary
just check # test + lint + formatMIT