Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions skills/devbox/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
name: devbox
description: Devbox expert guidance. Use when creating isolated development environments, managing project dependencies with Nix packages, authoring devbox.json, writing scripts or services, or generating Dockerfiles and devcontainers from a devbox project.
metadata:
docs:
- "https://www.jetify.com/devbox/docs"
- "https://github.com/jetify-com/devbox"
pathPatterns:
- 'devbox.json'
- 'devbox.lock'
- '.devbox/**'
bashPatterns:
- '^\s*devbox(?:\s|$)'
---

# Devbox Skill

[Devbox](https://github.com/jetify-com/devbox) creates isolated, reproducible development environments powered by Nix. You declare packages and scripts in a `devbox.json`; Devbox materializes a shell where everyone on the team gets the exact same tool versions without polluting the host machine. Use `devbox <command> -h` for full flag details on any command.

## Quick Start

```bash
curl -fsSL https://get.jetify.com/devbox | bash # install devbox
devbox init # create devbox.json in cwd
devbox add go@1.22 nodejs@20 # add packages (name@version)
devbox shell # enter the isolated shell
devbox run <script> # run a script from devbox.json
```

Packages resolve against the Nix package registry. Browse versions at [nixhub.io](https://www.nixhub.io).

## The `devbox.json` File

The project's source of truth. Minimum viable file:

```json
{
"packages": ["go@1.22", "nodejs@20"],
"shell": {
"init_hook": ["echo 'Welcome'"],
"scripts": {
"test": "go test ./...",
"build": ["go build ./...", "echo done"]
}
},
"env": {
"GOENV": "off",
"PATH": "$PWD/bin:$PATH"
}
}
```

- `packages`: array of `name@version` strings, or an object with per-package `platforms` / `excluded_platforms` / `outputs` / `patch` settings.
- `shell.init_hook`: commands run every time the environment starts (both `devbox shell` and `devbox run`). Keep it fast — it runs often.
- `shell.scripts`: named commands invoked with `devbox run <name>`. A value can be a string or an array of strings executed in order.
- `env`: extra env vars. Only `$PATH` and `$PWD` are expanded; no other variable expansion or command substitution.
- `include`: plugin references (e.g. `"plugin:nginx"`, `"path:./mydir"`, `"github:owner/repo"`).

See `references/devbox-json.md` for the full schema.

## Decision Tree

Use this to route to the correct sub-topic:

- **Add or remove a package** → `devbox add <pkg>@<ver>` / `devbox rm <pkg>`. See `references/packages.md`.
- **Enter an isolated shell** → `devbox shell`. Add `--pure` for a shell that inherits almost nothing from the host.
- **Run a task** → `devbox run <script>`. Pass arguments after `--` (e.g. `devbox run -- cowsay -d hi`). See `references/scripts-services.md`.
- **Install all packages in CI** → `devbox install` (no shell). Pair with `actions/cache` keyed on `devbox.lock`.
- **Update packages** → `devbox update` (all) or `devbox update <pkg>` (one). Use `--no-install` to update the lockfile only.
- **Find a package** → `devbox search <pkg>`.
- **Inspect installed packages** → `devbox list` / `devbox info <pkg>`.
- **Long-running services (dbs, workers)** → `devbox services start|stop|ls|attach`. See `references/scripts-services.md`.
- **Global tools (available everywhere)** → `devbox global add|rm|list`. See `references/global-and-templates.md`.
- **Bootstrap from a template** → `devbox create --template <name>` (use `--show-all` to list templates).
- **Generate Dockerfile / devcontainer / direnv** → `devbox generate dockerfile|devcontainer|direnv|alias|readme`.
- **Load env into the host shell** → `eval "$(devbox shellenv)"`, or `devbox generate direnv` for automatic loading.
- **Secrets (Jetify Cloud)** → `devbox secrets init|set|list|download|upload`.
- **Multiple envs (dev/prod/preview)** → `--environment <name>` flag.
- **Multi-project repos** → `--all-projects` on `run` and `update`; `--sync-lock` on `update`.

## Critical: Lockfile Hygiene

`devbox.lock` pins exact Nix store paths for every package. **Always commit it.** Without it, teammates and CI will get different versions.

- `devbox install --tidy-lockfile` repairs missing store paths.
- `devbox update --sync-lock` reconciles lockfiles across multiple projects in one repo.
- Do not hand-edit `devbox.lock`.

## Integrating with the Host Shell

`devbox shell` spawns a subshell, which is noisy for daily work. Two better options:

1. **direnv**: `devbox generate direnv` writes a `.envrc` so entering the directory auto-loads the environment. Requires `direnv` installed on the host.
2. **shellenv**: `eval "$(devbox shellenv)"` inline-loads the environment into the current shell. Useful in CI or one-off scripts.

## CI/CD

Typical GitHub Actions pattern:

```yaml
- uses: jetify-com/devbox-install-action@v0.13.0
with:
enable-cache: 'true'
- run: devbox run test
```

Without the action, use `devbox install` + cache `~/.nix-*` and `.devbox/` keyed on `devbox.lock`. Avoid `devbox shell` in CI — use `devbox run <cmd>` (non-interactive) or `eval "$(devbox shellenv)"` instead.

## Anti-Patterns

- **Running devbox without a lockfile committed.** Defeats reproducibility. Commit `devbox.lock` alongside `devbox.json`.
- **Using unversioned packages in production configs** (e.g. `"go"` instead of `"go@1.22"`). The resolver will pick whatever `@latest` resolves to the day you first install it; `devbox update` is the only way to bump it. Pin versions.
- **Shell substitution in `env` values.** Only `$PATH` / `$PWD` expand. Put dynamic logic in `init_hook` instead.
- **Heavy work in `init_hook`.** It runs on *every* `devbox run`, not just shell entry. Keep it to env mutations; move builds to scripts.
- **`devbox shell` inside scripts or CI.** Blocks on an interactive prompt. Use `devbox run` or `devbox shellenv` instead.
- **Editing `devbox.lock` by hand.** Let `devbox update`, `devbox install --tidy-lockfile`, or `devbox add` regenerate it.
- **Forgetting `--` before flags to the target command.** `devbox run cowsay -d hi` tries to parse `-d` as a devbox flag. Use `devbox run -- cowsay -d hi`.
- **Mixing `devbox` and `devbox global`.** `global` manages a separate config at `devbox global path` — project installs never leak into it, and vice versa.

## Common Recipes

- **New Go project**: `devbox init && devbox add go@latest && devbox shell`
- **Dockerize**: `devbox generate dockerfile` produces a `Dockerfile` that replicates the shell.
- **Reproduce in a devcontainer**: `devbox generate devcontainer` writes `.devcontainer/` for VS Code.
- **Share a global toolset**: `devbox global push` (to Jetify Cloud or a git repo); teammates run `devbox global pull`.
- **Run Postgres for local dev**: `devbox add postgresql` then `devbox services up postgresql`.
134 changes: 134 additions & 0 deletions skills/devbox/references/devbox-json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# `devbox.json` Reference

Full schema is at `.schema/devbox.schema.json` in the devbox repo. This is the practical subset.

## Top-level fields

| Field | Type | Notes |
|---|---|---|
| `$schema` | string | Schema version URL. Optional. |
| `name` | string | Project name. Optional. |
| `description` | string | Human-readable description. Optional. |
| `packages` | array \| object | Packages to install. See below. |
| `env` | object | Extra env vars. Only `$PATH` / `$PWD` expand. |
| `shell.init_hook` | string \| array<string> | Runs on every shell/run entry. |
| `shell.scripts` | object | Named commands; value is string or array<string>. |
| `include` | array<string> | Plugin includes. See below. |
| `env_from` | string | Inherit env from another devbox project path. |

## `packages` — two forms

**Array form** (simple, most common):

```json
"packages": ["go@1.22", "nodejs@20", "postgresql@15"]
```

**Object form** (per-package metadata):

```json
"packages": {
"go": "1.22",
"postgresql": { "version": "15", "excluded_platforms": ["aarch64-darwin"] },
"ffmpeg": { "version": "latest", "outputs": ["bin", "lib"], "patch": "always" }
}
```

Per-package options:

- `version`: semver or `latest`.
- `platforms`: only install on these platforms (allowlist).
- `excluded_platforms`: skip on these platforms (denylist). Cannot be combined with `platforms`.
- `outputs`: Nix outputs to install (most packages need only the default). Useful for libraries.
- `patch`: `auto` (default), `always`, or `never`. Controls glibc patching on Linux.
- `glibc_patch`: boolean shorthand for forcing glibc patching.
- `allow_insecure`: mark a CVE-flagged package as allowed. Pair with `devbox add --allow-insecure`.
- `disable_plugin`: skip any built-in plugin registered for this package.

Platform values: `i686-linux`, `aarch64-linux`, `aarch64-darwin`, `x86_64-darwin`, `x86_64-linux`, `armv7l-linux`.

## `env` — environment variables

```json
"env": {
"GOENV": "off",
"PATH": "$PWD/bin:$PATH",
"DATABASE_URL": "postgres://localhost/dev"
}
```

Only `$PATH` and `$PWD` are expanded. **No command substitution, no other variable expansion.** Put dynamic logic in `init_hook` instead.

## `shell` — scripts and hooks

```json
"shell": {
"init_hook": [
"unset GOROOT GOTOOLCHAIN",
"export PROJECT_ROOT=$PWD"
],
"scripts": {
"test": "go test ./...",
"build": ["go mod tidy", "go build -o bin/app ./cmd/app"],
"dev": "air"
}
}
```

- `init_hook` runs on every `devbox shell` AND every `devbox run`. Keep it cheap.
- Script values can be a single string or an array of strings executed sequentially, stopping on first non-zero exit.
- Invoke with `devbox run <name>`. Arguments after `--` are passed to the final command.

## `include` — plugins

```json
"include": [
"plugin:nginx",
"path:./plugins/my-plugin",
"github:jetify-com/devbox-plugins#path/to/plugin"
]
```

- `plugin:<name>` — built-in plugin shipped with devbox (see `pkg` directory in the devbox repo).
- `path:<dir>` — local plugin directory containing a `plugin.json`.
- `github:owner/repo[#path]` — plugin from a GitHub repo.

Plugins can contribute packages, env vars, services, and files. See `.schema/devbox-plugin.schema.json` for the plugin schema.

## `env_from`

```json
"env_from": "../shared-env"
```

Inherits env and packages from another devbox project on disk. Useful for monorepos with a shared base environment.

## Full example

```json
{
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.17.2/.schema/devbox.schema.json",
"name": "my-api",
"description": "Backend service",
"packages": [
"go@1.22",
"postgresql@15",
"redis@7"
],
"env": {
"CGO_ENABLED": "0",
"PATH": "$PWD/bin:$PATH"
},
"shell": {
"init_hook": [
"test -d bin || mkdir bin"
],
"scripts": {
"build": "go build -o bin/api ./cmd/api",
"test": "go test -race ./...",
"dev": ["devbox services up -b", "air"]
}
},
"include": ["plugin:postgresql", "plugin:redis"]
}
```
91 changes: 91 additions & 0 deletions skills/devbox/references/global-and-templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Global Packages, Templates, and Generators

## `devbox global` — machine-wide tools

`devbox global` manages a separate config (kept at `$(devbox global path)`) that's always on your PATH, independent of any project. Mirror of the per-project commands:

```bash
devbox global add jq ripgrep fzf # add tools
devbox global list # show installed
devbox global rm jq
devbox global install # reinstall from config
devbox global update # update all
devbox global path # print config directory
```

To make it live in your shell, add one of:

```bash
eval "$(devbox global shellenv)" # in ~/.zshrc or ~/.bashrc
```

### Sharing a global config

```bash
devbox global push # push to Jetify Cloud
devbox global push git@github.com:me/dotfiles-devbox.git # or your own git repo
devbox global pull <url-or-file> # pull on another machine
```

Useful for keeping the same CLI toolkit across laptops.

**Global and project configs never mix.** A project's `devbox.json` doesn't see global packages unless you explicitly run `eval "$(devbox global shellenv)"` in your shell first.

## `devbox create` — templates

```bash
devbox create --show-all # list templates
devbox create my-proj --template go # scaffold into ./my-proj
devbox create . --template python # scaffold into cwd
```

Templates are starter `devbox.json` + supporting files for common stacks (go, python, node, rust, etc.). Use when starting fresh.

## `devbox generate` — supporting files

```bash
devbox generate readme # regenerate the project README from devbox.json
devbox generate dockerfile # Dockerfile that replicates the shell
devbox generate devcontainer # .devcontainer/ for VS Code
devbox generate direnv # .envrc for direnv auto-loading
devbox generate alias # shell aliases for scripts
```

### `generate dockerfile`

Produces a `Dockerfile` that installs Nix, runs `devbox install`, and sets the entrypoint. The resulting image reproduces the dev shell. Pair with `.dockerignore` to avoid shipping `.devbox/` build artifacts.

### `generate devcontainer`

Writes `.devcontainer/devcontainer.json` and `.devcontainer/Dockerfile`. VS Code's Remote-Containers will pick it up and build an identical environment inside Docker.

### `generate direnv`

Writes a `.envrc` at the project root that runs `use devbox`. After `direnv allow`, the devbox environment activates automatically when you `cd` into the directory and deactivates when you leave. The recommended daily-use setup.

### `generate readme`

Regenerates the auto-generated README section (the `<!-- gen-readme start -->` block) from the current `devbox.json` — scripts, packages, env, init hook. Run after changing `devbox.json` to keep docs fresh.

## Secrets

`devbox secrets` integrates with Jetify Cloud for encrypted secret storage per environment:

```bash
devbox secrets init # link project to a Jetify secrets store
devbox secrets set API_KEY=sk-... # store a secret
devbox secrets list --environment prod # list for an environment
devbox secrets download .env.local # materialize to a file
devbox secrets upload .env # bulk import from a .env file
devbox secrets remove API_KEY
```

Environments (`dev` / `prod` / `preview`) scope secrets separately. Pass `--environment <name>` on `run`, `shell`, and `secrets` commands.

## Auth

```bash
devbox auth login # log in to Jetify Cloud (needed for secrets, global push)
devbox auth logout
devbox auth whoami
```
Loading
Loading