← Wszystkie wpisy

Hooki w pracy z Apple Development: wzorce, które ratują projekt

From the guide: Claude Code Comprehensive Guide

Sesja Claude Code skierowana na projekt iOS ma zasięg, jakiego nie posiada zwykły Python ani projekt webowy. Agent może uruchamiać xcodebuild i xcrun poprzez narzędzie Bash. Może czytać i edytować pliki .pbxproj (domyślnie listy właściwości w starym formacie ASCII, czasem XML lub JSON po konwersji narzędziami — w każdym z tych formatów równie łatwo je nieodwracalnie uszkodzić). Posiada tożsamości podpisujące programisty, ponieważ działa na jego maszynie. Może wymazać symulator. Może zbudować projekt z błędnym schematem. Może wykonać commit i push. Protokół niczego z tego nie blokuje: system plików programisty jest systemem plików agenta, a flaga --dangerously-skip-permissions w Claude Code to jedno naciśnięcie klawisza dzielące od pełnej automatyzacji.

Środkiem zaradczym nie jest „zaufanie agentowi”. Środkiem zaradczym są hooki: deterministyczne skrypty powłoki, które host uruchamia w momentach granicznych cyklu życia (PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop).1 Hooki spowalniają agenta przy niebezpiecznych danych wejściowych, walidują destrukcyjne wyniki i uzależniają zakończenie sesji od poprawnej kompilacji. Stanowią nośny prymityw bezpieczeństwa, który każdy programista iOS uruchamiający agenta powinien skonfigurować, zanim agent cokolwiek zrobi.

Cztery wzorce hooków zasługują na miejsce w projektach iOS. Mają charakter ramowy, nie projektowy; aplikacje klastra (Return, Get Bananas, Reps, Water, Ace Citizenship) korzystają z ich wariantów. Każdy wzorzec nazywa konkretny tryb awarii, konkretny skrypt i zdarzenie cyklu życia, które ogranicza zasięg szkód.

TL;DR

  • Cztery wzorce hooków, które się liczą w iOS: walidacja .pbxproj (PostToolUse, zwraca błędy do agenta), blokowanie niebezpiecznych poleceń bash (PreToolUse, blokuje przed wykonaniem), bramka Stop wymagająca zielonej kompilacji, higiena stanu symulatora (Stop).
  • Kody wyjścia hooków mają znaczenie i działają inaczej w zależności od zdarzenia. exit 2 blokuje proponowane działanie w PreToolUse (narzędzie nigdy się nie uruchamia); w PostToolUse nie może blokować (narzędzie już zostało uruchomione), ale przekazuje stderr z powrotem do agenta, aby ten mógł naprawić lub cofnąć zmianę; w Stop uniemożliwia agentowi zakończenie sesji. exit 0 zezwala. exit 1 zwykle loguje, ale nie blokuje.1
  • Skrypty hooków znajdują się w .claude/hooks/*.sh w repozytorium, z odwołaniem przez ścieżkę względną z .claude/settings.json. Obowiązuje code review.
  • Uprawnienia agenta są uprawnieniami programisty. Hooki to sposób, w jaki programista wycina te uprawnienia z powrotem w przemyślany zestaw zatwierdzonych działań.

Wzorzec pierwszy: walidacja .pbxproj przy każdej edycji

Plik projektu Xcode to jedyny plik regularnie modyfikowany przez agenta o najwyższym stosunku zasięgu szkód do liczby linii. Jeden źle postawiony nawias w project.pbxproj po cichu psuje kompilację każdemu programiście w zespole. Błąd kompilacji pojawia się przy następnym wywołaniu xcodebuild, a nie w momencie edycji, więc agent zwykle deklaruje, że zmiana zadziałała, zanim awaria wyjdzie na jaw.

Hook uruchamia plutil -lint przy każdym zapisie .pbxproj. PostToolUse nie może zablokować samego zapisu (plik jest już na dysku, gdy hook się uruchamia), ale exit 2 natychmiast przekazuje błąd walidacji z powrotem do agenta jako niepowodzenie wywołania narzędzia: agent czyta niepowodzenie, wie, że plik jest uszkodzony, i może cofnąć lub naprawić zmianę przed kontynuowaniem sesji:

#!/bin/bash
# .claude/hooks/post-write-pbxproj.sh
# Runs after every Edit or Write tool call. Exits 2 to surface the
# validation failure to the agent so it can revert/repair the broken
# .pbxproj before the session moves on. (PostToolUse cannot prevent
# the write itself; it can only feed the error back.)

INPUT=$(cat)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

if [[ "$FILE" != *.pbxproj ]]; then
    exit 0
fi

if ! plutil -lint "$FILE" >/dev/null 2>&1; then
    echo "ERROR: $FILE failed plutil -lint after write" >&2
    echo "The Xcode project file is structurally broken. Revert and try again." >&2
    exit 2
fi

exit 0

plutil -lint wychwytuje uszkodzenia strukturalne: niezbalansowane nawiasy klamrowe lub okrągłe, brakujące średniki, nieprawidłowe tokeny plist, błędne zagnieżdżenie XML.2 Nie wychwytuje błędów semantycznych Xcode, takich jak źle sformułowany UUID, który akurat jest poprawnym składniowo tekstem plist, czy faza kompilacji odwołująca się do brakującego pliku. Te dają zwykłe błędy kompilacji, które agent może debugować w normalny sposób. Bramka plutil wychwytuje katastrofalną klasę błędów parsowania; błędy semantyczne przechodzą do samej kompilacji.

Konfiguracja hooka w .claude/settings.json (uwaga na cudzysłowy wokół $CLAUDE_PROJECT_DIR dla ścieżek ze spacjami):

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Write|Edit",
      "hooks": [{
        "type": "command",
        "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/post-write-pbxproj.sh"
      }]
    }]
  }
}

Matcher uruchamia hook tylko przy wywołaniach narzędzi Write i Edit; pierwszą czynnością skryptu jest wczesne zakończenie dla ścieżek innych niż .pbxproj. Koszt uruchamiania przy każdej edycji jest pomijalny, ponieważ filtr ścieżki to pierwsze sprawdzenie.

Wzorzec drugi: blokowanie destrukcyjnych poleceń Bash przed ich uruchomieniem

xcrun simctl erase wymazuje dane symulatora. xcodebuild archive wywołuje podpisywanie i może wytworzyć podpisane artefakty, których programista nie zamierzał stworzyć. git push --force przepisuje historię. Agent ma dostęp do nich wszystkich poprzez narzędzie Bash. Hook PreToolUse na Bash dopasowuje wzorzec proponowanego polecenia i decyduje, czy zezwolić na kontynuację.

Schemat:

#!/bin/bash
# .claude/hooks/pre-bash-xcode.sh
# Runs before every Bash tool call. Exits 2 (blocking) on irreversible
# Xcode/signing/git operations the developer hasn't explicitly approved.
# PreToolUse hooks CAN block: exit 2 prevents the tool from running.

INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

case "$COMMAND" in
    *"simctl erase"*)
        echo "ERROR: simulator erase requires explicit human approval" >&2
        echo "Tell the developer what you wanted to erase and why; let them run it." >&2
        exit 2
        ;;
    *"xcodebuild archive"*|*"xcodebuild -exportArchive"*)
        echo "ERROR: xcodebuild archive/export invokes signing; requires human approval" >&2
        exit 2
        ;;
    *"git push --force"*|*"git push -f"*)
        echo "ERROR: force-push rewrites history; requires human approval" >&2
        exit 2
        ;;
    *"rm -rf"*)
        echo "ERROR: rm -rf requires explicit approval" >&2
        exit 2
        ;;
esac

exit 0

Hook to przełącznik na fragmentach wzorca polecenia. Klasą blokującą jest klasa działań nieodwracalnych: wymazanie, podpisanie, force-push, rekurencyjne usunięcie. Operacje odwracalne (zwykłe kompilacje, testy, commity git bez force) przechodzą bez zatrzymania.

Częstym ulepszeniem jest dopuszczenie pewnych poleceń, gdy programista jawnie zdecydował się na nie poprzez zmienną środowiskową lub flagę w rozmowie. Na przykład: xcodebuild archive można dopuścić, jeśli CLAUDE_ALLOW_ARCHIVE=1 znajduje się w środowisku, ustawione przez programistę przed sesją dla konkretnego zadania archiwizacji. Hook czyta zmienną środowiskową i omija blokadę:

*"xcodebuild archive"*)
    if [[ "${CLAUDE_ALLOW_ARCHIVE:-0}" == "1" ]]; then
        exit 0
    fi
    echo "ERROR: xcodebuild archive requires CLAUDE_ALLOW_ARCHIVE=1" >&2
    exit 2
    ;;

Wzorzec: domyślne odmawianie dla klasy nieodwracalnej, zawór bezpieczeństwa typu opt-in dla przypadków, w których programista chce, aby agent się tym zajął.

Wzorzec trzeci: hook Stop, który uzależnia zakończenie od zielonej kompilacji

Agent lubi deklarować zadanie jako wykonane, gdy rozmowa wydaje się rozstrzygnięta. Bez bramki „wykonane” może oznaczać „edytowałem pliki i czat jest w spójnym stanie”, a nie „kompilacja nadal się powodzi”. Hook Stop to miejsce, w którym narzuca się właściwe znaczenie.

#!/bin/bash
# .claude/hooks/stop-build-check.sh
# Runs when the agent tries to stop. Exits 2 if the build is broken,
# which prevents the session from concluding until the agent fixes it.

cd "$CLAUDE_PROJECT_DIR" || exit 0

# Hard-code project, scheme, and destination per repo. Do not rely on
# auto-discovery: workspaces, multiple projects, or shared-vs-user
# schemes all break naive heuristics.
PROJECT="MyApp.xcodeproj"
SCHEME="MyApp"
DESTINATION="platform=iOS Simulator,name=iPhone 17 Pro"

LOG=/tmp/claude-stop-build.log
if ! xcodebuild -project "$PROJECT" -scheme "$SCHEME" \
        -configuration Debug \
        -destination "$DESTINATION" \
        build > "$LOG" 2>&1; then
    echo "ERROR: build failed; cannot stop with a broken build" >&2
    echo "See $LOG for the full xcodebuild output." >&2
    tail -50 "$LOG" >&2
    exit 2
fi

exit 0

Twarde zakodowanie PROJECT, SCHEME i DESTINATION to właściwa forma dla hooków zatwierdzonych w repozytorium: wartości nigdy nie dryfują, przestrzenie robocze i repozytoria z wieloma projektami działają bez korekt na każdej maszynie, a system kompilacji CI używający tego samego hooka może podmienić cel poprzez zmienną środowiskową. Automatyczne wykrywanie (ls *.xcodeproj, xcodebuild -list | awk) działa w najprostszym przypadku jednoosobowym, ale zawodzi przy projektach z .xcworkspace, przy repozytoriach z wieloma plikami .xcodeproj oraz przy rozróżnieniu schematów współdzielonych i użytkownika. Łańcuch destination podąża za udokumentowaną składnią platform=...,name=... w xcodebuild;3 musi to być symulator, który maszyna programisty rzeczywiście posiada, w przeciwnym razie hook zawiedzie z powodów środowiskowych, a nie kodu.

Dwie decyzje produktowe podejmowane przez hook:

Stop blokuje sygnał agenta „skończyłem”, a nie człowieka. Programista zawsze może użyć Ctrl+C, zamknąć terminal lub zignorować blokadę. Hook stanowi barierkę przeciwko optymizmowi agenta, a nie blokadę dla człowieka.

Hook uruchamia prawdziwą kompilację, a nie sprawdzenie składni. swift build względem projektu specyficznego dla iOS pomija kroki kompilacji właściwe dla iOS; tylko xcodebuild udowadnia, że cel iOS się kompiluje. Kosztem jest czas samej kompilacji (10–60 sekund w większości projektów); wartością jest wychwytywanie za każdym razem przypadku „uszkodzona kompilacja oznaczona jako wykonana”.

Wzorzec czwarty: higiena stanu symulatora

Po długiej sesji agenta symulatory mogą się piętrzyć: uruchomione symulatory, których agent zapomniał wyłączyć, stare instalacje aplikacji, które buforują nieaktualny stan, dane środowiska uruchomieniowego, które przeżywają sesje i wytwarzają nieodtwarzalne błędy. Hook Stop może posprzątać.

#!/bin/bash
# .claude/hooks/stop-simulator-cleanup.sh
# Soft cleanup: shuts down booted simulators we don't need anymore.
# Does NOT erase data; does NOT block. Logs only.

BOOTED=$(xcrun simctl list devices booted 2>/dev/null | grep -E "Booted" | wc -l | xargs)
if (( BOOTED > 0 )); then
    echo "[hook] $BOOTED booted simulators at session end; consider shutdown" >&2
    # Uncomment to auto-shutdown:
    # xcrun simctl shutdown all 2>/dev/null
fi

exit 0

Forma jest z założenia nieblokująca: hook raportuje stan, ale nie działa, dopóki programista nie odkomentuje linii wyłączającej. Powodem jest to, że następna sesja agenta może chcieć zachować uruchomiony symulator (szybsze uruchomienie na zimno, gdy symulator już działa). Decyzja należy do programisty: jeśli symulatory piętrzą się przez wiele sesji i koszt jest realny, można odkomentować wyłączanie; w przeciwnym razie pozostawić jako sygnał logu.

Bardziej agresywny wariant wymazuje symulatory między sesjami, ale to wkracza na obszar operacji destrukcyjnych z wzorca drugiego. Wymazanie należy do blokowania PreToolUse, a nie do automatyki Stop.

Czego hooki nie rozwiązują

Powyższe cztery wzorce to zestaw roboczy, a nie cały obraz. Trzy klasy awarii, których hooki nie potrafią wychwycić:

Błędy logiczne w kodzie agenta. Hook waliduje strukturę, a nie semantykę. Agent może napisać klasę @Model, która się kompiluje, przechodzi lint pliku projektu, kompiluje się na zielono i nadal jest semantycznie błędna (brakująca migracja, uszkodzone ograniczenie unikalności, relacja SwiftData bez odwrotności). Poprawność logiczna mieszka w testach, code review i oczach programisty; hooki służą sprawom strukturalnym i cyklu życia.

Powolny dryf jakości agenta. Każdy pojedynczy hook zatrzymuje klasę awarii przy pierwszym napotkaniu, ale skumulowany dryf przez wiele sesji (stopniowo bardziej zabałaganiony kod, stopniowo słabsze testy, stopniowo nieaktualne instrukcje CLAUDE.md) nie jest tym, co hooki mierzą. To problem przeglądu sesji, a nie problem hooków.

Naruszenia granic zaufania poza powierzchnią narzędzi agenta. Hook na Bash i Edit obejmuje typową ścieżkę. Hook na każde narzędzie MCP, które agent może wywołać, wymaga matcherów per narzędzie; niektóre serwery MCP wystawiają dziesiątki lub setki narzędzi (XcodeBuildMCP ogłasza około 80) i pisanie hooka per narzędzie jest niewykonalne. Właściwym wzorcem jest tutaj ograniczenie dostępu serwerów MCP (.mcp.json na poziomie projektu, przepływ zatwierdzania przy pierwszym użyciu), a nie hookowanie każdego pojedynczego narzędzia, oraz akceptacja faktu, że agent operujący swoimi serwerami MCP jest częścią swojej usankcjonowanej władzy.

Relację między hookami a szerszą postawą zaufania omówiono w Repozytorium nie powinno głosować nad własnym zaufaniem: zaufanie jest niezmiennikiem kolejności ładowania, a nie kontrolą poniżej. Hooki to kontrole poniżej dla działań podejmowanych przez już zaufanego agenta; nie zastępują wcześniejszej decyzji, czy agent powinien być w ogóle zaufany.

Co zbudowałbym inaczej

Trzy wzorce, które aplikacje klastra albo wdrażają, albo żałują, że nie wdrożyły.

Skrypty hooków w kontroli wersji wraz z resztą projektu. Skrypty hooków znajdują się w .claude/hooks/*.sh w repozytorium. Plik .claude/settings.json odwołuje się do nich przez ścieżkę względną. Zespół otrzymuje te same zabezpieczenia na różnych maszynach, code review obejmuje zmiany hooków, a wdrożenie nowego programisty to git clone zamiast ćwiczenia z kopiuj-wklej. Hooki na poziomie użytkownika w ~/.claude/settings.json to niewłaściwa granulacja dla blokad specyficznych dla projektu.

Hook SessionStart, który wypisuje aktywną konfigurację hooków. Hooki są ciche, dopóki się nie uruchomią. Hook SessionStart, który uruchamia się na początku każdej sesji Claude Code i wypisuje „Active hooks: pbxproj-validation, dangerous-bash-gate, build-check-on-stop”, przypomina programiście (i agentowi), jakie zabezpieczenia działają. Kosztem jest jedna linia stderr na sesję; wartością jest to, że nikt nie pracuje, nie wiedząc, że siatka bezpieczeństwa istnieje.

Dziennik audytowy wywołań narzędzi agenta na poziomie repozytorium. Hook PostToolUse, który dopisuje każde wywołanie narzędzia (ze znacznikiem czasu, nazwą narzędzia, argumentami) do pliku JSONL w .claude/logs/ (wykluczonego z gita). Dziennik odpowiada na pytanie „co robił agent w tej sesji?” zapytaniem jq zamiast przewijania historii czatu. Hook dodaje kilka milisekund na wywołanie narzędzia i wytwarza trwałe dane audytowe, które programista może przeszukać, gdy coś pójdzie nie tak.

Kiedy hooki są złą odpowiedzią

Dwa przypadki, w których warstwa hooków jest złym miejscem do rozwiązania problemu.

Same serwery MCP agenta. Zły serwer MCP robiący niewłaściwe rzeczy nie jest problemem hooka; jest problemem serwera MCP. Naprawą jest ograniczenie tego, którym serwerom MCP projekt ufa (przegląd .mcp.json, zatwierdzenie przy pierwszym użyciu na poziomie projektu) oraz przeczytanie kodu źródłowego serwera, jeśli jest otwarty. Hook na każde wywołanie narzędzia MCP dodaje narzut, nie odnosząc się do kwestii zaufania.

Agenci działający bez nadzoru. Pełna postawa hooków zakłada, że programista jest blisko sesji i może zinterpretować nieudany hook. Agent działający w CI bez człowieka w pętli wymaga innej postawy: ściślejszego ograniczenia MCP, węższych zestawów narzędzi, innego modelu zaufania. Same hooki nie przerzucają mostu między rozwojem nadzorowanym a automatyzacją bez nadzoru; ta luka jest zamierzona.

Co ten wzorzec oznacza dla aplikacji iOS publikowanych na iOS 26+

Trzy wnioski.

  1. Domyślna odmowa dla operacji nieodwracalnych, walidacja plików o strukturalnym zasięgu szkód, uzależnienie zakończenia od zielonej kompilacji. Trzy zdarzenia cyklu życia hooków (PreToolUse, PostToolUse, Stop), cztery wzorce, pokrywające typowe tryby awarii iOS. Połączony zestaw jest na tyle mały, by napisać go w popołudnie, i na tyle trwały, by przetrwać każdego konkretnego agenta lub model.

  2. Kod wyjścia ma znaczenie i różni się w zależności od zdarzenia. exit 2 blokuje akcję w PreToolUse (narzędzie nigdy się nie uruchamia); w PostToolUse nie może blokować (narzędzie już zostało uruchomione), ale przekazuje stderr z powrotem do agenta, aby ten mógł naprawić lub cofnąć zmianę; w Stop uniemożliwia agentowi zakończenie sesji. exit 1 nie blokuje przy większości zdarzeń. Każdy hook należy przetestować z celowo niepoprawnym przypadkiem, zanim zacznie się na nim polegać.

  3. Hooki ograniczają uprawnienia. Nie nadają ich. Zasięg agenta w maszynie programisty to cokolwiek system operacyjny pozwala robić sesji terminala programisty. Hooki pozwalają programiście wyciąć konkretne działania z tych uprawnień i wymagać jawnego zatwierdzenia. Domyślnie obowiązuje to, co przyznaje system operacyjny; celem hooków jest uczynić ten domyślny zakres mniejszym, a nie większym.

Pełny klaster Apple Ecosystem: typowane App Intents dla powierzchni Apple Intelligence; serwery MCP dla powierzchni agenta; pytanie o routing między nimi; Foundation Models dla funkcji LLM działających na urządzeniu w aplikacji; rozróżnienie LLM runtime vs tooling; synteza trzech powierzchni; wzorzec pojedynczego źródła prawdy; Dwa serwery MCP dla integracji Xcode, która łączy się z tymi hookami; Live Activities dla maszyny stanów ekranu blokady iOS; kontrakt runtime watchOS na Apple Watch; wewnętrzne mechanizmy SwiftUI dla podłoża frameworka; przestrzenny model mentalny RealityKit dla scen visionOS; dyscyplina schematu SwiftData dla persystencji; wzorce Liquid Glass dla warstwy wizualnej; wieloplatformowe wydawanie dla zasięgu między urządzeniami. Centrum znajduje się w serii Apple Ecosystem. Szerszy kontekst iOS-z-agentami-AI znajduje się w przewodniku po programowaniu agentowym iOS.

FAQ

Czym są hooki Claude Code i dlaczego mają znaczenie dla programowania iOS?

Hooki Claude Code to deterministyczne skrypty powłoki, które uruchamiają się w zdarzeniach cyklu życia (PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop). W programowaniu iOS ograniczają uprawnienia agenta wobec operacji destrukcyjnych: wymazania symulatora, podpisywania kodu, mutacji pliku projektu, force-pushy. Bez hooków agent ma pełne uprawnienia maszyny programisty; z hookami konkretne niebezpieczne działania wymagają jawnego zatwierdzenia.

Którym zdarzeniom hooków programista iOS powinien nadać priorytet?

PreToolUse na Bash dla blokowania destrukcyjnych poleceń (simctl erase, xcodebuild archive, git push --force). PostToolUse na Edit/Write dla walidacji integralności .pbxproj. Stop dla bramki zielonej kompilacji. SessionStart dla logowania aktywnej konfiguracji hooków. Te cztery razem wychwytują najczęstsze awarie agenta specyficzne dla iOS.

Jaka jest różnica między kodami wyjścia 0, 1 i 2?

Exit 0 zezwala na akcję i kontynuuje. Exit 2 zachowuje się inaczej w zależności od zdarzenia: w PreToolUse blokuje proponowane działanie (narzędzie nigdy się nie uruchamia); w PostToolUse nie może blokować, ponieważ narzędzie już się wykonało, ale przekazuje stderr z powrotem do agenta, aby ten mógł naprawić lub cofnąć zmianę; w Stop uniemożliwia agentowi zakończenie sesji. Exit 1 loguje błąd, ale nie blokuje przy większości zdarzeń hooków. Dla wzorców bezpieczeństwa, które muszą rzeczywiście zapobiec działaniu przed jego uruchomieniem, należy użyć exit 2 w PreToolUse. Dla walidacji po destrukcyjnym zapisie należy użyć exit 2 w PostToolUse, aby przekazać niepowodzenie z powrotem do agenta. Każdy hook trzeba przetestować z celowo niepoprawnymi danymi wejściowymi, aby potwierdzić, że zachowuje się zgodnie z oczekiwaniami dla danego zdarzenia.

Gdzie powinny znajdować się skrypty hooków?

W .claude/hooks/*.sh w katalogu głównym projektu, z .claude/settings.json odwołującym się do nich przez ścieżkę względną. Pod kontrolą wersji i z code review wraz z resztą projektu. Hooki na poziomie użytkownika w ~/.claude/settings.json także działają, ale stanowią niewłaściwą granulację dla specyficznych dla projektu blokad iOS.

Czy hooki zastępują potrzebę code review?

Nie. Hooki wychwytują błędy strukturalne (uszkodzone pliki projektu, niebezpieczny bash, uszkodzone kompilacje), zanim trafią na produkcję. Code review wychwytuje błędy semantyczne (błędy logiczne, brakujące migracje, słabe testy). Te dwie warstwy uzupełniają się wzajemnie: hooki czynią agenta bezpieczniejszym do wdrożenia w pętli wewnętrznej, code review zachowuje uczciwość wyniku agenta na granicy.

Bibliografia


  1. Anthropic, „Claude Code reference: Hooks”. Zdarzenia cyklu życia (PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, Stop), składnia matchera, kształt polecenia oraz rola kodów wyjścia. Exit 2 zachowuje się inaczej w zależności od zdarzenia: w PreToolUse i Stop blokuje akcję; w PostToolUse nie może blokować (narzędzie już zostało uruchomione), ale przekazuje stderr z powrotem do agenta. Exit 0 zezwala; exit 1 zwykle loguje, ale nie blokuje. Analizę autora zawiera Kiedy LLM żyje w aplikacji vs w narzędziach, omawiając postawę zaufania LLM runtime vs tooling, którą hooki operacjonalizują. 

  2. Apple, strona man plutil(1). Flaga -lint waliduje składnię listy właściwości w starym formacie ASCII, XML i binarnym. Wykrywa uszkodzenia na poziomie parsowania, ale nie sprawdza semantyki specyficznej dla Xcode, takiej jak odwołania faz kompilacji czy poprawność UUID w grafie projektu. 

  3. Apple Developer, „xcodebuild Destination Specifier” i strona man xcodebuild. Składnia -destination 'platform=...,name=...' to kanoniczny sposób na przypięcie celu kompilacji; środowiska CI nadpisują nazwę symulatora poprzez zmienne środowiskowe lub skryptowe wykrywanie dostępności urządzeń. 

Powiązane artykuły

Single Source Of Truth: SwiftData, MCP, iCloud

Three callers can write to the same shopping list: a human, Apple Intelligence, and an external agent. Truth has to live…

18 min czytania

Claude Code as Infrastructure

Claude Code is not an IDE feature. It is infrastructure. 84 hooks, 48 skills, 19 agents, and 15,000 lines of orchestrati…

15 min czytania