One Docker container with its own unprivileged sshd, published only on the node's Tailscale address. A
herdr client on a laptop attaches to it as a saved machine and runs OMP and Claude Code
agents inside β the container is the agent sandbox.
π Documentation Β· Installation Β· Connecting Β· Git identities Β· CLI
| Feature | What it gives you |
|---|---|
| Agent sandbox | Agents with bypassed permissions reach the project tree, the internet and LAN, and a rootless project Docker daemon only |
| Tailnet-only access | One sshd port, published on the Tailscale address (BIND_ADDR) and loopback β never 0.0.0.0 |
| No private keys | Public keys only; manual git borrows the laptop's 1Password agent, agent git gets HTTPS and per-operation tokens |
| Multiple identities | One identities.conf routes git author, signing key and GitHub token by directory and GitHub owner |
| Project Docker | docker compose against a rootless sibling daemon, with path identity and project ports kept off the Tailnet |
| Persistent workspace | herdr panes survive client exit; /home/dev is a host bind mount that survives every rebuild |
| One CLI, both sides | ./bin/devbox for workstation and laptop, with a doctor acceptance test on each |
Important
The container is the sandbox: agents never reach the host filesystem, the host's root Docker daemon or a private key β the box holds public keys only. It contains authority, not data: outbound internet is unrestricted and the LAN is reachable β only the host's own services and the Tailnet overlay are blocked β so assume anything inside can leave. See Security model.
Requires a workstation running Ubuntu 26.04 LTS with Docker and Tailscale β₯ 1.98, two 1Password SSH keys β the Devbox
Laptop key and your default identity's key, with only ~/.ssh/devbox.pub and ~/.ssh/id_<slug>.pub on disk β the two
~/.ssh/config blocks, a non-empty BIND_ADDR and bash >= 4.2 on the laptop (brew install bash; macOS
ships 3.2, which the generated bin/devbox refuses) β see Installation. A laptop set up with
dotfiles has the keys, the blocks and bash already.
From the laptop:
./bin/devbox install # devbox + bash completion on this laptop's PATH
./bin/devbox deploy <workstation> # sync the repo to ~/devbox (and `devbox` there too)
ssh <workstation> 'cd ~/devbox && ./bin/devbox env' # .env from .env.example, BIND_ADDR from Tailscale
ssh -t <workstation> 'nano ~/devbox/.env' # DEVBOX_EXTRA_AUTHORIZED_KEYS: ~/.ssh/devbox.pub
ssh -t <workstation> 'cd ~/devbox && sudo ./bin/devbox docker setup' # once: project Docker, asks for a password
ssh <workstation> 'cd ~/devbox && ./bin/devbox up && ./bin/devbox doctor'
herdr machine add devbox --label "Devbox" # once the ~/.ssh/config blocks exist
ssh <workstation> 'cd ~/devbox && ./bin/devbox skills' # optional: agent skills + browser automation
./bin/devbox sync omp # optional: this laptop's OMP preset β devbox
ssh -t devbox claude # once, if you use Claude Code: /login
./bin/devbox agent install # laptop: the same agent git override
./bin/devbox doctor laptop # laptop: acceptance testThen run herdr and open panes on the Devbox machine, or ssh devbox for a plain shell.
Warning
up, down and rebuild recreate the container and drop every live SSH session and herdr pane; they ask first
unless --force is given.
Everything else β architecture, installation, connecting, git identities, secrets, toolchain, networking, project Docker, operations, security, CLI and development β lives in docs/.
| Item | Details |
|---|---|
| Maintainer | @rozsival (see CODEOWNERS) |
| Issues | GitHub Issues |
| License | MIT |