A development environment is a toolkit component of kind environment. It is a
container with one purpose, an isolated home, and one language toolchain.
The environment module is components/<id>/. It declares the container, the
files that install it, and the router markers it owns. Nothing outside the
module holds a list of environment names, so adding an environment is adding a
module.
./install.sh --components web-dev # one environment, and what it needs
./install.sh --environments # every module, as TSV| Environment | Status | Toolchain |
|---|---|---|
web-dev |
supported | Node and pnpm, through nvm, plus the agent CLIs |
python-dev |
supported | Python and uv |
golang-dev |
supported | Go and the Go module toolchain |
rust-dev |
supported | Rust and cargo, through rustup |
dotnet-dev |
supported | .NET SDK for C# |
android-dev |
supported | Android SDK, JDK 25 and Gradle wrapper |
godot-dev |
supported | Godot engine .NET build, plus the C# SDK |
A planned module is a boundary without an installation. It declares the container name and the router markers, and nothing else. The installer refuses to install one. Every module above is supported: each has a container definition and an in-container bootstrap.
component.json carries the ordinary component contract, plus one block that
only an environment declares.
{
"id": "web-dev",
"kind": "environment",
"status": "supported",
"requires": ["distrobox", "devbox"],
"install": ["components/web-dev/install.sh"],
"environment": {
"container": "web-dev",
"ini": "distrobox/web-dev.ini",
"packages": "manifests/web-dev-packages.txt",
"toolchain": "manifests/toolchain.env",
"bootstrap": "bootstrap/web-dev.sh",
"router": "config/devbox-router/environments.d/web-dev.env",
"inference": "components/web-dev/inference.tsv",
"home": "~/.local/share/distrobox-homes/web-dev/"
}
}| Field | Meaning |
|---|---|
container |
The Distrobox container name. |
ini |
The distrobox assemble definition that creates the container. |
packages |
The base packages the container image installs. |
toolchain |
The verified toolchain versions the in-container bootstrap reads. |
bootstrap |
The script that converges the toolchain inside the container. |
router |
The router environment file: box, workspace mapping, login shell. |
inference |
The router markers this environment owns. |
home |
The isolated container home. It is machine-local state. |
A planned module declares container and inference only. A supported module
declares all of them, and verification fails when a declared path is missing.
components/<id>/inference.tsv holds the markers of one environment:
web-dev package.json
web-dev pnpm-workspace.yamlA rule takes an optional third field, the tier:
godot-dev project.godot specificThe tier is general when the field is absent. Resolution keeps the strongest
tier that matched, and judges ambiguity only inside that tier. A specific
marker therefore outranks the general markers of another environment.
Use specific only when one environment's repositories necessarily carry
another environment's markers. A Godot C# project holds project.godot and
a .csproj and a .sln, and the .csproj alone does not say which of the two
environments owns the repository. project.godot does, so it is the specific
marker and dotnet-dev keeps its general ones.
Markers must not otherwise overlap between environments. When the markers of two environments both match a repository in the same tier, the router fails with exit code 7 instead of guessing. Two specific markers are still ambiguous, because neither one is more specific than the other.
bootstrap/lib/devbox.sh assembles every module's file into
~/.config/devbox-router/inference.tsv. That file is generated, not linked into
the checkout, because several modules own it together.
bin/devbox carries the same table as a fallback, for a host whose
configuration is not installed yet. verify.sh --only 5 fails when the two
disagree, so the module stays the source of truth.
mkdir components/<id>and writecomponent.jsonwith the environment block. Start at"status": "planned"and declarecontainerandinferenceonly.- Write
components/<id>/inference.tsv. Every line names<id>. Add thespecifictier only for the case the section above describes. - Add the same rules to the fallback table in
bin/devbox, in module order. - When the environment becomes real, add the container definition, the package
manifest, the toolchain manifest, the in-container bootstrap and the router
environment file, declare each of them in the block, and set
"status": "supported". - Add the component operations:
installcreates the container and converges the toolchain, andverifynames the verification module. ./verify.sh --only 17checks the modules../verify.sh --only 5checks the router configuration they produce.
Nothing else changes. bootstrap/host.sh creates the container of every
supported module, and the router installation links the environment file of
every supported module.
- The isolated container home. It is machine-local state;
docs/not-tracked.mdsays why. - Repository assignments in
~/.config/devbox-router/repos.tsv. They are absolute host paths. - Distribution facts. An environment asks for the
distroboxandcontainer-runtimecapabilities;docs/platforms.mdsays how a platform supplies them.