Typická hodina práce v režimu Manual. Agent čte projekt, navrhne úpravu, požádá o spuštění testů, pak navrhne další úpravu a znovu testy. U dvacátého dotazu kliknete na "Yes" skoro bez přemýšlení. A někde mezi nimi projde úprava ve složce legacy/, na kterou už dlouho nikdo nesahá a sahat nemá.
Tento článek ukazuje, jak ponechat dotazy jen tam, kde je rozhodnutí opravdu na vás. K tomu má Claude Code pravidla oprávnění: tři seznamy v souboru nastavení, které určují, co agent smí udělat hned, na co se má zeptat a co nesmí dělat vůbec. Podíváme se, proč jsou užitečná, jak je číst a jak uklidit soubor s pravidly, který už nejspíš máte.
Jedno nastavení pro všechno
Režim oprávnění je jediný ovladač pro celou relaci. Můžete jím otočit kterýmkoli směrem, ale vždy pro všechno najednou.
V přísném režimu Manual se agent ptá před každou úpravou a téměř před každým příkazem. Dotaz vás chrání jen do chvíle, kdy ho skutečně čtete. Když je jich moc, lidé je přestanou číst a ochrana zůstane jen na papíře.
Ve volnějším režimu acceptEdits se úpravy provádějí bez dotazu, stejně jako souborové příkazy typu rm a mv. Pro vlastní kód je to pohodlné. Režim ale nerozlišuje složky: úprava v legacy/ projde stejně tiše jako kdekoli jinde v projektu.
Do souboru CLAUDE.md můžete napsat "nesahej na legacy/". Agent se tím bude snažit řídit, ale je to pokyn pro model, ne zákaz. Pravidla oprávnění kontroluje přímo Claude Code před provedením akce a text v CLAUDE.md ani v zadání na ně nemá vliv.
Různé akce tedy mají různou cenu chyby, ale režim s nimi zachází stejně. Testy by měly běžet bez dotazu. Úpravu cizího modulu chcete vidět. Do zmrazené složky agent nemá vůbec vstupovat. Tři různé odpovědi na tři různé akce, a to samotný režim neumí.
Tři seznamy
Pravidla dávají právě tyto tři odpovědi:
allow- provést bez dotazu. Odstraní zbytečný šum: časté a bezpečné akce vás už nevyrušují;ask- vždy se zeptat. Dotaz zůstane tam, kde je rozhodnutí na vás, a to v každém režimu, i v tom nejvolnějším;deny- neprovádět. Agent dostane zamítnutí a vám se dotaz ani nezobrazí. Platí také v každém režimu.
Pravidla se zapisují do souboru nastavení, například do projektového .claude/settings.json. Pro projekt z úvodu by to mohlo vypadat takto:
{
"permissions": {
"allow": [
"Bash(npm test)"
],
"ask": [
"Edit(src/partner/**)"
],
"deny": [
"Edit(legacy/**)",
"Bash(git push *)"
]
}
}Zde je src/partner/ cizí modul, který upravujete opatrně, legacy/ je zmrazená část projektu a npm test je kontrola, kterou agent během úkolu spouští třeba desetkrát. Dvě hvězdičky znamenají "všechno uvnitř složky v libovolné hloubce".
Podívejme se, co se v relaci změní. Stejných pět akcí ve třech variantách:
| Akce | Manual bez pravidel | acceptEdits bez pravidel | acceptEdits s pravidly |
|---|---|---|---|
Úprava jinde v src/ | dotaz | bez dotazu | bez dotazu |
Úprava v src/partner/ | dotaz | bez dotazu | dotaz |
Úprava v legacy/ | dotaz | bez dotazu | zamítnuto |
npm test | dotaz | dotaz | bez dotazu |
git push | dotaz | dotaz | zamítnuto |
Všimněte si posledního sloupce. Relace běží v rychlejším režimu: vlastní kód se upravuje bez zastavení a testy se spouštějí samy. Zůstal jediný dotaz, a ten se týká místa, kde chcete úpravu opravdu zkontrolovat. Dvě nepřípustné akce už nezávisí na tom, jak jste večer unavení.
Právě proto pravidla potřebujete. Cílem není dát agentovi více oprávnění, ale rozdělit je podle ceny chyby. Pak můžete pracovat ve volnějším režimu, aniž byste ztratili kontrolu nad důležitými místy.
Jedna akce může odpovídat několika pravidlům zároveň, proto Claude Code kontroluje seznamy v přesném pořadí:
Schéma se čte shora dolů a každá akce agenta jím prochází znovu. Jakmile se pravidlo shoduje, kontrola končí a konkrétnější pravidlo už přednost nedostane. Pokud je v deny pravidlo Bash(git push *), žádné pravidlo v allow už push nepovolí. Zákaz tedy nejde omylem přepsat, což je dobře.
Dolní obdélník si zapamatujte zvlášť. Když akce neodpovídá žádnému seznamu, neznamená to "povoleno". Rozhoduje režim: v Manual se agent zeptá, v acceptEdits úprava proběhne sama. Jinými slovy, pravidla nic neruší, jen upřesňují režim v místech, která jste určili.
Jak číst pravidlo
Téměř správné pravidlo je horší než žádné. Bez pravidla víte, že hranice neexistuje. U nepřesného pravidla si myslíte, že hranice existuje, ale ta ve skutečnosti chrání něco jiného, než čekáte.
Všechna pravidla mají stejný formát: název nástroje a v závorkách upřesnění, na co se vztahuje. Bez závorek pravidlo platí pro všechna volání nástroje, takže Bash v deny agentovi odebere celý terminál.
Soubory
Pro soubory jsou důležité dva nástroje: Edit pro každou úpravu a Read pro čtení. Cesta se zapisuje jako vzor, podobně jako v .gitignore: jedna hvězdička znamená libovolný název uvnitř jedné složky, dvě libovolnou hloubku vnoření. Cesta bez úvodního lomítka se počítá od složky, ve které byla spuštěna relace, proto Claude Code spouštějte z kořene projektu.
Častou chybou je zapsat Write(legacy/**). Agent sice nástroj s tímto názvem má, ale Claude Code kontroluje pravidla pro soubory jen vůči nástrojům Edit a Read. Pravidlo s Write přijme, při spuštění na to upozorní a dál ho nekontroluje. Zato Edit pokrývá všechny vestavěné způsoby změny souborů včetně vytvoření nového.
A ještě jedna praktická věc: zákaz čtení, například Read(./.env) v deny, agentovi zároveň zakáže i úpravu tohoto souboru.
Příkazy
Pravidlo Bash(...) porovnává text příkazu. Hvězdička zastupuje libovolný text včetně mezer. O tom, zda se pravidlo shoduje, rozhodují tři drobnosti:
- bez hvězdičky se pravidlo shoduje s jediným příkazem znak po znaku;
- hvězdička se píše za podpříkaz.
Bash(git log *)propustí jengit logs libovolnými přepínači, zatímcoBash(git *)propustí libovolný příkaz git včetně push; - součástí pravidla je i mezera před hvězdičkou:
Bash(ls *)se neshoduje slsof, aleBash(ls*)ano.
Modrá část se porovnává s příkazem znak po znaku, oranžovou část hvězdička pokryje celou, ať je v ní cokoli. Šířku pravidla tedy určuje text před hvězdičkou. V prvním pravidle je to git log, takže nepropustí nic jiného než prohlížení historie. Ve druhém je to jen git a za hvězdičkou může být push, smazání větve nebo zahození změn. Až budete číst cizí pravidlo, začněte otázkou: co je před hvězdičkou?
| Pravidlo | Shoduje se | Neshoduje se |
|---|---|---|
Bash(npm test) | npm test | npm test --watch |
Bash(npm run *) | npm run build, npm run lint --fix | npm install |
Bash(git log *) | git log, git log --oneline | git push |
Bash(git *) | libovolný příkaz git včetně git push | - |
Edit(src/partner/**) | úprava libovolného souboru ve src/partner/ | úprava src/app.js |
Read(./.env) | čtení souboru .env v kořeni projektu | čtení souboru .env.example |
Složený příkaz typu a && b Claude Code rozdělí na části. allow ho propustí, jen když každá část odpovídá vlastnímu pravidlu allow. ask a deny se uplatní, pokud odpovídá alespoň jedna část. Oprávnění pro npm test tedy s sebou nepropustí i npm test && git push.
Pravidla existují také pro další nástroje, například mcp__github__* pro všechny nástroje jednoho MCP serveru nebo WebFetch(domain:example.com) pro načítání stránek z jednoho webu. Fungují stejně, proto je tu nebudeme rozebírat zvlášť.
Ve kterém souboru pravidla uchovávat
Pravidlo v nesprávném souboru může potichu narušit práci. Zákaz uložíte do svého osobního souboru, kolegové ho nemají a jejich agent bezstarostně vstoupí do legacy/. Oprávnění, které vyhovuje vám, vložíte do společného souboru a dostane ho každý, kdo si projekt stáhne.
| Soubor | Čí pravidla | Dostane se do Gitu |
|---|---|---|
~/.claude/settings.json | vaše, ve všech projektech na tomto počítači | ne, je v domovské složce |
.claude/settings.json | společná pro všechny, kdo pracují na projektu | ano, soubor se commituje |
.claude/settings.local.json | vaše, jen v tomto projektu | ne |
Kromě těchto tří může organizace distribuovat vlastní soubor nastavení a jeho pravidla nelze přepsat. Ve výukových projektech se s tím obvykle nesetkáte.
Seznamy z různých souborů si nekonkurují, ale skládají se dohromady: allow z vašeho souboru se přidá ke společnému allow. Pořadí kontroly je pro všechny stejné a deny z libovolného souboru má přednost před allow z kteréhokoli jiného. Rozdělení je tedy jednoduché. Hranice projektu, například legacy/, .env nebo push, patří do společného souboru, aby cestovaly s repozitářem. Vlastní pohodlná nastavení patří do místního.
Společný soubor má jednu ochrannou vlastnost. Jeho pravidla allow začnou platit až poté, co potvrdíte, že složce důvěřujete: při prvním spuštění Claude Code v projektu se na to zeptá a ukáže, co soubor povolí. Pravidla ask a deny platí hned, protože jen omezují. Cizí repozitář s oprávněním pro celý terminál tedy nic nezíská, dokud s tím nesouhlasíte.
Aktivní pravidla můžete ověřit dvěma příkazy. /permissions zobrazí všechna pravidla i soubor, ze kterého každé pochází; přímo tam je můžete také přidávat a odebírat. Řádek Setting sources v /status vypíše načtené soubory. Změny souborů Claude Code načte bez restartu. Soubor nastavení musí být striktní JSON: komentář pomocí // nebo čárka za poslední položkou ho rozbije a Claude Code vás na to upozorní při spuštění.
Když se agent zeptá na příkaz a vyberete "Yes, and don't ask again", Claude Code zapíše pravidlo allow do souboru .claude/settings.local.json. Pokud soubor ještě neexistuje, vytvoří ho a zajistí, aby se nedostal do commitů. U úprav souborů je to jinak: takový souhlas platí do konce relace a do souboru se nezapíše.
Rozbor skutečného settings.local.json
Tento soubor už nejspíš máte, ale nevytvořili jste ho ručně. Každé kliknutí na "Don't ask again" do něj přidalo řádek a za pár týdnů agentovi povoluje víc, než si myslíte. Tady je skutečný blok, který se nashromáždil během několika týdnů práce na projektu v Pythonu:
{
"permissions": {
"allow": [
"Bash(python3 *)",
"Bash(PYTHONIOENCODING=utf-8 python3 *)",
"Bash(git status *)",
"Bash(git log *)",
"Bash(git diff *)",
"Bash(git show *)",
"Bash(git branch *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git fetch *)"
]
}
}Než se pustíte do rozboru, zkuste to sami. Které řádky byste ponechali, které zúžili a které odstranili?
Bash(python3 *)
Nejširší pravidlo v souboru. Povoluje spustit libovolný skript i jakýkoli kód přes python3 -c. Python přitom umí všechno: mazat soubory, přistupovat k síti i spouštět jiné programy. Prakticky jde o povolení spustit cokoli bez dotazu. Pravidlo je lepší zúžit na skript, kvůli kterému vzniklo, například na Bash(python3 scripts/build.py *).
Bash(PYTHONIOENCODING=utf-8 python3 *)
Stejný příkaz, jen s proměnnou prostředí na začátku. Pravidlo allow takový zápis propustí pouze tehdy, když je proměnná na krátkém seznamu předem známých bezpečných proměnných. Pokud tam není, Bash(python3 *) příkaz nepokryje, agent se zeptá zvlášť a tlačítko uloží další pravidlo. Právě tak tento řádek nejspíš vznikl. Zúžit ho lze stejně, na konkrétní skript.
git status, git log, git diff, git show
V běžné podobě tyto příkazy pouze čtou a Claude Code příkazy pouze pro čtení provádí bez dotazu a bez pravidel. Tyto řádky ničemu neškodí, ale skoro nic nepřinášejí. Odstraňte je a soubor bude kratší a přehlednější.
Bash(git branch *)
Vypadá neškodně: jen vypíše seznam větví. Pravidlo ale porovnává text a také git branch -D feature začíná na git branch. Smazání větve tedy proběhne bez dotazu. Tento řádek raději odstraňte. Pokud vás začne obtěžovat dotaz na seznam větví, povolte přesný příkaz Bash(git branch) bez hvězdičky.
git add a git fetch
První přidává změny do příštího commitu, druhý stahuje novou historii ze serveru a pracovních souborů se nedotýká. Oba příkazy lze snadno vrátit, můžete je ponechat.
Bash(git commit *)
Agent provede commit bez dotazu, tedy ještě předtím, než si přečtete diff. Právě tady je dotaz na místě: commit je okamžik, kdy se změnou souhlasíte. Přesuňte tento řádek do ask. Pouhé odstranění nestačí. V režimu Manual se agent zeptá i tak, ale ask zachová dotaz v jakémkoli režimu včetně toho nejvolnějšího.
Co v souboru chybí
git push. To je dobře, jen to závisí na tom, že nikdo nikdy neklikl na "Don't ask again" u push. Spolehlivější je zapsat zákaz výslovně.
Po rozboru by to tedy vypadalo takto:
{
"permissions": {
"allow": [
"Bash(python3 scripts/build.py *)",
"Bash(PYTHONIOENCODING=utf-8 python3 scripts/build.py *)",
"Bash(git add *)",
"Bash(git fetch *)"
],
"ask": [
"Bash(git commit *)"
],
"deny": [
"Bash(git push *)"
]
}
}Z deseti řádků zůstalo šest a každý dělá přesně to, co má. Dotazů při práci skoro nepřibylo: build probíhá sám a agent se ptá jen na jednom místě, před commitem. Pokud se zákaz push týká celého týmu, přesuňte ho do společného souboru .claude/settings.json podle pravidla z předchozí části.
Pravidla jako Bash(python3 *), Bash(node *), Bash(npm *) nebo Bash(npx *) vypadají jako oprávnění pro jeden nástroj. Ve skutečnosti dovolují spustit jakýkoli kód, který daný nástroj dokáže spustit. Povolte konkrétní skript nebo příkaz, ne celý program.
Co pravidlo nezachytí
Agent dostal zamítnutí. Pro něj je to běžná odpověď nástroje a práce pokračuje. Někdy hledá jiný způsob, jak udělat totéž. Pak je důležité vědět, co přesně pravidlo kontroluje.
Pravidlo Bash(...) porovnává text příkazu, nikoli program, který se spustí. Zákaz proto pokryje běžný zápis příkazu, ale ne všechny jeho podoby:
Bash(git push *)vdenynezastavígit -C . push. Jde o stejný příkaz, ale jinak zapsaný;Bash(rm *)nezastaví/bin/rmanibash -c 'rm ...';- zákaz pro
Read(...)nezabrání skriptu v Pythonu, aby soubor otevřel sám.
Nemusíte kvůli tomu pravidla zahazovat. Agent příkaz téměř vždy napíše v běžné podobě a deny zachytí právě tu. Pravidlo ale není neprostupná zeď (a dokumentace Claude Code to říká výslovně). Aby agent nemusel hledat obcházení, popište zákaz také slovy v souboru CLAUDE.md: "legacy/ je zmrazená; pokud úkol vyžaduje úpravu této složky, zastav se a zeptej se". Pravidlo akci blokuje, CLAUDE.md vysvětluje proč a dohromady fungují lépe než každé zvlášť.
Pokud má být hranice opravdu spolehlivá, existují další mechanismy: hook, který kontroluje každý příkaz před spuštěním, a sandbox, jenž omezuje přístup na úrovni systému. To už jsou samostatná témata.
Pravidla pro každý den
Když to shrneme do několika návyků:
- do
denypatří to, co je v projektu za všech okolností nepřípustné: zmrazená složka,.env, push; - do
askpatří jen hraniční případy, kdy rozhodnutí náleží vám.askpro všechno vrátí únavu z dotazů; - do
allowpatří úzce vymezené a opakované akce: konkrétní kontrola, konkrétní skript; - hranice projektu patří do společného
.claude/settings.json, osobní pohodlná nastavení do.claude/settings.local.json; - čas od času otevřete
/permissionsa odstraňte, co se nashromáždilo po kliknutí na "Don't ask again"; - nové pravidlo ověřte: požádejte agenta o zakázanou akci a zkontrolujte, že ji odmítne.
Popište agentovi jednotlivé zóny projektu: co lze upravovat volně, na co se má ptát a kam nesmí vstoupit. Požádejte ho o návrh bloku permissions a před uložením si JSON přečtěte. Položte si stejné otázky jako v předchozím rozboru: Není pravidlo širší, než je potřeba? Dostane se do správného souboru?
Režim určuje celkové tempo práce, pravidla rozhodují, kde zpomalit. Společně umožňují to, co samotný režim nedokáže: rychlou práci tam, kde je chyba levná, a dotaz nebo zamítnutí tam, kde by byla nákladná.
GO TO FULL VERSION