Files
agent-helm/helmd
claude 12ffcaa2bd
All checks were successful
helmd-image / build (push) Successful in 36s
helmd-release / build-release (push) Successful in 1m6s
helmd: inbäddad webbklient (vanilla SPA) + Docker-image för Pi5 (LAN-only)
- 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>
2026-08-05 22:17:12 +02:00
..

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:8788 som default. På det privata nätet kan man binda 0.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 0600 i ~/.config/helmd/config.json, visas med helmd token. Skickas som Authorization: Bearer <t>, X-Api-Token: <t> eller ?token=<t> (för SSE/EventSource och <img>-länkar).
  • Delad HTML serveras med Content-Security-Policy: sandbox så 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.yamllocalhost: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 cycle skickar Shift+Tab (BTab) — verifierat tangentnamn i tmux men inte bekräftat att agy byter läge på det; justera via /keys om 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.