Operacje wsadowe: jedna zmiana w setkach plików
Operacje wsadowe w Claude Code wprowadzają jedną zmianę, na przykład migrację biblioteki, zmianę nazwy albo usunięcie wersji API, w dziesiątkach lub setkach plików. Wbudowany skill /batch planuje zmianę, dzieli ją na 5–30 niezależnych jednostek i uruchamia każdą w osobnym worktree Gita jako agenta w tle, który otwiera pull request.
Ta strona jest dla programistów, którzy odpowiadają za szeroką zmianę, i dla tech leadów, którzy muszą potem scalić jej wynik. Sytuacja: zespół przechodzi z moment.js na date-fns, moment importuje 147 plików, a każdy korzysta z innego wycinka API. „Znajdź i zamień” nie zadziała, bo moment().format('YYYY-MM-DD') zamienia się w format(new Date(), 'yyyy-MM-dd'), a nikt nie chce czytać 147 diffów linijka po linijce.
Wszystko poniżej sprawdzono 2026-09-26 na Claude Code v2.1.283 (kanał latest).
Co daje dobrze ustawiona operacja wsadowa
Dział zatytułowany „Co daje dobrze ustawiona operacja wsadowa”- Tabelę decyzyjną: jedna sesja,
/batch, skryptclaude -pczy dynamiczny workflow, zanim wydasz pierwsze tokeny. - Prompt, w którym Claude pisze codemod do przejrzenia w 30 liniach zamiast 300 zmienionych plików.
- Prompt „najpierw plan”, który zwraca tabelę migracji plik po pliku do zatwierdzenia, zanim cokolwiek się zmieni.
- Prompt
/batch, który wnosi własną procedurę weryfikacji do każdego wykonawcy. - Pętlę headless z limitem wydatków, wąską listą dozwolonych narzędzi i testami, których agent nie może edytować.
- Skrypt weryfikacyjny, który dowodzi zakresu, kompletności i zachowania bez czytania każdego diffu.
- Sposoby wyjścia z konfliktów między jednostkami, osłabionych testów, zatrzymań na budżecie i przebiegów bez pull requesta.
Które podejście wsadowe pasuje do zmiany?
Dział zatytułowany „Które podejście wsadowe pasuje do zmiany?”Wybieraj według tego, jak niezależne są części zmiany, a nie tylko według liczby plików.
| Podejście | Kiedy go użyć | Co dostajesz | Gdzie działa weryfikacja |
|---|---|---|---|
| Jedna sesja: plan, potem wykonanie | Mniej niż około 20 plików albo edycje, które muszą wejść w kolejności zależności | Jedną gałąź, przeglądaną partia po partii | Testy, które Claude uruchamia po każdej partii |
/batch | Zmiana dzieli się na niezależne jednostki, każdą do scalenia osobno | 5–30 pull requestów, po jednym na jednostkę | W każdym wykonawcy, potem w CI na każdym PR |
Pętla claude -p | Powtarzasz tę samą zmianę per katalog, pakiet lub repozytorium albo uruchamiasz ją z CI | Wyniki JSON z każdego przebiegu i commity, które robisz sam | W twoim skrypcie, poza agentem |
| Dynamiczny workflow | Audyty lub zmiany wymagające dziesiątek do setek agentów i skryptu do ponownego uruchomienia | Zapisany workflow i jego raport | W fazie weryfikacji samego workflow |
| Codemod napisany przez agenta | Przekształcenie jest czysto składniowe (ścieżka importu, nowa nazwa symbolu) | Deterministyczny skrypt do ponownego uruchomienia | W próbnym przebiegu codemodu i w twoich testach |
Ostatni wiersz zespoły najczęściej pomijają. Gdy każde miejsce wywołania zmienia się tak samo, poproś Claude o regułę ast-grep albo transformację jscodeshift i przejrzyj 30 linii transformacji zamiast 300 zmienionych plików. Oba narzędzia uruchomisz przez npx bez instalacji w projekcie: npx -p @ast-grep/cli ast-grep oraz npx jscodeshift, który ma flagę --dry. Pakiet ast-grep dostarcza pliki wykonywalne o nazwach ast-grep i sg, więc samo npx @ast-grep/cli kończy się błędem „could not determine executable to run” (sprawdzone 2026-09-26 na @ast-grep/cli 0.45.3 i jscodeshift 17.4.0). Edycje agenta zostaw dla miejsc, których codemod nie wyrazi.
Zaplanuj zmianę, zanim agent dotknie pierwszego pliku
Dział zatytułowany „Zaplanuj zmianę, zanim agent dotknie pierwszego pliku”Każde podejście zaczyna się tak samo: od pełnej inwentaryzacji, którą zatwierdzasz. Uruchom sesję w trybie planowania (/plan albo Shift+Tab, aż wskaźnik trybu pokaże plan), żeby Claude mógł czytać i szukać, ale nie edytować.
-
Zinwentaryzuj każde miejsce wywołania. Wklej poniższy prompt. Claude przeszukuje kod i zwraca jeden wiersz na plik.
-
Czytaj oznaczone wiersze, nie wszystkie. Wiersze oznaczone jako NO DIRECT EQUIVALENT (brak bezpośredniego odpowiednika) to miejsca, w których migracja może zmienić zachowanie. Każde rozstrzygnij sam: zostaw shim, przepisz ręcznie albo zaakceptuj zmianę zachowania i ją zapisz.
-
Najpierw wprowadź wspólne warunki wstępne. Dodaj
date-fnsdopackage.json, utwórz wspólne helpery, na przykładsrc/lib/dates.ts, i scal to jako osobny, mały pull request. Bez tego każda jednostka doda zależność osobno, a pull requesty wejdą w konflikt na lockfile. -
Utrwal obecne zachowanie w testach. Tam, gdzie pokrycie jest słabe, dodaj testy charakteryzacyjne, które zapisują dzisiejszy wynik, zanim ruszy jakakolwiek jednostka. Te testy są wyrocznią dla całej migracji.
-
Wybierz sposób wykonania z tabeli powyżej i przekaż zatwierdzoną tabelę jako plan.
Jak przeprowadzić dużą zmianę przez /batch?
Dział zatytułowany „Jak przeprowadzić dużą zmianę przez /batch?”/batch to wbudowany skill, który możesz uruchomić tylko ty: Claude nie wywołuje go sam (sprawdzone w v2.1.283). Wpisz /batch i po nim polecenie. Skill działa w trzech fazach.
- Rozpoznanie i plan, w trybie planowania. Subagenci badawczy znajdują każdy plik i każde miejsce wywołania. Claude dzieli pracę na 5–30 samodzielnych jednostek, najchętniej po jednej na katalog lub moduł, i pisze procedurę testu end-to-end, którą każdy wykonawca uruchomi sam. Jeśli jej nie znajdzie, pyta cię, jak zweryfikować zmianę. Zatwierdzasz plan, zanim cokolwiek ruszy.
- Uruchomienie wykonawców. Jeden agent w tle na jednostkę, każdy w odizolowanym worktree Gita. Każdy wykonawca wdraża swoją jednostkę, uruchamia skill
/code-reviewi poprawia znalezione błędy, uruchamia testy i procedurę end-to-end, po czym robi commit, push i otwiera pull request przezgh pr create. - Śledzenie postępu. Claude prowadzi tabelę statusów ze stanem każdej jednostki i linkiem do jej pull requesta, a na koniec podaje jednolinijkowe podsumowanie: ile jednostek trafiło do pull requestów.
Przed uruchomieniem sprawdź trzy warunki. Katalog musi być repozytorium Gita (tryb worktree bez niego nie działa, chyba że skonfigurujesz hooki WorktreeCreate). GitHub CLI musi być zainstalowane i zalogowane z prawem do push; bez tego wykonawcy kończą pracę, ale nie otwierają pull requesta. Polecenie testów musi być łatwe do znalezienia, najlepiej zapisane w CLAUDE.md, bo szuka go każdy wykonawca.
Najważniejsza jest ostatnia reguła. Wbudowane instrukcje wykonawcy każą mu naprawiać oblewane testy (sprawdzone w v2.1.283), więc bez tej linii wykonawca może przepisać oczekiwany wynik. Wykonawca, który może edytować oblewany test, prędzej czy później „naprawi” go właśnie w ten sposób. Prompt tego zabrania, a skrypt weryfikacyjny poniżej to wykrywa. Jeśli chcesz twardej blokady, dodaj do .claude/settings.json regułę Edit typu deny dla plików testów, tak jak opisuje ochrona wyroczni.
Dla tech leada /batch zamienia jedną zmianę w nawet 30 pull requestów naraz. Przed uruchomieniem ustalcie, kto je scala i w jakiej kolejności, i upewnij się, że CI uruchamia pełny zestaw testów na każdym z nich. Jak rozłożyć to obciążenie, opisuje przewodnik po kolejce review.
Skrypty do powtarzalnych partii z claude -p
Dział zatytułowany „Skrypty do powtarzalnych partii z claude -p”Pętla w trybie print pasuje wtedy, gdy powtarzasz tę samą zmianę w wielu pakietach lub repozytoriach albo gdy musi działać w CI. Rozstrzygające sprawdzenia uruchamia skrypt, nie agent, i skrypt zatrzymuje się na pierwszym błędzie.
#!/usr/bin/env bash# migrate-moment.sh: run in the terminal from the repo root, on a fresh branchset -euo pipefailresults=$(mktemp -d) # keep run logs out of the repo, or git add would commit them
for dir in src/utils src/components src/api src/services; do out="$results/$(echo "$dir" | tr / _).json"
claude -p "Migrate every moment import in $dir/ to date-fns, following the \approved plan in docs/migration/moment-to-date-fns.md. Touch only files under $dir/. \When done, run npx tsc --noEmit and npx jest $dir --ci and report the results." \ --permission-mode acceptEdits \ --allowedTools "Bash(npx tsc *)" "Bash(npx jest *)" \ --disallowedTools "Edit(**/*.test.ts)" \ --permission-prompts none \ --max-budget-usd 5 \ --output-format json > "$out" || true
status=$(jq -r '.subtype // "missing"' "$out") if [ "$status" != "success" ]; then echo "Stopped at $dir: $status"; exit 1 fi
# The script, not the agent, decides whether the batch is good. if git status --porcelain | grep -Ev " $dir/"; then echo "Changes outside $dir"; exit 1 fi if git status --porcelain -- "$dir" | grep -E '\.test\.ts$|__snapshots__/'; then echo "Test files changed in $dir"; exit 1 fi npx tsc --noEmit npx jest "$dir" --ci git add -- "$dir" && git commit -m "refactor($dir): migrate moment to date-fns"doneecho "Run logs: $results"Co robi każda flaga według claude --help w v2.1.283:
--permission-mode acceptEditspozwala Claude edytować pliki bez pytania. Tryb print nie startuje w trybie auto, więc bez tej flagi każda edycja czekałaby na zgodę, której nikt nie udzieli.--allowedToolsz góry zatwierdza tylko sprawdzanie typów i uruchamianie testów.--disallowedTools "Edit(**/*.test.ts)"trzyma wyrocznię poza zasięgiem agenta.--permission-prompts noneodrzuca wszystko, co w innym razie wymagałoby zgody, zamiast czekać.--max-budget-usd 5zatrzymuje przebieg, który wymknął się spod kontroli. Wynik JSON ma wtedy podtyperror_max_budget_usdzamiastsuccess, co wyłapuje sprawdzeniejq.
Reguła deny obejmuje narzędzia Claude do edycji plików, a nie każdy sposób, w jaki proces może zapisać plik. Dlatego skrypt sam sprawdza drzewo robocze: każda zmiana poza $dir albo w teście lub snapshocie zatrzymuje pętlę przed commitem.
Typowe operacje wsadowe i prompty do nich
Dział zatytułowany „Typowe operacje wsadowe i prompty do nich”Ten sam wzorzec obsługuje większość szerokich zmian. Zmienia się tylko sprawdzenie kompletności, czyli polecenie, które dowodzi, że niczego nie pominięto:
| Zmiana | Sprawdzenie kompletności |
|---|---|
| Migracja biblioteki | git grep starego importu nic nie zwraca |
| Zmiana nazwy klasy lub modułu | git grep -w OldName nic nie zwraca, a npx tsc --noEmit przechodzi |
| Przeniesienie katalogu | Każdy import się rozwiązuje (npx tsc --noEmit), a starej ścieżki nie ma w żadnym pliku konfiguracyjnym |
| Usunięcie wersji API | Każda usunięta trasa miała następcę, a żądania do starych tras kończą się błędem w testach integracyjnych |
| Dodanie szablonu do każdego handlera | Reguła lintera albo git grep -L nie wskazuje żadnego handlera bez niego |
Jak zweryfikować zmianę wsadową bez czytania każdego diffu?
Dział zatytułowany „Jak zweryfikować zmianę wsadową bez czytania każdego diffu?”Przy 150 plikach przegląd linijka po linijce przestaje być uczciwy. Zastąp czytanie sprawdzeniami, które kończą się wyraźnym błędem, i czytaj tylko tam, gdzie one wskażą.
- Zakres: każdy zmieniony plik leży w katalogach wskazanych w planie.
- Kompletność: stary wzorzec nie występuje nigdzie.
- Nienaruszona wyrocznia: żaden plik testów nie zmienił się w tej samej jednostce, co kod.
- Zachowanie: sprawdzanie typów, testy jednostkowe i testy charakteryzacyjne przechodzą, a CI uruchamia pełny zestaw na każdym pull requeście.
- Czytanie celowane: czytasz tylko miejsca oznaczone jako NO DIRECT EQUIVALENT i pliki wskazane przez sprawdzenia.
Uruchom ten skrypt na gałęzi każdej jednostki, lokalnie albo jako zadanie CI, z katalogami jednostki jako argumentami (./verify-batch.sh src/utils albo ./verify-batch.sh src/utils src/reports dla jednostki obejmującej dwa katalogi):
#!/usr/bin/env bash# verify-batch.sh DIR [DIR...]: run from the repo root on the unit's branchset -euo pipefail[ $# -gt 0 ] || { echo "usage: verify-batch.sh src/utils [src/other ...]"; exit 2; }UNIT_DIRS=("$@")BASE=${BASE:-origin/main}changed=$(git diff --name-only "$BASE"...HEAD)
# 1. Scope: nothing outside this unit's directories changedpattern="^($(IFS='|'; echo "${UNIT_DIRS[*]}"))/"outside=$(echo "$changed" | grep -vE "$pattern" || true)[ -z "$outside" ] || { echo "Out of scope:"; echo "$outside"; exit 1; }
# 2. Completeness: no moment import is left in this unitif git grep -nE "from ['\"]moment['\"]|require\(['\"]moment['\"]\)" -- "${UNIT_DIRS[@]}"; then echo "moment is still imported in ${UNIT_DIRS[*]}"; exit 1fi
# 3. Oracle intact: no test or snapshot changedif echo "$changed" | grep -E '\.test\.ts$|__snapshots__/'; then echo "Test files changed: review these by hand before merging"; exit 1fi
# 4. Behaviour: the whole suite, not only this unit's testsnpx tsc --noEmitnpx jest --ciSprawdzenie kompletności celowo obejmuje tylko jednostkę. Na gałęzi jednostki pozostałe katalogi nadal importują moment, więc git grep po całym repozytorium oblałby każdą jednostkę. Wersję dla całego repozytorium uruchom raz na main, po scaleniu ostatniej jednostki: pusty wynik git grep -nE "from ['\"]moment['\"]" -- src oznacza, że migracja jest skończona, i dopiero wtedy usuwasz moment z package.json. Jednostki z miejscami NO DIRECT EQUIVALENT mogą obejmować kilka katalogów: przekaż skryptowi każdy katalog, który plan przypisuje tej jednostce, a ich diffy i tak przeczytaj.
Podział odpowiedzialności jest prosty. Programista, który uruchomił partię, zatwierdza tabelę planu i oznaczone wiersze. CI odpowiada za zielone sprawdzenia na każdej jednostce. Recenzent każdego pull requesta czyta oznaczone miejsca wywołań i wynik sprawdzeń, a nie cały diff. Jak wzmocnić sprawdzanie typów i testy jako bramki, opisują strony testowanie z Claude Code i funkcje dopasowania architektury.
Co psuje się w operacji wsadowej i jak z tego wyjść?
Dział zatytułowany „Co psuje się w operacji wsadowej i jak z tego wyjść?”Jednostki wchodzą w konflikt przy scalaniu
Dział zatytułowany „Jednostki wchodzą w konflikt przy scalaniu”Objaw: kilka pierwszych pull requestów z /batch się scala, a reszta ma konflikty na pliku barrel, konfiguracji routera albo lockfile. Przyczyna: jednostki nie były niezależne, bo wspólny plik należał do kilku z nich. Wyjście: zamknij konfliktowe pull requesty, przenieś wspólny plik do osobnego, pierwszego pull requesta, scal go i uruchom /batch ponownie z zaktualizowanej gałęzi main dla pozostałych katalogów. Zapobiega temu punkt 5 promptu inwentaryzacyjnego.
Wykonawca kończy pracę, ale nie otwiera pull requesta
Dział zatytułowany „Wykonawca kończy pracę, ale nie otwiera pull requesta”Objaw: tabela statusów pokazuje jednostkę jako gotową bez linku, a wynik wykonawcy brzmi PR: none z podaniem przyczyny. Przyczyna: zwykle brak GitHub CLI, brak logowania albo odrzucony push. Wyjście: napraw gh auth status, wypchnij gałąź z worktree wykonawcy i otwórz pull request ręcznie. Kod jest tam już zacommitowany.
Testy przechodzą, bo agent je zmienił
Dział zatytułowany „Testy przechodzą, bo agent je zmienił”Objaw: zielona jednostka, której diff dotyka plików *.test.ts albo snapshotów. Przyczyna: wykonawca trafił na oblany test i „poprawił” oczekiwanie. Wyjście: cofnij zmiany w testach, uruchom je ponownie i każde niepowodzenie traktuj jako prawdziwą różnicę w zachowaniu do rozstrzygnięcia. Zapobiegają temu reguła deny dla Edit i sprawdzenie 3 w skrypcie weryfikacyjnym.
Edycje wychodzą poza zaplanowany zakres
Dział zatytułowany „Edycje wychodzą poza zaplanowany zakres”Objaw: sprawdzenie zakresu wymienia pliki w src/core/ albo w konfiguracji. Przyczyna: agent szedł za błędem typów coraz dalej. Wyjście: cofnij te pliki, a zależność dodaj do planu jako osobną jednostkę albo warunek wstępny. Edycje poza zakresem zwykle znaczą, że plan przeoczył wspólny plik.
Kontekst zapełnia się w trakcie długiej sesji
Dział zatytułowany „Kontekst zapełnia się w trakcie długiej sesji”Objaw: w długiej sesji obejmującej dziesiątki plików odpowiedzi stają się mgliste, a wcześniejsze decyzje giną. Wyjście: zacommituj to, co przechodzi, wykonaj /clear i zacznij od tabeli planu z ukończonymi katalogami oznaczonymi jako gotowe. Powyżej około 20 plików przejdź na /batch albo własnych subagentów, z których każdy ma własne okno kontekstu.
Przebieg headless zatrzymuje się na budżecie
Dział zatytułowany „Przebieg headless zatrzymuje się na budżecie”Objaw: pętla kończy się z error_max_budget_usd. Przyczyna: katalog był większy lub trudniejszy od pozostałych. Wyjście: podziel ten katalog na liście w pętli i uruchom ją od niego; katalogi już zacommitowane pozostają gotowe. Jak śledzić koszt przebiegów, opisuje kontrola kosztów.
Claude naprawia jeden plik i psuje inny
Dział zatytułowany „Claude naprawia jeden plik i psuje inny”Objaw: te same dwa lub trzy pliki na zmianę oblewają i przechodzą. Przyczyna: kolejność zależności, którą plan pominął. Wyjście: zatrzymaj przebieg, poproś w trybie planowania o kolejność zależności i wykonaj te pliki jako jedną sekwencyjną partię, zanim rozdzielisz resztę.
Dokąd dalej po operacjach wsadowych
Dział zatytułowany „Dokąd dalej po operacjach wsadowych”- Przepływy wieloplikowe obejmują skoordynowane zmiany, w których pliki zależą od siebie, czyli przypadek, do którego
/batchnie służy. - Migracje baz danych i kodu stosują to samo podejście „najpierw plan” do schematów i aktualizacji frameworków.
- Dynamiczne workflow przejmują zadania, które wymagają dziesiątek do setek agentów i skryptu uruchamianego ponownie.
- Agent view pokazuje agentów w tle na jednym ekranie, gdy działa
/batch. - Automatyzacja review stawia automatycznego recenzenta przy pull requeście każdej jednostki.
- Zmiany masowe w Codex to siostrzana strona o zadaniach w chmurze i worktree w Codex.