feat(lxc102): script tmux sbt pentru sandbox + statusline Claude Code

- sbt: sesiuni tmux (sbx1..3) care intră în sandbox și lansează agentul
  (claude/opencode/orice binar); tmux rulează pe host, panes prin sbx exec
- statusline.sh + bootstrap-statusline.sh pe /home/workspace/.agent
  (virtiofs persistent), reinstalat la fiecare intrare fiindcă /home/agent
  din sandbox e overlay efemer
- fix printf "--" -> printf -- "--" (eroare de usage când API-ul de cote
  nu răspunde)
- copii versionate ale scripturilor agents/sb + documentație README

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-07-31 11:13:55 +00:00
parent a6b26ba23d
commit 6ff2c6ee2c
6 changed files with 472 additions and 0 deletions

View File

@@ -70,6 +70,64 @@ sbx daemon stop
---
## Scripturi de lucru (userul `work`)
Trei scripturi în `/home/work/.local/bin/`, copii versionate în `scripts/` din acest director:
| Script | Rol |
|--------|-----|
| `agents` | pornește sandbox-ul și îl ține pornit (keepalive); nu lansează niciun agent |
| `sb` | un shell interactiv în sandbox, într-un director de proiect |
| `sbt` | **sesiune tmux** cu sandbox + agent — echivalentul lui `start-agent.sh` de pe LXC 171 |
### `sbt` — tmux + sandbox + agent
```bash
sbt # sesiune 1, /home/workspace, claude în pane-ul stâng
sbt 2 proiect-a # sesiune 2, /home/workspace/proiect-a
sbt 1 proiect-a opencode # alt agent (orice binar din sandbox: opencode, jcode…)
sbt 1 proiect-a shell # doar shell, fără agent
sbt list | sbt kill 2 | sbt detach 2
```
Sesiunile se numesc `sbx1`, `sbx2`, `sbx3`. Layout: 2 pane-uri pe orizontală — stânga cu
agentul, dreapta shell. Când agentul se oprește, pane-ul rămâne cu un shell în sandbox
(`exec bash -l`), deci sesiunea nu moare.
**tmux rulează pe host (LXC 102), nu în sandbox** — în imaginea sandbox-ului nu există tmux
(și nici `git`). Fiecare pane e un `sbx exec -it -w <dir> <sandbox> bash -l`. Consecința utilă:
sesiunea supraviețuiește oricărei reporniri a agentului, iar `sbt` apelează întâi `agents up`,
deci sandbox-ul e pornit chiar dacă nu era.
Prefixul tmux e `Ctrl+A` (cu `Ctrl+B` ca secundar) — vezi `/home/work/.tmux.conf`.
### Statusline Claude Code în sandbox
Același statusline ca pe LXC 171 (model, context, cote 5h / weekly / sonnet din API-ul OAuth
Anthropic). Două fișiere, ambele pe **`/home/workspace/.agent/`**, adică pe bind-mount-ul
virtiofs — singurul loc persistent văzut identic din host și din sandbox:
| Cale | Rol |
|------|-----|
| `/home/workspace/.agent/statusline.sh` | scriptul propriu-zis (rulat de Claude Code) |
| `/home/workspace/.agent/bootstrap-statusline.sh` | scrie `statusLine` în `~/.claude/settings.json` din sandbox |
`sbt` face `source` la bootstrap la fiecare intrare în sandbox. Este necesar pentru că
**`/home/agent` din sandbox stă pe overlay efemer** — `settings.json` se pierde la recrearea
sandbox-ului, în timp ce `/home/workspace` rămâne. Bootstrap-ul e idempotent și nu suprascrie
restul setărilor (merge cu `jq`).
Statusline-ul e activat și pentru `claude` rulat direct pe host ca `work`, prin aceeași cale.
**De reținut:**
- `git` lipsește din imaginea sandbox-ului, deci linia 1 nu arată branch-ul acolo (degradează curat).
- Datele de cotă vin de la `https://api.anthropic.com/api/oauth/usage`, cu token-ul din
`~/.claude/.credentials.json` **al sandbox-ului** (login separat de cel al userului `work`).
Cache 60s în `/tmp/claude-statusline-usage.json`. Dacă API-ul răspunde `rate_limit_error`,
barele arată `0% ↺ --` până la următoarea reîmprospătare — nu e o defecțiune de config.
---
## Cum funcționează sbx (relevant pentru depanare)
`sbx` **nu** folosește dockerd-ul de sistem. Are propriul containerd embedded, per-user, care pornește