NO DAEMONS · NO ROOT · NO DRIFT

Dev environments, reproduced.

One committed config file. Isolated shells and service stacks built from pinned Nix packages on Linux, or booted as lightweight VMs via apple/container on macOS — warm starts in about a second. Docker export when you need it.

# macOS: brew install container && container system start
$ curl -fsSL https://raw.githubusercontent.com/imraghavojha/lagoon/main/install.sh | bash

linux arm64/amd64 · macos 15+ apple silicon

SCROLL
lagoon shell
$ lagoon shell
vm ready — 0.9s
[lagoon] /workspace $ uname -s
Linux
[lagoon] /workspace $ python3 --version
Python 3.12.4
[lagoon] /workspace $ exit
$
lagoon shell on a Mac — an isolated Linux environment, booted in about a second. Exit, and nothing persists.
(01)

Services, simply.

Declare services in lagoon.toml and run lagoon up. Ports are inferred from the commands and published to localhost, logs stream into one dashboard, and q tears everything down. It covers the docker compose up workflow for small projects.

lagoon up
lagoon up 2 services · network on
web node server.js → localhost:3000
api python3 manage.py … → localhost:8000
web listening on :3000
api dev server at 0.0.0.0:8000
web GET / 200 0.8ms
api GET /api/health 200 1.2ms
[q] stop everything
lagoon up — live status, published ports, and request logs in one dashboard.
lagoon ps
$ lagoon ps
project myproject
packages python3 nodejs
profile minimal
cached yes
PID MEMORY PROJECT PACKAGES
12345 42.1 MB myproject python3 nodejs
lagoon ps — machine, cache, and everything running for the project.
(02)

Setup in seconds.

lagoon init detects your hardware, suggests sane defaults, and previews the config before writing it. Presets for Python, Node, Go, llama.cpp, and whisper.cpp.

lagoon init
$ lagoon init
? what are you building python api
? preset python 3.12 + uv
? network access yes
verifying on nixpkgs… python311 uv
preview lagoon.toml — write it? [Y/n] y
wrote lagoon.toml — commit it
lagoon init — pick an intent and preset, preview, write.
(03)

One file, the lightest runtime everywhere.

The same lagoon.toml resolves through the lightest runtime each platform has.

LINUX

Nix + bubblewrap

Packages come from a pinned nixpkgs commit, so the environment is identical on every machine and stays identical over time.

Shells run in a bubblewrap sandbox: empty filesystem, project at /workspace, ephemeral home, network only if the profile allows it. No daemon — nothing runs when you're not inside.

MACOS

apple/container

Each shell and service boots in its own lightweight VM. Warm starts land in about a second on Apple Silicon.

The preset maps to a small official image (python:3.12-slim, node:22-slim, …), overridable with image = "…". Docker Desktop works as an automatic fallback.

(04)

The whole config fits on a postcard.

One file in your project root. Commit it — every machine that clones the repo gets the same environment, today and a year from now.

packages = ["python311", "uv"]

# pinned nixpkgs revision — set by lagoon init, used on linux
nixpkgs_commit = "26eaeac4e409d7b5a6bf6f90a2a2dc223c78d915"
nixpkgs_sha256 = "1knl8dcr5ip70a2vbky3q844212crwrvybyw2nhfmgm1mvqry963"

profile = "network"          # "minimal" = no network
memory_cap = "2g"
image = "python:3.12-slim"   # optional: image used on macos
on_enter = "uv sync"         # optional: runs on shell entry

[up]
web = "python3 -m http.server 8000"
(05)

Ten commands, no flags to memorise.

lagoon init
create lagoon.toml interactively — hardware detection, presets, live nixpkgs search
lagoon shell
enter the sandboxed environment
lagoon run <cmd>
run a one-off command in the sandbox
lagoon up
start [up] services with a live dashboard
lagoon ps
machine, cache, and running processes
lagoon watch <cmd>
re-run a command on file changes
lagoon check
validate the config and verify packages exist
lagoon save / load
move environments to offline machines as one file
lagoon docker <file>
export a docker-compatible image tar
lagoon rm
remove the project's cached environment