Skip to content

Commit 91c98f2

Browse files
author
rozsival-agent
committed
refactor: replace bin scripts with one bashly-generated devbox cli
1 parent f5fa97f commit 91c98f2

63 files changed

Lines changed: 6155 additions & 1861 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/devbox-basics/SKILL.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ rootless project Docker daemon - never the host filesystem or its root Docker da
1717
```
1818
laptop <workstation> (host) container "devbox"
1919
herdr client --ssh--> BIND_ADDR:2223 --DNAT--> :2222 sshd running as dev
20-
./bin/push --rsync-> ~/devbox (the repo) /home/dev <- bind mount of
20+
devbox deploy --rsync-> ~/devbox (the repo) /home/dev <- bind mount of
2121
${DEVBOX_DATA_DIR} ${DEVBOX_DATA_DIR}
2222
```
2323

@@ -35,7 +35,7 @@ Four facts:
3535
4. **No root, no root socket.** `USER dev`, PID 1 `dev`, `cap_drop: [ALL]`, `no-new-privileges`; the host's
3636
root Docker socket is never mounted. Project containers come from a *second* daemon: a rootless
3737
`dockerd` owned by the dedicated host user `dev`, socket `/run/devbox/docker.sock`, provisioned once by
38-
`sudo ./bin/rootless-docker` - after which `docker` and `docker compose` work in the box. That daemon
38+
`sudo ./bin/devbox docker setup` - after which `docker` and `docker compose` work in the box. That daemon
3939
publishes project ports on the devbox bridge gateway (`--ip` plus `--default-network-opt`, since `--ip`
4040
alone covers only the default bridge). `devbox-docker-firewall` - nftables matching the daemon's socket
4141
cgroup - holds the line regardless: even an explicit `0.0.0.0:` port never reaches the Tailnet or the
@@ -63,7 +63,7 @@ Dev servers are never published. Forward them: `ssh -N -L 5173:localhost:5173 de
6363
## Identity registry: any number of accounts, one file
6464

6565
`~/.config/devbox/identities.conf` is the single source of identity truth, held on both machines
66-
(`./bin/sync-identities` copies the laptop's copy to the devbox). One `[slug]` block per account, routed by
66+
(`./bin/devbox sync identities` copies the laptop's copy to the devbox). One `[slug]` block per account, routed by
6767
directory prefix - the longest match wins, and exactly one block with no `dir` is the default that catches
6868
every tree no other block claims:
6969

@@ -86,7 +86,7 @@ PRs carry the bot author too. Full mechanism: `docs/git.md`.
8686

8787
`./bin/devbox skills` (workstation) installs `agent-browser`, `skill-creator`, `find-skills` into
8888
`~/.agents/skills` (OMP) with a symlink each in `~/.claude/skills` (Claude Code), plus its CLI and a Chrome
89-
build, so panes can drive a headless browser. `./bin/sync-omp` (laptop) copies `~/.omp/agent/config.yml`
89+
build, so panes can drive a headless browser. `./bin/devbox sync omp` (laptop) copies `~/.omp/agent/config.yml`
9090
into the devbox so panes share the laptop's OMP preset. Neither runs during bootstrap; both are idempotent.
9191
Claude Code itself is installed by bootstrap and needs one `/login` in a pane (`docs/toolchain.md#claude-code`).
9292

@@ -121,7 +121,7 @@ Answer from these files, not memory - each ends with an FAQ of real failures.
121121
| Identity split, signing, verification | `docs/git.md` |
122122
| Installed tools, pinned versions, agent skills | `docs/toolchain.md` |
123123
| Secret layers, `secrets.env`, `gh` tokens, GCP ADC | `docs/secrets.md` |
124-
| Every `bin/devbox` / `bin/push` / `bin/sync-omp` cmd | `docs/cli.md` |
124+
| Every `bin/devbox` command (workstation + laptop) | `docs/cli.md` |
125125
| Exposure model, why UFW cannot help | `docs/networking.md` |
126126
| Redeploy, restart, backup, `doctor`, troubleshooting | `docs/operations.md` |
127127
| Project containers, path identity, `devbox-ports` | `docs/docker.md` |

‎.agents/skills/devbox-deploy/SKILL.md‎

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,50 @@
11
---
22
name: devbox-deploy
3-
description: Pushes repo changes out to the devbox and applies them - ./bin/push, choosing between up, rebuild and bootstrap for the file you actually changed, ./bin/sync-identities for the identity registry, rehearsing the rsync, and verifying with doctor. Use this whenever someone wants to deploy, redeploy, sync or "push to the devbox", has edited the Dockerfile, docker-compose.yml, container/, home/, .env or identities.conf and wants it live, is bumping a pinned tool version, asks whether a redeploy will wipe their keys or projects, or needs to restart, roll back or back up the devbox.
3+
description: Pushes repo changes out to the devbox and applies them - ./bin/devbox deploy, choosing between up, rebuild and bootstrap for the file you actually changed, ./bin/devbox sync identities for the identity registry, rehearsing the rsync, and verifying with doctor. Use this whenever someone wants to deploy, redeploy, sync or "push to the devbox", has edited the Dockerfile, docker-compose.yml, container/, home/, .env or identities.conf and wants it live, is bumping a pinned tool version, asks whether a redeploy will wipe their keys or projects, or needs to restart, roll back or back up the devbox.
44
---
55

66
# devbox deploy
77

8-
Deploying is two easily-conflated steps: **sync the repo** to the workstation (`bin/push`, laptop side), **apply it** to
9-
the running container (`bin/devbox`, workstation side) - picking the wrong one is usually
10-
why a change seems to do nothing. Syncing the *identity registry* is a separate, third step (`bin/sync-identities`): it
11-
never travels with `bin/push`, since `identities.conf` is gitignored, hand-held
12-
state, not repo content.
8+
Deploying is two easily-conflated steps: **sync the repo** to the workstation (`devbox deploy`, laptop side),
9+
**apply it** to the running container (`devbox up` and friends, workstation side) - picking the wrong one is
10+
usually why a change seems to do nothing. Syncing the *identity registry* is a separate, third step
11+
(`devbox sync identities`): it never travels with `devbox deploy`, since `identities.conf` is gitignored,
12+
hand-held state, not repo content.
1313

1414
Full reference: `docs/cli.md` (flags), `docs/operations.md` (restart, backup, troubleshooting).
1515

1616
## The common case
1717

1818
```bash
19-
./bin/push <workstation> --up # rsync, then ./bin/devbox up on the host
19+
./bin/devbox deploy <workstation> --up # rsync, then ./bin/devbox up on the host
2020
```
2121

22-
`bin/push` is `rsync -az --delete` excluding `.git`, `.env`, `data/`, `.DS_Store` - host defaults to
23-
`$DEVBOX_HOST` then `<workstation>`, remote to `$DEVBOX_REMOTE_PATH` then `~/devbox`.
22+
`devbox deploy` is `rsync -az --delete` excluding `.git`, `.env`, `data/`, `.DS_Store` - host defaults to
23+
`$DEVBOX_HOST` (environment or `.push.env`), remote to `$DEVBOX_REMOTE_PATH` then `~/devbox`.
2424

2525
`--up` runs remote `up` over `ssh -t` so the live-session prompt reaches a human; an agent has none, so
2626
`up` refuses instead - correct, not an obstacle. Check `./bin/devbox sessions` first; if connected, sync
2727
files, report the pending step and whose session dies, let the user decide. `--force` needs an explicit
2828
go-ahead: it kills shells/panes with no client-side message.
2929

30-
`bin/devbox` only runs on the workstation, driving the local Docker daemon. From the laptop that's
31-
`ssh <workstation> 'cd ~/devbox && ./bin/devbox <cmd>'`, or just `--up`.
30+
The workstation commands (`up`, `down`, `rebuild`, `bootstrap`, ...) only run on the workstation, driving the
31+
local Docker daemon, and `deploy`/`sync`/`agent install` only on the laptop. From the laptop that's
32+
`ssh <workstation> 'cd ~/devbox && ./bin/devbox <cmd>'`, or just `deploy --up`.
3233

3334
## Which apply step does the change need
3435

35-
| Changed | Apply with | Why |
36-
|---------------------------------------|----------------------------------|-----------------------------------|
37-
| `docker-compose.yml`, `.env` | `up` | Config hash change recreates |
38-
| `Dockerfile`, apt list, install block | `up` | Rebuilds changed layers |
39-
| A pinned `ARG <TOOL>_VERSION` | `up`, or `rebuild` for no cache | `ARG` invalidates that layer |
40-
| `container/*`, `home/*` | `up` | In build context, recreate |
41-
| Re-apply user setup only | `bootstrap` | No restart, no lost panes |
42-
| Only a `bin/*` script | nothing | Read at invocation, on host |
43-
| `container/skills.sh` | `up`, then `./bin/devbox skills` | Only run on demand |
44-
| `~/.omp/agent/config.yml` (laptop) | `./bin/sync-omp` | Personal state, not repo content |
45-
| `~/.config/devbox/identities.conf` | `./bin/sync-identities` | Hand-held state, not repo content |
46-
| `bin/rootless-docker` on a new host | `sudo ./bin/rootless-docker` | Host provisioning, needs sudo |
36+
| Changed | Apply with | Why |
37+
|----------------------------------------|----------------------------------|-----------------------------------|
38+
| `docker-compose.yml`, `.env` | `up` | Config hash change recreates |
39+
| `Dockerfile`, apt list, install block | `up` | Rebuilds changed layers |
40+
| A pinned `ARG <TOOL>_VERSION` | `up`, or `rebuild` for no cache | `ARG` invalidates that layer |
41+
| `container/*`, `home/*` | `up` | In build context, recreate |
42+
| Re-apply user setup only | `bootstrap` | No restart, no lost panes |
43+
| `bin/devbox` (regenerated from `cli/`) | nothing | Read at invocation, on host |
44+
| `container/skills.sh` | `up`, then `./bin/devbox skills` | Only run on demand |
45+
| `~/.omp/agent/config.yml` (laptop) | `./bin/devbox sync omp` | Personal state, not repo content |
46+
| `~/.config/devbox/identities.conf` | `./bin/devbox sync identities` | Hand-held state, not repo content |
47+
| A new host needing project Docker | `sudo ./bin/devbox docker setup` | Host provisioning, needs sudo |
4748

4849
`up` = `docker compose build` then `docker compose up -d` behind a preflight (`BIND_ADDR` non-empty,
4950
`${DEVBOX_DATA_DIR}` present and owned by `HOST_UID:HOST_GID`); missing project Docker socket only warns -
@@ -70,14 +71,14 @@ One caveat for `home/`: bootstrap rewrites several files unconditionally - `~/.b
7071
`identities.conf`, locks it again) - all generated, not hand-edited, so template edits land next run.
7172
`~/.gitconfig`, `~/.config/devbox/secrets.env`, `~/.config/devbox/identities.conf`, OMP config are
7273
create-if-absent: editing those templates doesn't reach an existing home - delete the file under
73-
`${DEVBOX_DATA_DIR}`, or apply by hand (`identities.conf` specifically: edit it, or `./bin/sync-identities`
74-
from the laptop). Git identity re-applies via `git config --global` regardless.
74+
`${DEVBOX_DATA_DIR}`, or apply by hand (`identities.conf` specifically: edit it, or
75+
`./bin/devbox sync identities` from the laptop). Git identity re-applies via `git config --global` regardless.
7576

7677
## What a redeploy cannot destroy
7778

7879
This matters: "will I lose my keys / repos / gh login" is a flat no, by construction:
7980

80-
- `.env` is gitignored **and** rsync-excluded, so host-local config survives every push.
81+
- `.env` is gitignored **and** rsync-excluded, so host-local config survives every deploy.
8182
- `${DEVBOX_DATA_DIR}` is a host bind mount, not the image: `~/.ssh/id_*.pub`,
8283
`~/.ssh/signing_*.pub` (public keys only - devbox holds no private key), sshd host key under
8384
`~/.ssh/host/`, `~/.config/gh`, `~/.config/devbox/identities.conf`, `~/.config/devbox/secrets.env`,
@@ -118,17 +119,17 @@ resolving to publish address, and `devbox-docker-firewall` active.
118119
If `doctor` reports `BIND_ADDR is X but Tailscale reports Y`, the node's address changed:
119120
`./bin/devbox env && ./bin/devbox up`.
120121

121-
For a failed start, `./bin/devbox logs` (100 lines, `-f` follows) shows the entrypoint's output:
122+
For a failed start, `./bin/devbox logs` (100 lines, `--follow`/`-f` follows) shows the entrypoint's output:
122123
host-key generation, `authorized_keys` assembly, bootstrap, then `Server listening on 0.0.0.0 port 2222`.
123124

124125
## Rolling back and backing up
125126

126127
A rollback is just deploying an earlier commit - the image builds from the repo, no separate artifact to
127-
revert. `bin/push` syncs the working tree; commit or stash first, or in-flight edits ship instead:
128+
revert. `devbox deploy` syncs the working tree; commit or stash first, or in-flight edits ship instead:
128129

129130
```bash
130131
git stash # or commit
131-
git switch --detach <good-commit> && ./bin/push <workstation> --up
132+
git switch --detach <good-commit> && ./bin/devbox deploy <workstation> --up
132133
git switch - && git stash pop # back to where you were
133134
```
134135

0 commit comments

Comments
 (0)