Skrypty z Claude Code: uruchomienia headless, potoki, cron i hooki git
Skryptowanie Claude Code to uruchamianie claude -p (tryb print) ze skryptu powłoki, hooka git, zadania cron lub kroku CI zamiast sesji interaktywnej. Taki przebieg startuje w trybie uprawnień Manual i nikt nie zatwierdza pytań, więc działa tylko wtedy, gdy skrypt nadaje dokładne uprawnienia, ogranicza tury i koszt oraz sprawdza zwrócony wynik JSON.
Masz prompt, który działa: wrzucasz diff przez potok, prosisz o wpis do changeloga i dopisujesz go do CHANGELOG.md. Przed każdym wydaniem odpalasz go ręcznie i za każdym razem przepisujesz z pamięci. Potem przenosisz go do crona i przez tydzień co noc „kończy się sukcesem”, nie zapisując niczego, bo każda edycja pliku została odrzucona, a skrypt sprawdzał tylko, czy proces się zakończył. Ta strona jest dla developera albo tech leada, który chce, żeby takie przebiegi były powtarzalne i głośno zgłaszały błędy. Zakłada, że Claude Code jest zainstalowany i zalogowany; przegląd sekcji Automatyzacja pokazuje, gdzie skrypty stoją obok hooków, routines i Agent SDK.
Co zyskujesz, skryptując Claude Code
Dział zatytułowany „Co zyskujesz, skryptując Claude Code”- Skrypt opakowujący, który uruchamia jedno zadanie bez nadzoru, ponawia tylko awarie przejściowe i kończy się kodem niezerowym, jeśli przebieg naprawdę się nie udał.
- Przepisy na uprawnienia dla skryptów, od raportów tylko do odczytu po edycje w jednym katalogu, oraz pułapkę w ustawieniach projektu, która po cichu wyłącza twoje reguły
allow. - Bramkę pre-commit, która zwraca werdykt zwalidowany schematem zamiast tekstu do grepowania.
- Wzorzec zadania cron z uwierzytelnianiem, jednorazową gałęzią i raportem, który scala człowiek.
- Prompty do skopiowania: skill wydania, masowa migracja i zadanie utrzymaniowe.
Który mechanizm automatyzacji pasuje do zadania?
Dział zatytułowany „Który mechanizm automatyzacji pasuje do zadania?”Wybierz mechanizm, zanim napiszesz prompt. Większość błędów z sekcji o awariach na końcu strony bierze się z uruchomienia zadania w niewłaściwym miejscu.
| Chcesz… | Użyj | Dlaczego |
|---|---|---|
| Powtarzać wieloetapowe zadanie, patrząc na nie | Skill (/release) w sesji interaktywnej | Możesz odpowiadać na pytania i zatwierdzać ryzykowne kroki. |
| Uruchomić jedno zadanie ze skryptu, Makefile’a albo hooka git | claude -p | Wejście na stdin, wynik na stdout, kod wyjścia dla wywołującego. Temat tej strony. |
| Uruchamiać zadanie według harmonogramu przy zamkniętym laptopie | Routines | Sesje w chmurze Anthropic; research preview, minimalny odstęp to godzina. |
| Uruchamiać zadanie według harmonogramu na własnej maszynie | cron + claude -p | Twoja sieć, twoje poświadczenia, dowolny odstęp. |
| Przeglądać PR-y albo reagować na zgłoszenia w GitHubie | anthropics/claude-code-action@v1 | Działa na zdarzeniach i harmonogramach GitHuba, komentuje PR. |
| Reagować na każdą edycję, którą Claude robi w sesji | Hooki | Deterministyczne polecenia powłoki na zdarzeniach cyklu życia, bez promptu. |
| Zbudować długo działający program wokół pętli agenta | Claude Agent SDK | Sesje, callbacki i uprawnienia z Pythona albo TypeScriptu. |
Czym claude -p różni się od sesji interaktywnej?
Dział zatytułowany „Czym claude -p różni się od sesji interaktywnej?”Pięć różnic decyduje o tym, czy skrypt zadziała. Wszystkie sprawdziliśmy 2026-09-26 na Claude Code 2.1.283 i w dokumentacji trybu headless.
- Startuje w trybie Manual na każdym planie. Na kanale
latesttryb auto jest domyślny w sesjach interaktywnych, ale nie w-p. Wszystko, co wymagałoby zatwierdzenia, zostaje odrzucone, bo nikt nie odpowie, a przebieg idzie dalej bez tego. - Pomija okno zaufania do workspace’u. Hooki projektu, jego blok
envi wszystkie serwery z.mcp.jsonnadal się ładują i działają. Regułypermissions.allowz.claude/settings.jsonprojektu nie obowiązują w folderze, któremu nigdy nie zaufałeś interaktywnie; Claude Code wypisuje wtedy na stderr ostrzeżeniethis workspace has not been trusted. Świeży checkout w CI albo w cronie to właśnie taki folder, więc podawaj uprawnienia w linii poleceń. - Kod wyjścia ma znaczenie. Wynosi
0przy sukcesie i jest niezerowy, gdy przebieg się nie powiedzie, także po osiągnięciu--max-turns. Błąd wewnątrz przebiegu, na przykład brak uwierzytelnienia, trafia jako wynik na stdout. SIGTERM kończy proces kodem143i nie zapisuje wyniku. - Stdin ma limit 10 MB. Powyżej Claude Code kończy się błędem. Większe dane zapisz do pliku i podaj ścieżkę w prompcie.
--barepomija lokalną konfigurację. Pomija hooki, pluginy, pamięć automatyczną oraz automatyczne wykrywanie skilli, serwerów MCP iCLAUDE.md, a uwierzytelnia się wyłącznie przezANTHROPIC_API_KEY(alboapiKeyHelperprzekazany w--settings), nigdy przez login do subskrypcji.claude --help(2.1.283) podaje też, że skille „still resolve via /skill-name”, więc skill wprost wymieniony w prompcie może się mimo to rozwinąć. Używaj--bare, gdy zadanie ma działać identycznie na każdej maszynie, a zadanie oparte na skillu uruchom raz z--bare, zanim zaczniesz polegać na którymkolwiek z tych zachowań; pomiń tę flagę, gdy zadanie korzysta zCLAUDE.md. Dokumentacja trybu headless zaleca--baredla skryptów i zapowiada, że w przyszłym wydaniu stanie się on domyślny dla-p, więc zadanie, które potrzebujeCLAUDE.md, powinno wczytać go jawnie (na przykład przez--append-system-prompt-file CLAUDE.md), zamiast polegać na automatycznym wykrywaniu.
Formaty wyjścia:
--output-format | Dostajesz | Zastosowanie |
|---|---|---|
text (domyślny) | Tylko końcową odpowiedź | Tekst dla człowieka albo plik, który commitujesz |
json | Jeden obiekt wyniku: subtype, is_error, result, total_cost_usd, permission_denials, session_id | Każdy skrypt, który rozgałęzia się na wyniku |
stream-json | Zdarzenia w formacie NDJSON na bieżąco | Postęp na żywo i długie zadania |
Dodaj --json-schema do --output-format json, a zwalidowany obiekt trafi do pola structured_output. To różnica między parsowaniem prozy grepem a odczytem pola.
Nadaj skryptowi dokładnie te uprawnienia, których potrzebuje
Dział zatytułowany „Nadaj skryptowi dokładnie te uprawnienia, których potrzebuje”Zdecyduj, co zadanie może robić, zanim się uruchomi, i zapisz to w linii poleceń, żeby uprawnienia podróżowały razem ze skryptem.
| Zadanie | Flagi |
|---|---|
| Raport albo przegląd tylko do odczytu | --permission-mode dontAsk (odczyty w katalogu roboczym i polecenia tylko do odczytu nadal działają) |
| Raport, który uruchamia konkretne polecenia | --permission-mode dontAsk --allowedTools "Bash(npm audit *),Bash(npm outdated *)" |
| Edycje ograniczone do jednego katalogu | --permission-mode dontAsk --allowedTools "Edit(./src/api/**),Bash(npm test *)" |
| Szerokie zmiany, przy których każdą akcję ma ocenić klasyfikator | --permission-mode auto --permission-prompts none |
| Wszystko wolno | --dangerously-skip-permissions, tylko w jednorazowym sandboksie bez sieci i bez sekretów |
W skryptach liczą się trzy szczegóły reguł. Końcowe * w Bash(npm test *) oznacza dopasowanie prefiksu, a spacja przed * sprawia, że reguła nie pasuje do npm test-e2e. Reguły ścieżek są sprawdzane tylko dla Edit(...) i Read(...): reguła Write(reports/**) zostanie przyjęta i nigdy nie będzie użyta, więc pisz Edit(./reports/**). A dontAsk odrzuca wszystko, czego nie wymieniłeś, i właśnie tego chcesz, gdy nikt nie patrzy.
Napisz wrapper, który głośno zgłasza błędy
Dział zatytułowany „Napisz wrapper, który głośno zgłasza błędy”Każde zadanie bez nadzoru z tej strony przechodzi przez jeden wrapper. Ponawia próbę tylko wtedy, gdy nie ma żadnego wyniku (awaria sieci albo procesu), a nigdy wtedy, gdy Claude zadziałał i zatrzymał się z konkretnego powodu, bo druga próba zadania, które wyczerpało limit tur, tylko podwaja rachunek.
#!/usr/bin/env bash# scripts/claude-job.sh — uruchamia jedno zadanie Claude Code bez nadzoru; kod niezerowy, jeśli się nie udało.# Użycie: scripts/claude-job.sh "PROMPT" [dodatkowe flagi claude...]set -euo pipefail
PROMPT="$1"; shiftRUN_DIR="${RUN_DIR:-.claude-runs}"mkdir -p "$RUN_DIR"OUT="$RUN_DIR/$(date +%Y%m%dT%H%M%S).json"
for attempt in 1 2 3; do claude -p "$PROMPT" \ --output-format json \ --permission-mode dontAsk \ --max-turns 25 \ --max-budget-usd 3.00 \ "$@" > "$OUT" 2>> "$RUN_DIR/stderr.log" && break # Obiekt wyniku oznacza, że Claude zadziałał i zatrzymał się celowo: ponowienie nie pomoże. jq -e '.type == "result"' "$OUT" > /dev/null 2>&1 && break [ "$attempt" -lt 3 ] || break # bez czekania po ostatniej próbie echo "attempt $attempt produced no result; retrying in $((attempt * 30))s" >&2 sleep $((attempt * 30))done
subtype=$(jq -r '.subtype // "missing"' "$OUT" 2> /dev/null || echo missing)is_error=$(jq -r '.is_error' "$OUT" 2> /dev/null || echo null)cost=$(jq -r '.total_cost_usd // 0' "$OUT" 2> /dev/null || echo 0)denied=$(jq -r '(.permission_denials // []) | length' "$OUT" 2> /dev/null || echo 0)echo "subtype=$subtype is_error=$is_error cost_usd=$cost denials=$denied" >&2
if [ "$denied" != "0" ]; then echo "denied tool calls (grant them or change the prompt):" >&2 jq -c '.permission_denials[]' "$OUT" >&2 [ "${ALLOW_DENIALS:-0}" = 1 ] || exit 1 # odrzucone wywołanie kończy zadanie błędem, chyba że wywołujący wyrazi zgodęfi[ "$subtype" = "success" ] && [ "$is_error" = "false" ] || exit 1jq -r '.result' "$OUT"Wywołujący dodaje własne uprawnienia po prompcie, na przykład scripts/claude-job.sh "Summarize open TODOs" --allowedTools "Bash(git log *)". Przebieg z choćby jednym odrzuconym wywołaniem narzędzia kończy się kodem 1, nawet gdy subtype to success, bo to właśnie zadanie, które „kończy się sukcesem”, niczego nie zapisując. Zadanie, które spodziewa się odmów, na przykład raport mogący sięgnąć po polecenie, którego celowo nie nadałeś, musi to jawnie zadeklarować: ALLOW_DENIALS=1 scripts/claude-job.sh …. Flaga --max-turns działa, ale nie ma jej w claude --help (sprawdzone na 2.1.283; przebieg po limicie kończy się kodem 1 i subtype równym error_max_turns); udokumentowanym limitem jest --max-budget-usd. Pliki JSON w .claude-runs/ to twój ślad audytowy: dodaj katalog do .gitignore i trzymaj pliki tak długo, jak logi CI.
Zostaw model domyślny dla Claude Code. W raporcie o dużym wolumenie, w którym liczy się koszt, dodaj --model z tańszym aliasem, takim jak sonnet, dopiero wtedy, gdy twoje własne testy pokażą, że wynik nadal się broni; aktualne opcje i ceny znajdziesz w przeglądzie modeli.
Przekaż przez potok wynik buildu, diff albo logi
Dział zatytułowany „Przekaż przez potok wynik buildu, diff albo logi”Potok to najtańsza integracja: dane przychodzą na stdin, więc Claude nie potrzebuje uprawnień do Bash, żeby je pobrać.
# Wyjaśnij nieudany build, nie pozwalając Claude niczego dotknąćnpm run build 2>&1 | claude -p "Explain the root cause of each distinct error, most fundamental first. Name the file and line. Do not propose fixes for errors caused by an earlier one."
# Linter literówek jako skrypt npm (z dokumentacji trybu headless)git diff main | claude -p "you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else."
# Wpis do changeloga z commitów od ostatniego tagagit log --oneline "$(git describe --tags --abbrev=0)..HEAD" \ | claude -p "Write a Keep a Changelog entry for version 2.4.0 dated $(date +%F). Group under Added, Changed, Fixed, Removed. One line per user-visible change, past tense. Drop chore and CI commits." \ > /tmp/changelog-entry.mdPrzekieruj wynik do pliku i przejrzyj go, zanim trafi dalej; potok zapisujący prosto do CHANGELOG.md zamienia jeden zły przebieg w zły commit.
Zamień powtarzany prompt w skill, który wywołają twoje skrypty
Dział zatytułowany „Zamień powtarzany prompt w skill, który wywołają twoje skrypty”Gdy prompt ma więcej niż trzy kroki, przestań go wklejać. Polecenia niestandardowe są teraz skillami: plik .claude/skills/release/SKILL.md i starszy .claude/commands/release.md tworzą to samo /release, a istniejące pliki poleceń nadal działają. Format opisuje przewodnik po poleceniach niestandardowych; przy skryptach liczą się dwie rzeczy: disable-model-invocation: true, żeby Claude nigdy sam z siebie nie zaczął wydania, oraz $ARGUMENTS, które dostaje wszystko, co stoi po nazwie polecenia.
Przebieg -p rozwija skill wymieniony w prompcie, więc ten sam plik obsługuje ciebie w sesji i twoje skrypty bez nadzoru:
scripts/claude-job.sh "/release minor" \ --allowedTools "Edit(./package.json),Edit(./CHANGELOG.md),Bash(npm test *),Bash(git add *),Bash(git commit *),Bash(git tag *)"Lista celowo pomija git push. Skrypt taguje lokalnie; wypycha człowiek albo CI, po przeczytaniu diffu taga.
Zablokuj commit przeglądem pre-commit
Dział zatytułowany „Zablokuj commit przeglądem pre-commit”Hook git pre-commit uruchamia się przed każdym commitem, w twoim terminalu, niezależnie od tego, czy kod napisał Claude. To coś innego niż hook Claude Code, który działa na wywołaniach narzędzi Claude wewnątrz sesji. Hooka git używaj do ostatniej kontroli zestagowanego diffu; hooków Claude Code do formatowania i blokowania w trakcie sesji.
Ten hook prosi o werdykt zgodny ze schematem JSON, więc skrypt czyta pole, zamiast szukać BLOCK: w prozie, która może brzmieć „nie znaleziono problemów BLOCK:”.
#!/usr/bin/env bash# .git/hooks/pre-commit — blokuje commit przy krytycznym problemie w zestagowanym diffieset -euo pipefail
diff=$(git diff --cached --no-color)[ -z "$diff" ] && exit 0
gitleaks git --staged # najpierw deterministyczny skan sekretów; przy wycieku kod 1 blokuje commit
schema='{"type":"object","properties":{"verdict":{"type":"string","enum":["pass","block"]},"findings":{"type":"array","items":{"type":"string"}}},"required":["verdict","findings"]}'
if ! out=$(printf '%s' "$diff" | claude -p \ "Review this staged diff for critical problems only: credentials or API keys in the code, SQL built by string concatenation, a removed authorization check, an error swallowed in auth or payment code. Ignore style and naming. Return verdict block only for a problem you can name by file and line; put each one in findings as 'file:line - problem'." \ --output-format json --json-schema "$schema" \ --permission-mode dontAsk --max-turns 3 --max-budget-usd 0.50); then echo "pre-commit: Claude review did not complete; commit allowed. Re-run before you push." >&2 exit 0fi
if [ "$(jq -r '.structured_output.verdict // "missing"' <<< "$out")" = "block" ]; then echo "pre-commit: blocked by Claude review" >&2 jq -r '.structured_output.findings[]' <<< "$out" >&2 echo "Fix the findings, or bypass once with: git commit --no-verify" >&2 exit 1fiZapisz go jako .git/hooks/pre-commit i nadaj prawo wykonywania: chmod +x .git/hooks/pre-commit. Git po cichu pomija hook bez tego prawa, więc skopiowany plik bez niego to bramka, która nigdy się nie uruchamia.
W skrypt wbudowane są dwie decyzje projektowe. Hook przepuszcza commit, gdy Claude nie może się uruchomić (brak sieci, limit zapytań), bo bramka blokująca każdy commit przy błędzie sieci zostanie usunięta w ciągu dnia; zabezpieczeniem jest przegląd w CI. A model to druga linia obrony przed sekretami, nie pierwsza: przed wywołaniem Claude hook uruchamia Gitleaks (open source, około 29,5 tys. gwiazdek na GitHubie we wrześniu 2026), bo dopasowanie wzorców łapie klucz w znanym formacie za każdym razem, a model tylko w większości przypadków. Zainstaluj go przez brew install gitleaks (README podaje też obrazy Dockera i budowanie ze źródeł); gitleaks git --staged skanuje tylko to, co zaraz trafi do commita. Przed wersją 8.19.0 ten sam skan wywoływało się jako gitleaks protect --staged, co nadal działa, ale nie jest widoczne w --help.
Pilnuj, żeby hook był szybki. Kontrola pre-commit trwająca minutę uczy ludzi wpisywać --no-verify. Jeśli twoje diffy są duże, przenieś ją do pre-push.
Zaplanuj cykliczne zadania w cronie
Dział zatytułowany „Zaplanuj cykliczne zadania w cronie”Używaj crona, gdy zadanie potrzebuje twojej sieci, twoich poświadczeń albo odstępu krótszego niż godzina; używaj routines, gdy ma działać przy zamkniętym laptopie. Zadanie cron, które edytuje kod, trzyma się czterech zasad: własny checkout, jednorazowa gałąź, flagi z minimalnymi uprawnieniami i raport, który czyta człowiek.
#!/usr/bin/env bash# crontab: 7 6 * * 1 /opt/jobs/dep-audit.sh >> /var/log/dep-audit.log 2>&1set -euo pipefail
export PATH="$HOME/.local/bin:/usr/local/bin:/usr/bin:/bin" # PATH crona nie zawiera natywnej instalacjisource "$HOME/.config/claude-cron.env" # eksportuje CLAUDE_CODE_OAUTH_TOKENcd /srv/checkouts/billing-api # checkout, w którym nie pracuje żaden człowiekgit fetch -q origin && git checkout -q -B chore/dep-audit origin/main
/opt/jobs/claude-job.sh \ "Run npm audit --json and npm outdated --json. For each high or critical advisory, grep our src/ for imports of the affected module and mark it reachable or not, naming the importing file. Write reports/dep-audit.md with one table: package, severity, reachable, fixed version, breaking changes in that version. Do not edit package.json or the lockfile." \ --allowedTools "Bash(npm audit *),Bash(npm outdated *),Edit(./reports/**)" \ > /dev/null || { echo "dep-audit failed $(date -Is)" >&2; exit 1; }
git add reports/dep-audit.mdgit commit -q -m "chore: weekly dependency audit $(date +%F)" || exit 0 # nic się nie zmieniłogit push -q -f origin chore/dep-auditgh pr create --fill --head chore/dep-audit 2> /dev/null || true # w kolejnych tygodniach PR już istniejeNajpierw psuje się uwierzytelnianie. Cron nie ma przeglądarki ani sesji w pęku kluczy, więc wygeneruj roczny token poleceniem claude setup-token i eksportuj go jako CLAUDE_CODE_OAUTH_TOKEN z pliku, który może czytać tylko użytkownik zadania, albo użyj ANTHROPIC_API_KEY, jeśli zadanie ma być rozliczane przez API. Ostatnia linia za pierwszym razem otwiera pull request; w kolejnych tygodniach gh pr create zwraca błąd, bo PR jest już otwarty, a force-push go zaktualizował. Minuta to 7, a nie 0: zadania zaplanowane na pełną godzinę tłoczą się ze wszystkimi innymi.
Przekaż komunikat o błędzie do systemu alertów, który powiadamia zespół. Zadanie z harmonogramu, którego błędy lądują tylko w pliku logu, to zadanie, o którego zatrzymaniu nikt nie wie.
Masowe zmiany uruchamiaj w pętli, nie jednym wielkim promptem
Dział zatytułowany „Masowe zmiany uruchamiaj w pętli, nie jednym wielkim promptem”Jeden prompt „zmigruj każdy plik” daje jeden ogromny diff i żadnej możliwości ustalenia, który plik zepsuł build. Pętla w powłoce daje każdemu plikowi osobny przebieg, osobną bramkę testów i osobny commit:
for f in $(git grep -l "from 'moment'" -- ':(glob)src/**/*.ts'); do scripts/claude-job.sh "Migrate $f from moment to date-fns. Convert format tokens (YYYY-MM-DD becomes yyyy-MM-dd). Change only this file." \ --allowedTools "Edit(./$f)" > /dev/null \ && [ "$(git diff --name-only)" = "$f" ] \ && npx vitest related "$f" --run \ && git add -- "$f" && git commit -qm "refactor: $f moment -> date-fns" \ || { echo "FAILED: $f" >> migration-failures.txt; git checkout -- . && git clean -fdq src/; }doneUprawnienie do edycji obejmuje tylko bieżący plik, a sprawdzenie git diff --name-only oblewa iterację, jeśli zmienił się jakikolwiek inny śledzony plik, więc „zmień tylko ten plik” jest egzekwowane, a nie tylko zapisane w prompcie. Testy uruchamia pętla, już po zakończeniu Claude, więc przebieg, który je pominie albo przekłamie ich wynik, nie wyprodukuje commita. Prefiks :(glob) sprawia, że ** pasuje też do plików leżących bezpośrednio w src/, a git clean usuwa nowe pliki pozostawione przez nieudany przebieg.
Przy zmianach obejmujących dziesiątki niezależnych jednostek w jednej sesji wbudowany skill /batch dzieli pracę na 5 do 30 jednostek, każdą we własnym worktree; zobacz operacje wsadowe. Pętla powyżej sprawdza się wtedy, gdy chcesz jednego commita na plik i listy plików, które się nie udały.
Jak sprawdzić, co zrobił przebieg bez nadzoru?
Dział zatytułowany „Jak sprawdzić, co zrobił przebieg bez nadzoru?”Nikt nie czyta każdej linii diffu z nocnego zadania i nikt nie powinien musieć. Zamiast tego sprawdzaj dowody, w tej kolejności:
- Przebieg się udał. Kod wyjścia wrappera,
subtyperównesuccess,is_errorrównefalsei pusta listapermission_denials. Przebieg z odmowami mógł „udać się” w mniejszym zadaniu niż to, o które prosiłeś. - Kontrole uruchomił skrypt, nie model. Zadanie kończy się poleceniem
npm testalbonpx tsc --noEmit, które wykonuje twój skrypt po zakończeniu Claude. Podsumowanie modelu „wszystkie testy przechodzą” nie jest wynikiem testów. - Zmiana nie wyszła poza granice.
git diff --stat origin/main...HEADpokazuje tylko ścieżki dozwolone na liście uprawnień, a liczba plików mieści się w oczekiwanym zakresie. Uznaj zadanie za nieudane (kod niezerowy), jeśli zmienił się lockfile, choć prompt tego zabraniał. - Wynik strukturalny jest zwalidowany. Gdy skrypt korzysta z odpowiedzi Claude, czyta
structured_outputwygenerowane z--json-schema, nigdy wolny tekst. - Drugi agent przejrzał diff. Przy zmianach w kodzie uruchom na gałęzi
/code-review(alboclaude ultrareviewz powłoki, żeby dostać wieloagentowy przegląd w chmurze; po 3 darmowych przebiegach na Pro i Max każdy kolejny jest płatny, a organizacje z Zero Data Retention nie mają do niego dostępu, podobnie jak użytkownicy Amazon Bedrock, Google Cloud i Microsoft Foundry), zanim spojrzy człowiek. - Koszt jest logowany.
total_cost_usdz każdego przebiegu trafia do logu; zadanie, którego koszt podwaja się z tygodnia na tydzień, robi coś nowego.
Człowiek zatwierdza zmianę, scalając PR. Zadania z harmonogramu wypychają gałęzie i otwierają pull requesty; nie wypychają na main. Pełny pakiet, który powinien dostać recenzent, opisuje pakiet dowodów (evidence bundle).
Kiedy skrypty z Claude Code zawodzą
Dział zatytułowany „Kiedy skrypty z Claude Code zawodzą”Zadanie „kończy się sukcesem” i niczego nie zmienia. Każdy zapis został odrzucony: -p startuje w trybie Manual, a reguły permissions.allow projektu nie działają w niezaufanym checkoucie. Naprawa: wypisz permission_denials z wyniku JSON i dodaj dokładne reguły przez --allowedTools w linii poleceń.
Zadanie zatrzymuje się z error_max_turns albo error_max_budget_usd. Limit zadziałał zgodnie z przeznaczeniem. Nie ponawiaj tego samego promptu; zawęź zadanie (jeden katalog, jeden pakiet) albo raz podnieś limit i sprawdź num_turns w wyniku, żeby zobaczyć, ile tur było potrzebne.
Zadanie cron działa ręcznie, a o 06:07 pada. Środowisko crona ma minimalny PATH i żadnej sesji logowania. Naprawa: ustaw PATH jawnie w skrypcie, eksportuj CLAUDE_CODE_OAUTH_TOKEN z claude setup-token i testuj przez env -i HOME="$HOME" /bin/bash /opt/jobs/dep-audit.sh, co odtwarza gołe środowisko crona.
Sklonowane repozytorium uruchamia własne hooki i serwery MCP. W -p okno zaufania się nie pojawia, więc hooki z ustawień repozytorium działają, a serwery z jego .mcp.json się łączą. Naprawa: dla kodu, którego nie napisałeś, uruchamiaj z --bare --setting-sources "" --strict-mcp-config. Tryb bare pomija automatyczne wczytywanie hooków, skilli, pluginów, serwerów MCP i CLAUDE.md; --setting-sources "" nie wczytuje żadnego pliku ustawień, więc nie obowiązują ani ustawienia repozytorium, ani twoje ustawienia użytkownika (z ich blokiem env i regułami allow), a --strict-mcp-config ignoruje jego .mcp.json. Te dwie flagi domykają to, co sam tryb bare zostawia otwarte, i utrzymują zamiar jawnym, jeśli kolejne wydanie zmieni to, co czyta tryb bare. I nigdy nie uruchamiaj takiego zadania z sekretami w środowisku, do których może sięgnąć kod z repozytorium.
--bare kończy się błędem uwierzytelniania. Tryb bare nigdy nie czyta loginu do subskrypcji. Naprawa: wyeksportuj ANTHROPIC_API_KEY albo zrezygnuj z --bare i zaakceptuj, że lokalna konfiguracja się załaduje.
Parser psuje się na nowym sformułowaniu. Wyjście tekstowe różni się między przebiegami. Naprawa: przejdź na --output-format json z --json-schema i czytaj structured_output.
Pętla ponowień kończy się przy pierwszym błędzie. Przy set -e zwykłe result=$(claude -p …), które się nie powiedzie, kończy skrypt, zanim dojdzie do logiki ponowień. Naprawa: sprawdzaj polecenie wewnątrz &&, || albo if, tak jak robi to wrapper powyżej.
/release uruchamia coś innego. Skill i plik polecenia o tej samej nazwie rozwiązują się do skilla, a osobisty skill w ~/.claude/skills/ wygrywa ze skillem projektu o tej samej nazwie, więc na twoim laptopie skrypt może uruchomić inny plik niż na maszynie z cronem. Naprawa: nadawaj skillom automatyzacji konkretne nazwy, na przykład /release-prep, i wpisz / w sesji, żeby zobaczyć, do czego rozwiązuje się dana nazwa.
Zadanie zostaje zabite i zostawia połowę zmiany. SIGTERM kończy proces kodem 143 i nie zapisuje wyniku. Naprawa: wysyłaj SIGINT, żeby tura mogła się zakończyć, i zawsze uruchamiaj zadania na gałęzi, żeby git checkout -- . było bezpiecznym resetem.