AIDive

Pakiet do filmu

Claude Code Mods: eksperyment fail-open, pomiary, lista kontrolna i źródła

10 min czytania

TL;DR

  • Mod do Claude Code składa się z trzech plików: .claude-plugin/plugin.json, hooks/hooks.json z {"modules":["./index.ts"]} oraz modułu TypeScript eksportującego register(on). Nic więcej nie jest potrzebne, żeby się załadował.
  • W buildzie 2.1.272 typowana powierzchnia zapisana przez /plugin-types to 11,783 linii claude-code.d.ts: 84 nazwy zdarzeń lub wywołań w 23 rzeczownikach. fs.readFile zniknęło, rzeczownik to fs.read i fs.write.
  • Hook tool.call na 42 linie sprawił, że model czytał API_KEY=[REDACTED] zamiast prawdziwego klucza, zarówno w narzędziu Read, jak i Bash, przy 27.9 ms na zdrowy hop i około 0 tokenów dodanych do sesji.
  • Hook, który śpi dłużej niż budżet 10 s albo rzuca wyjątek, jest pomijany i uruchamia się polecenie pod nim. Log to zgłasza, ale efekt to obejście: Mod strażnik zawodzi otwarcie (fail open).
  • Ścieżka generowana działa: jedno zdanie dało w około 4 minuty i za $1.23 Mod na 190 linii plus 53 linie testów, który przeszedł claude plugin validate bez ostrzeżeń i claude plugin test z wynikiem 4 pass / 0 fail.
  • Jednej rzeczy nie udało się odtworzyć: Mod ładował się pod claude -p, ale milczał w interaktywnym REPL sterowanym przez pty, w dwóch próbach. Traktuj ładowanie w REPL jako niezweryfikowane, dopóki nie sprawdzisz tego w prawdziwym terminalu.

Co mówią pomiary

Wszystko poniżej uruchomiono na Claude Code 2.1.272 z ustawionym CLAUDE_CODE_ENABLE_FUNCTION_HOOKS, na ręcznie napisanym Modzie redact-secrets oraz na trzech jednorazowych Modach zbudowanych, żeby go złamać. Sama funkcja jest śledzona w issue z propozycją Function Hooks, które nadal jest najbliższe oficjalnej specyfikacji s3.

Narzędzia istnieją przed dokumentacją. Build 2.1.272 zawiera claude plugin validate, test, eval i details; test działa, choć plugin --help nie wymienia go w bloku poleceń s3. Uruchomienie /plugin-types w sesji zapisało 11,783 linii do .claude/types/claude-code.d.ts, plus claude-code-mcp.d.ts na 3,438 linii obejmujący 150 narzędzi MCP z 7 serwerów s3. Zliczenie wygenerowanych typów daje 84 nazwy zdarzeń lub wywołań w 23 rzeczownikach, a plik zmienia nazwę jednej rzeczy, o której mogłeś czytać we wrześniowych wpisach: fs.readFile już nie istnieje, powierzchnia to fs.read i fs.write s9. Te same typy mówią, że hook tool.call zwraca { result, context? } albo { deny }; text i ref pochodzą z rdzenia i nie są częścią własnej odpowiedzi hooka, więc nadpisujesz result, nie text s3.

claude plugin validate wypisuje ślad, zanim Mod w ogóle ruszy: ./index.ts hooks: tool.call i ./index.ts calls: $.ui.toast, albo calls: nothing on $, gdy moduł nie dotyka żadnej możliwości hosta s4. Ta statyczna linia to jedyna weryfikacja, jaką katalog taki jak awesome-claude-code-mods może dziś zautomatyzować, co ma znaczenie w następnym akapicie.

Redakcja działa w trybie -p. 42-liniowy hook przechwytywał tool.call, a model dostawał API_KEY=[REDACTED] tam, gdzie plik i wyjście powłoki zawierały sk-test1234567890abcdef, zarówno dla narzędzia Read, jak i Bash s3. Log debugowania zmierzył zdrowy hop na 27.9 ms w obie strony, wliczając hop workera i next() s3. claude plugin details wycenił Mod na około 0 tokenów dodanych do każdej sesji: Mod to kod w procesie, nie tekst promptu, i to główny argument jego zwolenników przeciw hookom powłoki i skillom s7.

Strażnik zawodzi otwarcie. Mod slow-guard śpiący 15 s został ucięty przy budżecie 10 s komunikatem hook failed: slow-guard: exceeded 10000ms budget (tool.call; skipped; what is below it ran in its place), a echo hi i tak się wykonało s3. Mod throw-guard rzucający wyjątek został pominięty tak samo, hook failed: throw-guard: boom (tool.call; skipped; what is below it ran in its place), zgłoszony po 574.2 ms s3. Głośno w logu, obejście w skutkach. Każdego Moda, którego zadaniem jest coś zablokować, trzeba czytać z tą świadomością: błąd w strażniku to dziura, nie awaria.

Generowanie jest tanie. Z jednego zdania model napisał działający Mod na 190 linii plus 53 linie testów w około 4 minuty, 34 tury i $1.23 (19,053 tokeny wyjścia, 497,282 odczytów z cache, 8,357 thinking) s3. Ten Mod przeszedł claude plugin validate bez ostrzeżeń i claude plugin test z wynikiem 4 pass / 0 fail w 0.31 s, i ukrywał klucze na żywo s3. Na ręcznie napisanym Modzie claude plugin test działał bez klucza API i bez wywołania modelu: 1 pass w 0.25 s s3. Skill uczący agentów pisać Mody już istnieje, jeśli chcesz powtórzyć to z szablonem s12.

Czego nie udało się odtworzyć: $.ui.toast nigdy się nie wyświetlił, bo Mod nie załadował się w REPL sterowanym przez pty w 2 próbach; pod -p odpowiednik pojawił się tylko jako linia debugowania. Zaobserwowano odwrotność twierdzenia "tylko REPL", które krąży na X, a przyczyny nie wyizolowano s8. Nie przetestowano też 5-sekundowego heartbeatu zawieszonego workera; zmierzono tylko 10-sekundowy budżet await i ścieżkę wyjątku.

Pomiary

Przypadek Co robi Mod Wynik Czas
redact-secrets, narzędzie Read Nadpisuje result w tool.call Model widzi API_KEY=[REDACTED] 27.9 ms na hop
redact-secrets, narzędzie Bash Ten sam hook, wyjście powłoki Model widzi API_KEY=[REDACTED] 27.9 ms na hop
slow-guard Śpi 15 s w tool.call Pominięty, echo hi się wykonało ucięty przy 10000 ms
throw-guard Rzuca boom w tool.call Pominięty, polecenie się wykonało 574.2 ms
wygenerowany Mod 190 linii + 53 linie testów z jednego zdania validate: bez ostrzeżeń; test: 4 pass / 0 fail ~4 min, 34 tury, $1.23
claude plugin test na redact-secrets Bez klucza API, bez wywołania modelu 1 pass 0.25 s
claude plugin details Koszt sesji Moda ~0 dodanych tokenów n/a

Protokół: Claude Code 2.1.272, function hooks włączone zmienną środowiskową. Każdy Mod to katalog pluginu z plugin.json, hooks/hooks.json i jednym index.ts. Uruchomienia szły przez claude -p z włączonym logowaniem debugowania; podłożony plik i polecenie powłoki zawierały sk-test1234567890abcdef. Przypadki fail-open sterował Mod śpiący 15 s i Mod rzucający wyjątek, z echo hi jako chronionym poleceniem. Interaktywny REPL był sterowany przez pty i w dwóch próbach nie załadował Moda.

Zrób to w poniedziałek

  • Uruchom /plugin-types w sesji i otwórz .claude/types/claude-code.d.ts: wyszukaj fs.read i tool.call, zanim zaufasz jakiemukolwiek fragmentowi z wrześniowego wpisu.
  • Napisz trzyplikowy szkielet Moda (plugin.json, hooks/hooks.json z {"modules":["./index.ts"]}, index.ts eksportujący register(on)) i uruchom na nim claude plugin validate: przeczytaj linie śladu hooks: i calls:.
  • Przenieś swój najczęściej używany hook powłoki do handlera tool.call, który nadpisuje result, a potem porównaj czas hopa w logu debugowania z wersją powłokową.
  • Dodaj obok Moda plik claude plugin test, żeby strażnik działał bez klucza API w CI.
  • Owiń każdy handler strażnika w try/catch zwracający { deny } przy błędzie: w tym buildzie wyjątek lub 10-sekundowy zastój pomija cię i przepuszcza polecenie.
  • Przetestuj Moda osobno pod claude -p i w swoim prawdziwym interaktywnym terminalu i zapisz, który go załadował.
  • Przed instalacją cudzego Moda uruchom na nim claude plugin validate i odrzuć każdy, którego linia calls: wymienia możliwości hosta, do których Mod nie ma powodu sięgać.

Czytaj dalej

  • Przeczytaj w całości issue z propozycją, razem z PDF-em architektury dołączonym w komentarzach: to jedyny pisemny kontrakt dla register(on), budżetów i hopa workera s3.
  • Porównaj z projektem Command Code Mods, który uruchamia TypeScript względem ModApi w procesie hosta: oba systemy mają ten sam kształt i ograniczony wczesny dostęp s2.
  • Podgląd z claudefa.st powstał, gdy funkcja była jeszcze propozycją: przydatny, żeby zobaczyć, co zmieniło się między tekstem z 3 wrz a binarką 2.1.272 s9.
  • Note tweet Prathkuma to najjaśniejsze krótkie wyjaśnienie, dlaczego hooki w procesie biją hooki powłoki pod względem tokenów i opóźnień s7.
  • cc-mod-waitwhat to dobry pierwszy Mod do czytania: UI nad promptem, nic nie trafia do transkryptu s11.
  • cc-arcade pokazuje, jak daleko sięga $.ui: gry renderowane nad promptem przez Moda s5.
  • Dokumentacja hooków nadal opisuje model powłoki; trzymaj ją otwartą, żeby zmapować każde stare zdarzenie na nową nazwę noun.event s1.
  • Sceptycy na X twierdzą, że pluginy już to pokrywają, a powierzchnia będzie się psuć z każdym wydaniem; zmieniony rzeczownik fs to dla nich jeden punkt danych s23.

Źródła

  • Function Hooks proposal (issue #91870), GitHub, anthropics/claude-code. Dlaczego warto: jedyny tekst zbliżony do specyfikacji dla Modów, z PDF-em architektury i śladem wdrożenia w komentarzach.
  • Hooks reference, Claude Code docs. Dlaczego warto: model hooków powłoki, z którego migrujesz, zdarzenie po zdarzeniu.
  • Command Code Mods documentation, Command Code. Dlaczego warto: wcześniejszy przykład o tym samym kształcie TypeScript w procesie, przydatny, by zauważyć, co Anthropic skopiował, a czego uniknął.
  • awesome-claude-code-mods, GitHub, karanb192. Dlaczego warto: automatycznie skanowany katalog publicznych Modów, w którym ślad z validate jest jedyną weryfikacją.
  • cc-arcade, GitHub, sezaakgun. Dlaczego warto: demo, które uwidoczniło funkcję, i przegląd $.ui.
  • Boris Cherny announcement tweet, X, Boris Cherny. Dlaczego warto: komunikat o starcie od inżyniera Anthropic, skoro nie ma wpisu na blogu.
  • Prathkum: Function Hooks explained, X, Prathkum. Dlaczego warto: najlepsze krótkie wyjaśnienie hooków kontra Mody dla kogoś, kto już pisze hooki powłoki.
  • shipnotesai reaction thread, X, shipnotesai. Dlaczego warto: miejsce, gdzie krążyło twierdzenie "tylko REPL", któremu nasz test zaprzeczył.
  • Claude Code Function Hooks: Preview Behind a Flag, claudefa.st. Dlaczego warto: wyjaśnienie sprzed premiery, dobre do porównania propozycji z binarką.
  • cc-mod-waitwhat, GitHub, GGGODLIN. Dlaczego warto: mały, czytelny Mod, który pisze do UI, a nie do transkryptu.
  • claude-mods-skill, GitHub, BeLazy167. Dlaczego warto: skill do generowania Modów, jeśli chcesz powtórzyć eksperyment z jednym zdaniem.
  • AxialisSoftware reaction, X, AxialisSoftware. Dlaczego warto: sceptyczny punkt widzenia w jednym tweecie.

FAQ

Czy Mod zastępuje dziś moje hooki powłoki?

Jeszcze nie w niczym, co musi blokować. W 2.1.272 hook, który rzuca wyjątek albo zawiesza się ponad 10 s, jest pomijany i polecenie się wykonuje. Hooki powłoki nadal działają, więc zostaw blokujące tam, dopóki nie pojawi się zadeklarowany catch albo opcja fail-closed.

Po co validate, skoro Mod działa dobrze?

Bo jego linie hooks: i calls: to jedyny statyczny widok tego, czego Mod dotyka na $. Dla własnego Moda potwierdza ślad; dla cudzego Moda to cały przegląd, jaki dostajesz, zanim kod ruszy w twoim procesie.

Ile kosztuje Mod na sesję?

claude plugin details pokazał około 0 dodanych tokenów. Mod to kod działający w silniku, nie tekst w prompcie, i to główna przewaga nad skillem czy regułą w CLAUDE.md.

Dlaczego Mod załadował się pod -p, ale nie w REPL?

Nie wiadomo. Dwie próby sterowane przez pty milczały, podczas gdy claude -p załadował i zastosował hook. Prawdopodobną przyczyną jest środowisko pty, a nie sama funkcja, więc sprawdź we własnym terminalu, zanim zaufasz któremukolwiek kierunkowi.