Tips & Tricks (Updated: 6/3/2026)

Claude Code Permission Budget Loop: Check Permissions, Cost, and Logs in 5 Minutes

A practical Claude Code loop for allow/deny rules, cost limits, execution logs, and team handoff.

Claude Code Permission Budget Loop: Check Permissions, Cost, and Logs in 5 Minutes

Why a five-minute morning loop matters

The first operational question with Claude Code is not “can it code?” It is “what should it be allowed to do without stopping?” Approving every Bash command feels careful for one afternoon, then prompt fatigue arrives. Letting everything through is worse: .env reads, package installs, git push, production deploys, database migrations, and billing changes can end up in the same approval lane.

A permission budget is a short operating table for Claude Code. It says which actions can run without approval, which actions must ask a human first, and which actions are never allowed in that repository. The loop is the habit of checking that table every morning against yesterday’s execution log and usage. In plain terms, it is the five-minute routine of counting the keys and the wallet you handed to the agent.

As of June 3, 2026, the official Claude Code docs describe permission rules with allow, ask, and deny; deny rules take precedence over ask and allow rules. The /permissions UI shows active rules and the settings file they came from. Cost tracking should combine /usage for local/session visibility with Claude Console usage and workspace controls for authoritative billing. Keep these official pages nearby: Configure permissions, Claude Code settings, Manage costs effectively, and the CLI reference.

For related internal reading, connect this loop to the Claude Code permissions guide, the permission audit checklist, and the permission receipt pattern.

The basics, without security jargon

Claude Code permissions are enforced by the CLI, not by the model’s good intentions. A line in CLAUDE.md that says “do not read secrets” is useful guidance, but it is not a boundary. A deny rule such as Read(./.env) or Read(./secrets/**) is a boundary Claude Code can enforce.

Permission modes matter too. default is the standard approval flow. plan keeps the session focused on reading and investigation. acceptEdits makes file edits smoother. dontAsk denies tools unless they are pre-approved by rules. bypassPermissions, also exposed as --dangerously-skip-permissions, skips permission prompts and should be reserved for isolated containers or virtual machines where damage is contained.

Cost has the same shape. /usage is excellent for spotting an unexpectedly expensive local session, but API billing should be confirmed in Claude Console. For scripted claude -p runs, --max-budget-usd and --max-turns are useful guardrails. They are not a substitute for a team budget or a review of runaway agent sessions.

The daily permission budget loop

Keep the routine small enough to repeat. The goal is not a perfect audit; it is to avoid beginning the day with a dangerous allowance left open.

StepCheckPass condition
1/permissionsNo Bash(*) or overly broad Bash(npm *) rule
2.claude/settings.jsonsecrets, deploys, database work, and billing are in ask or deny
3/usage and ConsoleYesterday’s spend did not jump without explanation
4git diff and execution logThe approved work matches the diff
5handoff noteOpen allowances, blocked actions, and next reviewer are written down

Use a short starter 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.

Shared settings.json starter

This is a practical .claude/settings.json starting point. defaultMode: "dontAsk" is strict: tools that are not allowed or marked as ask-first do not run. Try it locally before making it the shared project default.

{
  "$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 *)"
    ]
  }
}

The important part is not the exact command list. It is the habit of making safe commands narrow. Bash(npm *) can drift from tests into installs and publishes. Bash(git *) can drift from diff into push. Keep read, lint, test, and build narrow; keep install, push, deploy, and apply behind a human gate.

Keep budget and execution logs as JSON

Permissions are only half of the loop. The other half is spend. Long investigations, repeated failing tests, background sessions, and large pasted logs can grow quietly. Keep a small budget file and a daily log so the review is visible in pull requests.

{
  "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"
  ]
}

Store these as .claude/permission-budget.json and .claude/daily-claude-log.json. A spreadsheet is fine for management reporting, but JSON works better for code review and automation.

Copy-paste Node audit script

Save this as scripts/audit-claude-loop.mjs and run node scripts/audit-claude-loop.mjs. It has no external dependencies. It checks for broad Bash access, deploy commands in the allow lane, missing .env deny rules, budget overruns, and missing handoff notes.

#!/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.");

For CI, start in warning mode or manual mode. A permission budget works only if the team trusts it; a strict gate on day one often creates workarounds instead of better behavior.

Four concrete use cases

The first use case is article and documentation work. Markdown, MDX, internal links, CTAs, typo fixes, and image paths usually do not touch secrets or production systems. Narrowly allow file reads, git diff, lint, tests, and local builds so Claude Code can produce small diffs without stopping on every safe command.

The second use case is dependency changes. npm install and pnpm add affect lockfiles, postinstall scripts, licenses, vulnerabilities, and bundle size. Put them in ask. When Claude Code requests approval, require the reason for the new dependency, the alternative considered, and the removal plan if the change is rejected.

The third use case is deploys and migrations. wrangler deploy, vercel deploy, terraform apply, kubectl apply, and database migrations change external state. Claude Code can draft the command, blast radius, rollback, verification URL, and monitoring checklist, but execution should stay behind human approval.

The fourth use case is team handoff. If someone else continues the work later, write open allowances, proof commands, blocked actions, and remaining budget. Without this note, the next person repeats the same investigation, spends more tokens, and may reopen the same risky permission.

Failure cases to avoid

The most common failure is broad Bash permission. Bash(npm *) and Bash(git *) look convenient, but they mix read-only habits with state-changing commands. Prefer exact commands for the daily lane.

The next failure is a forgotten deploy allowance. During an incident, someone may temporarily move wrangler deploy * from ask to allow. If it stays there the next morning, normal feature work now has production power. The morning loop should explicitly close this.

Another failure is ignoring token and cost growth. A long investigation can feel productive while it burns through budget. Check /usage, compare with Console when billing matters, and stop sessions that are no longer doing useful work.

Finally, do not confuse prompts with enforcement. “Do not read secrets” is guidance. Read(./.env) in deny is enforcement. “Do not deploy” is guidance. Bash(wrangler deploy *) in ask or deny is enforcement. The harness, the agent’s operating frame, needs prompts, settings, logs, and review together.

Products, training, and rollout

For solo practice, copy the JSON files and audit script into a small repository first. For reusable checklists, CLAUDE.md templates, and review prompts, use /products/. For a team rollout that needs permissions, cost controls, CI policy, reviewer training, and repository-specific rules, use /training/.

Practice note: the biggest improvement did not come from blocking every risky command. It came from checking /permissions, /usage, git diff, and the handoff note for five minutes each morning. Narrow allow rules stayed useful, while deploys, billing, and secrets reliably returned to ask or deny.

#claude-code #permissions #security #approval #workflow #team
Free

Free PDF: Claude Code Cheatsheet

Enter your email and download the one-page Claude Code cheatsheet for commands, review habits, and safe workflows.

We handle your data with care and never send spam.

Level up your Claude Code workflow

Start with the free PDF, use Gumroad guides when you need repeatable workflows, and book consultation when rollout or revenue paths need human judgment.

Masa

About the Author

Masa

Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.