How to make an informative project README
Tags: github
Published: 2020-11-27 08:10:41

There are lots of projects with rudimentary READMEs. It's sad because many of those are good, promising projects, but they make it hard for prospective users to assess them and try them out.
There are also people who advocate flashy READMEs with images, animated GIFs and lots of shields. Being flashy isn't always a bad idea by itself, but a README must be informative first.

Here's my checklist for making READMEs informative.

## Add usage examples

A bunch of examples cannot replace proper reference documentation, but reference documentation cannot replace introductory examples either.

As a potential user, I want to see what is it like to use your project. For a GUI tool, screenshot is an obvious way to show what it looks like. Libraries and CLI tools benefit from it even more though.

### For libraries, show a self-contained program

When I'm looking for libraries, I find a demonstration in a REPL or a small self-contained program very helpful.

If your library is hard to demo that way, maybe the library itself needs work. For example, when I wanted to sort dependencies, one thing I found annoying about existing graph manipulation libraries is how much initialization they need, when I _just_ wanted to sort dependencies.

So one of my goals for [ocaml-tsort](https://github.com/dmbaturin/ocaml-tsort) was to make it easy to show in a one-line example:

```ocaml
# #require "tsort";;

# Tsort.sort [
  ("roof", ["walls"]);
  ("foundation", []);
  ("walls", ["foundation"])]
;;
- : string Tsort.sort_result = Tsort.Sorted ["foundation"; "walls"; "roof"]
```

Some projects, like MVC frameworks, are genuinely difficult to showcase in a README. In that case a "starter project" repo can be a good alternative.

### For CLI tools, show output or use animated demos

CLI tools can benefit from some examples _with output_. Man pages usually just give you command examples with descriptions, but if you can show how the tool changes its input data, that's much better.

Tools that work with text are usually easy to showcase. Suppose you were to tell a novice about [sed](https://en.wikipedia.org/wiki/Sed).

```
sed is a tool for non-interactive text editing.

Example: replace every occurence of "hello" with "hi".

$ echo "hello world" | sed -e 's/hello/hi/g'
hi world
```
If your tool works with files and directories, you can show before/after `tree` outputs.

Interactive tools can be difficult to showcase, but if you aren't limited to plain text, you can do it with an animated GIF or a video. I love how [thefuck](https://github.com/nvbn/thefuck) did it, for example.

## Add build/installation instructions

Even if it's just the "usual procedure", say what that procedure is!

One reason is that a user may be coming from another language and isn't familiar with _your_ language and ecosystem convention.
C programmers who suddenly need to install a JS application may have never encountered `npm` before, while JS programmers may not know that `./configure && make && make install` is a usual procedure for a C project.

Another reason is to reassure users that there's no unusual procedure. I see `./configure && make && make install` and I know that I will not need to install a fashionable build tool of the week and purchase black candles to build your project.

You should make sure that your stated procedure actually works from a clean repo state. For example, some users of GNU autotools don't include autogenerated `configure` scripts and makefiles in the git repos and don't tell the user to run `autoreconf -i` in their README.
Then users who never created their own autotools projects see "Run `./configure`" and wonder how to run it if there's no `./configure` to begin with.
You can avoid that confusion with just one additional line:

```
$ autoreconf -i
$ ./configure && make
```

## Specify your dependencies

Some people just cannot use latest versions of everything, no matter how much they want it. There are many reasons people may not be able to "just" upgrade.

For those people, it's really important to know if they can even use your project at all. So, if your project needs Python 3.7, then people stuck with 3.6 will know they cannot use it.

If you don't know your minimum requirements, then you should find out. 

## Specify expected level of maintenance and community interaction

Every open source license comes with a clause that says there's no warranty. We all understand that in practice, that situation is very different for, say, the Linux kernel and a script I cobbled together for a one-off task and uploaded in hope someone else some day finds it useful.

Sadly there's no commonly accepted way to specify how much effort you _intend_ to put into handling bug reports and interacting with the community.

There's a "[no maintenance intended](http://unmaintained.tech/)" shield meant for completely abandoned projects. 

Some informal statements may help, like "I'm using this in production and I'm ready to fix bugs" or "I'm not planning to add support for use cases I don't have, but I'm ready to merge your patches".

Make sure you actually follow your own policy of course. If your README says "Bug reports and contributions are welcome", but in reality you auto-close them for "inactivity", you need to reconsider it.