- web/: token-login, sessionslista, ANSI-skärmvy (SSE+poll), promptfält, frågekort, tangentrad, delningsflik (bild/HTML-sandbox/markdown), inställningar - go:embed via webfs.go — servern förblir en enda binär, strikt CSP - browser-verifierad mot riktig agy (fråga -> kort -> svar -> kört) - Dockerfile (alpine + tmux/bash) + helmd-image.yaml -> localhost:5000/helmd - integrationstest utökat till 29 gröna Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6.9 KiB
helmd — agent-helm v2-servern
En enskild statisk Go-binär som äger kommunikationen med en tmux-session där en CLI-agent (agy, claude, …) kör, och exponerar ett REST-API + SSE som webb- och mobilklienterna pratar med.
Designen bygger på insikten från Gemini-OAuth-döden: att integrera mot
en specifik agents hook-mekanism är skört. helmd behandlar i stället
tmux som sanningskälla — den läser skärmen, känner igen frågor och
skickar tangenter. Fungerar därför med vilken TUI-agent som helst, och
överlever att helmd själv startas om (sessioner adopteras tillbaka).
webb-PWA / Android ──(LAN eller SSH-tunnel)──► helmd :8788 ──tmux──► agy
│
└──► ntfy.brasse-pc.eu (pushar till mobilen)
Säkerhetsmodell
- Ingen publik exponering. Servern binder
127.0.0.1:8788som default. På det privata nätet kan man binda0.0.0.0:8788(helmd serve --listen 0.0.0.0:8788). Utifrån: SSH-tunnel —ssh -L 8788:127.0.0.1:8788 <host>— eller Android-klientens inbyggda tunnel (steg 3 i planen). - Bearer-token på alla endpoints. Genereras vid första start,
lagras
0600i~/.config/helmd/config.json, visas medhelmd token. Skickas somAuthorization: Bearer <t>,X-Api-Token: <t>eller?token=<t>(för SSE/EventSource och<img>-länkar). - Delad HTML serveras med
Content-Security-Policy: sandboxså att ett delat dokument aldrig kan anropa API:et med klientens token.
Kommandon
helmd serve [--listen host:port] [--config fil] starta servern
helmd share [--note text] [--session namn] <fil> dela en fil till klienterna
helmd token skriv ut API-token
helmd version
helmd share är agentens verktyg för att dela filer (html, md,
png, jpg, …) till klienterna: agenten kör kommandot i sin shell, filen
laddas upp till servern och dyker upp i klientens delningsflik.
Tillåtna filtyper styrs av share_exts i konfigen.
API
Alla svar är JSON om inget annat sägs. Auth krävs överallt.
| Metod & väg | Gör |
|---|---|
GET /api/health |
{ok, version, sessions} |
GET /api/sessions |
lista sessioner (namn, alive, seq, pending question) |
POST /api/sessions |
{name, cmd?, cwd?} startar agent i ny tmux-session helm-<name>; {name, adopt:true, tmux?} adopterar befintlig |
GET /api/sessions/{n} |
en sessions tillstånd |
DELETE /api/sessions/{n} |
döda sessionen |
GET /api/sessions/{n}/screen |
pane-text; ?ansi=1 behåller färger, ?history=N tar med N rader scrollback |
POST /api/sessions/{n}/prompt |
{text, submit?:bool} klistrar in text (radbrytningar ok) och trycker Enter |
GET /api/sessions/{n}/question |
{question} — detekterad väntande fråga eller null |
POST /api/sessions/{n}/answer |
{option:N} väljer alternativ N (1-baserat). Numrerade listor väljs med siffertangent, onumrerade navigeras med pil+Enter |
POST /api/sessions/{n}/keys |
{keys:["Escape","Down","Enter"]} råa tmux-tangenter |
POST /api/sessions/{n}/mode |
{action:"cycle"} skickar Shift+Tab (lägesbyte i agy/claude) |
GET /api/config / PUT /api/config |
läs/ändra agentkommando, args, workdir, poll-intervall, ntfy-inställningar (token ändras aldrig via API) |
GET /api/shares / POST /api/shares |
lista / ladda upp (multipart, fält file, note, session) |
GET /api/shares/{id} / …/raw |
metadata / själva filen |
DELETE /api/shares/{id} |
ta bort delning |
POST /api/notify |
{topic?, title?, message, priority?} → ntfy; topic måste finnas i allowed_topics (agent-helm, claude) |
GET /api/events |
SSE-ström: screen (seq), question, session, share |
Frågedetektering
Pollern läser panen (default var 500:e ms), och DetectQuestion
känner igen agy:s frågeformer: godkännande-listor (1. Yes … 4. No),
trust-/val-listor med >-markör, och gamla Gemini-CLI:s inramade
pickers. Varje fråga får en stabil hash — servern ntfy:ar en gång
per ny fråga till topic agent-helm (kan stängas av med
notify_on_question:false).
Verifierat mot riktiga agy 1.1.9-sessioner (trust-prompt, kommandogodkännande) och mot mock i integrationstestet.
Konfiguration
~/.config/helmd/config.json (skapas vid första start; override med
HELMD_CONFIG eller --config):
{
"listen": "127.0.0.1:8788",
"token": "<genereras>",
"agent_cmd": "agy",
"agent_args": [],
"workdir": "/home/brasse",
"share_dir": "~/.local/share/helmd/shares",
"share_exts": [".html", ".htm", ".md", ".txt", ".json", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".pdf"],
"poll_ms": 500,
"cols": 200, "rows": 50,
"ntfy": {
"server": "https://ntfy.brasse-pc.eu",
"topic": "agent-helm",
"allowed_topics": ["agent-helm", "claude"],
"enabled": true,
"notify_on_question": true
}
}
Webbklienten
Inbäddad i binären (web/ + go:embed) och serveras på / — surfa
till servern (t.ex. http://127.0.0.1:8788 genom en SSH-tunnel) och
klistra in din token. Ramverksfri (ren ES-moduler): sessionslista,
ANSI-färgad skärmvy (SSE + poll), promptfält, frågekort med knappar,
tangent-verktygsrad, delningsflik (bilder, sandboxad HTML, markdown)
och inställningar. Statiska filer kräver ingen auth (koden är publik);
allt data går genom det token-skyddade API:et.
Docker på Pi5 (LAN-only)
Dockerfile bygger en arm64-image med tmux+bash via
.gitea/workflows/helmd-image.yaml → localhost:5000/helmd:latest.
Stack: /srv/dockge-staks/helmd/ med host-port 8788 och volym
/srv/docker/helmd → /data. Ingen NPM-vhost — nås bara på LAN
(http://192.168.0.19:8788) eller via SSH-tunnel utifrån. Sessionerna
kör i containern (bash tills en agent installeras där).
Bygga & testa
cd helmd
go test ./... # enhetstester (frågedetektorn m.m.)
CGO_ENABLED=0 go build -o build/helmd .
bash scripts/run-integration.sh # 26 API-tester i isolerad Docker-container
Integrationstestet startar helmd i en debian:stable-slim-container
med en mock-agent (testdata/mock-agent.sh) som härmar agy:s båda
frågetyper, och kör hela API-ytan med curl.
CI / release
.gitea/workflows/helmd-release.yaml kör på push till master som rör
helmd/: go vet + go test, bygger linux x64 + arm64 statiskt
och publicerar på den rullande releasen helmd-latest
(helmd-linux-x64, helmd-linux-arm64, checksums.txt).
Kända begränsningar (v1)
mode cycleskickar Shift+Tab (BTab) — verifierat tangentnamn i tmux men inte bekräftat att agy byter läge på det; justera via/keysom agy använder annan tangent.- Ingen WebSocket-terminal ännu — klienterna pollar
screen+ lyssnar på SSE. Räcker för kort-UI:t; rå terminal-vy kommer med webbklienten (steg 2). - En helmd-instans per maskin/användare; flera agenter = flera sessioner i samma helmd.