git farm

A repository drawn as a pixel farm β€” in your terminal, in your README, and back through its own history.

git-farm's own repository drawn as a farm
This repository, drawn by itself, redrawn on every push. Hover a field for what it is. A directory is a field, a file is a plant.

Every farm on this page, in either theme. At night the sun is a crescent moon, the sky fills with stars, and the farmer carries a lantern β€” --night=auto turns it on by itself when the last commit was made after its author’s own midnight.

$ go install github.com/bright98/git-farm/cmd/git-farm@latest

No server, no account, no network. It runs git log in the folder you are standing in and draws a picture.

It looks like a toy

It is really a code health map. Three of the things it draws are true and useful, and the rest is weather. Every mark is a rank inside your repository, never a fixed number β€” β€œmore than forty commits is a hotspot” makes a small project look immaculate and a large one look doomed.

✦a green upright plant β€” a file that changed recently
♣a tall plant β€” a big file, by line count
✽a weed β€” churn: many authors, many commits, one file
βŒ„a bent grey plant β€” untouched for a year
▁a flat mark at ground level β€” a file that was deleted
☻the farmer β€” whoever committed last, standing where they committed
β–­a fenced field β€” the directory has tests
β”„a broken fence β€” no test files were found
⌐corners only β€” no rule applies here, so no claim is made

That last one matters more than it looks. The fence is the one claim that can be wrong in public, on somebody else’s README β€” so a directory of SQL migrations gets no verdict at all rather than a wrong one.

In the terminal

git farm

The quiet theme paints no sky, no grass and no soil, so your session shows through and the farm sits in the terminal rather than covering it. Truecolor degrades to 256, to 16, to none β€” and it still reads without any colour at all, because the plants are held apart by silhouette before colour.

Two palettes, because a file cannot ask its reader whether the page behind it is light or dark. This starts on whichever your system is set to β€” and the Day/Night switch above works on this one too, so there are four farms here.

the same farm in the quiet theme, painting no background
The same repository, the same commit, the same farm β€” drawn quiet.

In your README

git farm --out farm.svg --theme both

Every row is cut into runs of one colour and every rectangle of one colour goes into a single <path>: a 120Γ—72 farm is 8,640 pixels and comes out as about seventy elements. The names are real <text>, the fences are real strokes, and the farmer walks on CSS keyframes β€” never a <script>, which GitHub strips.

Two files, because a file cannot ask its reader whether the page is light or dark. The same bytes every time, so a re-run over an unchanged repository is genuinely a no-op.

Add two files and a GitHub Action keeps it up to date on every push:

# .github/workflows/farm.yml
- uses: actions/checkout@v5
  with: { fetch-depth: 0 }

- uses: bright98/git-farm@v0.3.0
  with:
    out: farm.svg
    theme: full
    night: auto

# then force-push farm.svg to an orphan branch: one commit, forever

The picture goes on a branch with no history, force-pushed, so your main never fills with β€œupdate farm”. The Action downloads a released binary and checks it against the release’s checksums.txt before running anything.

Walk around it

git farm --watch

The picture answers what shape a repository is. This answers the next question, which is which file. A cursor moves between fields; enter opens one and the cursor runs down its files, worst first β€” churned, deleted, quiet, big, the rest. That is the same order the picture uses to decide what a square shows, so the list is the field’s own reasoning written out.

  internal/gitlog/ β€” healthy, tests found Β· 2 files
  internal/gitlog/  2 files, worst first
  ──────────────────────────────────────────────────────────────────────
β–Έ ✦ gitlog.go                          379 lines    4 ✎   1 ✍  today
  ✦ gitlog_test.go                     223 lines    2 ✎   1 ✍  today

The cursor is a mark and not only a colour, because --no-color, a dumb TERM and a pipe all paint nothing β€” and a farm you cannot find your cursor in is not navigable.

The whole history, played back

git farm --gif history.gif

The layout is computed once and never again. Every frame pours its own crop into the same fields, so what moves is the crop and not the ground β€” re-running the treemap per frame would re-flow the farm whenever a directory appeared, and the eye would follow the rearranging instead of the growing.

this repository's history played back as a time-lapse
One frame per commit here. On an older repository it becomes a day, a week, or a month β€” whatever keeps the file small enough to put in a README.

A field for every directory the history ever had, sized by the biggest it ever was. Sizing from HEAD is the obvious thing, and it hides the most interesting half: a directory that grew for two years and was deleted last month would never appear, grow, or die.

What it refuses to do

Four cases produce a farm that is quietly wrong, so they produce an error instead: not a git repository, a repository with no commits, a shallow clone, and a window too small to read.

ClaimHow it is decided
biglines in the top 10% of files in this repository
weedcommits Γ— distinct authors in the top 10%
quietno commit has touched it for more than a year
deletedin the history, but not in the HEAD tree

Time is measured back from the newest commit, never from today β€” so two runs a week apart over the same commit draw the same farm.