O czym to jest
Claude Code pozwala definiować skille, czyli wielokrotnego użytku procedury zapisane w pliku Markdown. Skill może wykonać zadanie na kilka sposobów: samodzielnie w bieżącej rozmowie, delegując pracę do równoległych subagentów, albo zbierając parametry od użytkownika i przekazując całą robotę jednego agentowi z pełną instrukcją wczytaną z pliku. To, jak skill działa, wynika wyłącznie z tego, co jest napisane w jego treści.
Skill to zawsze plik SKILL.md z frontmatterem i treścią. "Agentowość" nie jest osobnym typem pliku ani flagą w nagłówku. Zależy wyłącznie od tego, czy instrukcje w treści każą Claude'owi wykonać pracę samemu, czy uruchomić narzędzie Agent, które spawnuje izolowany subagent.
Zwykły skill
Treść skilla zostaje doklejona do bieżącego promptu Claude'a. Claude czyta instrukcje i wykonuje je samodzielnie, używając swoich narzędzi (Read, Edit, Grep, Bash, itd.). Cała praca dzieje się w tej samej rozmowie, którą prowadzisz, więc każdy tool call widzisz w terminalu.
Przykład: skill bump-version wydający nową wersję projektu. Wielokrokowy, ale lokalny, więc nie ma sensu delegować go do subagenta.
# .claude/skills/bump-version/SKILL.md
---
name: bump-version
description: Bumpuje wersję projektu (patch/minor/major), aktualizuje CHANGELOG, tworzy commit i tag
---
# bump-version
Otrzymujesz typ bumpa: `patch`, `minor` lub `major`. Jeśli argument nie został
podany, zapytaj użytkownika przed wykonaniem czegokolwiek.
## Procedura
Wykonaj kroki **sekwencyjnie**. Jeśli któryś zawiedzie, przerwij i raportuj.
### 1. Sprawdź stan repozytorium
- `git status --porcelain` musi być puste. Jeśli są niezacommitowane zmiany,
przerwij i poproś użytkownika o zacommitowanie lub stash.
- Bieżąca gałąź musi być `main`. Inaczej przerwij.
- `git fetch` i sprawdź, czy lokalny `main` nie jest za remote.
### 2. Wczytaj bieżącą wersję
- Otwórz `package.json` i odczytaj pole `version`.
- Policz nową wersję według semver dla podanego typu bumpa.
- Sprawdź, czy tag `v<nowa-wersja>` nie istnieje już w repo (`git tag -l`).
### 3. Zaktualizuj pliki
- `package.json`: pole `version` na nową wartość.
- `CHANGELOG.md`: nad ostatnim wpisem dodaj nagłówek `## [<nowa-wersja>] - <data ISO>`
oraz pustą sekcję `### Changed` z listą commitów od ostatniego tagu
(`git log <ostatni-tag>..HEAD --oneline`).
- Pokaż użytkownikowi diff CHANGELOG i poproś o akceptację treści przed dalszymi
krokami.
### 4. Commit i tag
- `git add package.json CHANGELOG.md`
- `git commit -m "chore: release v<nowa-wersja>"`
- `git tag -a v<nowa-wersja> -m "Release v<nowa-wersja>"`
- **Nie pushuj.** Wypisz instrukcję dla użytkownika: `git push && git push --tags`.
### 5. Raport końcowy
Wypisz: starą wersję, nową wersję, SHA commita, nazwę taga, listę plików zmienionych.
Wywołanie /bump-version minor powoduje, że Claude w głównym wątku otwiera package.json, edytuje CHANGELOG (widzisz diff), wykonuje git commit, tworzy tag i raportuje. Każdy krok widoczny w rozmowie, każdy plik gotowy do podglądu. Idealny przypadek dla zwykłego skilla: kroków jest sporo, ale każdy z nich tani i wymagający Twojego wglądu.
Skill-agent
Treść skilla też zostaje doklejona do promptu, ale instrukcje każą Claude'owi nie robić pracy samemu, tylko uruchomić narzędzie Agent. To narzędzie startuje oddzielny subagent z czystym kontekstem, który nie widzi historii Twojej rozmowy. Subagent dostaje brief, wykonuje pracę swoimi narzędziami i wraca z jednym komunikatem końcowym. Główna rozmowa widzi tylko ten raport, a nie dziesiątki pośrednich tool calli.
Przykład: skill audit-deps, który dla każdej zależności w package.json sprawdza, czy faktycznie jest używana w kodzie, czy ma znane CVE i czy są nowsze wersje. Dziesiątki subagentów lecą równolegle.
# .claude/skills/audit-deps/SKILL.md
---
name: audit-deps
description: Równoległy audyt zależności projektu — użycie, CVE, nowsze wersje
---
# audit-deps
Audytujesz wszystkie zależności z `package.json` (sekcje `dependencies` i
`devDependencies`). Cała praca poszczególnych audytów leci równolegle przez
subagenty, żeby nie zaśmiecać głównej rozmowy i przyspieszyć całość.
## Procedura
### 1. Zbierz listę zależności
- Otwórz `package.json` (samodzielnie, w głównym wątku) i wczytaj nazwy paczek.
- Jeśli lista jest dłuższa niż 50, zapytaj użytkownika, czy chce ograniczyć
zakres (np. tylko `dependencies`).
### 2. Spawnuj subagenty równolegle
Dla **każdej** paczki uruchom narzędzie `Agent` z poniższym briefem. Wszystkie
wywołania wyślij w **jednym** bloku narzędzi, żeby ruszyły naraz.
Brief subagenta:
"Audyt paczki <nazwa> w wersji <wersja>. Wykonaj:
1. Sprawdź, czy paczka jest faktycznie importowana w kodzie projektu
(`grep -r \"from '<nazwa>'\" src/ lib/`). Jeśli nie — oznacz `UNUSED`.
2. Sprawdź w bazie CVE (WebSearch: `<nazwa> <wersja> CVE`), czy są
aktywne podatności. Wypisz CVE-ID i severity.
3. Sprawdź najnowszą wersję na npm (WebFetch
`https://registry.npmjs.org/<nazwa>/latest`). Porównaj z używaną wersją.
4. Wróć z **jednolinijkowym** raportem: `<nazwa>@<wersja> | <UNUSED/OK> |
<CVE-ID lub —> | <nowsza-wersja lub —>`. Nic więcej."
### 3. Zbierz wyniki
Po powrocie wszystkich subagentów posortuj wyniki:
- najpierw paczki z aktywnym CVE,
- potem `UNUSED`,
- potem te z nowszą wersją major,
- na końcu wszystko inne.
Wygeneruj tabelę w formacie `table_dsl` i krótkie podsumowanie:
ile paczek do usunięcia, ile do aktualizacji, ile z CVE.
### 4. Nie modyfikuj `package.json`
Raportuj — decyzje zostawiasz użytkownikowi.
Wywołanie /audit-deps startuje wielu subagentów naraz. W głównym wątku widzisz tylko zbiór krótkich linijek z raportami, a nie setki tool calli. Każdy subagent ma czysty kontekst, więc rozmowa nie puchnie. To są dwa powody, dla których ten skill ma sens jako agentowy: równoległość i higiena kontekstu.
Hybryda
Skill może łączyć oba podejścia: większość kroków robi w głównym wątku, a wybrane fragmenty deleguje do subagentów. Granicę przesuwa się tam, gdzie zaczyna się szum: jeśli krok generuje dziesiątki tool calli albo wynik nie nadaje się do oglądania w terminalu, idzie do subagenta. Reszta zostaje w głównej rozmowie, żebyś miał wgląd i kontrolę.
Przykład: skill verify-post-lite weryfikuje post bloga przed publikacją. Lokalne sprawdzenia (frontmatter, linki, struktura) robi sam, a kosztowną weryfikację faktów spawnuje równolegle do subagentów z WebSearch.
# .claude/skills/verify-post-lite/SKILL.md
---
name: verify-post-lite
description: Hybrydowa weryfikacja posta — lokalnie struktura, subagenty do faktów
---
# verify-post-lite
Otrzymujesz ścieżkę do pliku `.md` posta. Wykonujesz weryfikację w dwóch
trybach: kroki **lokalne** robisz sam w głównym wątku, krok **faktów**
delegujesz równolegle do subagentów.
## Procedura
### 1. (Lokalnie) Frontmatter
Otwórz post i przeczytaj nagłówek YAML. Sprawdź:
- wymagane pola: `title`, `postId`, `slug`, `date`, `tags`,
- `slug` jest ASCII i zgadza się z nazwą folderu,
- `date` w formacie `YYYY-MM-DD` i nie z przyszłości (chyba że `draft: true`),
- `postId` jest unikalny (`grep -r "postId:" blog_data/`).
Raportuj problemy. Nie idź dalej, jeśli brakuje wymaganych pól.
### 2. (Lokalnie) Linki i pliki
Dla każdego shortcode'a w treści sprawdź istnienie zasobu:
- `@[include_img file="X"]` — czy plik `X` jest w folderze posta,
- `@[include_code file="X"]` — czy plik istnieje,
- `@[include_link post_id="X"]` — czy istnieje post o tym `postId`,
- `@[include_youtube video_id="X"]` — czy `X` ma postać 11-znakowego ID.
Wszystko da się sprawdzić lokalnie, więc rób to w głównym wątku.
### 3. (Lokalnie) Struktura
- Hierarchia nagłówków: `##` jako sekcje, `###` jako podsekcje, nigdy `#`.
- Bloki `:::` są domknięte.
- Code fence'y mają język (`` ```python ``, `` ```bash ``).
- Brak placeholderów `TODO` w treści.
### 4. (Subagenty) Weryfikacja faktów
Z treści wyodrębnij listę **twierdzeń faktycznych**: daty, liczby, nazwy
produktów, wersje, cytaty, twierdzenia techniczne. Jedno twierdzenie =
jedna pozycja na liście.
Dla **każdego** twierdzenia uruchom narzędzie `Agent`. Wszystkie wywołania
wyślij w jednym bloku, żeby leciały równolegle.
Brief subagenta:
"Zweryfikuj twierdzenie: '<dokładny cytat z posta>'.
1. Wyszukaj co najmniej dwa wiarygodne źródła (WebSearch).
2. Oceń: OK / DO SPRAWDZENIA / BŁĄD.
3. Jeśli BŁĄD — podaj prawidłową wartość i URL źródła.
4. Wróć z jedną linią: `<OCENA> | <komentarz, max 20 słów> | <URL lub —>`.
Nic więcej, żadnego rozumowania, żadnych cytatów."
Powód delegacji: każdy fact-check to kilka wyszukań i sporo tekstu w wynikach.
Trzydzieści faktów w głównym wątku zaśmieciłoby kontekst. Subagenty zwracają
po jednej linii.
### 5. (Lokalnie) Agregacja
Zbierz raporty z subagentów oraz problemy z kroków 1–3 i wygeneruj zbiorczy
raport w `table_dsl` plus rekomendację: PUBLIKUJ / POPRAW PRZED PUBLIKACJĄ /
WYMAGA POWAŻNYCH ZMIAN.
Podział obowiązków jest tutaj świadomy. Kroki 1–3 są tanie, lokalne i ich wyniki chcesz widzieć (bo to one wskazują, co poprawić w pliku). Krok 4 jest kosztowny, generuje dużo szumu z WebSearch i da się go zrównoleglić. Krok 5 znów jest lokalny, bo to tylko zlepienie wyników w tabelę.
Skill jako fasada dla długiej instrukcji
Inny powód, żeby sięgnąć po subagenta to długa instrukcja skilla. Gdy procedura rozrasta się do kilkuset linii, ładowanie jej w całości do głównej rozmowy przy każdym wywołaniu jest marnotrawstwem — tokeny idą na przeczytanie dokumentu, który i tak nie wchodzi w skład historii rozmowy.
Lepszy wzorzec: główny skill robi tylko to, co wymaga kontekstu rozmowy, czyli zbiera parametry od użytkownika, waliduje je, uzupełnia brakujące, a potem spawnuje jednego agenta z briefem zawierającym parametry i ścieżkę do pliku z pełną instrukcją. Agent wczytuje plik samodzielnie i wykonuje całą robotę.
Przykład: skill migrate-db, który przeprowadza migrację schematu bazy danych. Instrukcja jest długa (obsługuje kilka silników, rollback, dry-run, punkty kontrolne), więc trzyma się ją w osobnym pliku.
# .claude/skills/migrate-db/SKILL.md
---
name: migrate-db
description: Migracja schematu bazy danych — zbiera parametry i deleguje wykonanie do subagenta
---
# migrate-db
Skill działa w dwóch fazach: zbierasz parametry w głównym wątku, a całą migrację
deleguje do subagenta z instrukcją wczytaną z pliku.
## Faza 1 — zbieranie parametrów (w głównym wątku)
### 1. Wymagane parametry
Sprawdź, czy użytkownik podał:
- `target` — środowisko docelowe (`dev`, `staging`, `prod`)
- `migration` — nazwa pliku migracji lub `all` (niezastosowane migracje po kolei)
Jeśli brakuje któregokolwiek — zapytaj przed wykonaniem czegokolwiek.
### 2. Walidacja wstępna
- `target=prod` wymaga jawnego potwierdzenia: wypisz ostrzeżenie i poczekaj na `yes`.
- Sprawdź, czy plik `migrations/<migration>.sql` istnieje (lub że `migrations/`
nie jest puste gdy `all`). Jeśli nie — przerwij z błędem.
- Odczytaj z `config/db.json` connection string dla podanego `target`. Jeśli
brakuje wpisu — przerwij z błędem.
### 3. Przekaż do subagenta
Uruchom narzędzie `Agent` z briefem:
"Przeprowadź migrację bazy danych według instrukcji w pliku
`.claude/skills/migrate-db/PROCEDURE.md`.
Parametry: target=<target>, migration=<migration>,
connection_string=<connection_string>.
Wykonaj procedurę dokładnie według pliku — nie skracaj kroków."
# .claude/skills/migrate-db/PROCEDURE.md
Pełna procedura migracji — 200+ linii obsługujące backup, dry-run,
punkty kontrolne, rollback, raport końcowy.
(Treść zbyt długa żeby ją tu reprodukować — to właśnie sedno wzorca:
ta instrukcja nie trafia do głównej rozmowy, tylko do subagenta który
wczytuje ją na żądanie.)
Główna rozmowa widzi tylko: zebranie parametrów, potwierdzenie dla prod i końcowy raport subagenta. Kilkaset linii procedury zostaje w pliku i trafia do kontekstu tylko wtedy, gdy faktycznie jest potrzebna — i tylko do subagenta który ją wykonuje.
Co zapamiętać
Skill to plik z instrukcjami. To, czy jest "zwykły", czy "agentowy", zależy wyłącznie od tego, czy instrukcje każą Claude'owi wykonać pracę samemu, czy zdelegować ją przez narzędzie Agent.