Lekcja 6 · Kto wygrywa, gdy dwa pliki się kłócą

Ustawienia i uprawnienia: hierarchia settings.json

W Lekcji 5 poznałeś trzy miejsca, gdzie mieszkają hooki. To był uproszczony obraz — pełna hierarchia settings.json ma pięć warstw, a permission rules (allow/deny/ask) rządzą się inną logiką niż zwykłe nadpisywanie. Zrozumienie tego jest warunkiem, żeby bezpiecznie wrzucić konfigurację do repo zespołowego, zamiast zgadywać.

Polecane źródło Configure permissions — Claude Code Docs — pełna specyfikacja reguł, kolejności ewaluacji i trybów. Uzupełniająco: Claude Code settings dla lokalizacji plików.

Pięć warstw, nie trzy

WarstwaLokalizacjaKto ustawia
1. Managedrejestr/plik zarządzany przez adminafirma — nie da się nadpisać
2. CLI argumentsflagi przy starcie claudeTy, tymczasowo na tę sesję
3. Local.claude/settings.local.jsonTy, w tym projekcie, gitignored
4. Project.claude/settings.jsonzespół, przez git
5. User~/.claude/settings.jsonTy, wszystkie projekty

Wyższa warstwa wygrywa przy tym samym kluczu — z jednym ważnym wyjątkiem: permission rules się nie nadpisują, tylko łączą ze wszystkich warstw naraz.

Kluczowy wniosek: reguły uprawnień są oceniane w stałej kolejności deny → ask → allow, niezależnie z której warstwy pochodzą i jak bardzo są szczegółowe. Szeroka reguła deny blokuje każde pasujące wywołanie — nawet takie, które pasuje też do węższej reguły allow. Deny nie da się "przedziurawić" wyjątkiem w allow.

Składnia reguł

RegułaZnaczenie
Bashdopasowuje każdą komendę Bash
Bash(npm run build)dopasowuje dokładnie tę komendę
Bash(npm run *)dopasowuje każdą komendę zaczynającą się od npm run
Read(.env)dopasowuje odczyt pliku .env na dowolnej głębokości (semantyka gitignore)
WebFetch(domain:example.com)dopasowuje żądania do tej domeny

Przykład z dokumentacji: deny: ["Bash(git push *)"] razem z allow: ["Bash(git * main)"] nadal blokuje git push origin main — deny wygrywa mimo że allow też pasuje.

Gdzie wpisać co

Chcesz...Plik
Zablokować niebezpieczną komendę dla całego zespołu.claude/settings.json (project) — trafia do gita
Dodać własny skrót tylko dla siebie, w tym projekcie.claude/settings.local.json — gitignored
Ustawić coś dla siebie we wszystkich projektach~/.claude/settings.json (user)

Zadanie praktyczne — reguła zespołowa vs osobisty skrót

Ten projekt ma już plik .claude/settings.json z Twoim hookiem z Lekcji 5. Dopisz do niego (obok istniejącego klucza hooks, nie zamiast) regułę bezpieczeństwa, którą mógłby przejąć cały zespół:

{
  "hooks": { /* ...zostaje bez zmian... */ },
  "permissions": {
    "deny": ["Bash(rm -rf *)"]
  }
}

Następnie w swoim osobistym ~/.claude/settings.json dodaj skrót, który ma działać tylko u Ciebie:

{
  "permissions": {
    "allow": ["Bash(git status)"]
  }
}
  1. Wpisz /permissions w Claude Code.
  2. Znajdź obie reguły na liście i sprawdź, czy UI pokazuje, z którego pliku settings.json pochodzi każda z nich.
  3. Zastanów się: gdyby ktoś w zespole dodał allow: ["Bash(rm -rf /tmp/*)"] do swojego settings.local.json, czy przebiłby Twój zespołowy deny? (Odpowiedź jest w quizie niżej.)

Sprawdź się

1. Która warstwa settings.json wygrywa, gdy ten sam klucz (np. model) jest ustawiony i w project, i w user settings?

Kolejność priorytetu to managed > CLI args > local > project > user. Project stoi wyżej niż user, więc dla zwykłych (nie-permission) kluczy project nadpisuje user.

2. Masz deny: ["Bash(aws *)"] w project settings i allow: ["Bash(aws s3 ls)"] w swoim user settings. Co się stanie przy próbie aws s3 ls?

Reguły są oceniane w kolejności deny → ask → allow, niezależnie od warstwy i szczegółowości. Szeroki deny blokuje każde pasujące wywołanie, nawet gdy węższy allow też pasuje.

3. Chcesz dodać osobisty skrót klawiszowy do komend, którego nie chcesz commitować do repo zespołowego. Gdzie go wpiszesz?

settings.local.json jest gitignored z założenia — to miejsce na osobiste ustawienia specyficzne dla tego projektu, których nie chcesz narzucać zespołowi.

4. Reguła Bash bez nawiasu w deny robi coś innego niż Bash(rm *). Co dokładnie?

Goły identyfikator narzędzia w deny usuwa je z kontekstu — Claude w ogóle go nie widzi. Reguła ze specyfikatorem, jak Bash(rm *), zostawia narzędzie dostępne i blokuje tylko wywołania pasujące do wzorca.

5. Który plik NIE powinien trafić do .gitignore w projekcie zespołowym?

.claude/settings.json to wersja projektowa, którą celowo commitujesz, żeby cały zespół dostał te same hooki i reguły uprawnień. Local i CLAUDE.local.md są osobiste i powinny być gitignored.
Coś niejasne? Zapytaj mnie wprost — mogę pomóc dobrać konkretne reguły allow/deny/ask pod ryzyka w Twoim prawdziwym projekcie firmowym.
← Lekcja 5: Hooki Następna lekcja: .claude/rules/ — instrukcje przypięte do ścieżek w monorepo →