How to Use Devbox: The Beginner's Guide (First Project, Nix Shells, Scripts, Services, and the Dockerfile Rule)
CodexFuse Team · 2026-11-01T16:39:43.000Z · 15 min read
Learning how to use Devbox takes one evening, and by the end you will have a project whose entire toolchain — language runtime, linters, database services — is declared in one file and reproducible on any teammate's machine. Devbox is Jetify's CLI for creating isolated, reproducible development shells from a devbox.json file: you declare the packages your project needs, run devbox shell, and the exact same tool versions appear, powered by the Nix package manager but without ever writing the Nix language. This devbox tutorial runs the complete beginner arc in one place: the mental-model lesson, installing Devbox, your first project from init to shell, the devbox.json and devbox.lock lesson, scripts versus init_hook, services, shipping the environment to Docker, direnv and offline mode, and the lane lines that keep Devbox from being confused with Docker, Nix, or Mise. If you are coming from containerized workflows, start with our Docker beginner guide — Docker puts applications in containers; Devbox puts developer tools in Nix shells. No containers, no virtualization layer, no Dockerfile required to start. One naming note before anything else: this guide is about Devbox by Jetify at jetify.com — not Sealos's "DevBox" cloud development product, and not the unrelated "devbox" Python repository-setup tool on PyPI, both of which clutter the search results for this exact keyword.
What Is Devbox, Exactly?
Devbox is a command-line tool that creates isolated development shells from a devbox.json file. The official Devbox Jetify documentation describes it as a package manager like yarn — except the packages it manages are at the operating-system level, the brew/apt-get level, rather than the library level. Jetify describes it as a package manager like yarn — except the packages it manages are at the operating-system level, the brew/apt-get level, rather than the library level. Under the hood it uses the Nix package manager to install more than 400,000 package versions from the Nix Package Registry, but it generates the Nix configuration for you, so you never write the Nix language. Two files define the environment: devbox.json, the human-readable declaration you edit, and devbox.lock, an auto-generated file with the exact resolved versions and nixpkgs commit hashes. Commit both to your repository, and any developer running devbox shell from the same commit gets bit-for-bit identical tool versions. Devbox itself is open source under the Apache 2.0 License and free; Jetify sells paid cloud products built on top of it, but the CLI costs nothing.
How Do You Install Devbox?
The official install path is a single script: curl -fsSL https://get.jetify.com/devbox | bash. Run it as a non-root user. If Nix is missing, Devbox installs it for you — in single-user mode on Linux and WSL2, and in multi-user (daemon) mode on macOS. If you would rather install Nix yourself first, Jetify's docs recommend the Determinate Systems Nix Installer. Verify the install with devbox version, which prints the CLI version. The current stable release is 0.19.0, published on 2026-10-29: its headline change is that Devbox is now its own launcher, replacing the old bash launcher, so starting the CLI dropped from roughly 78 milliseconds to roughly 8, and the daily update check now runs in the background. Two compatibility facts worth knowing up front: Devbox requires Nix 2.12 or newer, and it is incompatible with Lix 2.95 or newer, because Lix removed the builtins.fetchClosure function Devbox depends on — Devbox reports that clearly if you hit it. To update the CLI later, run devbox version update; the 0.19.0 release makes that a self-download instead of re-running the installer (if you installed via Nix or Homebrew it will point you at your package manager instead). Devbox runs on Linux, macOS, and Windows through WSL2 — there is no native Windows build, because the Nix layer it is built on targets Unix-like systems, so Windows users are routed to WSL2.
How Do You Create Your First Devbox Project?
This is the core arc of the whole guide. Each step below builds on the previous one, and at the end you will have a working, version-pinned dev environment.
- Move into your project directory. Devbox works per project, so every command runs inside the folder whose environment you are defining.
- Initialize the project. Run
devbox init. It creates a devbox.json file in the current directory. Jetify's own quickstart is explicit here: you should commit it to source control. - Search for packages. Run
devbox search python3(or any package name) to see what versions the registry offers. Package search resolves against www.nixsearch.com by default, and you can also search the Nixhub.io web catalog. - Add packages. Run
devbox add ripgrepfor the latest version, or pin one withdevbox add [email protected]. Version pins follow semver where possible, sodevbox add python@3means the latest major-3 release. To remove a package, rundevbox rm python. - Enter the shell. Run
devbox shell. The first run downloads the packages — a one-time cost — and your prompt gains a(devbox)prefix. Inside the shell,python --versionandwhich pythonpoint at the Nix store paths Devbox assembled, not at anything installed on your host. Runexitto leave, and your host environment is untouched. - Run a script without entering the shell. Run
devbox run devto execute a named script from devbox.json in the environment and exit — scripts always run with the project's pinned tools, regardless of what is installed globally. - Commit both files.
devbox.jsonanddevbox.lockboth go into git. The lock file records resolved versions, nixpkgs commit hashes, and per-platform Nix store paths, so a teammate checking out the same commit gets the identical environment.
# the whole arc in one block
cd my-project
devbox init
devbox search python3
devbox add [email protected] ripgrep
devbox shell
# inside the shell: (devbox) $ python --version
exit
devbox run dev
A useful detail for teams: you can pin which Devbox CLI version a project expects with a devbox_version field in devbox.json — for example "^0.18.0" in npm style, or an object with on_mismatch set to error to fail instead of warn. Since 0.19.0 there is also an auto mode that switches versions automatically. And if you prefer JSON with comments, devbox.jsonc is a recognized config filename — devbox.json still wins if both exist.
What Goes Inside devbox.json (and What Is devbox.lock)?
The devbox.json file is the artifact you commit — that is the one sentence to remember about Devbox's model. Its packages list holds entries like [email protected], or, for advanced cases, Nix flake references (GitHub and local flakes are both supported), and packages can also be declared as a map when you need per-package options such as platforms, excluded_platforms, or disable_plugin. The shell object has exactly two fields: init_hook, commands that run every time a shell starts (including via devbox run, after your shell's own rc files — for environment variables, aliases, and quick setup), and scripts, name-to-command mappings you invoke with devbox run <name>, each defined as a string or an array of strings. An env block sets environment variables for the shell, scripts, and services; those take precedence over machine variables and plugin variables, and values are limited to string literals plus $PWD and $PATH. An env_from block loads variables from .env files or Jetify Secrets, with a missing referenced file producing a warning rather than a failure. An include block pulls in extra configuration from plugins, merged in listed order with later plugins overriding earlier ones and your project config winning any conflict. The devbox.lock file, which Devbox maintains for you, records the resolved package versions, the exact nixpkgs commit hashes the environment came from, last-modified timestamps, and per-platform Nix store paths. Since 0.18.5, Devbox no longer rewrites each package's plugin_version to the running binary on every shell, run, or install — so mixed-version teams no longer fight over lockfile churn in git.
Shell Scripts vs init_hook: What Is the Difference?
This is the distinction beginners get wrong most often, so here it is plainly: scripts are commands you run on demand with devbox run <name>; the devbox init_hook commands run automatically every time anyone enters the shell. Put repeatable project tasks in scripts — dev starting the dev server, test running the suite, build producing a bundle — so a new teammate can discover them by reading devbox.json. Put environment preparation in init_hook: installing language-specific dependencies (for example a pip install or npm install that should happen on shell entry), exporting environment variables, and defining aliases. For complex setup logic, Jetify's own guidance is to call a normal shell script from init_hook rather than embedding a wall of commands in JSON — the logic stays readable, version-controlled, and reviewable as a plain file.
How Do Devbox Services Work?
Devbox services give your project its supporting cast — a Postgres, a Redis, a queue — without a second tool. They are backed by process-compose, an open-source process manager with an interactive TUI, and some Nix packages (postgres, redis, and friends) ship pre-configured services through Devbox's plugin system; if you do not want a package's plugin, add it with devbox add <pkg> --disable-plugin. Run devbox services up to start all services with the TUI in the foreground, devbox services up postgresql for just one, and devbox services up -b to background them so they survive the shell closing. Inspect with devbox services ls, stop everything with devbox services stop, restart with devbox services restart, reattach the TUI with devbox services attach, and stop every project's services at once with devbox services stop --all-projects. For services the plugins do not cover, define your own in a process-compose.yml file in the project root. One section is all this deserves in a usage guide: the point is that services live in the same devbox.json world as your tools, so one file still describes the whole development environment.
How Do You Ship a Devbox Environment with Docker?
Devbox does not need Docker, but it can produce one when you do — that is the Dockerfile rule. Running devbox generate dockerfile creates a Dockerfile for your project based on debian:stable-slim that installs Nix in single-user mode plus Devbox itself, giving you a single source of truth for the local shell and the container image. Related generators cover the rest of the packaging surface: devbox generate devcontainer produces a devcontainer.json plus Dockerfile for VS Code and Codespaces, devbox generate direnv writes an .envrc so entering the project directory auto-activates the environment, and devbox generate readme documents your scripts and services for teammates. The rule is simple: declare the environment once in devbox.json, and let the generators translate it — never maintain a hand-written Dockerfile and a devbox.json as two separate truths.
What About Direnv and Offline Mode?
Two quality-of-life features close out the core loop. Direnv integration removes the need to type devbox shell at all: install direnv, hook it into your shell, run devbox generate direnv inside the project, and approve the generated .envrc with direnv allow. From then on, cd-ing into the project auto-activates the Devbox environment and cd-ing out deactivates it. Devbox offline mode covers the other end of the workflow — working with no network at all. Introduced in the 0.8.4 release, it works by caching the generated shell environment in .devbox/.nix-print-dev-env, with hashes of devbox.json and devbox.lock tracked in local.lock so Devbox knows when the cache is stale. If your packages are already fetched into the local Nix store, shells and scripts simply reuse the cache and start without touching the network — handy on planes, trains, and conference Wi-Fi.
Devbox vs Docker vs Nix vs Mise: Which Lane Is It?
Devbox gets compared to everything, so here is each lane line drawn once, and only once. The devbox vs nix question comes up most often, because Nix is the engine underneath — but needing Nix's power and learning Nix's language are different things.
| Tool | What it actually is | The one-line difference |
|---|---|---|
| Docker | Containerized applications | Docker runs apps in containers; Devbox puts dev tools in Nix shells — Devbox's own FAQ says it requires no Docker or containers to work. |
| Nix | The package manager underneath | Devbox gives you Nix's reproducibility without requiring you to learn the Nix language — it writes the Nix configuration for you. |
| Mise | A version manager for runtimes | Mise shims per-directory tool versions into your path; Devbox builds an isolated Nix shell per project. Different layer, different mechanism — version management is not the same job as environment isolation. |
The docs' own comparison framing puts it this way: Devbox claims the benefits over pure Docker containers, pure Nix shells, or managing your own environment directly. Two siblings live nearby without being rivals: our mise beginner guide covers the version-manager lane if that is all you need, and our Nixpacks beginner guide covers Nix-powered builds for deployment — Devbox is the per-project dev-shell lane, and none of these three replaces the others. Also note where Flox sits in this map: our Flox beginner guide covers the other major Nix-backed environment manager; the two overlap in promise but differ in mechanism and config format, so treat that comparison as its own reading, not a verdict in this guide.
What Are the Beginner Mistakes with Devbox?
Every tool has the same seven traps. Here they are, learned so you do not have to.
| Mistake | What actually happens |
|---|---|
| Committing devbox.json but not devbox.lock | Teammates resolve packages against a newer nixpkgs commit and get different versions — the lock file is the reproducibility, not a convenience. |
| Installing tools globally "just in case" | The host tool shadows nothing, but you lose the whole point: inside the shell, Devbox's packages take precedence over machine-installed ones, so global installs only create confusion. |
| Running the installer as root | Devbox expects the installer to run as a non-root user so the Nix store layout matches its assumptions. |
| Embedding long setup scripts in init_hook | JSON becomes unreadable; call a separate shell script from init_hook instead, so setup logic is reviewable. |
| Expecting native Windows support | Devbox does not run on native Windows — WSL2 is the supported path, because the Nix layer underneath needs a Unix-like system. |
Forgetting init_hook runs on devbox run too | Expensive init_hook commands slow every script invocation; keep hooks light and put heavy work in on-demand scripts. |
Skipping devbox version when a project behaves oddly | Behavior differs across 0.18.x and 0.19.x (launcher rewrite, auto version mode) — a project's devbox_version pin exists precisely for this. |
Sources
Every fact in this guide was verified against a source fetched on 2026-11-01: Jetify's Devbox documentation home (what Devbox is, the yarn-for-OS-packages positioning), installing-devbox (install script, non-root requirement, Nix auto-install modes, Determinate Systems recommendation, devbox version update), the quickstart (init, search, add/remove, shell behavior, lock file commit guidance), configuration (version pinning syntax, packages as flake references or maps, shell init_hook/scripts fields, env, env_from, include), the services guide (process-compose backing, up/ls/stop/restart/attach/stop --all-projects, plugin services, custom process-compose.yml), the FAQ (Docker-not-required, Nix >= 2.12, Lix incompatibility), the Nix-powered Docker containers blog post (generate dockerfile base image, generate devcontainer), the weekly-update-15 release notes (offline mode in 0.8.4, cache mechanism in .devbox/.nix-print-dev-env with local.lock hash tracking), the 0.19.0 GitHub release notes (own-launcher change with 78ms-to-8ms startup, background update check, on_mismatch auto, generate direnv --print-envrc, generate readme/debug, nixsearch.com default search host since 0.18.4, devbox.jsonc recognition, plugin_version lockfile fix in 0.18.5), the Devbox landing page (no Docker containers or Nix lang required, open-source project), Jetify Cloud pricing (Devbox CLI free; Jetify Deploys and Devspace cloud products paid), and community install guides for the Homebrew tap path.
Frequently Asked Questions
Do you need to learn Nix to use Devbox?
No. That is the entire point of the tool: Devbox uses the Nix package manager under the hood and generates the Nix configuration for you. You declare packages in plain JSON and never write a Nix expression. (You will still benefit from knowing what the Nix store is when you debug, but it is never required.)
Do you need Docker to use Devbox?
No. Devbox environments are Nix shells, not containers — the official FAQ answers this directly. Use devbox generate dockerfile only when you want a container artifact for deployment or Dev Containers.
Should you commit devbox.lock to git?
Yes — always commit both devbox.json and devbox.lock. The lock file pins the exact nixpkgs commits and per-platform store paths, which is what makes every machine reproduce the same environment.
Does Devbox work on Windows?
Only through WSL2. There is no native Windows build because the Nix layer Devbox is built on targets Unix-like systems; Linux and macOS are supported natively.
How does offline mode work?
If your packages are already in the local Nix store, Devbox reuses the cached generated shell environment in .devbox/.nix-print-dev-env and skips the network entirely. Cache invalidation is tracked with hashes of devbox.json and devbox.lock in local.lock.
Devbox belongs to the family of tools trying to kill "works on my machine" for good — commit devbox.json and devbox.lock like your project's future depends on it, because your onboarding time does. If you maintain the containerized half of your workflow too, our Docker beginner guide covers the deploy-runtime side; and if you want to pin shell histories and tool versions on the lighter version-manager end, see our mise beginner guide and our Git beginner guide for keeping all of this in version control.