Choosing a permission mode per task
In this lesson we give a coding agent the same small task twice. The first
time it asks before every edit and every command. The second time it edits
without asking and only stops for commands. We count the prompts in each
run and read what they were for. Then we decide which mode the task
deserved. The setting is the to-do fixture from Your first session with a
coding agent, committed to a throwaway git repository, where a wrong edit
costs one git checkout.
The mode names and flags here are Claude Code’s, checked against the vendor’s documentation on the date at the end of the lesson [1]. Other coding agents have the same levels under other names. The reasoning transfers, and the exact flags may not.
The modes are presets
Section titled “The modes are presets”In your first session the agent asked before it edited a file, and you
approved one line at a time. That behavior is a setting. Permission
modes are preset levels of how much the agent may do without asking,
from approving every action to running unattended. The mode sets the
baseline for the session, and the allowlists you write in the next lesson
widen or narrow it per command. Which mode a fresh session starts in
depends on your plan and your settings. On some plans the built-in
starting mode is auto, so check the status bar before you assume the
agent asks [1].
Claude Code’s modes, with what runs without a prompt in each. The last column is our paraphrase of the vendor’s advice on when to use it [1].
| Mode (config value) | Runs without asking | When the vendor suggests it |
|---|---|---|
default (Manual) | Reads | You want to see each action, or the work is sensitive |
acceptEdits | Reads, file edits in the working directory, and file commands such as mkdir, mv and cp | Code you read back afterwards |
plan | Reads and exploratory shell commands. Edits are blocked until you approve a plan | Understanding a codebase before you change it |
auto | Everything a second model, the classifier, approves | Long tasks where the prompts wear you down |
dontAsk | Reads and pre-approved tools. Anything that would prompt is denied instead | CI and scripts with an exact allowlist |
bypassPermissions | Everything, apart from the few actions listed below | Only inside a container or virtual machine that isolates it |
The acceptEdits and bypassPermissions rows have fine print that
matters for this lesson. acceptEdits approves an edit only when
the path is inside the working directory, and any shell command outside
the built-in read-only set still prompts, so the test run in our task
stops for you in that mode too. bypassPermissions skips the permission
prompts, including for writes to protected paths such as .git that the
other modes guard. A few actions still prompt in it: a tool matched by an
ask rule you wrote, and a tool that needs your answer to work. The
vendor’s own page limits the mode to isolated containers and virtual
machines, and the tool refuses to start in it as root or under sudo,
“for security reasons”, as the vendor puts it
[1].
You pick the mode for one session with a flag, claude --permission-mode acceptEdits, or cycle through the modes in a running session with
Shift+Tab. A defaultMode entry in a settings file sets where every
session starts, with one exception: auto and bypassPermissions in a
project’s settings files don’t take effect, so a repository can’t check in
a setting that starts every clone in a hands-off mode
[1]. This lesson uses the flag. Each run then
states its mode in the command that started it.
Here is the decision as a small program. NO_PROMPT holds the table above
for the three kinds of action our task uses, and TASK is the task as
the agent most often does it: two reads, two edits, one command. The complete file is
site/examples/customizing-agents/permission-modes/modes.py in the
repository.
NO_PROMPT = { "default": {"read"}, "acceptEdits": {"read", "edit"}, "bypassPermissions": {"read", "edit", "run"},}
TASK = [ ("read", "todo.py"), ("read", "test_todo.py"), ("edit", "todo.py"), ("edit", "test_todo.py"), ("run", "python3 -m unittest -q"),]
def prompts(mode, actions): return [f"{kind} {target}" for kind, target in actions if kind not in NO_PROMPT[mode]]Count the prompts
Section titled “Count the prompts”A small Python program models which actions a coding agent's permission mode lets through without a prompt. NO_PROMPT maps three modes to the kinds of action (read, edit, run) that need no approval, and TASK lists five actions: two reads, two edits and one command.
What does this print, one line per mode?
for mode in ("default", "acceptEdits", "bypassPermissions"): count = len(prompts(mode, TASK)) noun = "prompt" if count == 1 else "prompts" print(f"{mode}: {count} {noun}")default: 3 prompts acceptEdits: 1 prompt bypassPermissions: 0 prompts
Output verified in CI from site/examples/customizing-agents/permission-modes/modes.py.
For each mode, which kinds of action in TASK are missing from its NO_PROMPT set?
The program is a model. The real agent may edit a file twice or run an
extra command, and each of those adds a prompt in the modes that ask for
it. Reads don’t change the tally, because no mode prompts for a read
inside the working directory. Your counts in the two runs below can differ from the
model by one or two. The comparison stays the same: every edit and every
command prompts in Manual mode, only the commands prompt in acceptEdits,
and nothing prompts in bypassPermissions.
Run one: ask before everything
Section titled “Run one: ask before everything”Make a fresh copy of the fixture directory,
site/examples/coding-with-agents/first-session/fixture-repo/, outside the
course repository, and change into it. The copy has no git history of its
own, so give it one before the agent touches anything. This commit is the
point you reset to between the runs.
git init -q && git add -A && git commit -q -m "fixture"Run the tests next. One of them fails on purpose, because that bug is the first-session lesson’s task, and you want to know that before the agent tells you.
The suite before the agent starts
Section titled “The suite before the agent starts”Run this and compare the last line with the output below.
python3 -m unittest -qFAILED (failures=1)
Output verified in CI from site/examples/coding-with-agents/first-session/tests.py.
Start the agent in Manual mode, claude --permission-mode default, and
send this brief.
Add an `undo` command to todo.py that marks item N as not done, themirror of `done`. Add one test for it to test_todo.py. Then run`python3 -m unittest -q`. One test, test_done_marks_the_numbered_item,already fails and is not your task. Leave it. Do not edit todos.json.Now count. Keep a tally of every prompt, and for each one write down what
it asked to do: which file, or which command. Approve each one after you
have read it. Expect an edit to todo.py, an edit to test_todo.py and
one command, and don’t be surprised by a second edit to the same file.
The agent also reads both files first, and those reads never prompt.
When the agent reports done, read the diff with git diff and check the
tally against it. Every changed file should have a prompt in your list.
Then reset the fixture to the commit you made with git checkout -- . so
the second run starts from the same place.
Run two: accept the edits
Section titled “Run two: accept the edits”Start the agent again, this time with claude --permission-mode acceptEdits, and send the same brief. The status bar reads
accept edits on. Tally again.
This time the two edits are written without a prompt, and the session
stops once, at the test command. The vendor’s guidance for this mode is
to review the changes afterwards in your editor or with git diff, rather
than approving each edit inline [1]. Do that
now. Read the diff as carefully as you read the prompts in run one,
because this is the first time you see what changed.
Now compare the two runs on one question: what would a mistake have cost?
In run one, a wrong edit shows up in a prompt before it is written, and
you decline it. In run two, the same wrong edit is written, and you find it
in the diff. The fixture is a committed copy you reset with one command,
so in both runs the repair costs the same git checkout. The mode changed
when you saw the edit, and the place decided how much a late look could
cost. Choose the mode by what a mistake costs in the place the agent
works, and remember the blast radius habit from the safety course: say
out loud what the agent can reach before you press enter.
The same task in your own repository
Section titled “The same task in your own repository”A developer has just run a small task in a committed fixture repository in the accept-edits permission mode of a coding agent, where edits and file commands are written without a prompt. They now want the same task done in their team's real repository.
The undo task went well in the fixture. You want the same change in your
team’s repository, where you have half a day of uncommitted work in the
working tree. Which mode do you start with, and what do you do first?
What is in the working tree that a mode with no edit prompts could touch, and is there a cheaper way to protect it than a prompt on every edit?
Which mode for which task
Section titled “Which mode for which task”The vendor’s course on running the tool unattended makes the same point from the other side: hands-off runs belong in an environment built to be thrown away, such as a container, and the check afterwards is the review of what it produced [2]. The mode is the last thing you choose, after you know where the agent works and what a wrong action there would cost.
Which mode for which task?
Section titled “Which mode for which task?”Claude Code's permission modes: default (Manual) prompts before every edit and command, acceptEdits approves edits inside the working directory but prompts for other commands, plan reads and blocks edits until a plan is approved, and bypassPermissions skips the permission prompts and is meant for isolated containers and virtual machines.
Place each task in the mode you would start it in.
For each task, what does the agent need to do without stopping, and what would a wrong action cost in that place?
What does each mode do?
Section titled “What does each mode do?”Claude Code has four permission modes that this lesson compares: default, acceptEdits, plan and bypassPermissions.
Match each description to its mode.
Which actions go through without a prompt in each mode?
Modes and rules together
Section titled “Modes and rules together”In Claude Code the permission mode sets the baseline, and allow, ask and deny rules in the settings refine it per command.
Which two of these are true?
Which rules still count when the mode skips the prompts?
An overnight run without prompts
Section titled “An overnight run without prompts”The lesson chooses a mode by what a mistake would cost where the agent works, and steps a mode up only inside a sandbox or a container.
You want an overnight task to run with the permission prompts skipped. Where does it run?
What can the agent reach from where it runs, if a step goes wrong at 3 a.m.?
Exercise
Do the two runs from this lesson, if you haven’t already, in a fresh
copy of the fixture with its own first commit: once in Manual mode and
once in acceptEdits, with the same brief. For each run write down the
number of prompts and what each one asked for. Then write one line that
names the mode you would use for this task in this place, and why. The
point is to practice choosing a mode from what a mistake costs, before you
do it in a repository that matters.
A good result: the Manual tally has one entry per edit and per command,
the acceptEdits tally has only the command, both diffs contain the same
change, and your one line mentions where the agent worked and what a wrong
edit would have cost there. Reflection: in which of your own repositories
would the answer be different, and what’s in them that makes it so?
Stretch: Run the task a third time in plan mode and note where the agent stops: it reads and proposes, and the edits wait until you approve the plan.
Recap
- A permission mode is a preset for what the agent may do without asking.
In Claude Code,
defaultprompts for every edit and command,acceptEditsapproves edits inside the working directory and still prompts for other commands,planblocks edits, andbypassPermissionsskips the permission prompts apart from your ownaskrules and the tools that need your answer [1]. - The mode sets the baseline, and allowlists refine it per command. Deny
rules hold in every mode, and allow rules do nothing in
bypassPermissions. - Choose the mode by what a mistake would cost in the place the agent works, and say the blast radius out loud first.
- Step a mode up only inside a sandbox or a container, and only as far as the task in front of you needs. A worktree or a branch isn’t isolation.
- In a mode that skips prompts, the diff is your review. Read it as carefully as you would have read the prompts.
You can now
- Sets permissions to the least the work needs
References
Section titled “References”- Anthropic. Choose a permission mode. Claude Code documentation. Reference.
Claude Code permission modes - Anthropic. Claude Code in action. Claude Academy. Course.
Academy claude-code-in-action