Claude Code Skills vs Rules — agent kontra reguła

Budując tę stronę przez dwa dni z Claude Code — i przenosząc ją na własną domenę po drodze — trafiłem na konkretne rozdroże. Chcę, żeby agent zawsze trzymał się konwencji mojej taksonomii zdarzeń, kiedy dotyka pliku events.ts — ale jednocześnie żeby pisał wpis na bloga tylko wtedy, gdy o to poproszę. To dwie różne potrzeby, które w Claude Code obsługują dwa mechanizmy o przeciwnej naturze: jeden probabilistyczny, drugi deterministyczny. I jest to dokładnie ta sama różnica, którą znam z architektury analitycznej.

Claude Code Skills vs Rules: probabilistyczne kontra deterministyczne

Claude Code Skills vs Rules to dwa narzędzia, które łatwo pomylić, bo oba to pliki w .claude/:

  • Skills — probabilistyczne. Trigger jest semantyczny: piszesz „napisz nowy artykuł”, model czyta pole description skilla i sam decyduje, że pasuje do Twojej intencji. Decyduje model — chyba że wywołasz skill jawnie (/nowy-artykul) albo dasz mu w nagłówku disable-model-invocation: true; wtedy odpala go tylko człowiek.
  • Rules (pliki w .claude/rules/) — deterministyczne. Trigger jest techniczny: reguła ma w nagłówku paths z wzorcem glob, a harness ładuje ją automatycznie, gdy czytany plik pasuje do wzorca. Zero interpretacji. Decyduje harness.
SkillsRules
Charakterprobabilistycznydeterministyczny
Triggersemantyczny (intencja)ścieżka pliku (glob)
Decydujemodel (albo Ty przez /nazwa)harness
Podstawapole descriptionpole paths
Do czegoprocedury, zadania intencyjnestałe zasady obszaru kodu

events.ts jako kandydat na Rule

W tym projekcie mam plik, który jest podręcznikowym przykładem na Rule: src/data/events.ts — rejestr zdarzeń dataLayer, jedno źródło prawdy taksonomii. Dodanie nowego eventu to sztywna procedura:

  1. stała w EVENTS (klucz camelCase → wartość snake_case),
  2. wpis w EVENT_CATALOG z metadanymi,
  3. import stałej tam, gdzie pushujesz — pushEvent(EVENTS.x), nigdy goły string.

Plus niezmienniki: EVENT_CATALOG nie wolno importować po stronie klienta (inaczej trafia do bundla), a 4 nazwy cookie_consent_* są mirrorem w <head> i muszą być synchronizowane.

Do wczoraj te zasady żyły jako komentarz w pliku i akapit w CLAUDE.md. Sam CLAUDE.md ładuje się do kontekstu na starcie każdej sesji — to akurat jest pewne. Problem leży w tym, kiedy i obok czego. Akapit o eventach wisi tam od pierwszej wiadomości, między dziesiątkami innych zasad, a gdy agent dotyka events.ts po długiej sesji, jest daleko w historii i przegrywa z bieżącym zadaniem. Dla taksonomii, gdzie jedna literówka w nazwie zdarzenia rozjeżdża raport w GA4, to za mało.

Rozwiązanie: przeniosłem te zasady do .claude/rules/events.md z nagłówkiem:

---
paths:
  - "src/data/events.{ts,js}"
---

Najważniejsze, gdzie ten plik leży w drzewie projektu — a właściwie, że jego położenie nie ma znaczenia:

Personal-Page/
├── .claude/
│   ├── CLAUDE.md          # instrukcje (zawsze w kontekście)
│   ├── rules/
│   │   └── events.md      # paths: events.{ts,js}
│   └── skills/
│       └── nowy-artykul/  # Skill (trigger semantyczny)
└── src/
    └── data/
        └── events.ts      # plik pilnowany przez regułę

Reguła i pilnowany przez nią kod siedzą w zupełnie innych gałęziach drzewa. Jedyne, co je łączy, to wzorzec paths — nie sąsiedztwo folderów, nie żaden podkatalog. Reguły są wykrywane rekurencyjnie w .claude/rules/, więc podfoldery (frontend/, backend/) służą wyłącznie porządkowi: to paths, a nie struktura katalogów, decyduje o wyzwoleniu. Od teraz, ilekroć agent czyta lub edytuje events.ts, harness gwarantuje, że reguły są w kontekście — bez polegania na tym, że model sam je sobie przypomni. Wzorzec dopasowuje ścieżkę, reguła wjeżdża, koniec.

Skill nowy-artykul — druga strona medalu

Dla kontrastu: pisanie tego artykułu odpalił Skill, nie Rule. I słusznie — „napisz wpis na bloga” to intencja, nie ścieżka pliku. Nie ma globa, który by to sensownie wyzwalał (plik artykułu jeszcze nie istnieje, gdy proszę o jego napisanie). Zadanie wielokrokowe, twórcze, zależne od intencji — domena Skilla.

Reguła kciuka:

  • Skill — gdy trigger to intencja („zrób mi X”), a zadanie jest proceduralne/twórcze.
  • Rule — gdy trigger to miejsce w kodzie („gdy ktoś dotyka tego pliku”), a zasady są stałe.

Co to daje przy rozbudowie architektury analitycznej

Tu robi się ciekawie z perspektywy analityka. Architektura analityczna to nie zbiór skryptów — to taksonomia, kontrakty i niezmienniki. Dokładnie ten typ wiedzy, który gnije w głowie seniora i znika, gdy do projektu wchodzi ktoś nowy (albo agent AI). Reguła daje agentowi te niezmienniki we właściwym momencie — podobnie jak semantyczny graf repozytorium daje mu mapę kodu zamiast ślepego skanowania plik po pliku.

Gdy rozbudowuję stronę o nową funkcję — np. formularz z eventem form_submit — Rule pilnuje, że nowy event przejdzie pełną procedurę: stała, katalog, typowany push. Agent nie wrzuci gołego dataLayer.push({event:'form_submit'}) w komponencie, bo reguła jest w kontekście dokładnie w momencie edycji taksonomii. Konwencja, która kiedyś była tylko w mojej głowie, teraz egzekwuje ją maszyna.

To przesunięcie z „dokumentuję architekturę” na „architektura pilnuje się przy każdej zmianie”.

Granica: Rule kontra Hook

Żeby nie obiecać za dużo. Rule gwarantuje obecność wytycznej w odpowiednim momencie — ale model wciąż musi ją wykonać. To deterministyczny trigger, nie deterministyczne wymuszenie. Jeśli potrzebujesz twardej blokady — „nie wpuszczę commita, jeśli event nie ma wpisu w katalogu” — to zadanie dla Hooka (PreToolUse), który wykonuje harness bez udziału modelu. Oś: Skills (model decyduje, czy w ogóle je wczytać) → CLAUDE.md i Rules z paths (harness wczytuje — CLAUDE.md na starcie, Rule przy pliku — a model wykonuje) → Hooks (harness wykonuje, zero modelu). Im bardziej coś musi zadziałać, tym niżej schodzisz.

Skala e-commerce: setki eventów

Na tej stronie mam kilka zdarzeń — Rule jest tu wygodą, nie koniecznością. Ale przełóż to na platformę e-commerce, gdzie tracking plan ma setki eventów (view_item, add_to_cart, begin_checkout, purchase i dziesiątki wariantów), wielu wydawców i kontrakt z GTM, w którym jedna rozjechana nazwa psuje atrybucję i raporty przychodu. Tam deterministyczna reguła na plikach tracking planu przestaje być wygodą, a staje się polisą: każdy, kto dotyka taksonomii — człowiek czy agent — dostaje te same niezmienniki w kontekście, automatycznie.

To dla mnie sedno bycia „analytics architect” przy pracy z agentami AI: nie pisać każdej linijki, tylko zaprojektować zasady tak, żeby narzędzie samo ich pilnowało.

Podsumowanie

Skills i Rules wyglądają podobnie, ale mają przeciwną naturę. Skill to probabilistyczny trigger na intencję — do zadań proceduralnych jak pisanie treści. Rule to deterministyczny trigger na ścieżkę pliku — do pilnowania obszaru kodu o stałych konwencjach, jak taksonomia eventów. Jeśli pracujesz z architekturą analityczną, Rules są naturalnym miejscem, żeby zakodować niezmienniki tam, gdzie agent na pewno je zobaczy. A gdy „na pewno zobaczy” to za mało i trzeba „na pewno wykona” — sięgasz po Hooka.

Powiązane wpisy