Four ways into the container, landing as dev in the same bind-mounted /home/dev - laptop and
workstation ~/projects differ.
| Route | From | Use it for |
|---|---|---|
herdr |
Laptop | Normal work: survives client exit, network loss |
ssh devbox |
Laptop | One-off commands, scripts, tunnels, rsync, git |
| Moshi | Phone | Watching, steering an agent away from the desk |
./bin/devbox shell |
Workstation | Recovery when SSH or the network is broken |
herdr # select "Devbox" in the sidebarA pane opens a login shell in /home/dev, running server-side after detach or quit - lid-close or
killed client won't interrupt a build, clone, or agent; reconnecting restores it.
herdr requires the pinned binary at /usr/local/bin/herdr - background connections get only the
default non-interactive SSH PATH, so it's missing from ~/.local/bin.
devbox is an SSH config alias, not a shell alias (Setup). Expands
to:
ssh -p 2223 -l dev -o IdentitiesOnly=yes -i ~/.ssh/devbox.pub <workstation>Interactive, then one-shot; quote so ~ expands remotely, not on the laptop:
ssh devbox
ssh devbox 'cd ~/projects/devbox && git status -sb'Anything reading ~/.ssh/config honours it: scp, rsync, git, ssh -L.
Add -A to forward the laptop's 1Password agent for one connection - manual git needs it (clone, fetch,
push, signed commit; agent sessions use HTTPS instead - Git identities):
ssh -A devboxPlain ssh devbox (no -A), herdr panes, ./bin/devbox shell never forward the agent - manual git
fails, on purpose: Git identities.
ssh <workstation> 'cd ~/devbox && ./bin/devbox shell' # docker compose exec -it devbox bash -lThis bypasses the container's sshd, working even if authorized_keys, the host key, or Tailscale is
broken.
Moshi's an SSH client: host <workstation>, port 2223, user dev, container-authorized key. Add the
phone's key to DEVBOX_EXTRA_AUTHORIZED_KEYS in .env on the workstation, not via Easy Pair - the
entrypoint rebuilds authorized_keys from GitHub plus that variable each start, erasing direct edits at
the next ./bin/devbox up.
Notifications, lock-screen approvals, and transcript view need moshi-hook, which bootstrap installs
and the entrypoint starts. One pairing step activates it - Toolchain.
Clone inside the container, agent forwarded, target directory picking the identity - the remote is the same plain GitHub URL either way:
ssh -A devbox
git clone git@github.com:<your-github-username>/<repo> ~/projects/<repo> # default identity
git clone git@github.com:<org>/<repo> ~/projects/work/<repo> # non-default, org in its `orgs`Full rules - how the ssh tag and the hasconfig: org include pick a non-default identity's key and author,
how agent sessions authenticate without either - in
Git identities.
Dev servers aren't published - forward the port over the existing SSH connection:
# in a devbox pane
pnpm dev # or python3 -m http.server 5173
# on the laptop
ssh -N -L 5173:localhost:5173 devbox &
curl -sS -o /dev/null -w '%{http_code}\n' localhost:5173 # 200AllowTcpForwarding yes in container/sshd_config enables this. Add more -L pairs for more ports; no
docker-compose.yml changes.
Do I clone on the laptop, the workstation, or in the container?
In the container: the bind mount makes a repo cloned in a herdr pane visible over ssh devbox and
./bin/devbox shell, surviving docker compose restart.
Is ssh devbox reachable from outside the Tailnet?
No - the port publishes only on the node's Tailscale address and 127.0.0.1 (Networking).
Why does git push fail over plain ssh devbox?
The devbox holds no private key; -A forwards the laptop's 1Password agent - see
Git identities.
Too many authentication failures - why?
The agent offered more than six keys before the right one; IdentitiesOnly yes plus
IdentityFile ~/.ssh/devbox.pub in Host devbox fixes it.
Host key verification failed after a rebuild?
Shouldn't happen: the host key lives in /home/dev/.ssh/host/'s bind mount, surviving rebuilds. Wiped
data dir? Remove the stale line: ssh-keygen -R '[<workstation>]:2223', reconnect.
Moshi connected to my laptop and 1Password asked to use the Devbox Laptop key - why?
Moshi's laptop host runs herdr, and every herdr client connects every saved machine itself: the new client
opens its own ssh devbox for the Devbox machine, and that is what 1Password is approving. Approve, and that
client shows the devbox through the laptop; deny, and only its Devbox entry sits at Attention - Local
panes, the desktop client and a direct phone → devbox connection are unaffected. The direct route above
involves neither the laptop nor 1Password, which is why it is the recommended one.
Which tools resolve in a non-interactive ssh devbox '<cmd>'?
All of them: pinned binaries in /usr/local/bin (node/npm/npx/corepack/pnpm, symlinked from
/opt/nvm); ~/.bashrc.d/devbox.sh loads above Ubuntu's non-interactive early return, putting
~/.local/bin (OMP's and Claude Code's install dir) on PATH, and ~/.bash_profile reasserts that order
for login shells, where ~/.profile would re-prepend ~/.local/bin ahead of the agent launchers. Verify
both routes: ssh devbox 'command -v omp claude node pnpm herdr' and
ssh devbox 'bash -lc "command -v omp claude"' - the second must print
~/.local/libexec/devbox-agent/omp and …/claude, the launchers.
Can I use VS Code / JetBrains Remote?
Yes - point Remote-SSH at devbox: an OpenSSH server, sftp enabled.
Does a pane keep running if the container restarts? No - the herdr server dies with the container; only the filesystem survives. herdr restores the shape, but running processes are gone.