devshell
wipReproducible, declarative development environments defined as code — spun up in seconds on top of Docker and Nix.
·#devtools#docker
GoDockerNix
const{Fragment:e,jsx:n,jsxs:t}=arguments[0];function _createMdxContent(a){const s={code:"code",p:"p",...a.components};return t(e,{children:[t(s.p,{children:[n(s.code,{children:"devshell"})," is a small CLI that takes a declarative spec of a project's toolchain — language version, system packages, env vars, services — and produces an identical, isolated shell anywhere. The spec lives in the repo, so onboarding a new contributor is one command instead of a wiki page."]}),"\n",n(s.p,{children:"The Go binary parses the spec, resolves it against a Nix flake for reproducible package versions, and wraps it in a Docker container for isolation. The result is a shell that behaves the same on my machine, a teammate's laptop, and CI — without anyone installing the toolchain on the host."}),"\n",n(s.p,{children:"Why both Nix and Docker? Nix gives bit-for-bit reproducible package versions across platforms, while Docker gives a hard isolation boundary so different projects can have conflicting runtimes on the same machine. Combining them gets you both properties without compromise."}),"\n",n(s.p,{children:"The work in progress is around startup time: cold-starting a container still costs seconds, and caching layers aggressively without breaking reproducibility is a subtle tradeoff. The current experiment is a daemon that keeps warm shells around and reuses them across projects with overlapping specs."}),"\n",n(s.p,{children:'It\'s a side project driven entirely by my own frustration with "works on my machine" — every feature exists because I hit the pain point myself.'})]})}return{default:function(e={}){const{wrapper:t}=e.components||{};return t?n(t,{...e,children:n(_createMdxContent,{...e})}):_createMdxContent(e)}};