# cachix/devenv: declarative developer environments on top of Nix

> devenv wraps Nix in a devenv.nix file, a Rust process manager and a terminal UI so a repository can declare its compilers, services and tasks. It is a good fit for teams already willing to run Nix, and a poor fit for anyone who wants to avoid it.

**cachix/devenv** — Fast, Declarative, Reproducible, and Composable Developer Environments using Nix.

- Repository: https://github.com/cachix/devenv
- Website: https://devenv.sh
- Stars: 7,677 · Forks: 571
- Language: Rust
- License: Apache-2.0
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/cachix-devenv

## The problem devenv solves, and the name collision it does not

Setting up a working environment for a repository usually means a README list of versions, a shell script nobody maintains, and a container that drifts from both. devenv's answer is a single devenv.nix file that declares the environment, with devenv.lock pinning the Nix inputs it resolves against. The README describes the project as "Fast, Declarative, Reproducible, and Composable Developer Environments" and the init command scaffolds devenv.yaml, devenv.nix and .gitignore.

The audience is teams that already accept Nix, or are willing to. The README advertises 50+ languages with compilers, LSP servers, formatters, linters and version selection, 100,000+ packages from Nixpkgs for Linux, macOS, x64 and ARM64 including WSL2, and 40+ services such as PostgreSQL, Redis, MySQL, MongoDB, Elasticsearch and Caddy. If your environment is one language with no services, that surface area is more than you need.

One thing worth stating plainly: searches for devenv often mean devenv.exe, the Visual Studio process. That is a different product. This repository is the Nix-based developer environment tool from Cachix, and nothing here has anything to do with Visual Studio.

## How devenv.nix, devenv.lock and the Rust workspace fit together

The configuration split is the core mechanism. devenv.nix holds the declaration: env.GREET, packages, languages, processes, services, scripts and enterShell. devenv.yaml holds inputs, the Nix dependencies the environment is built from, and devenv update regenerates devenv.lock from them. The README links separate references for yaml options and for devenv.nix options, which is where the actual option surface lives; the quick start file is a scaffold, not a specification.

Below that, the repository is a Rust workspace. Cargo.toml lists members including devenv, devenv-core, devenv-processes, devenv-tasks, devenv-tui, devenv-reload, devenv-shell, devenv-nix-backend, devenv-eval-cache, devenv-cache-core, devenv-proxy and nix-conf-parser. The default-members list is devenv, devenv-proxy, devenv-run-tests and devenv-shell, and the comment above it says Nixpkgs and other downstream packagers invoke Cargo from the workspace root and use that list. That comment is the clearest signal of how the project expects to be packaged.

The pieces map onto advertised features. devenv-processes is the native process manager, which the README says supports dependency ordering, restart policies, readiness probes (exec, HTTP, systemd notify), socket activation, watchdog heartbeats and file watching. devenv-tasks covers DAG-based task execution, caching, parallel runs and namespace support. devenv-eval-cache is the incremental Nix evaluation caching behind the sub-100ms claim for unchanged environments. devenv-tui is the terminal UI with live build progress, task hierarchy and error details. devenv-reload backs native shell reloading, which the README says rebuilds in the background while the shell stays interactive.

## Installing devenv and getting a first shell running

The README does not include an installation section; it points to the Getting Started page at devenv.sh for setup, and the commands block shows version 2.0.0 while the release list and Cargo.toml workspace version are further along. Follow the Getting Started page for the install method for your platform rather than copying a command from here.

Once the binary is on your PATH, the workflow in the README is two commands. First, scaffold the files:

```bash
devenv init
```

That generates devenv.nix, devenv.yaml and .gitignore. The generated devenv.nix is a commented scaffold. The parts that matter on first run are env.GREET, packages and a script:

```nix
{ pkgs, lib, config, inputs, ... }:

{
  env.GREET = "devenv";
  packages = [ pkgs.git ];
  scripts.hello.exec = ''
    echo hello from $GREET
  '';
  enterShell = ''
    hello
    git --version
  '';
}
```

The README notes that scripts can be run directly, which is why enterShell calls hello as a bare command. Then activate the environment:

```bash
devenv shell
```

You should land in a shell where git resolves to the pinned Nixpkgs build and hello prints the value of GREET. To enable a language, uncomment the matching line, for example languages.rust.enable = true, and to add a database, services.postgres.enable = true. The README also documents ad hoc environments from the CLI without any config file, using the form --option languages.rust.enable:bool true, and out of tree devenvs via --from github:myorg/configs. When you change inputs in devenv.yaml, devenv update rewrites devenv.lock.

The commands block lists init, generate, shell, update, search and info. generate uses AI to produce devenv.yaml and devenv.nix, and search looks through packages and options in nixpkgs; the README links a section on searching for a file. For editor support, the README points to an LSP for devenv.nix with autocomplete, hover docs and go to definition via bundled nixd.

## Where devenv gets in the way

The dependency on Nix is the first constraint, and it is not hidden. Every package comes from Nixpkgs, every input is pinned through devenv.yaml and devenv.lock, and the Getting Started path assumes you can install and run Nix on your machine. On a team where that is not acceptable, devenv is the wrong tool regardless of how good the declarative layer is.

Evaluation cost is the second. The sub-100ms figure the README gives applies when nothing changed, which is what incremental evaluation caching is for. The first evaluation of a new environment, or one after an input change, still has to resolve the Nix expression and build what is missing. The caching crate exists precisely because that cost is real.

The README is also thin in places that matter for operations. There is no documented rollback for devenv.lock after devenv update, and no documented policy for how devenv.yaml inputs should be reviewed before an update. For a file that pins the environment every developer builds, that is a gap, and it is the kind of gap you discover when an update breaks a build on a Friday.

Finally, the feature list is broad: containers, outputs, polyrepo support, profiles, imports, inputs, SecretSpec, git hooks, tests, direnv integration, an MCP server and AI generation. Each of those is a surface with its own documentation page. A small project that only needs a compiler and a formatter will spend more time reading those pages than the environment saves.

## devenv compared with direnv and with devbox

direnv is the comparison the README itself invites, since it links a direnv integration page. direnv is a shell hook: it watches a directory, and when you enter it, it evaluates .envrc and loads whatever that file exports. It has no opinion about where those variables or binaries come from, and it does not manage services, processes or tasks. devenv uses direnv for automatic activation when entering a directory, but the environment itself is declared in devenv.nix and built through Nix. If your .envrc already works and your problem is only activation, direnv alone is the smaller answer.

devbox is the closer comparison: both declare Nix-backed environments from a config file. The difference visible in this repository is scope. devenv ships a native process manager with readiness probes, socket activation and automatic port allocation, a task runner with DAG execution and caching, OCI container builds without Docker, and outputs for packaging apps with language-specific tools such as crate2nix and uv2nix. That is a larger surface than environment provisioning alone, and it is the reason the Rust workspace has separate crates for processes, tasks, reload, TUI and proxy rather than one binary doing everything.

Profiles and imports are the composition story. The README shows environment variants selected with --profile backend --profile testing, and sharing environments across projects through imports. For a polyrepo setup, the inputs mechanism pins and overrides Nix dependencies, and the polyrepo guide covers referencing outputs and options across repositories.

## Maintenance, licensing and what an upgrade costs

The repository is not archived, and the last push was on 2026-08-13, with v2.2.2 tagged the same day, following v2.2.1 on 2026-08-02 and v2.2 on 2026-07-28. That is a steady release cadence through the summer of 2026. The Cargo.toml workspace version reads 2.3.2, ahead of the newest published release in the list, which is normal for a repository between a release and its next tag but worth knowing if you are pinning by version.

The licence is Apache-2.0, both in the repository metadata and in the Cargo.toml workspace.package section, and the repository carries a LICENSE file. Apache-2.0 is a permissive licence with an explicit patent grant and a requirement to preserve notices; it is not a copyleft licence. That is a statement about the licence text, not advice about your situation. If you redistribute devenv or a container built from it, read the LICENSE file and the notices it requires, and treat the Nixpkgs packages your environment pulls in as separate works with their own licences, since devenv does not relicense them.

Upgrade cost is tied to devenv.yaml inputs rather than to the binary. devenv update regenerates devenv.lock from those inputs, so the size of an upgrade depends on how far your pinned inputs have moved. The RELEASE.md file in the repository root is where release practice is recorded, and CHANGELOG.md is where behaviour changes land. Neither is summarised in the README, so budget time to read the changelog between your current version and the target before running update on a repository other people depend on.

## Conclusion

Adopt devenv if your team already runs Nix or is willing to, and you want languages, services and tasks declared in one devenv.nix that composes across repositories through imports and inputs. Do not adopt it if you need a Nix-free setup, if you are looking for Visual Studio's devenv.exe, or if your project is a single language with no services and a plain lockfile already covers it. Before committing, run devenv init in a scratch repository, check that the languages and services you need are listed in the language and service references, and confirm that devenv update resolves your pinned inputs, since the README does not document a rollback path for devenv.lock.

## FAQ

### What is devenv nix?

devenv is a tool from Cachix that declares developer environments in a devenv.nix file and builds them from Nixpkgs, with devenv.lock pinning the Nix inputs. The README describes it as fast, declarative, reproducible and composable, and lists 50+ languages, 100,000+ packages and 40+ services.

### How do I install devenv?

The README does not include installation steps; it links the Getting Started page at devenv.sh for setup. Once the binary is available, devenv init scaffolds devenv.yaml, devenv.nix and .gitignore, and devenv shell activates the environment.

### How do I use devenv?

Run devenv init to generate the config files, edit devenv.nix to set packages, languages, processes, services and scripts, then run devenv shell. The README also documents ad hoc environments from the CLI with --option languages.rust.enable:bool true and out of tree configs with --from github:myorg/configs.

### What is devenv sh?

devenv shell is the command that activates the developer environment declared in devenv.nix, and the README links devenv.sh as the project's documentation site. The commands block lists shell alongside init, generate, update, search and info.

### What is the devenv command?

devenv is the CLI for the environment. Its subcommands are init, which scaffolds devenv.yaml, devenv.nix and .gitignore; generate, which uses AI to produce those files; shell, which activates the environment; update, which updates devenv.lock from devenv.yaml inputs; search, which searches packages and options in nixpkgs; and info, which prints information about the environment.

### What is the devenv.exe process?

devenv.exe is the Visual Studio process, a different product from this repository. This project's executable is the Nix-based devenv CLI from Cachix, invoked as devenv init or devenv shell.

## Sources

- [Official documentation](https://devenv.sh)
- [Official README](https://github.com/cachix/devenv#readme)
- [Project repository](https://github.com/cachix/devenv)
- [Release notes](https://github.com/cachix/devenv/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cachix-devenv
