Writing a README that answers the first questions
A README is the first technical document most people read about a project, and often the only one. It decides whether someone tries the project, gives up, or files an issue asking a question the README should have answered. Yet it is usually written last, in a hurry, by the person who least needs it: the author, who already knows how everything works.
This is our view of what a good README contains and in what order. It applies to a library, a command-line tool or the sample repository that goes with a tutorial.
Answer three questions before the first scroll
A visitor arriving at a repository wants to know, quickly: what is this, is it for me, and does it work? The top of the README should answer all three before they have to scroll.
- What it is. One sentence, in plain words, that says what the project does. “A command-line tool that removes duplicate lines from large log files” is better than a slogan, and much better than nothing.
- Who it is for. The situation in which someone would reach for it, and any obvious limits: “for Linux and macOS”, “needs Python 3.10 or later”.
- Its status. Is it maintained, experimental, finished or archived? A single line saves people from building on something that will not be fixed.
Everything else, such as badges, logos and the story of why you wrote it, can come later or not at all. If the first screen is taken up by decoration, readers have to dig for the one sentence they came for.
Install from a clean machine
Installation instructions are where READMEs fail most often, for the same reason tutorials do: they were written on the author’s machine, where everything was already set up. List the prerequisites with versions, then give the exact commands, in the order they must be run:
git clone https://example.com/you/project.git
cd project
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txtReplace the URL and the commands with your own, then test them the honest way: on a fresh container or a new user account, copying each line from the rendered README rather than from your shell history. It is the same clean-machine run-through we recommend for tutorials, and it catches the same missing steps.
If installation differs between operating systems, give each its own short subsection instead of one block full of “on macOS, instead do…” remarks. Readers only need to follow their own path.
Show a quick start with visible output
After installation, show the smallest thing that does something real, and show what it prints. This is the moment a reader decides whether the project works, so make the result unmistakable:
python -m project --versionThen one realistic command, with its input and its output in separate blocks. A quick start that ends with “you are now ready to use the library” and no visible result leaves the reader unsure whether anything happened. One that ends with output they can compare to their own screen gives them confidence to continue.
Keep the commands copyable: no shell prompts inside the blocks, placeholders that fail clearly if they are not filled in, and output kept apart from input. We covered those conventions in Code blocks readers can copy and paste safely.
Use a skeleton, then cut what you do not need
Starting from a fixed outline helps, because it reminds you of sections you would otherwise forget. This is the one we suggest. Copy it, replace the capitalised words, and delete any section that has nothing to say:
<!-- Replace every CAPITALISED word, delete empty sections. -->
# PROJECT
ONE SENTENCE: what it does and for whom.
Status: maintained | experimental | archived
## Requirements
- OPERATING SYSTEMS
- RUNTIME AND VERSION
## Install
COMMANDS, IN ORDER
## Quick start
ONE COMMAND AND ITS OUTPUT
## Configuration
- SETTING: what it does, default value
## Troubleshooting
EXACT ERROR TEXT: cause and fix
## Licence
LICENCE NAME, see LICENSEConfiguration deserves a line per setting: its name, what it does and its default. Readers scan this section looking for one option, so a list works better than paragraphs. If the list grows long, move it to a separate document and link to it from the README.
Write troubleshooting with real error text
A troubleshooting section is where a README earns its keep. Whenever someone reports a problem that turns out to be a setup mistake rather than a bug, add it: the exact error message as text, a sentence on the cause, and the fix. People search for error messages, and a matching line in your README may answer them before they open an issue.
Write the message exactly as the program prints it, not a paraphrase, and keep the cause short. How to turn an error into a clear explanation is the subject of How to explain an error message in a post; the same structure works at README scale, just shorter.
Licence, contributions and keeping it current
End with the practical information people need before they reuse or improve your work. Name the licence and point to the licence file, because without one, others cannot safely use the code even if they want to. If you welcome contributions, say how: where to report bugs, whether to open an issue before a pull request, how to run the tests. If you do not have time to review contributions, saying so is a kindness, not a failure.
Finally, treat the README as part of the code. When a command, a default or a requirement changes, update the README in the same commit, so the two never disagree. A README that was right two versions ago is worse than a short one, because readers trust it. If you also write about the project in a longer post, link to it from the README and back again; the features page describes how author blogs, categories and topics work on TechDug if you want to group such posts into a series.




Comments 0
Comments are reviewed before they appear. Oldest first.
No comments yet. Spotted a typo, a better flag, or a step that failed for you? Say so below.