A headless agent gets the permissions you write down, and nothing asks twice — cheat sheet
claude-code, ai-agents
# what a run did and what was refused
jq '{result, num_turns, is_error, permission_denials}' run.json
claude -p "…" --output-format json 2>run.err >run.json # keep stderr: trust and config warnings
# the modes, strict to loose
claude -p "…" --permission-mode dontAsk # unattended: anything not allowed is refused
claude -p "…" --permission-mode acceptEdits # edits run without asking — not for jobs
claude -p "…" --dangerously-skip-permissions # = bypassPermissions: disposable machines only
# fewest tools, narrowest allow, caps
claude -p "…" --tools "Read,Edit,Glob,Grep" \
--allowedTools "Edit(./docs/**)" --max-turns 10 --no-session-persistence
# where modes and rules come from (highest first)
cat /etc/claude-code/managed-settings.json # managed
# command line flags / --settings file
cat .claude/settings.local.json # local project (honoured untrusted)
cat .claude/settings.json # shared project: allow ignored by untrusted -p
cat ~/.claude/settings.json # user
grep -rn 'bypassPermissions\|dangerously' ~/.claude .claude ~/bin
# a deny rule for a secret — and why it is not enough with Bash
{ "permissions": { "deny": ["Read(./.env)", "Read(./.env.*)"] } }
# stops: Read, Grep on the file, cat/head/tail .env does not stop: grep -r ., cat .e*
# get deleted files back from the last commit
git status --short
git restore --source=HEAD --staged --worktree -- drafts
# what past runs sent the model
ls ~/.claude/projects/*/ # one .jsonl transcript per session
grep -l 'SECRET_PATTERN' ~/.claude/projects/*/*.jsonl