Explore, with the pen taken away
Read-only exploration: letting an agent look without letting it touch
Ask a coding agent to work out how your auth path reaches the database and it will read files, run greps, open a test, and quite possibly rewrite something on the way. The rewrite happens during the deciding, not during the doing. By the time you read the result, the repository has already moved and reviewing it has turned into archaeology.
Disclosure: I build Ordewell, and a read-only envelope is how its planner works. The interesting part is not the flag. It is what the flag does and does not promise, and there is one failure mode in this area that is worse than having no read-only mode at all.
Exploration is the phase that surprises you
A build request is bounded. You asked for rate limiting on the public route, so a competent agent touches the limiter and maybe the config. An exploration request is unbounded by nature: to say how auth reaches the database, the agent has to decide which files are relevant, and that decision is made by looking. Looking invites edits, because the cheapest way to test a hypothesis about a codebase is to change it.
Three things go wrong in that window. Unrelated files pick up changes that look like yours. The agent's own summary of the codebase becomes the thing you are reviewing, and you cannot tell which parts are findings and which are inventions. And if the session is long enough, the work it eventually does rests on edits it made to its own context on the way. None of those are model-quality problems. They are a permission problem.
What read-only means in each CLI
Read-only is not a property of a model. It is a property of a process, and every coding CLI spells it differently. In Ordewell a planning session is started with the strongest form each harness exposes:
- Claude Code:
--permission-mode plan, with the write tools named explicitly in--disallowedTools(Edit,Write,MultiEdit,NotebookEdit,KillShell). The permission mode already refuses edits. Naming the tools is there so a future permission mode cannot quietly hand the planner aWrite. - OpenCode:
--agent plan, its read-only agent for analysis and exploration. - Codex:
--sandbox read-only, with approvals off, so there is no interactive moment where a write can be waved through.
The guarantee is enforced at spawn, not by asking the model politely in a prompt. That distinction holds up under pressure: when a planning session requests a write anyway, it gets a refusal rather than a permission dialog.
request Write(src/auth/session.ts)
deny The Ordewell planner is read-only.
Mutation belongs to the runners that execute the plan.
Read-only never means the agent sits still. To explore anything it has to run
commands, and most of those are inspection: listings, grep, git
log, reading a test file. Those run unprompted, because prompting on a read is
how an agent turns into a dialogue box. Anything outside that read-only surface is
classified before it runs and denied, and the classifier has to understand the shell
it is in rather than pattern-match a string, since dir under
cmd.exe and dir in a POSIX shell are not the same program.
The envelope is per task, not just per planner
The planner is the obvious place for a read-only session. It is not the only one. A plan usually contains a step whose whole deliverable is understanding: measure the current query counts, confirm which module owns session refresh, list every caller before the signature changes. Those steps want to run in the same envelope, so in Ordewell mode is an assignment on the task like its runner and model.
ordewell task-mode 6 # prints the modes this runner exposes, current one starred
ordewell task-mode 6 plan # keep this task read-only when the plan runs
The useful part is that it is a line in an artifact you read before execution, so an analysis step cannot silently become a code change because the agent got ambitious halfway through. If the task's real output is a decision, say so in the plan and the executor keeps its hands off.
The failure mode that is worse than no sandbox
Here is the part worth knowing before you trust any read-only setup, mine included. A read-only session that cannot run commands does not stop and tell you. It answers from memory, plus whatever it can fetch from the web, and produces a confident plan about a codebase it never read.
A concrete instance, because this is not hypothetical: on Ubuntu 24.04, AppArmor restricts unprivileged user namespaces, so Codex's bubblewrap sandbox fails to start and every command the planner runs dies with an error about the network interface. The agent still replies. What it replies with is a guess shaped like a plan.
The repair is to find out which sandbox actually works on that machine instead of
assuming. Ordewell asks the binary rather than reading /proc or
/etc/apparmor.d, because it is the same question put to the thing that
has to answer it, and it costs one short process. If bubblewrap cannot start, Codex is
pointed at its earlier Landlock backend, which needs no namespace and still denies the
writes that make read-only planning read-only. If both fail, the honest reading is
that Codex cannot explore on this machine at all, and that is a different problem than
a plan you dislike.
What a read-only envelope does not give you
- It is a guarantee on Linux and macOS, and a weaker statement on Windows. On Windows, Codex's own sandboxing is not the kernel-enforced equivalent of Seatbelt or Landlock, so read-only there may be honoured by the tool layer rather than by the operating system. Approvals are still off by construction, but I am not going to call that the same guarantee.
- It says nothing about correctness. A read-only session can still be wrong. The envelope makes a wrong analysis safe to read, not right.
- It does not stop a test suite from mutating your working tree. Read-only governs the agent's tool permissions. A build or test command you allowed can still write build output, caches and fixtures, which is why those commands are a separate decision from this one.
- It is not a security boundary against a hostile agent. It is a guardrail against the ordinary case: a capable model doing something reasonable that you did not ask for in a directory you care about.
- It costs you a round trip. An agent that can write explores by editing. An agent that cannot has to reason from what it reads, and some questions genuinely are faster to answer by trying.
Running it
The planner runs read-only by default, and nothing in the plan executes until you say go, so exploring costs you nothing but the plan itself.
npm install -g ordewell
AI_PROVIDER=claude-code ordewell plan --goal "Map how request auth reaches the database layer"
ordewell task-mode 6 plan
ordewell run
If you want the wider argument for separating the thing that decides from the thing that writes, plan-first orchestration covers when that shape wins, and assigning an executor per task is where the runner, model and mode decisions live. The verification side is the other half of the same question: an envelope controls what an agent may change, and a marker decides whether it actually did the job.