envy
what's yours... is mine.
envy is an unopinionated, hermetic, per-project, serverless package manager.
- Unopinionated. A toolchain, a vendor SDK, an interpreter, a Homebrew formula, a udev rule: each is a package if a handful of Lua verbs can describe it.
- Hermetic. One
envy.luapins the whole toolchain, envy included, by version and checksum. Clone the repo and run a tool. - Per-project. Every project declares its own world, into a content-addressed cache, so ten projects pinning one compiler store it once. A project that wants its packages inside its own tree says so in one line.
- Serverless. No registry, no daemon, no server. Specs fetch bits from wherever they already live and verify them.
It ships as one batteries-included executable per platform: macOS, Linux, and Windows, on arm64 and x86_64. Lua, the archive formats, git, and S3 are compiled in, so there is nothing to install and no daemon to run. The committed bootstrap script downloads the build your project pins.
An optional package depot lets CI publish prebuilt artifacts
that everyone else's sync downloads instead of building. An accelerator you can
add, never a requirement.
See it work
Four real sessions, recorded end to end against the public first-party specs. The elapsed times on screen are the ones the machine actually took.
- One machine, many toolchains
- Builds what nobody ships
- Or downloads what CI built
- No project required
Two projects that need two different pythons, and a machine python that neither
of them touched. Switching between them is a cd, because the
shell hook puts each project's bin
directory on PATH as you arrive.
Why envy?
One job: give a project the tools it declares, on any machine, without disturbing anything else on it.
Attestable end to end, as far as you want it. Every link in the chain can be
pinned by content hash, envy's own binary included. The committed bootstrap
script verifies the release against @envy sha256sums before it runs anything,
a bundle from git requires a full commit
sha, a
spec carries a sha256 or a commit sha of its own, and each
spec's downloads are pinned in its fingerprint table. Pinning is per link, so a
project tightens it as far as it needs and no further.
Supply-chain resilience has the whole chain.
Not a system package manager. Homebrew and apt own one global set of packages
and are built around moving you forward. envy never updates anything. A version
is an option in a manifest, changed by editing that manifest. There is no
envy upgrade and no "outdated".
Alongside Nix. Nix takes on a larger problem than envy does and takes it on thoroughly. envy's scope is one project's tools, and it stays small enough to commit: a single executable, one bootstrap script, no daemon, no store to initialize, nothing that needs root. macOS, Linux, and Windows all run the same binary against the same manifest. Packages are ordinary directories, so anything that takes a path can use them.
Not Hermit. envy takes Hermit's best idea, the committed bootstrap script, but a Hermit package is a descriptor while an envy spec is a program. Any verb can be a Lua function, so a spec can accept a license over POST, drive a platform installer, or install a udev rule. Declarative shapes remain for the simple cases, and four-line specs are common.
So: apt or Homebrew for your machine, envy for your project.
A standalone toolbox
A package manager has to download from anywhere, unpack anything, verify bytes, and run scripts. envy exposes all of it, no manifest or project required:
| Command | What it does |
|---|---|
envy fetch | Download over https, http, ftp, ftps, s3://, git://, git+ssh://, or a local path |
envy extract | Unpack tar, tar.gz, tar.xz, tar.bz2, tar.zst, zip, 7z, rar, iso, and bare compressed streams, with glob selection |
envy hash | Print sha256sum-style lines, ready to paste into a spec or a depot index, or one BLAKE3 digest for a whole directory |
envy git-resolve | Turn a remote branch or tag into a full commit sha without cloning |
envy lua | Run a Lua script with envy's whole API available |
All compiled in rather than shelled out to: the AWS SDK for s3:// with your
ambient credentials, libgit2 for git, libarchive for formats. No CLI tools
required on the host. Specs reach the same machinery through
envy.fetch and friends.
Supply-chain resilience
No advisory feed, no scanner. The protection is structural: no registry to compromise, nothing resolved by name alone, and every link pinnable by content hash and committed to your repo.
- Nothing is fetched by name. No index, so no namespace to squat and no "latest" a publisher can push at you. A spec comes from a URL, a commit, or a bundle you named.
- envy verifies itself.
@envy versionand@envy sha256sumspin the release, and the bootstrap script verifies every binary before running it. Retargeting is one command and a reviewable diff. - Pins go all the way down. Specs carry a
sha256or a full commit sha, bundles require one, and a spec's downloads are pinned in its own fingerprint table. An unhashed download is re-fetched rather than trusted from cache. - Prebuilt artifacts are an accelerator, not an authority. A depot hit is checked against its hash, and a mismatch builds from source. A private mirror republishes the checksum file byte for byte, so one pin validates against both.
- Nothing modifies your machine by accident. Packages land in a cache you can delete. Host-level work lives in a named SETUP pair that runs only when a manifest entry selects it.
One limit: specs are Lua and envy runs them, which is how a spec handles a
license-acceptance POST. A spec source you do not control is code you do not
control. Pin it, review the diff when it moves, and keep your own specs under
local.*. Reproducibility has the full trust
chain.
The name, and the raccoon
Your project wants a pile of shiny things off the internet. envy goes and gets them, then pins the pile into a hermetic environment.
Ruckus is a raccoon. Raccoons take shiny things that are not theirs and have no idea what any of them do. Neither does envy. A compiler, a udev rule, and a license-gated vendor blob are all just shiny things to it.
Read envy for agents, a one-page, maximally dense summary of everything on this site.
Conventions
Examples call tools by bare name, envy sync and cmake --version, assuming the
shell hook is installed. Without it, prefix
the project's bin directory: ./bin/envy sync, or bin\envy.bat sync on
Windows. Snippets are POSIX for brevity, and every command behaves the same on
Windows.
Where to go
- Getting started to run an existing project's tools, or start a new one.
- Guides for recipes: packages, specs, monorepos, depots, CI.
- Concepts for the model: manifests, specs, verbs, dependencies.
- Reference for the CLI, file formats, and the Lua API.