O oră obișnuită de lucru în modul Manual. Agentul citește proiectul, propune o modificare, vă cere să rulați testele, apoi urmează altă modificare și alte teste. La a douăzecea întrebare apăsați "Yes" aproape fără să vă uitați. Și, printre aceste întrebări, se strecoară o modificare în folderul legacy/, de care nimeni nu s-a mai atins de mult și nici n-ar trebui să se atingă.
Articolul acesta arată cum să păstrați întrebările doar pentru situațiile în care decizia chiar vă aparține. În Claude Code aveți pentru asta reguli de permisiune: trei liste în fișierul de setări, care stabilesc ce poate face agentul imediat, pentru ce să vă întrebe și ce să nu facă deloc. Să vedem la ce folosesc, cum se citesc și cum puteți pune în ordine fișierul cu reguli pe care probabil îl aveți deja.
O singură setare pentru toate
Modul de permisiuni e un singur buton pentru întreaga sesiune. Îl puteți roti în orice direcție, dar schimbarea se aplică mereu pe toată sesiunea, în bloc.
În modul strict Manual, agentul vă întreabă înainte de fiecare modificare și aproape înaintea fiecărei comenzi. Întrebarea vă protejează doar cât timp o citiți. Când sunt prea multe, nu le mai citiți, iar protecția rămâne doar pe hârtie.
În modul mai liber acceptEdits, modificările se fac fără să vă întrebe, la fel și comenzile pentru fișiere, precum rm și mv. E comod pentru propriul dumneavoastră cod. Dar modul nu face diferența între foldere: o modificare în legacy/ trece la fel de discret ca oriunde altundeva în proiect.
Puteți scrie în CLAUDE.md "nu atinge legacy/". Agentul va încerca să respecte indicația, însă e o rugăminte adresată modelului, nu o interdicție. Regulile de permisiune le verifică însuși Claude Code, înainte ca acțiunea să fie executată, iar textul din CLAUDE.md sau din prompt nu le influențează.
Acțiunile au costuri diferite în caz de greșeală, dar modul le tratează la fel. Testele ar trebui să ruleze fără întrebări. Modificările într-un modul al altcuiva ar trebui să le vedeți. Agentul n-ar trebui să intre deloc într-un folder înghețat. Trei acțiuni, trei răspunsuri diferite, iar modul nu le poate diferenția.
Trei liste
Regulile vă oferă exact aceste trei răspunsuri:
allow- execută fără să întrebe. Elimină zgomotul: acțiunile frecvente și sigure nu vă mai întrerup;ask- întreabă întotdeauna. Păstrează întrebarea acolo unde decizia e a dumneavoastră, indiferent de mod, chiar și în cel mai liber;deny- nu execută. Agentul primește un refuz, iar dumneavoastră nici nu vedeți întrebarea. Se aplică în orice mod.
Regulile se trec într-un fișier de setări, de exemplu în .claude/settings.json al proiectului. Pentru proiectul din introducere, ar putea arăta așa:
{
"permissions": {
"allow": [
"Bash(npm test)"
],
"ask": [
"Edit(src/partner/**)"
],
"deny": [
"Edit(legacy/**)",
"Bash(git push *)"
]
}
}Aici, src/partner/ e un modul al altcuiva, pe care îl modificați cu grijă, legacy/ e o parte înghețată a proiectului, iar npm test e verificarea pe care agentul o rulează de zece ori într-o sarcină. Cele două asteriscuri înseamnă "tot ce se află în folder, la orice nivel de adâncime".
Să vedem acum ce se schimbă în sesiune. Aceleași cinci acțiuni, în trei variante:
| Acțiune | Manual fără reguli | acceptEdits fără reguli | acceptEdits cu reguli |
|---|---|---|---|
Modificare în restul folderului src/ | întreabă | fără întrebare | fără întrebare |
Modificare în src/partner/ | întreabă | fără întrebare | întreabă |
Modificare în legacy/ | întreabă | fără întrebare | refuză |
npm test | întreabă | întreabă | fără întrebare |
git push | întreabă | întreabă | refuză |
Uitați-vă la ultima coloană. Sesiunea rulează într-un mod rapid: codul propriu se modifică fără opriri, iar testele pornesc singure. A rămas o singură întrebare, despre locul unde chiar vreți să vedeți modificarea. Cele două acțiuni interzise nu mai depind de cât de obosiți sunteți spre seară.
De asta sunt utile regulile. Scopul nu e să-i dați agentului mai multe permisiuni, ci să le organizați după costul unei greșeli. Așa puteți lucra într-un mod mai liber fără să pierdeți controlul asupra zonelor importante.
O acțiune poate corespunde mai multor reguli, așa că Claude Code verifică listele într-o ordine strictă:
Schema se parcurge de sus în jos, iar fiecare acțiune a agentului trece din nou prin ea. De îndată ce se potrivește o regulă, verificarea se oprește, iar o regulă mai specifică nu primește prioritate. Dacă deny conține Bash(git push *), nicio regulă din allow nu va permite push-ul. Interdicția nu poate fi anulată din greșeală, ceea ce e bine.
Merită să rețineți separat dreptunghiul de jos. Dacă acțiunea nu se potrivește cu nicio listă, asta nu înseamnă "permisă". Decide modul: în Manual agentul vă întreabă, în acceptEdits modificarea se aplică direct. Cu alte cuvinte, regulile nu anulează modul, ci îl particularizează în situațiile pe care le-ați indicat.
Cum se citește o regulă
O regulă scrisă aproape corect e mai rea decât lipsa ei. Fără regulă știți că nu există o limită. Cu una imprecisă, credeți că limita există, dar protejează altceva decât vă imaginați.
Formatul e același pentru toate regulile: numele instrumentului, apoi între paranteze o precizare despre ce anume vizează. Fără paranteze, regula se aplică tuturor apelurilor instrumentului, așa că Bash în deny îi ia agentului accesul la întregul terminal.
Fișiere
Pentru fișiere aveți nevoie de două instrumente: Edit pentru orice modificare și Read pentru citire. Calea se scrie cu un șablon, ca în .gitignore: un asterisc înseamnă orice nume într-un singur folder, două înseamnă orice nivel de imbricare. O cale fără slash la început se raportează la folderul în care a fost pornită sesiunea, așa că lansați Claude Code din rădăcina proiectului.
O greșeală frecventă e să scrieți Write(legacy/**). Agentul are un instrument cu acest nume, dar Claude Code verifică regulile pentru fișiere doar cu Edit și Read. Va accepta regula cu Write, vă va avertiza la pornire și nu o va mai verifica ulterior. În schimb, Edit acoperă toate metodele încorporate de modificare a fișierelor, inclusiv crearea unora noi.
Mai e și o suprapunere utilă: interdicția de citire, de exemplu Read(./.env) în deny, îl oprește pe agent și să modifice acel fișier.
Comenzi
Regula Bash(...) compară textul comenzii. Asteriscul înlocuiește orice text, inclusiv spațiile, iar potrivirea depinde de trei detalii:
- fără asterisc, regula se potrivește cu o singură comandă, literă cu literă;
- asteriscul se pune după subcomandă.
Bash(git log *)permite doargit logcu orice opțiuni, pe cândBash(git *)permite orice comandă git, inclusiv push; - spațiul dinaintea asteriscului face parte din regulă:
Bash(ls *)nu se potrivește culsof, darBash(ls*)se potrivește.
Partea albastră se compară cu comanda literă cu literă, iar asteriscul acoperă complet partea portocalie, indiferent ce conține. Așadar, textul dinaintea asteriscului stabilește cât de largă e regula. În primul caz e git log, deci nu permite nimic în afară de consultarea istoricului. În al doilea e doar git, iar după asterisc poate urma push, ștergerea unei ramuri sau resetarea modificărilor. Când citiți o regulă scrisă de altcineva, începeți cu întrebarea asta: ce apare înaintea asteriscului?
| Regulă | Se potrivește | Nu se potrivește |
|---|---|---|
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 *) | orice comandă git, inclusiv git push | - |
Edit(src/partner/**) | modificarea oricărui fișier din src/partner/ | modificarea src/app.js |
Read(./.env) | citirea fișierului .env din rădăcina proiectului | citirea fișierului .env.example |
Claude Code împarte comenzile compuse de tipul a && b în părți. allow le permite doar dacă fiecare parte se potrivește cu propria regulă. ask și deny se aplică dacă se potrivește măcar una. Așadar, permisiunea pentru npm test nu va permite și npm test && git push.
Există reguli și pentru alte instrumente, de exemplu mcp__github__* pentru toate instrumentele unui server MCP sau WebFetch(domain:example.com) pentru încărcarea paginilor de pe un anumit site. Logica e aceeași, așa că nu le vom analiza separat aici.
În ce fișier păstrați regulile
O regulă pusă în fișierul greșit poate strica lucrurile pe nesimțite. Dacă puneți o interdicție în fișierul personal, colegii nu o au, iar agentul lor intră în legacy/ ca și cum nimic nu s-ar fi întâmplat. Dacă puneți o permisiune comodă pentru dumneavoastră în fișierul comun, ajunge la toți cei care descarcă proiectul.
| Fișier | Regulile cui | Ajunge în Git |
|---|---|---|
~/.claude/settings.json | ale dumneavoastră, în toate proiectele de pe acest calculator | nu, se află în folderul personal |
.claude/settings.json | comune tuturor celor care lucrează la proiect | da, fișierul este inclus în commit |
.claude/settings.local.json | ale dumneavoastră, doar în proiectul acesta | nu |
Pe lângă aceste trei fișiere, organizația poate distribui propriul fișier de setări, ale cărui reguli nu pot fi suprascrise. În proiectele de exercițiu, de obicei nu există așa ceva.
Listele din fișiere diferite nu se contrazic, ci se adună: lista allow din fișierul dumneavoastră se adaugă la lista allow comună. Ordinea de verificare rămâne aceeași pentru toate, iar deny din orice fișier are prioritate față de allow din oricare altul. De aici rezultă o împărțire simplă. Puneți limitele proiectului, cum ar fi legacy/, .env sau push, în fișierul comun, ca să ajungă la toată lumea odată cu repository-ul. Preferințele personale de lucru merg în fișierul local.
Fișierul comun are o particularitate de siguranță. Regulile sale allow intră în vigoare doar după ce confirmați că aveți încredere în folder: la prima pornire în proiect, Claude Code vă întreabă acest lucru și vă arată ce urmează să permită fișierul. Regulile ask și deny se aplică imediat, fiindcă doar restricționează. Un repository străin care își permite singur tot terminalul nu obține nimic până nu vă dați acordul.
Puteți verifica ce se aplică de fapt cu două comenzi. /permissions afișează toate regulile și fișierul din care provine fiecare; tot de aici le puteți adăuga sau șterge. Linia Setting sources din /status enumeră fișierele încărcate. Claude Code preia modificările făcute în fișiere fără repornire. Fișierul de setări folosește JSON strict: un comentariu cu // sau o virgulă după ultimul element îl va invalida, iar Claude Code vă va avertiza la pornire.
Când agentul vă întreabă despre o comandă și alegeți "Yes, and don't ask again", Claude Code adaugă regula allow în .claude/settings.local.json. Dacă fișierul nu exista încă, îl creează și se asigură că nu va ajunge în commit-uri. La modificările fișierelor, lucrurile stau altfel: acordul se aplică până la sfârșitul sesiunii și nu este scris în fișier.
Analizăm un settings.local.json real
Probabil aveți deja fișierul acesta, deși nu dumneavoastră l-ați scris. De fiecare dată când ați ales "nu mai întreba", s-a adăugat o linie, iar după câteva săptămâni agentul primește mai multe permisiuni decât credeți. Iată un bloc real, acumulat în câteva săptămâni de lucru la un proiect Python:
{
"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 *)"
]
}
}Înainte să citiți analiza, încercați și dumneavoastră. Ce linii ați păstra, pe care le-ați restrânge și pe care le-ați șterge?
Bash(python3 *)
Cea mai largă regulă din fișier. Permite rularea oricărui script și a oricărui cod prin python3 -c. Iar Python poate face orice: șterge fișiere, accesează rețeaua, pornește alte programe. Practic, regula permite executarea oricărui lucru fără întrebare. Ar trebui restrânsă la scriptul pentru care a fost adăugată, de exemplu Bash(python3 scripts/build.py *).
Bash(PYTHONIOENCODING=utf-8 python3 *)
Aceeași comandă, cu o variabilă de mediu în față. Regula allow permite această formă doar dacă variabila face parte dintr-o listă scurtă de variabile considerate sigure dinainte. Dacă nu e pe listă, Bash(python3 *) nu acoperă comanda, agentul vă întreabă separat, iar butonul salvează încă o regulă. Probabil așa a apărut și linia aceasta. O restrângeți la fel, la un script anume.
git status, git log, git diff, git show
În forma obișnuită, aceste comenzi doar citesc, iar Claude Code le execută fără să întrebe și fără reguli. Liniile nu fac rău, dar nici nu adaugă mare lucru. Ștergeți-le, iar fișierul va fi mai scurt și mai clar.
Bash(git branch *)
Pare inofensivă: afișează lista de ramuri. Dar regula compară textul, iar git branch -D feature începe tot cu git branch. Ramura va fi ștearsă fără întrebare. Mai bine eliminați linia. Dacă întrebarea despre lista de ramuri devine deranjantă, permiteți comanda exactă Bash(git branch), fără asterisc.
git add și git fetch
Prima adaugă modificări pentru un commit viitor, a doua descarcă istoricul nou de pe server fără să atingă fișierele de lucru. Ambele se pot anula ușor, așa că le puteți păstra.
Bash(git commit *)
Agentul face commit fără să vă întrebe, înainte să citiți diff-ul. Tocmai aici e nevoie de o întrebare: commit-ul e momentul în care aprobați modificarea. Mutați linia în ask. Nu e suficient să o ștergeți. În Manual, agentul vă va întreba oricum, dar ask păstrează întrebarea în orice mod, inclusiv în cel mai liber.
Ce lipsește din fișier
git push. E bine că nu apare, dar asta depinde doar de faptul că nimeni n-a ales vreodată "nu mai întreba" pentru push. E mai sigur să adăugați interdicția explicit.
Iată rezultatul analizei:
{
"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 *)"
]
}
}Din cele zece linii au rămas șase, fiecare cu rolul ei. Numărul întrebărilor aproape că nu a crescut: build-ul rulează singur, iar agentul vă întreabă doar înainte de commit. Dacă interdicția pentru push se aplică întregii echipe, mutați-o în fișierul comun .claude/settings.json, conform regulii din secțiunea anterioară.
Regulile de tipul Bash(python3 *), Bash(node *), Bash(npm *) sau Bash(npx *) par să permită un singur instrument. De fapt, permit orice cod pe care îl poate rula instrumentul respectiv. Permiteți un anumit script sau o anumită comandă, nu întregul program.
Ce nu detectează regula
Agentul primește un refuz. Pentru el e un răspuns obișnuit al instrumentului, iar lucrul continuă. Uneori caută o altă cale de a face același lucru. În situația asta e important să știți exact ce verifică regula.
Regula Bash(...) compară textul comenzii, nu programul care va porni. Prin urmare, interdicția acoperă forma obișnuită a comenzii, dar nu toate variantele:
Bash(git push *)îndenynu opreștegit -C . push. Comanda e aceeași, forma de scriere diferă;Bash(rm *)nu oprește/bin/rmsaubash -c 'rm ...';- interdicția pentru
Read(...)nu împiedică un script Python să deschidă singur fișierul.
Nu renunțați la reguli din cauza asta. Agentul scrie aproape întotdeauna comanda în forma obișnuită, iar deny o detectează. Totuși, regula nu e un zid (și documentația Claude Code spune asta explicit). Ca să nu fie nevoit agentul să caute ocoliri, explicați interdicția și în CLAUDE.md: "legacy/ este înghețat; dacă sarcina cere o modificare acolo, oprește-te și întreabă". Regula impune limita, CLAUDE.md o explică, iar împreună funcționează mai bine decât separat.
Dacă limita trebuie garantată, există și alte mecanisme: un hook care verifică fiecare comandă înainte de execuție și un sandbox care restricționează accesul la nivel de sistem. Sunt subiecte separate.
Reguli pentru fiecare zi
Totul se reduce la câteva obiceiuri:
- în
denypuneți ce este interzis în proiect indiferent de situație: un folder înghețat,.env, push; - în
askpăstrați doar cazurile-limită, în care decizia vă aparține. Dacă puneți totul înask, revine oboseala provocată de întrebări; - în
allowtreceți reguli restrânse pentru acțiuni repetate: o verificare anume, un script anume; - limitele proiectului merg în fișierul comun
.claude/settings.json, preferințele personale în.claude/settings.local.json; - deschideți din când în când
/permissionsși eliminați regulile adăugate prin butonul "nu mai întreba"; - după ce adăugați o regulă, verificați-o: cereți-i agentului să facă ceva interzis și asigurați-vă că refuză.
Descrieți-i agentului în cuvinte zonele proiectului: ce poate modifica liber, ce necesită o întrebare și unde nu are voie să intre. Cereți-i să propună un bloc permissions, apoi citiți JSON-ul înainte să-l salvați și puneți-vă aceleași întrebări ca în analiza de mai sus. E regula mai largă decât trebuie? Ajunge în fișierul potrivit?
Modul stabilește ritmul general de lucru, iar regulile indică unde să-l încetiniți. Împreună vă oferă ce nu poate oferi niciun mod singur: lucru rapid acolo unde greșeala costă puțin și o întrebare sau un refuz acolo unde costă mult.
GO TO FULL VERSION