<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>README — documentation</title>
<link>https://readme.news/tags/documentation/</link>
<atom:link href="https://readme.news/tags/documentation/feed.xml" rel="self" type="application/rss+xml"/>
<description>README pieces tagged documentation.</description>
<language>en-us</language>
<lastBuildDate>Thu, 01 Oct 2026 13:20:31 +0000</lastBuildDate>
<item><title>The unreasonable effectiveness of a changelog</title><link>https://readme.news/the-unreasonable-effectiveness-of-a-changelog/</link><guid isPermaLink="true">https://readme.news/the-unreasonable-effectiveness-of-a-changelog/</guid><pubDate>Wed, 22 Jul 2026 09:00:00 +0000</pubDate><description>A file that takes ten minutes per release and answers most of the questions your users would otherwise ask you.</description><content:encoded><![CDATA[<p>Most projects do not have a changelog. Most projects have a commit log and a release page auto-generated from pull request titles, which is not the same thing and does not serve the same purpose.</p>
<p>A real changelog is a small amount of work with an outsized return.</p>
<h2 id="what-it-is-for">what it is for<a class="anchor" href="#what-it-is-for" aria-label="link to this section">#</a></h2>
<p><strong>Deciding whether to upgrade.</strong> The single most common reason someone reads a changelog. They are on version 3.2, version 3.7 exists, and they want to know whether it is worth the risk.</p>
<p><strong>Knowing what will break.</strong> The most important information you can provide, and the thing auto-generated release notes are worst at.</p>
<p><strong>Debugging.</strong> "This started failing after we upgraded" — a good changelog turns that into "here is the change that caused it" in thirty seconds.</p>
<p><strong>Finding out what exists.</strong> People discover features by reading changelogs. This is a real and underrated distribution channel for your own work.</p>
<h2 id="why-generated-release-notes-are-not-enough">why generated release notes are not enough<a class="anchor" href="#why-generated-release-notes-are-not-enough" aria-label="link to this section">#</a></h2>
<p>A list of merged pull request titles has three problems.</p>
<p><strong>It is written for the wrong audience.</strong> "Refactor connection handling" means something to the maintainer and nothing to the user. What changed <em>for them</em>?</p>
<p><strong>It has no hierarchy.</strong> A breaking change and a typo fix appear as sibling bullets of equal weight.</p>
<p><strong>It has no migration guidance.</strong> "Remove deprecated <code>parse()</code> method" tells you something broke. It does not tell you what to do about it.</p>
<h2 id="the-format">the format<a class="anchor" href="#the-format" aria-label="link to this section">#</a></h2>
<p>Keep a Changelog is the established convention and it is good. The structure:</p>
<div class="code"><span class="code-lang">markdown</span><pre><code class="lang-markdown">## [4.2.0] - 2026-07-22

### Breaking
- `Client.connect()` no longer accepts a positional timeout.
  Pass `timeout=` as a keyword.
      # before
      client.connect(host, 30)
      # after
      client.connect(host, timeout=30)

### Added
- `Client.ping()` for health checks without a full round trip (#412)
- Support for Unix domain sockets via `unix://` URLs (#398)

### Fixed
- Connections leaked when the handshake timed out (#405).
  If you saw file descriptor exhaustion under load, this was it.

### Deprecated
- `Client.legacy_mode` — will be removed in 5.0. Use `compatibility=`.

### Security
- Fixed a case where credentials could appear in debug logs (GHSA-xxxx-xxxx).
  Affects 4.0.0–4.1.3. Rotate credentials if debug logging was enabled.</code></pre></div>
<h2 id="the-rules-that-make-it-useful">the rules that make it useful<a class="anchor" href="#the-rules-that-make-it-useful" aria-label="link to this section">#</a></h2>
<p><strong>Breaking changes first, always.</strong> That is what people are scanning for. Do not bury them under twelve feature bullets.</p>
<p><strong>Include the migration.</strong> A breaking change without "do this instead" makes the reader open your source code. Two lines of before-and-after saves everyone time.</p>
<p><strong>Describe the user-visible effect, not the implementation.</strong> Not "refactored the retry logic." Rather: "<a class="xref" href="/retries-a-complete-guide-to-not-making-it-worse/" title="Retries: a complete guide to not making it worse">retries</a> now use exponential backoff with jitter; if you relied on the previous fixed 1-second interval, set <code>retry_delay=1.0</code>."</p>
<p><strong>Say who is affected.</strong> "If you use X, this changes for you. Otherwise nothing changes." Most readers can then stop reading, which is a service.</p>
<p><strong>Link to the issue or pull request</strong> for anyone who wants detail. The changelog is a summary, not a substitute.</p>
<p><strong>Date every release</strong>, in ISO format. Version numbers alone do not tell you whether you are two months or three years behind.</p>
<p><strong>Write it as you go</strong>, not at release time. An <code>Unreleased</code> section at the top that each pull request adds to. Reconstructing a changelog from git history at release time is miserable and it is why changelogs get skipped.</p>
<h2 id="the-security-section-specifically">the security section specifically<a class="anchor" href="#the-security-section-specifically" aria-label="link to this section">#</a></h2>
<p>If you fix a security issue, say so, with:</p>
<ul><li>Which versions are affected.</li><li>What the impact is.</li><li>Whether any action beyond upgrading is required.</li></ul>
<p>That last one is the part that gets omitted and it is critical. "Upgrade to 4.2.0" is insufficient if credentials may have been exposed — the user also needs to rotate them, and they will not know unless you say so.</p>
<h2 id="for-internal-projects">for internal projects<a class="anchor" href="#for-internal-projects" aria-label="link to this section">#</a></h2>
<p>The same file works for internal services, and the audience is your future self and the person who takes over the service.</p>
<p>The most valuable internal changelog entries are the ones that record a decision:</p>
<div class="code"><span class="code-lang">markdown</span><pre><code class="lang-markdown">## 2026-07-14
- Switched from polling to webhooks for order status. Polling was
  costing ~40 requests/second against the vendor's rate limit and
  we were getting throttled during peaks.</code></pre></div>
<p>Six months later, when someone asks why there is webhook infrastructure, the answer is in one place.</p>
<h2 id="the-return-on-investment">the return on investment<a class="anchor" href="#the-return-on-investment" aria-label="link to this section">#</a></h2>
<p>Ten minutes per release. In exchange:</p>
<ul><li>Fewer support questions.</li><li>Faster upgrades by your users, which means fewer people on old versions you have to support.</li><li>Fewer surprised users after a breaking change.</li><li>A record you can search when debugging.</li></ul>
<p>There are not many ten-minute tasks with that profile.</p>]]></content:encoded></item><item><title>The onboarding document that actually works</title><link>https://readme.news/the-onboarding-document-that-actually-works/</link><guid isPermaLink="true">https://readme.news/the-onboarding-document-that-actually-works/</guid><pubDate>Mon, 13 Jul 2026 09:00:00 +0000</pubDate><description>Most onboarding docs are written by people who already know. Here is what a new engineer needs on day one, in order.</description><content:encoded><![CDATA[<p>Onboarding documentation is written by someone who already knows the system, which means it is written from the wrong side of the knowledge gap.</p>
<p>The result is consistently: an architecture overview that is meaningless without context, a list of tools with no explanation of why, and no answer to any question a new person actually has.</p>
<h2 id="what-a-new-engineer-actually-needs-in-order">what a new engineer actually needs, in order<a class="anchor" href="#what-a-new-engineer-actually-needs-in-order" aria-label="link to this section">#</a></h2>
<p><strong>Day one: get something running.</strong></p>
<p>Not understanding. Running. A new engineer who has the application running locally on day one is in a completely different position from one who is still fighting a dependency on day three.</p>
<p>This section should be a numbered list of commands that work. Tested. On a clean machine. Recently.</p>
<div class="code"><span class="code-lang">markdown</span><pre><code class="lang-markdown">## get it running

1. Install prerequisites:  `brew bundle`   (or the equivalent — see below)
2. Copy the environment:   `cp .env.example .env`
3. Get secrets:            `./scripts/fetch-dev-secrets` (needs VPN)
4. Start dependencies:     `docker compose up -d`
5. Migrate:                `./scripts/db-reset`
6. Run:                    `pnpm dev`

You should see the app at http://localhost:5173 with seeded data.
Log in with dev@example.com / password.

If step 3 fails with "unauthorized", you need to be added to the
dev-secrets group — ask in #eng-onboarding.</code></pre></div>
<p>That last paragraph — the anticipated failure with its resolution — is the part that separates a document that works from one that does not. Every step that has ever failed for anyone should have a note.</p>
<p><strong>Day two: make a change and see it.</strong></p>
<p>A guided first change. Something trivial and real: change a label, add a field, fix a typo in a template. All the way through: edit, test, review, merge, deploy.</p>
<p>The point is not the change. It is that they have now executed the entire delivery pipeline once, so every subsequent change is a variation on something they have done.</p>
<p><strong>Day three to five: the map.</strong></p>
<p><em>Now</em> the architecture overview, and now it means something, because they have seen the system run.</p>
<p>Keep it to a page. What are the major pieces, what does each do, how do they talk. A diagram. Where the code for each piece lives.</p>
<p>Not a complete description. A map, at the resolution of "which building do I go to."</p>
<p><strong>Week two: the why.</strong></p>
<p>The decisions that are not obvious from the code. Why the database is structured that way. Why there is a queue between those two services. Why that module is frozen. Why the obvious approach to X does not work.</p>
<p>This is the highest-value and least-written documentation in any organization, because it exists only in the heads of people who were there. When they leave, it is gone, and the next person spends a year rediscovering it — usually by proposing the obvious approach and being told no.</p>
<h2 id="the-sections-everyone-forgets">the sections everyone forgets<a class="anchor" href="#the-sections-everyone-forgets" aria-label="link to this section">#</a></h2>
<p><strong>The glossary.</strong> Every organization has jargon: internal product names, acronyms, words used with a specific local meaning. A new person hears twenty of these in their first week and cannot ask about all of them without feeling stupid.</p>
<p>Write them down. This is a thirty-minute task with an outsized payoff.</p>
<p><strong>Who to ask about what.</strong> Not the org chart. "Payments: ask Priya. Deploy pipeline: #platform-help. Anything about the legacy importer: Marcus, and be warned it is complicated."</p>
<p><strong>The things that will surprise you.</strong> The test suite that fails on the first run until you seed a fixture. The service that takes four minutes to start. The one flaky test everyone knows about. The staging environment that resets on Sundays.</p>
<p>Every codebase has these. Writing them down converts "this is broken and I do not want to admit I cannot fix it" into "oh, that is expected."</p>
<p><strong>What not to touch.</strong> Frozen modules, generated files, anything requiring a specific review.</p>
<h2 id="the-maintenance-mechanism">the maintenance mechanism<a class="anchor" href="#the-maintenance-mechanism" aria-label="link to this section">#</a></h2>
<p>Onboarding docs rot faster than any other documentation, because the people who would notice the errors are the ones who no longer read it.</p>
<p><strong>The fix: the last person onboarded owns it.</strong></p>
<p>Every new engineer's first task is to follow the document, fix everything that was wrong, and add the things they had to ask about. Then they own it until the next person arrives.</p>
<p>This works because their frustration is fresh and their perspective is exactly the target reader's. It is the only mechanism I have seen that keeps these documents accurate.</p>
<h2 id="the-test">the test<a class="anchor" href="#the-test" aria-label="link to this section">#</a></h2>
<p>Hand it to a new engineer and do not help them.</p>
<p>Time how long until they have the application running. Note every question they had to ask. Each question is a gap, with a measured cost.</p>
<p>Then fix them, and repeat with the next person.</p>
<p>Most teams have never done this and would be surprised by the result.</p>]]></content:encoded></item><item><title>Design docs people actually read</title><link>https://readme.news/design-docs-people-actually-read/</link><guid isPermaLink="true">https://readme.news/design-docs-people-actually-read/</guid><pubDate>Wed, 18 Mar 2026 09:00:00 +0000</pubDate><description>The average design doc is eleven pages and gets three comments, all on page one. Here&#x27;s the format that works.</description><content:encoded><![CDATA[<p>Most design documents are written to satisfy a process and read by nobody. You can tell because the comments cluster in the first two pages and stop.</p>
<p>A design doc that works has a different shape, and the shape follows from being honest about why you are writing it.</p>
<h2 id="why-you-are-actually-writing-it">why you are actually writing it<a class="anchor" href="#why-you-are-actually-writing-it" aria-label="link to this section">#</a></h2>
<p>Three reasons, and they want different documents:</p>
<p><strong>To think.</strong> Writing forces you to discover that your plan has a hole. This version is for you and can be messy.</p>
<p><strong>To get input before it is expensive.</strong> The highest-value function. You want the person who knows the thing you do not know to tell you before you build.</p>
<p><strong>To create a record.</strong> So that in two years, someone can find out why.</p>
<p>Most templates optimize for the third and produce documents that fail at the second. The record is only worth having if the decision was good, and the decision is good because of the input.</p>
<h2 id="the-format">the format<a class="anchor" href="#the-format" aria-label="link to this section">#</a></h2>
<p>One page. Two if the problem genuinely needs it. Structured so a reader can stop after any section and have gotten something.</p>
<p><strong>Problem.</strong> What is wrong right now, with evidence. Not "we should improve X" — what breaks, how often, who it affects. If you cannot state the problem concretely, the design is premature.</p>
<p><strong>Goals and non-goals.</strong> The non-goals are the important half and almost always missing. "This does not address the reporting pipeline" prevents forty comments about the reporting pipeline.</p>
<p><strong>Proposal.</strong> What you are going to build, in enough detail to disagree with. Interfaces, data shapes, the sequence of operations. A diagram if the shape is not obvious in prose.</p>
<p><strong>Alternatives considered.</strong> Two or three, each with one honest sentence about why not. This is the section that gets the good comments, because it is where a reader sees the option you dismissed for a reason they know is wrong.</p>
<p>If your alternatives section contains obvious strawmen, experienced readers will notice and discount the whole document.</p>
<p><strong>Risks and open questions.</strong> What might go wrong. What you are unsure about. This is where you ask for help explicitly, and it is where the people who know things will engage.</p>
<p><strong>Rollout.</strong> How it ships, how it is verified, how it is rolled back. A design without a rollback plan is not finished.</p>
<p>That is it. Under a thousand words for most things.</p>
<h2 id="the-things-that-make-people-not-read-it">the things that make people not read it<a class="anchor" href="#the-things-that-make-people-not-read-it" aria-label="link to this section">#</a></h2>
<p><strong>Length.</strong> Past about two pages, readership drops sharply. If you need more, put the detail in an appendix and keep the main document short.</p>
<p><strong>Burying the proposal.</strong> If the reader has to get through three pages of background before learning what you want to do, they will not.</p>
<p><strong>No clear ask.</strong> Say what you want. "I need someone who knows the payment path to confirm the <a class="xref" href="/idempotency-is-the-only-distributed-systems-concept-you-need/" title="Idempotency is the only distributed systems concept you need">idempotency</a> assumption in section 3" gets a response. "Please review" does not.</p>
<p><strong>Passive voice throughout.</strong> "It was determined that" hides who decided and why. It also reads as evasive, because it usually is.</p>
<p><strong>No deadline.</strong> "Comments by Thursday, I will start Friday" produces comments by Thursday. An open-ended review produces comments never.</p>
<h2 id="the-review-that-works">the review that works<a class="anchor" href="#the-review-that-works" aria-label="link to this section">#</a></h2>
<p><strong>Ask specific people specific questions.</strong> Not "posting this to the channel." Three named people, each with a sentence about why you want their input.</p>
<p><strong>Give a real window.</strong> Three to five days. Long enough to fit into someone's week, short enough to stay on the top of the pile.</p>
<p><strong>Timebox the meeting, if there is one.</strong> For a contentious design, a 30-minute discussion after people have read it resolves more than two weeks of comments. For an uncontentious one, do not have a meeting.</p>
<p><strong>Record the decision at the top when it is made.</strong> A resolved design doc should start with "Decision: we are doing X, decided 2026-03-18, because Y." The person finding this in 2028 wants that sentence and nothing else.</p>
<h2 id="the-thing-that-makes-them-worth-writing">the thing that makes them worth writing<a class="anchor" href="#the-thing-that-makes-them-worth-writing" aria-label="link to this section">#</a></h2>
<p>The value is not the document. It is that you discovered the flaw while writing rather than while implementing, and that someone who knew something told you before you had built the wrong thing.</p>
<p>If you write a design doc and nothing changes as a result, either your design was already right — possible, uncommon — or nobody engaged, and the process is theater.</p>
<p>Measure it that way: how many of your design docs changed the design? If the answer is none, stop writing them in this format and figure out what would actually get you input.</p>]]></content:encoded></item><item><title>Documentation is a product and you should staff it like one</title><link>https://readme.news/documentation-is-a-product-and-you-should-staff-it-like-one/</link><guid isPermaLink="true">https://readme.news/documentation-is-a-product-and-you-should-staff-it-like-one/</guid><pubDate>Fri, 20 Feb 2026 09:00:00 +0000</pubDate><description>Every team says docs matter. Almost none of them assign an owner, a budget, or a metric.</description><content:encoded><![CDATA[<p>Ask any engineering team whether documentation matters and they will say yes. Ask who owns it and you will get a pause.</p>
<p>That pause is the entire problem.</p>
<h2 id="the-four-kinds-and-why-mixing-them-fails">the four kinds, and why mixing them fails<a class="anchor" href="#the-four-kinds-and-why-mixing-them-fails" aria-label="link to this section">#</a></h2>
<p>The taxonomy that fixed documentation for me — and it is not mine, it is the Diátaxis framework — is that there are four distinct kinds and they have incompatible goals.</p>
<p><strong>Tutorials</strong> teach a beginner by having them do something that works. The goal is a successful experience, not completeness. A tutorial that mentions every option has failed. It should be prescriptive, opinionated, and it should work exactly as written, every time.</p>
<p><strong>How-to guides</strong> help someone accomplish a specific task they already understand. "How to configure TLS." Goal-oriented, assumes competence, skips explanation.</p>
<p><strong>Reference</strong> describes the machinery precisely and completely. Every parameter, every return value, every error. Boring by design. Generated where possible.</p>
<p><strong>Explanation</strong> provides understanding. Why is it designed this way? What are the trade-offs? What is the mental model? This is the kind that is almost always missing and the kind that most reduces support burden.</p>
<p>Most documentation fails because it tries to be all four at once. A tutorial that stops to explain architecture loses the beginner. A reference page with a narrative is hard to scan. Separate them, label them, and each one gets better.</p>
<h2 id="what-staff-it-like-a-product-means">what "staff it like a product" means<a class="anchor" href="#what-staff-it-like-a-product-means" aria-label="link to this section">#</a></h2>
<p><strong>One named owner.</strong> Not "the team." A person whose review includes it.</p>
<p><strong>A budget in the sprint.</strong> Documentation work sized and scheduled alongside features, not appended to the end of a ticket where it gets cut.</p>
<p><strong>Metrics.</strong> Support tickets that a doc would have prevented. Search queries with no results. Time-to-first-successful-request for a new user. Page-level feedback. Every one of these is measurable and almost nobody measures them.</p>
<p><strong>A definition of done that includes it.</strong> A feature is not shipped until it is documented. This is either enforced or it is a slogan; there is no middle.</p>
<h2 id="the-practices-that-actually-move-the-needle">the practices that actually move the needle<a class="anchor" href="#the-practices-that-actually-move-the-needle" aria-label="link to this section">#</a></h2>
<p><strong>Docs live with the code.</strong> Same repository, same pull request, same review. Documentation in a separate wiki drifts within one quarter, guaranteed, without exception.</p>
<p><strong>Test the examples.</strong> Every code sample in your docs should be extracted and run in CI. Broken examples are worse than no examples — they destroy trust in the whole document, and every set of docs has them, because they were correct when written.</p>
<p><strong>Write the failure cases.</strong> The single highest-value section in any documentation is "common errors and what they mean." This is what <a class="xref" href="/stack-overflows-traffic-fell-off-a-cliff-and-it-is-not-coming-back/" title="Stack Overflow&#x27;s traffic fell off a cliff and it is not coming back">Stack Overflow</a> existed to provide and it is the thing your docs almost certainly lack.</p>
<p>Go read your support queue. Every recurring question is a documentation gap with a measured frequency attached.</p>
<p><strong>Date and version everything.</strong> "This page describes v4.2, last updated 2026-01-15." Undated documentation is untrustworthy documentation, because the reader cannot tell whether it is current.</p>
<p><strong>Make the first example work.</strong> The single most common documentation failure: the quickstart does not run. Someone changed a default, renamed a parameter, required a new config field. Test the quickstart in CI, on a clean environment, on every release.</p>
<h2 id="the-argument-that-gets-budget">the argument that gets budget<a class="anchor" href="#the-argument-that-gets-budget" aria-label="link to this section">#</a></h2>
<p>Documentation is deflection. Every question answered by a doc is a question not asked of an engineer.</p>
<p>Count your support load. Estimate the fraction that is documentation-shaped — "how do I," "what does this error mean," "does it support." In most organizations it is more than half.</p>
<p>Now price that in engineer-hours. That is your documentation ROI, and it is usually large enough to fund a technical writer, which is the actual right answer and which almost nobody does.</p>
<h2 id="the-new-reason-it-matters">the new reason it matters<a class="anchor" href="#the-new-reason-it-matters" aria-label="link to this section">#</a></h2>
<p>Your documentation is now also a model's training data and a model's retrieval corpus.</p>
<p>When a developer asks an assistant about your library, the answer is synthesized from your docs. If your docs are wrong, incomplete, or ambiguous, the assistant confidently produces wrong code, and the user blames your library.</p>
<p>You have less control over how your project is explained than you did three years ago, and the only lever you have is the quality of the source material.</p>
<p>That is a strange new incentive and it is the strongest argument for good documentation that has ever existed.</p>]]></content:encoded></item><item><title>AGENTS.md and the repository that explains itself</title><link>https://readme.news/agentsmd-and-the-repository-that-explains-itself/</link><guid isPermaLink="true">https://readme.news/agentsmd-and-the-repository-that-explains-itself/</guid><pubDate>Sun, 04 Jan 2026 09:00:00 +0000</pubDate><description>A convention nobody standardized became standard anyway. Here&#x27;s what belongs in it and what doesn&#x27;t.</description><content:encoded><![CDATA[<p>Over the last year, essentially every coding agent converged on the same mechanism: a markdown file in the repository root telling the agent how to work in this codebase.</p>
<p>The names varied — <code>AGENTS.md</code>, <code>CLAUDE.md</code>, <code>.cursorrules</code>, <code>.github/copilot-instructions.md</code> — and the format did not. It is prose. The model reads it. That is the whole protocol.</p>
<p>A convention that emerges independently in five products in one year is telling you something about the shape of the problem.</p>
<h2 id="what-actually-belongs-in-it">what actually belongs in it<a class="anchor" href="#what-actually-belongs-in-it" aria-label="link to this section">#</a></h2>
<p>I have written and rewritten these a dozen times. The version that works is shorter than you think and more specific than you want.</p>
<p><strong>Commands.</strong> The exact invocations. Not "run the tests" — the command, including the flags, including how to run one test file.</p>
<div class="code"><span class="code-lang">markdown</span><pre><code class="lang-markdown">## commands
- install: `pnpm install --frozen-lockfile`
- test: `pnpm vitest run`
- test one file: `pnpm vitest run src/foo.test.ts`
- typecheck: `pnpm tsc --noEmit`
- lint: `pnpm biome check --write .`
- dev server: `pnpm dev` (port 5173)</code></pre></div>
<p>This section alone eliminates most wasted agent turns. Without it, the agent guesses, guesses wrong, and spends four tool calls discovering your test runner.</p>
<p><strong>Non-obvious structure.</strong> Where things live, when it is not inferable. "Database migrations are in <code>db/migrations</code> and must be created with <code>pnpm db:new</code>, never by hand." "The <code>legacy/</code> directory is frozen — do not modify it."</p>
<p><strong>Conventions that a linter does not enforce.</strong> If your linter catches it, do not write it down; the linter will tell the agent. Write down the things that are policy rather than syntax: "prefer composition over inheritance in <code>src/domain</code>", "all public functions in <code>api/</code> need a docstring", "we do not use default exports".</p>
<p><strong>Things that will break.</strong> "Do not run <code>pnpm build</code> — it takes 12 minutes and is not needed for tests." "The integration tests require Docker; skip them if it is not running." "Never modify <code>schema.sql</code> directly."</p>
<p><strong>Boundaries.</strong> What the agent may not touch without asking. Production configs, migration files, anything with a security review requirement.</p>
<h2 id="what-does-not-belong">what does not belong<a class="anchor" href="#what-does-not-belong" aria-label="link to this section">#</a></h2>
<p><strong>Your entire architecture document.</strong> The agent reads this every session. A three-thousand-word essay costs tokens on every single request and dilutes attention across a lot of text that is irrelevant to most tasks.</p>
<p>Keep it under about 200 lines. If you need more, put it in a separate document and reference it: "for the event pipeline design, read <code>docs/events.md</code> before changing anything in <code>src/events/</code>."</p>
<p><strong>Anything the code already says.</strong> Do not restate the type signatures. The agent can read.</p>
<p><strong>Aspirations.</strong> "We value clean code" is not an instruction. "Functions over 40 lines get split" is.</p>
<p><strong>Rules you do not actually follow.</strong> If the codebase contradicts the file, the codebase wins in the model's attention, and now your instructions are noise.</p>
<h2 id="the-part-i-did-not-expect">the part I did not expect<a class="anchor" href="#the-part-i-did-not-expect" aria-label="link to this section">#</a></h2>
<p>Writing these has improved my documentation for humans.</p>
<p>The discipline of writing "here is exactly how to run the tests, here are the things that will surprise you, here is what not to touch" is precisely what a new engineer needs on day one, and it is precisely what most onboarding documents fail to contain because they were written by someone who already knew.</p>
<p>An agent is an infinitely patient new hire who will follow instructions literally and never ask a clarifying question out of politeness. That turns out to be an excellent test of whether your instructions are any good.</p>
<p>Several teams I know have merged their onboarding doc and their agent file into one. That is the correct end state.</p>
<h2 id="the-standardization-question">the standardization question<a class="anchor" href="#the-standardization-question" aria-label="link to this section">#</a></h2>
<p>There is an ongoing effort to consolidate on <code>AGENTS.md</code> as the common name, with tools reading it as a fallback. That would be good and it is a coordination problem, which means it will take longer than it should.</p>
<p>In the meantime: write one file, symlink the rest. It costs nothing.</p>
<div class="code"><span class="code-lang">bash</span><pre><code class="lang-bash">ln -s AGENTS.md CLAUDE.md</code></pre></div>]]></content:encoded></item><item><title>Write the README first</title><link>https://readme.news/write-the-readme-first/</link><guid isPermaLink="true">https://readme.news/write-the-readme-first/</guid><pubDate>Sat, 05 Jul 2025 09:00:00 +0000</pubDate><description>The oldest trick in the book, still the best design tool available, and almost nobody does it.</description><content:encoded><![CDATA[<p>Before you write the code, write the README. Not a stub. The real one — the one you would ship, with the install instructions, the first example, and the section explaining what it does not do.</p>
<p>You will throw most of it away. That is fine. The value is in what happens while you write it.</p>
<h2 id="what-it-forces">what it forces<a class="anchor" href="#what-it-forces" aria-label="link to this section">#</a></h2>
<p><strong>A name for the thing.</strong> If you cannot name it in one sentence, you do not know what it is. "A library for X" where X is three clauses joined by "and" is three libraries.</p>
<p><strong>A first example that fits on a screen.</strong> This is the brutal one. Write the code a new user types first. If it needs eleven lines of setup before anything happens, your API is wrong, and you found out before you built it rather than after.</p>
<div class="code"><span class="code-lang">python</span><pre><code class="lang-python"># if this is your example, stop and redesign
client = Client(config=Config(
    auth=AuthProvider(strategy=Strategy.OAUTH, ...),
    transport=Transport(pool=Pool(size=10), retry=RetryPolicy(...)),
    serializer=JsonSerializer(...),
))
result = client.get_resource(ResourceRequest(id=ResourceId("x")))</code></pre></div>
<div class="code"><span class="code-lang">python</span><pre><code class="lang-python"># if this is your example, you are probably fine
client = Client(api_key=key)
result = client.get("x")</code></pre></div>
<p><strong>An explicit list of non-goals.</strong> Every project has them and most only discover them in a GitHub issue eighteen months later when someone asks for a feature that would break the design. Writing them down early is the cheapest scope control that exists.</p>
<p><strong>Error cases described in prose.</strong> "If the token is expired, X happens." Writing that sentence often reveals that you have not decided what X is, and the decision is much cheaper now.</p>
<h2 id="why-it-works-better-than-a-design-doc">why it works better than a design doc<a class="anchor" href="#why-it-works-better-than-a-design-doc" aria-label="link to this section">#</a></h2>
<p>Design documents are written for reviewers. READMEs are written for users. The audience difference changes everything.</p>
<p>A design doc rewards completeness, so it grows sections about alternatives considered and migration strategies and rollout phases, and by page six nobody including the author is thinking about the <a class="xref" href="/the-interface-is-the-product/" title="The interface is the product">interface</a> anymore.</p>
<p>A README rewards clarity from the outside. It cannot contain your internal rationale, because users do not care. It can only contain what the thing does and how to use it, which is exactly the part that is expensive to change later.</p>
<h2 id="the-internal-service-version">the internal-service version<a class="anchor" href="#the-internal-service-version" aria-label="link to this section">#</a></h2>
<p>This works for services too, and possibly better.</p>
<p>Write the endpoint documentation before the endpoint. Write the example request and the example response. Write the error codes and what each one means.</p>
<p>Then send it to the team that will consume it — <em>before</em> you build anything. The feedback you get in that thread is worth more than any amount of code review after the fact, because at that point changing the interface is free.</p>
<p>Half the API design mistakes I have watched happen were mistakes that the consuming team would have caught in ninety seconds if anyone had shown them the shape first.</p>
<h2 id="the-objection">the objection<a class="anchor" href="#the-objection" aria-label="link to this section">#</a></h2>
<p>"I do not know what it does yet, that is why I am building it."</p>
<p>Sometimes true. Exploratory work where the shape is genuinely unknown should be exploratory, and forcing a README onto it is cargo cult.</p>
<p>But be honest about which mode you are in. Most of the time you do know roughly what it does, and "I will figure out the interface as I go" means "I will discover the interface from whatever was convenient to implement," which is how you end up with a function that takes eleven positional booleans.</p>
<h2 id="the-actual-test">the actual test<a class="anchor" href="#the-actual-test" aria-label="link to this section">#</a></h2>
<p>When you finish, read the README as if you had never seen the project.</p>
<p>If your reaction is "I do not understand what problem this solves," you have learned something enormously valuable for the cost of twenty minutes and no code.</p>
<p>That is the best exchange rate in software.</p>]]></content:encoded></item>
</channel>
</rss>
