Claude Code Permission Budget Loop: 권한, 비용, 로그를 5분에 점검하기
Claude Code의 allow/deny 규칙, 비용 한도, 실행 로그, 팀 인수인계를 점검하는 실전 루프.
매일 아침 5분 점검이 필요한 이유
Claude Code를 운영에 넣을 때 핵심 질문은 “코드를 잘 쓰는가”만이 아닙니다. 더 중요한 질문은 “멈추지 않고 무엇을 하게 둘 것인가”입니다. 모든 Bash 명령을 승인하는 방식은 처음에는 안전해 보입니다. 하지만 승인 창이 계속 나오면 사람은 내용을 덜 읽게 됩니다. 반대로 모두 허용하면 .env 읽기, 패키지 설치, git push, production deploy, DB migration, billing 변경이 같은 통로로 들어옵니다.
Permission budget은 Claude Code 운영표입니다. 승인 없이 실행해도 되는 작업, 사람에게 먼저 물어야 하는 작업, 이 저장소에서 금지할 작업을 짧게 적어 둡니다. Loop는 이 표를 매일 아침 전날 실행 로그와 사용량에 맞춰 확인하는 습관입니다. 쉽게 말하면 agent에게 건넨 열쇠와 예산을 매일 다시 세는 일입니다.
2026년 6월 3일 기준 공식 문서에서는 Claude Code 권한을 allow, ask, deny로 설명합니다. deny가 ask와 allow보다 우선합니다. /permissions는 현재 적용 중인 rule과 그 출처인 settings 파일을 보여 줍니다. 비용은 /usage로 local/session 상황을 보고, 실제 billing과 workspace limit은 Claude Console에서 확인합니다. 공식 문서는 Configure permissions, Claude Code settings, Manage costs effectively, CLI reference를 참고하세요.
관련 내부 글로는 Claude Code permissions guide, permission audit checklist, permission receipt pattern을 함께 연결하면 좋습니다.
보안 용어 없이 이해하는 기본
Claude Code permission은 모델의 약속이 아니라 CLI가 실제로 막는 경계입니다. CLAUDE.md에 “secret을 읽지 말라”고 쓰는 것은 좋은 지침이지만 기술적 차단은 아닙니다. Read(./.env) 또는 Read(./secrets/**) 같은 deny rule이 Claude Code가 강제할 수 있는 경계입니다.
Permission mode도 분리해서 봐야 합니다. default는 일반 승인 흐름입니다. plan은 읽기와 조사에 적합합니다. acceptEdits는 파일 수정을 더 부드럽게 만듭니다. dontAsk는 사전 승인되지 않았거나 ask에 없는 도구를 거부합니다. bypassPermissions, 즉 --dangerously-skip-permissions는 확인 prompt를 건너뛰므로 격리된 container나 VM에서만 쓰는 편이 안전합니다.
비용도 같은 방식으로 다룹니다. /usage는 예상보다 비싼 local session을 찾는 데 좋지만, API billing은 Claude Console에서 확인해야 합니다. claude -p 같은 script 실행에서는 --max-budget-usd와 --max-turns가 유용하지만, 이것만으로 팀 예산 관리가 끝나지는 않습니다.
매일 도는 permission budget loop
반복할 수 있을 만큼 짧아야 합니다. 목표는 완벽한 감사가 아니라 위험한 권한을 열어 둔 채 하루를 시작하지 않는 것입니다.
| 순서 | 확인 항목 | 통과 조건 |
|---|---|---|
| 1 | /permissions | Bash(*)나 너무 넓은 Bash(npm *)가 없음 |
| 2 | .claude/settings.json | secrets, deploy, database, billing이 ask 또는 deny에 있음 |
| 3 | /usage와 Console | 전날 비용 증가가 설명 가능함 |
| 4 | git diff와 실행 로그 | 승인한 작업과 diff가 일치함 |
| 5 | 인수인계 메모 | 열린 권한, 막은 작업, 다음 reviewer가 적혀 있음 |
시작 prompt는 짧게 둡니다.
Before starting today's Claude Code work, classify the task into:
1. safe to run without approval
2. requires human approval
3. should not run in this session
Then list up to five checks for /permissions, /usage, and git diff.
공유 settings.json 예시
다음 .claude/settings.json은 시작점으로 쓸 수 있습니다. defaultMode: "dontAsk"는 엄격합니다. allow나 ask에 없는 도구는 실행되지 않습니다. 팀 공유 설정으로 넣기 전에 local에서 먼저 시험하세요.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"defaultMode": "dontAsk",
"allow": [
"Bash(npm run lint)",
"Bash(npm run test)",
"Bash(npm run test *)",
"Bash(npm run build)",
"Bash(git status)",
"Bash(git diff)",
"Bash(git diff *)",
"WebFetch(domain:code.claude.com)"
],
"ask": [
"Bash(npm install *)",
"Bash(pnpm add *)",
"Bash(git push *)",
"Bash(wrangler deploy *)",
"Bash(vercel deploy *)",
"Bash(terraform apply *)",
"Bash(kubectl apply *)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(curl *)",
"Bash(wget *)",
"Bash(rm -rf *)"
]
}
}
중요한 것은 safe lane을 좁게 유지하는 습관입니다. Bash(npm *)는 test에서 install이나 publish로 쉽게 넓어집니다. Bash(git *)는 diff에서 push로 넓어집니다. 읽기, lint, test, build는 좁게 allow하고 install, push, deploy, apply는 사람 승인 뒤에 둡니다.
예산과 실행 로그를 JSON으로 남기기
Permission은 절반입니다. 나머지는 비용입니다. 긴 조사, 반복되는 실패 test, background session, 큰 log는 조용히 비용을 키웁니다. 작은 budget 파일과 daily log를 두면 pull request에서 검토할 수 있습니다.
{
"date": "2026-06-03",
"dailyLimitUsd": 6,
"warnAtUsd": 4,
"usageSource": "/usage plus Claude Console",
"safeAllow": [
"Bash(npm run lint)",
"Bash(npm run test)",
"Bash(git diff *)"
],
"askFirst": [
"Bash(npm install *)",
"Bash(git push *)",
"Bash(wrangler deploy *)"
],
"mustDeny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)"
],
"handoffRequired": true
}
{
"date": "2026-06-03",
"spentUsd": 1.85,
"usageChecked": true,
"settingsChecked": true,
"permissionsReviewed": [
"/permissions",
".claude/settings.json"
],
"openAllowances": [
"Bash(npm run lint)",
"Bash(npm run test *)"
],
"handoff": [
"No deploy allowance left open",
"Claude stopped before production data work"
]
}
각각 .claude/permission-budget.json과 .claude/daily-claude-log.json으로 저장합니다. 관리 보고에는 spreadsheet도 괜찮지만, code review와 automation에는 JSON이 더 좋습니다.
바로 실행 가능한 Node 감사 스크립트
아래 파일을 scripts/audit-claude-loop.mjs로 저장하고 node scripts/audit-claude-loop.mjs를 실행합니다. 외부 dependency는 없습니다. 넓은 Bash 허용, allow에 들어간 deploy, .env deny 누락, budget 초과, 인수인계 누락을 잡습니다.
#!/usr/bin/env node
import fs from "node:fs";
const readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8"));
const budget = readJson(".claude/permission-budget.json");
const log = readJson(".claude/daily-claude-log.json");
const settings = readJson(".claude/settings.json");
const problems = [];
const permissions = settings.permissions ?? {};
const allow = new Set(permissions.allow ?? []);
const ask = new Set(permissions.ask ?? []);
const deny = new Set(permissions.deny ?? []);
const hasPattern = (items, pattern) => [...items].some((item) => pattern.test(item));
if (typeof budget.dailyLimitUsd !== "number" || budget.dailyLimitUsd <= 0) {
problems.push("dailyLimitUsd must be a positive number");
}
if (typeof budget.warnAtUsd !== "number" || budget.warnAtUsd >= budget.dailyLimitUsd) {
problems.push("warnAtUsd must be lower than dailyLimitUsd");
}
if (log.spentUsd > budget.dailyLimitUsd) {
problems.push(`spentUsd ${log.spentUsd} exceeds daily limit ${budget.dailyLimitUsd}`);
}
if (log.spentUsd >= budget.warnAtUsd) {
console.warn(`WARN: spentUsd ${log.spentUsd} has reached warnAtUsd ${budget.warnAtUsd}`);
}
if (!log.usageChecked) problems.push("Run /usage and mark usageChecked true");
if (!log.settingsChecked) problems.push("Review /permissions and mark settingsChecked true");
if (allow.has("Bash") || allow.has("Bash(*)") || hasPattern(allow, /^Bash\(\*.*\)$/)) {
problems.push("Do not allow every Bash command");
}
if (hasPattern(allow, /(deploy|terraform apply|kubectl apply|git push)/)) {
problems.push("Deploy, infrastructure, and push commands must be ask-first, not allow");
}
for (const rule of budget.askFirst ?? []) {
if (!ask.has(rule)) problems.push(`Missing ask rule: ${rule}`);
}
for (const rule of budget.mustDeny ?? []) {
if (!deny.has(rule)) problems.push(`Missing deny rule: ${rule}`);
}
if (!hasPattern(deny, /Read\(.*\.env/)) {
problems.push("Deny rules should block .env reads");
}
if (!Array.isArray(log.handoff) || log.handoff.length === 0) {
problems.push("Add at least one handoff note");
}
if (problems.length) {
console.error(problems.map((problem) => `- ${problem}`).join("\n"));
process.exit(1);
}
console.log("Claude Code daily permission budget check passed.");
CI에는 처음부터 hard gate로 넣기보다 warning 또는 manual 실행으로 시작하세요. 팀이 신뢰하지 않는 policy는 우회됩니다.
네 가지 구체적 사용 사례
첫 번째는 글과 문서 수정입니다. Markdown, MDX, 내부 링크, CTA, 오탈자, 이미지 경로는 보통 secret이나 production을 건드리지 않습니다. file read, git diff, lint, test, local build를 좁게 allow하면 Claude Code가 불필요하게 멈추지 않고 작은 diff를 만들 수 있습니다.
두 번째는 dependency 변경입니다. npm install과 pnpm add는 lockfile, postinstall script, license, vulnerability, bundle size에 영향을 줍니다. ask에 두고, 승인 전에는 새 dependency가 필요한 이유, 대안, 되돌리는 방법을 쓰게 합니다.
세 번째는 deploy와 migration입니다. wrangler deploy, vercel deploy, terraform apply, kubectl apply, DB migration은 외부 상태를 바꿉니다. Claude Code는 command, 영향 범위, rollback, 확인 URL, monitoring checklist를 준비할 수 있지만 실행은 사람 승인 뒤에 둡니다.
네 번째는 팀 인수인계입니다. 다른 사람이 이어서 작업한다면 open allowances, proof commands, blocked actions, remaining budget을 적어야 합니다. 이 메모가 없으면 다음 사람은 같은 조사를 반복하고 같은 위험 권한을 다시 엽니다.
피해야 할 실패 사례
가장 흔한 실패는 넓은 Bash permission입니다. Bash(npm *)와 Bash(git *)는 편하지만 read-only 습관과 상태 변경 명령을 섞습니다. 매일 쓰는 lane에는 정확한 명령을 쓰세요.
다음 실패는 deploy allowance를 닫지 않는 것입니다. 장애 대응 중에 wrangler deploy *가 ask에서 allow로 옮겨질 수 있습니다. 다음 날까지 남아 있으면 일반 feature 작업도 production 권한을 갖습니다.
세 번째는 token과 cost 증가를 무시하는 것입니다. 긴 조사는 생산적으로 보이지만 budget을 태울 수 있습니다. /usage를 보고, billing이 중요하면 Console과 비교하며, 더 이상 가치가 없는 session은 멈춥니다.
마지막으로 prompt와 enforcement를 혼동하지 마세요. “secret을 읽지 마”는 지침입니다. Read(./.env) in deny가 enforcement입니다. Harness, 즉 agent가 일하는 틀은 prompt, settings, log, review가 함께 있어야 작동합니다.
제품, 교육, 팀 rollout
혼자 연습한다면 JSON과 script를 작은 repository에 먼저 넣어 보세요. 재사용 가능한 checklist, CLAUDE.md template, review prompt는 /products/에 있습니다. 팀 rollout에서 permission, cost control, CI policy, reviewer training, repository별 rule이 필요하면 /training/을 사용하세요.
실전 메모 (実際に試した結果): 가장 큰 개선은 위험한 명령을 전부 막아서 나온 것이 아니었습니다. 매일 아침 5분 동안 /permissions, /usage, git diff, 인수인계 메모를 본 것이 효과적이었습니다. 좁은 allow는 계속 도움이 되었고, deploy, billing, secrets는 안정적으로 ask 또는 deny로 돌아갔습니다.
무료 PDF: Claude Code 치트시트
이메일을 입력하면 명령, 리뷰 습관, 안전한 워크플로를 정리한 PDF를 받을 수 있습니다.
개인정보를 안전하게 관리하며 스팸을 보내지 않습니다.
작성자 소개
Masa
Claude Code 실무 워크플로와 팀 도입을 검증하는 엔지니어입니다.
관련 글
Claude Code 권한 세이프티 래더: 통제력을 잃지 않고 allow 넓히기
read-only에서 제한 편집, 검증 명령, deploy 확인까지 권한을 단계적으로 넓히는 방법.
Claude Code Small PR Proof Pack: 작은 PR을 리뷰 가능한 상태로 만드는 증거 세트
Claude Code의 작은 PR에 diff, 검증, 공개 URL, CTA 경로, rollback을 붙이는 실무 체크리스트.
Claude Code 커밋 전 리뷰 게이트: diff, 테스트, 공개 URL, CTA 확인
Claude Code 작업을 커밋하기 전에 diff 범위, build, 공개 URL, Gumroad 링크, 상담 CTA, 테스트 누락과 무관한 파일을 확인하는 방법입니다.