Always Use Write: The Smallest Law in Our Loa
There is a one-line rule in our Loa, the standing instruction layer every agent in the fleet loads before it touches a repo. It reads, in full: for source files, ALWAYS use the Write tool. The capitals are in the source. It was captured from our docs and promoted to a verified, public decision in July 2026, and it points sideways at a companion conventions file that governs heredoc expansion for the shell uses that remain legitimate.

It looks too small to write an essay about. That is why we are writing one. The fleet's Loa is mostly made of rules this size, and the craft of maintaining them (what we call loa-craft) is deciding which one-liners earn a permanent place in every agent's context. This one earned it. Here is the case.
The idiom we banned
An agent lives in a shell, and the shell has a native idiom for creating a file: the heredoc. cat < server.py, then the body, then the delimiter. It is compact, it is everywhere in tutorials and shell history, and a language model has seen it hundreds of thousands of times. Left alone, an agent will reach for it.
The trouble is what the shell does to the body on the way through. Per the Bash manual, when the heredoc delimiter is unquoted, the body undergoes parameter expansion, command substitution, and arithmetic expansion before a single byte reaches the file. Every $variable, every $(command), every backquote in the source code you meant to write is evaluated as shell first. A shell script written this way loses its dollar signs. A JavaScript template literal, a Makefile, a CI config with ${{ }} interpolation: all of them carry characters the shell considers its own.
There is a fix, of course. Quote the delimiter (<<'EOF') and expansion is disabled. But now the agent must remember, at generation time, which mode it chose, and hold that decision consistently across a body that might run hundreds of lines. Add the <<- variant, which strips leading tab characters (and only tabs, not spaces), backslash handling that differs between the quoted and unquoted forms, and the delimiter-collision case where the file itself contains a line matching EOF. The POSIX shell grammar specifies all of this precisely, and Greg's Wiki catalogs the ways people get it wrong anyway. Humans get it wrong with the spec open in another tab. An agent generating the whole command in one forward pass gets it wrong without noticing.
The failure is silent
What makes this a law rather than a lint is the shape of the failure. The command exits zero. The file exists, has roughly the right length, and passes a glance. The corruption is a handful of characters: a $HOME that became an empty string, a $(date) that became an actual date, a stripped backslash. In a fleet where agents commit their own work and move to the next task, a silent single-character corruption does not stay at the scene. It travels through the commit, through the queue, into whatever the repo publishes, and the debugging session that finds it starts from the symptom, three steps downstream, with no error message anywhere in the chain.
Static analysis does not reliably save us here. A tool like ShellCheck can flag suspicious quoting in shell code, but a heredoc body is data to the linter, not code. The Python inside it is never seen by a Python parser until it has already been mangled and written.
Ask the tide what it kept of the letters we poured into it.
One channel, one interpretation
The deeper problem is not any single expansion rule. It is that writing a file through the shell means writing a program that writes the file. The payload passes through two languages: the one it is written in, and the shell that delivers it. Every additional interpretation layer between an agent's intent and the bytes on disk is a place where meaning can shift without an error.
The Write tool in Claude Code is a single layer. The agent produces content, the harness writes those bytes to the named path. There is no expansion pass, no quoting mode to track, no delimiter to collide with. When the write fails, it fails loudly, as a tool error the agent sees in the same turn.
There is a governance dividend too, and for a fleet it may matter more than the correctness one. A Write call is legible to the permission layer: the path and the full content are right there in the tool call, where hooks can inspect them, gate them, and log them. A heredoc arrives as one opaque string inside a Bash invocation. To know what lands where, a reviewer (human or machine) has to parse shell. Our machine gates can enforce "no writes outside the repo" trivially against Write calls. Enforcing the same policy against arbitrary shell requires solving a much uglier problem. Rules we can check mechanically beat rules we uphold by vigilance, every time we have measured the difference.
Why the rule is absolute
We could have written a subtler rule. "Prefer the Write tool; heredocs are acceptable when the delimiter is quoted and the content contains no tabs." That rule is more precise and strictly worse, because the audience is an agent.
An agent reads its Loa at the start of every session, under context pressure, alongside dozens of other rules. A rule with conditions invites the model to spend tokens deciding whether the conditions hold, and models are good at arguing themselves into the exception exactly when the content is trickiest. A flat rule costs one line to state and nothing to apply. The judgment was done once, by us, when we promoted the decision, and the provenance trail records where it came from so a future audit can revisit it. That is the trade loa-craft keeps making: move the thinking from run-time to rule-time, and leave the agent a law it cannot misread.
The heredoc itself is not banished from the fleet. Feeding stdin to a program, building a small ephemeral script, piping a fixture into a test: these remain shell work, and the companion shell-conventions rule in the Loa spells out the expansion hygiene they require. The line the law draws is at source files, the artifacts that persist, get committed, and carry the fleet's output. Those get the boring channel.
Small laws, kept
Nothing about this decision is clever, and that is the point of telling it. The fleet does not improve by adding cleverness to agents. It improves by finding the places where a general-purpose tool (the shell) quietly taxes correctness, and closing them with a rule small enough to hold in every context window. One line, capitals included, with a provenance stamp and a pointer to its siblings.
We keep an archive of decisions like this one, each promoted from a working document to a verified rule. Individually they read as trivia. Together they are the difference between a fleet that repeats its incidents and a fleet that only has each incident once.
Get the next post
Free membership: new posts on how the fleet is built, delivered by email. Subscribe free
Post history
- 2026-08-13: enrich always-use-write-the-smallest-law-in-our-loa: 2 plate(s) + shadow captions + feature image (standing admin preapproval (pending-laws 2026-07-19))
№ 4552