Claude Code a další agenti na vic serverech z jednoho okna: herdr, jump uzivatel a par problemu po ceste
Claude Code mi ted bezi na dvou serverech a v nekolika projektech zaroven. Vsechno pritom ovladam z jednoho okna na domacim pocitaci. Nakonec na to stacil herdr, jeden dost omezeny SSH uzivatel na hostiteli a par veceru kdy jsem zjistoval proc se to chova jinak nez jsem cekal.
Proc ne dalsi okna a proc ne tmux
Jakmile mate tri Claudy na dvou strojich, zacne byt docela snadny ztratit prehled ktery ceka na schvaleni a ktery uz davno skoncil. Oken pribyva, SSH spojeni obcas spadne a s nim i to co jste tam zrovna delali.
tmux by vyresil hlavne preziti sessions po odpojeni. O agentech ale sam o sobe nevi nic. herdr je multiplexer delany primo pro kodovaci agenty. Terminaly drzi na serveru i kdyz zavru svoje okno a v bocnim panelu vidim jestli agent pracuje, ceka na mne nebo uz skoncil. Od verze 0.9 umi v jednom okne zobrazit i vic stroju najednou.
Jak to mam zapojene
Mam to rozdelene na tri vrstvy:
- Domaci pocitac: jen klient herdru, pod vlastnim uzivatelem bez sudo a se SSH klicem nahranym v agentovi.
- Hostitel: server s virtualkami. Klic herdru tu muze jen preposlat spojeni na SSH port konkretnich virtualek, shell neotevre.
- Virtualky: na kazde bezi vlastni herdr server a uvnitr Claude Code. Kazdy projekt mam zvlast.
Virtualky nemaji verejnou IP, takze se k nim chodi pres hostitele pomoci SSH ProxyJump.
Krok 1: uzivatel ktery umi jen preposilat
Klic kterym se herdr hlasi na virtualky nema mit moznost otevrit shell na samotnem hostiteli. Proto jsem tam vytvoril uzivatele jump bez shellu:
useradd -m -s /usr/sbin/nologin jump
mkdir -p /home/jump/.ssh
mcedit /home/jump/.ssh/authorized_keys
chown -R jump:jump /home/jump/.ssh
chmod 700 /home/jump/.ssh && chmod 600 /home/jump/.ssh/authorized_keys
V authorized_keys je jeden radek a omezeni je rovnou pred klicem:
restrict,port-forwarding,permitopen="<IP vm1>:22",permitopen="<IP vm2>:22" ssh-ed25519 AAAA... herdr@domaci-pc
restrict vypne shell, agent forwarding, X11 i PTY. port-forwarding z toho zase povoli jen preposilani a permitopen ho omezi na SSH port tech dvou VM.
ProxyJump v OpenSSH pouziva prave tohle (ssh -W), takze shell neni potreba. Kdyby nekdo ten klic ziskal, nedostane normalni shell hostitele. Dostane se maximalne k SSH prihlaseni na povolene virtualky a tam stejne potrebuje dalsi pristup.
Krok 2: dev, Claude Code a herdr na virtualkach
Na kazde VM poustim Claude pod uzivatelem dev se sudo. Ne pod rootem. Claude Code pod rootem nechce rezim bez potvrzovani a navic je nesmysl davat kazde chybe agenta rovnou prava roota.
useradd -m -s /bin/bash dev
echo "dev ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/dev && chmod 440 /etc/sudoers.d/dev
mkdir -p /home/dev/.ssh # sem prijde verejny klic herdru, tentokrat bez omezeni
Pak jako dev nainstalovat Node, Claude Code a herdr:
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
sudo npm install -g @anthropic-ai/claude-code
curl -fsSL https://herdr.dev/install.sh | sh
sudo ln -sf /home/dev/.local/bin/herdr /usr/local/bin/herdr
claude # prihlasit se, pak /exit
herdr integration install claude
Symlink do /usr/local/bin jsem tam nechal schvalne. Herdr se pripojuje neinteraktivnim SSH a tam nemusi byt ~/.local/bin v PATH.
Integraci je dobre instalovat az po prvnim spusteni Clauda. Kdyz jsem to udelal obracene, jen to hlasilo ze chybi ~/.claude, coz byla vlastne pravda.
Krok 3: klient na domacim pocitaci
Na domacim pocitaci ma herdr vlastniho uzivatele herdr, bez sudo. Ten ma SSH klic s heslem a SSH config kde je cesta pres hostitele:
Host jump-host
HostName <verejna IP hostitele>
User jump
Host vm1
HostName <interni IP vm1>
User dev
ProxyJump jump-host
Host vm2
HostName <interni IP vm2>
User dev
ProxyJump jump-host
Herdr se na stroje pripojuje na pozadi a neumel by se tam pokazde ptat na heslo ke klici. Klic proto musi byt v ssh-agent.
Pouzivam keychain. Balik nainstaluje uzivatel se sudo a do ~/.bashrc jsem pridal:
eval $(keychain --eval --quiet id_ed25519)
Heslo ke klici pak zadam jednou po prihlaseni a agent ho drzi az do odhlaseni.
Krok 4: vsechny stroje v jednom panelu
Nejdriv jsem se pripojoval pres herdr --remote vm1, jenze to znamena jeden stroj na jedno okno. Od verze 0.9 umi herdr ulozene stroje, takze doma bezi jeden klient a v bocnim panelu mam Local i obe virtualky.
herdr machine add vm1 --label vm1
herdr machine add vm2 --label vm2
herdr machine list
herdr
Kazdy stroj si pritom porad drzi vlastni herdr server a vlastni bezici procesy. Kdyz vypadne spojeni na jednu VM, ostatni normalne jedou dal. Po navratu spojeni se herdr pripoji znovu.
V seznamu agentu je videt i stroj na kterem bezi, takze z jednoho mista vidim kdo kde ceka na odpoved.
Jak si v tom delam poradek
Mam jednoduche pravidlo: stroj, pod nim projekt (workspace), v projektu taby a v tabu panely. Vsechno pod jednim strojem skutecne bezi na tom stroji. Tohle dost omezuje sanci ze omylem pustim migraci nekde uplne jinde.
Workspace hned po zalozeni pojmenuju (Ctrl+b Shift+w). Kdyz to neudelam, jmenuje se podle adresare. Novy workspace vznikne v home a za chvili jsem mel nekolik projektu co se vsechny jmenovaly jen ~. To je dost na nic.
Typicky projekt mam asi takhle:
| Tab | Obsah |
|---|---|
| 1 | claude |
| 2 | shell v adresari projektu: git, composer, testy |
| 3 | logy rozdelene na dva panely: tail -f weboveho logu a journalctl -f |
Barvy v bocnim panelu:
| Barva | Stav agenta |
|---|---|
| cervena | ceka na mne, typicky schvaleni nebo dotaz |
| zluta | pracuje |
| modra | hotovo ale jeste jsem se nepodival |
| zelena | hotovo a videno |
V realu stejne nejvic sleduju cervenou. Ostatni muzou bezet zatimco delam neco jineho.
Na cem jsem se zasekl
Kopirovani prihlasovaci URL
Claude pri prvnim spusteni vypise dlouhou prihlasovaci URL. Herdr mi napsal copied to clipboard, jenze ve schrance bylo neco uplne jineho.
Herdr kopiruje pres OSC 52 a muj terminal tuhle sekvenci ignoroval. Pomohlo Shift + tahnuti mysi, kdy vyber dela terminal a ne herdr. Druha moznost je terminal s podporou OSC 52, treba WezTerm.
.bashrc bez noveho radku na konci
Radek s keychain jsem pridal pres echo >>. Jenze soubor nekoncil novym radkem, takze se novy text nalepil hned za posledni fi a vzniklo:
fieval $(keychain ...)
Bash pak hlasil unexpected end of file a nenacetl ani prompt. Oprava byla trivialni ale chvili jsem hledal co jsem vlastne rozbil. Od te doby pred podobnym echo >> kontroluju konec souboru pres tail -c1.
Nove SSH klice po prejmenovani VM
Jednu virtualku jsem prejmenoval v Proxmoxu:
qm set <vmid> --name <nove-jmeno>
Po restartu pak SSH vyhodilo:
REMOTE HOST IDENTIFICATION HAS CHANGED
V tomhle pripade to nebyl utok. Proxmox odvozuje cloud-init instance-id z konfigurace VM a po zmene jmena dostal cloud-init novy instance-id. Stroj pak bral sam sebe jako novou instanci a vygeneroval nove host klice.
Otisk se da overit i bez SSH pres guest agenta:
qm guest exec <vmid> -- ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
Kdyz sedi s tim co hlasi SSH, staci odstranit stary zaznam:
ssh-keygen -R <IP VM>
A samozrejme vsude odkud se na tu VM hlasi.
Integrace na spatnem stroji
herdr integration install claude patri na stroj kde Claude skutecne bezi, tedy na VM. Na domacim pocitaci mi to jen hlasilo ze nenaslo ~/.claude. Chvili jsem na to cumel nez mi doslo ze to delam na spatnem stroji.
Tahak
Prefix je Ctrl+b. Zmacknout, pustit a pak teprve dalsi klavesu.
| Co | Klavesy |
|---|---|
| odpojit se, vsechno bezi dal | Ctrl+b q |
| prepnout stroj nebo projekt | klik v panelu, nebo Ctrl+b w a sipky |
| novy projekt na vybranem stroji | Ctrl+b Shift+n |
| prejmenovat / zavrit projekt | Ctrl+b Shift+w / Ctrl+b Shift+d |
| novy tab, dalsi, predchozi | Ctrl+b c, Ctrl+b n, Ctrl+b p |
| rozdelit vedle sebe / pod sebe | Ctrl+b v / Ctrl+b - |
| prepnout panel, zvetsit panel | Ctrl+b h j k l, Ctrl+b z |
| zavrit panel | Ctrl+b x |
| vyber terminalem misto herdru | Shift + tahnuti mysi |
Na zaver
Po par dnech pouzivani se mi ukazalo, ze nejdulezitejsi jsou vlastne tri veci: jump uzivatel ktery umi jen forwarding, SSH klic drzeny v agentovi a herdr s ulozenymi stroji.
Nejvic mi stejne pomaha cervena tecka. Nemusim obihat pet terminalu a hledat ktery Claude zrovna ceka na potvrzeni nebo dotaz.
Dalsi vec kterou jeste musim doresit jsou soubory webu patrici jinym uzivatelum nez tomu pod kterym bezi Claude. To uz je ale dalsi tema.
