Lekcja 6 · Kto wygrywa, gdy dwa pliki się kłócą
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ć.
| Warstwa | Lokalizacja | Kto ustawia |
|---|---|---|
| 1. Managed | rejestr/plik zarządzany przez admina | firma — nie da się nadpisać |
| 2. CLI arguments | flagi przy starcie claude | Ty, tymczasowo na tę sesję |
| 3. Local | .claude/settings.local.json | Ty, w tym projekcie, gitignored |
| 4. Project | .claude/settings.json | zespół, przez git |
| 5. User | ~/.claude/settings.json | Ty, 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.
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.
| Reguła | Znaczenie |
|---|---|
Bash | dopasowuje 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.
| 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) |
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)"]
}
}
/permissions w Claude Code.allow: ["Bash(rm -rf /tmp/*)"] do swojego settings.local.json, czy przebiłby Twój zespołowy deny? (Odpowiedź jest w quizie niżej.)1. Która warstwa settings.json wygrywa, gdy ten sam klucz (np. model) jest ustawiony i w project, i w user settings?
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?
3. Chcesz dodać osobisty skrót klawiszowy do komend, którego nie chcesz commitować do repo zespołowego. Gdzie go wpiszesz?
4. Reguła Bash bez nawiasu w deny robi coś innego niż Bash(rm *). Co dokładnie?
5. Który plik NIE powinien trafić do .gitignore w projekcie zespołowym?