Powoli podłączam każdą usługę w domowej sieci do Claude Code jako osobnego agenta, tak samo jak zrobiłem to z komendami devops w pracy. Kontroler sieci był kolejny na liście, głównie dlatego, że miałem dość otwierania aplikacji na telefonie tylko po to, żeby sprawdzić, dlaczego wifi muli, albo zablokować urządzenie, które uznało, że druga w nocy to dobra pora na synchronizację 40GB zdjęć.

Sprzęt, na którym to stoi

Kontroler tutaj to nie dedykowane pudełko od TP-Linka, czyli OC200. To Wyse ZX0, cienki klient zbudowany pierwotnie do bootowania sesji pulpitu zdalnego i niczego więcej, na którym teraz działa self-hosted kontroler Omada (obecnie wersja 5.15.x). Reszta sieci jest niczym niewyróżniająca się: dwa punkty dostępowe EAP650-Desktop, jeden w salonie i jeden w sypialni, gateway ER605 i switch ES216G, wszystko zarządzane z jednej strony w kontrolerze.

Wykorzystanie starego cienkiego klienta jako hosta kontrolera ma sens tylko wtedy, gdy już masz stary cienki klient, który i tak nic nie robi. Pobór mocy w spoczynku jest praktycznie zerowy, a jego jedynym zadaniem jest siedzieć i odpowiadać na zapytania API.

Dlaczego aplikacja nie wystarczała

Aplikacja i panel web Omady są ok do okazjonalnej konfiguracji. Czego nie dają, to szybkiego sposobu na zadanie pytania “kto teraz siedzi w sieci” bez odblokowywania telefonu, klikania przez trzy ekrany i czekania na spinner. I na pewno nie dają sposobu, żeby sprawdzanie dostępności aktualizacji firmware zmienić w nawyk zamiast jednorazowego zadania, o którym zapominasz na miesiące.

Omada faktycznie ma REST API. Nie jest udokumentowane do publicznego użytku, ale zapytania to standardowy JSON po HTTPS, a kształty odpowiedzi są na tyle spójne, że da się je odtworzyć z zakładki sieciowej w przeglądarce w jedno popołudnie.

Taniec z autoryzacją

Uzyskanie działającej sesji zajmuje trzy kroki. Najpierw zapytanie do endpointu z informacjami zwraca ID kontrolera, identyfikator konkretnej instalacji, pod który podpina się każda kolejna ścieżka. Potem POST logowania z loginem i hasłem zwraca ciasteczko sesji i token CSRF, a ten token musi jeździć jako nagłówek przy każdym kolejnym zapytaniu. Pominięcie ciasteczka albo nagłówka po prostu zwraca kod błędu zamiast danych, bez żadnej sensownej wiadomości.

Żadne z tych kroków nie jest drogie do powtórzenia przy każdym zapytaniu, ale to marnotrawstwo, więc skrypt cache’uje te elementy osobno: ID kontrolera na godzinę, token sesji na 25 minut, ID domyślnej strony aż do kolejnego logowania. Dane logowania siedzą w lokalnym Vaulcie, a nie w skrypcie, więc pierwszy ruch skryptu to zawsze odpytanie Vaulta, zanim w ogóle dotknie sieci.

Certyfikat jest self-signed, więc każde wywołanie curl potrzebuje flagi wyłączającej weryfikację. Nie zaakceptowałbym tego dla czegokolwiek dostępnego spoza sieci lokalnej, ale dla kontrolera gadającego sam ze sobą po sieci prywatnej to rozsądny kompromis.

1
2
3
4
5
6
7
_login() {
    local resp=$(curl -sk -c "$COOKIE_FILE" -X POST \
        -H "Content-Type: application/json" \
        "$url/$cid/api/v2/login" \
        -d "{\"username\":\"$user\",\"password\":\"$pass\"}")
    echo "$resp" | jq -r '.result.token' > "$TOKEN_FILE"
}

Owinięcie endpointów

Kiedy taniec z autoryzacją już działa, reszta to skrypt powłoki z jedną funkcją na akcję: devices, clients, block, unblock, reboot, warm-restart, firmware-check i tak dalej, obecnie blisko sześćdziesiąt. Każda z nich to cienki filtr jq na surowej odpowiedzi endpointu, przycięty do pól, które faktycznie się przydają. Sam endpoint z urządzeniami zwraca ścianę zagnieżdżonego JSON-a na każdy punkt dostępowy. Wrapper redukuje to do nazwy, statusu, IP, modelu, wersji firmware i uptime’u, i tłumaczy numeryczne kody statusu na słowa: 14 znaczy połączony, 0 znaczy rozłączony, wszystko inne to oczekujący. Sam dashboard Omady mógłby robić dokładnie to samo.

Dla wszystkiego, czego nie pokrywa nazwana akcja, jest wrapper raw, który przyjmuje metodę i ścieżkę. Potrzebowałem go może dwa razy, głównie przy grzebaniu w endpointach, których kształt nie jest na tyle stabilny, żeby uzasadniał stałą funkcję.

Jedna ciekawostka warta zapisania: adresy MAC trzeba podawać z myślnikami i wielkimi literami. Dwukropki albo małe litery po prostu cicho nie dopasują niczego. Nic w API tego nie mówi. Dowiadujesz się, dostając pusty wynik dla urządzenia, o którym wiesz, że jest podłączone.

Zmiana w agenta

Sam skrypt już jest przydatny z terminala. Zrobienie z niego agenta Claude Code oznacza, że mogę zapytać zwykłym językiem i dostać ten sam wynik, a Claude sam wybiera, która z sześćdziesięciu akcji faktycznie odpowiada na pytanie, zamiast żebym musiał pamiętać właściwą. Definicja agenta ogranicza jego narzędzia do uruchamiania komend i czytania plików, nic co zapisuje cokolwiek, i działa na najtańszym dostępnym modelu, bo parsowanie listy JSON na tabelkę to nie zadanie, które skorzysta na większym.

Instrukcje samego agenta niosą tę samą zasadę, o której pisałem w poście o hookach w kontekście wszystkiego, co destrukcyjne: potwierdź przed zablokowaniem klienta, potwierdź przed restartem urządzenia, potwierdź przed aktualizacją firmware. W praktyce oznacza to, że agent mówi mi dokładnie, którą komendę zamierza uruchomić, a ja mówię tak albo nie. Nie decyduje sam, że jakieś urządzenie wygląda podejrzanie i po cichu je blokuje. Ta decyzja zostaje moja. Agent tylko sprawia, że szybko mogę sprawdzić i szybko zadziałać, kiedy już faktycznie powiem tak.

Do czego to się realnie przydaje

Na co dzień to głównie szybkie sprawdzenia. “Kto jest w sieci” zamiast otwierania aplikacji. “Czy punkt dostępowy w sypialni dalej działa” po zaniku prądu. “Czy są jakieś aktualizacje firmware” co parę tygodni, po czym realne tak albo nie ode mnie, zanim cokolwiek trafi na urządzenie, które akurat działa dobrze. Nic w tym dramatycznego. To po prostu zamienia zadanie na pięć dotknięć telefonu w jedno pytanie w terminalu, co okazuje się mieć większe znaczenie, niż się spodziewałem, głównie dlatego, że tarcie starego sposobu sprawiało, że po prostu sprawdzałem rzadziej.

Reszta mojego setupu Claude Code ma podobny kształt: przyziemne usługi, owinięte skryptami, wystawione jako agenci z wąskim dostępem do narzędzi i bramką potwierdzenia na wszystko, co zmienia stan. Kontroler sieci był po prostu kolejnym pudełkiem na tej liście, które dostało to samo traktowanie.