# Show HN: Bough, Visualize your vibe coded project: progress, time, cost and more

> Source: <https://github.com/nickelsec/bough>
> Published: 2026-09-29 12:05:57+00:00

Reads your Claude Code, OpenAI Codex CLI and Pi session history, draws what you actually built, and prices it.

Not how long your streak is. Claude Code's own `/stats` covers that. This
answers a different question: what did you build, and what did each piece of
it cost?

Usage tools stop at a session, and a session is a hash that can cover weeks of unrelated work. bough works out where one piece of work ends and the next begins, so the money lands on things you recognise: that feature, that afternoon lost to one bug.

```
bough
```

That is the whole thing. It finds your projects, asks which one, and opens it in your browser.

What you get is a diagram of your own work. A square on the line is a sitting, labelled with the day, the time you started and how long you were at the keyboard. Smaller squares hanging off it are the tasks inside that sitting. Every circle is a single prompt you typed.

Hover anything and the path back to its day lights up, with a note saying what it was. Click it and the full record opens beside the drawing, scrolled to the exact prompt, in your own words and untrimmed. Work that went badly is drawn in rust rather than green.

A task carrying a small mark is one that ended in a commit, and the note gives you the hash and the message. Everything else in the drawing is worked out from your history; this is the part you can go and check.

Dotted lines join sittings that went back to the same files, so work picked up again later can be followed across the gap. On a long project there are a lot of them, and "What to show" in the rail turns them off.

Behind each task is a faint circle, sized by what that piece of work was charged. Hover it and the note breaks the figure down, in tokens and in dollars; the coins in the rail open the whole table, every day and every task, in the columns the agents themselves report. Most of it is the model re-reading the conversation, which is why a long discussion can cost more than a hard piece of engineering.

Following the figure on a record opens that table at that piece of work rather than at the top, and the rail will narrow the drawing to whatever passed a threshold you set, in dollars or in any of the token counts. The rates are published ones, built into the binary rather than fetched, so this works with the network unplugged like everything else here.

To get those right, bough also reads the git history of the project it is
describing, at the path your transcripts already name. That is a read and
nothing else: no writes, no network, no remote. It only ever looks at a
repository already on your disk, so whether it is private on a host somewhere
makes no difference. `--no-repo` turns it off, and a project that has moved or
was never a repository simply carries on without it.

The count may not match the number your host shows, and bough says so where it
is written. It counts what the agent did; `git log` holds what survived. A
commit you typed in a terminal never reaches your history, an amend is one
event more than the history keeps, and a rebase drops commits that really
happened.

The page is served from 127.0.0.1 and nothing else can reach it. Everything it needs is inside the binary, so it keeps working with the network unplugged.

macOS:

```
brew install nickelsec/tap/bough
```

Linux, or macOS without Homebrew:

```
curl -fsSL https://www.bough.run/install.sh | sh
```

Windows:

```
irm https://www.bough.run/install.ps1 | iex
```

Those scripts work out the newest release, check what they downloaded against
the published checksums, and put one binary on your path. Running the same
line again is how you upgrade. Homebrew is the exception, since `brew install`
on something already installed stops and says so: use
`brew upgrade nickelsec/tap/bough`.

If you would rather not pipe a script into a shell, every build is on the
[releases page](https://github.com/nickelsec/bough/releases) with a
`checksums.txt` beside it: unpack it and put `bough` anywhere on your path.

With Go, if you have it:

```
go install github.com/nickelsec/bough/cmd/bough@latest
```

Or build it yourself:

```
git clone https://github.com/nickelsec/bough
cd bough
go build ./cmd/bough
```

One dependency, `golang.org/x/term`, for reading arrow keys.

Add `--text` and the same work comes back as an indented list:

``` bash
$ bough bough --text

bough
=====
~/code/bough

486 prompts across 27 sittings
469 changes to 236 files, 32 hours at the keyboard
84 commits
2.8M written, 2.0B re-read: 730x more context than output
claude-opus-5
$1232.80 at API rates, priced Sep 2026

------------------------------------------------------------------------
31 Aug to 1 Sep Before we move further a small change the product will be...
16:57          4 tasks, 40 prompts, 4 hours
               kept coming back to hovercheck.js (5 times, 52 lines)

  Before we move further a small change the product will be...
    14 prompts, 5 failures, an hour and 29 minutes, 131k written, 420x context, $34.77
    28d4930  Rename the project to bough
    c541dd9  Implement the Claude Code source, and make it cheap to read
```

That figure is what the work would have cost at published API rates. It is not a receipt: a subscription is flat rate, and the transcript does not say which you were on.

Anything piped or redirected is written as text automatically, so
`bough > notes.txt` and `bough | less` behave as you would expect rather than
opening a window.

```
bough project-one      open a project by name
bough --text           write to the terminal instead
bough --list           show every project with history
bough -v               include every prompt in the text view
bough --json           write the graph as JSON
bough --no-repo        leave the project's git history unread
bough --agent=pi       read one agent only: claude, codex, pi, or all
bough -o notes.txt     write to a file instead of standard output
bough --root DIR       read history from here instead of the usual place
```

`--json` gives you the whole structure to do something else with. It carries no
colours, sizes or positions, only what is true about the work; the page works
those out for itself.

Everything happens on your machine. Nothing is sent anywhere, no model is called, and everything bough opens, your history and your repository alike, it only ever reads.

Claude Code, Codex and Pi keep a transcript of every session. Those transcripts hold the shape of what you built, and nothing surfaces it. bough reads them and rebuilds three levels:

**Prompts** are what you typed, with the files and failures that followed.

**Tasks** are runs of prompts working towards one thing. Where one ends and the
next begins is worked out from how long you paused, where the agent compacted
its context, and whether you changed both subject and files at once.

**Sittings** are the days, or the parts of one. People stop for the night and
come back to something else, and that turns out to be a better guide to what
belongs together than anything cleverer. Two sittings can fall on the same
date, which is why each one also says when it started.

It also notices when a sitting picked up work from an earlier one, and which file you kept going back to, and how much of that file actually changed each time. Coming back nine times to fix a typo is not the same as coming back nine times to rewrite it.

**What it cost** is carried per task as well as per project, which is the part
no other tool can give you: a session id is the finest grain they have, and
one of those covers weeks of unrelated work. Most of the figure will be the
model re-reading the conversation rather than writing anything: on the
histories this was built against, between 176 and 732 times more context than
output. A long session is expensive because it is long, not because the model
said much.

Claude Code, OpenAI Codex CLI and Pi. All three are found automatically, and a project worked on with any of them shows up in the same list.

```
bough --agent=claude      only Claude Code
bough --agent=codex       only Codex CLI
bough --agent=pi          only Pi
bough --agent=all         all three, which is the default
```

Codex and Pi support are newer and have had far less exposure than Claude Code, so treat their numbers with more suspicion and please report any that look wrong.

The agents record different things, so the diagram shows what each one actually wrote down rather than inventing the rest. All three carry prompts, tools, files, commits and token counts. Codex and Pi also record work handed to a sub-agent, which bough draws inside the prompt that asked for it.

Pi can reach dozens of model providers, and bough prices each one at the rates
published for that provider. A model running on your own machine or network,
through llama.cpp, Ollama, LM Studio and the like, is priced at nothing and
marked "(local)". Pi's own `models.json` is what says whether a provider is
local.

No streaks, and no claim to know what you were billed. It prices work at the published rates for the model that did it, which is what the same work would have cost had it been charged per token. A flat rate subscription pays none of that, and nothing in a transcript says which you were on.

Nothing is priced on a guess. A model with no published rate, or one charged by how large each request was, shows its token counts and NA where the figure would be, since a wrong number here is worse than no number.

No writes of any kind, to your history or your repository. No network. Agent directories are opened read only and never written to.

Every part of this was measured against real history rather than guessed, and two of the obvious approaches turned out not to work. Grouping tasks by what they have in common measured at noise, and cutting on any single weak signal turned one afternoon of styling into fifty two tasks out of a hundred and fifty four prompts. Sittings and corroborated signals replaced both.

The thresholds that remain are fitted to one developer's history and will suit
somebody else's differently. What each one does, what set it, and what happens
when you move it is in [docs/tuning.md](https://github.com/nickelsec/bough/blob/main/docs/tuning.md). They are constants
rather than flags for now, so changing one means editing Go.

Reading these files correctly is most of the work, and neither format is documented by the people who write it. What was learned is written down, one page per agent:

- [The Claude Code JSONL transcript format](https://www.bough.run/docs/format/claude-code) ([in this repo](https://github.com/nickelsec/bough/blob/main/docs/format-claude-code.md) ): where the files live, the
append-only replay that makes a naive parser overcount by more than three to
one, the tool results filed as though the user typed them, and the fields
that carry less than they look like they do.
- [The Codex CLI rollout file format](https://www.bough.run/docs/format/codex) ([in this repo](https://github.com/nickelsec/bough/blob/main/docs/format-codex.md) ): how items are shaped, how a tool call
is paired to its result, the replay that spans files rather than sitting
inside one, and why the input token count already contains the cached one.
- [The Pi session file format](https://www.bough.run/docs/format/pi) ([in this repo](https://github.com/nickelsec/bough/blob/main/docs/format-pi.md) ): a tree rather than a list,
forks that copy the whole conversation into a new file, skills stored with
their text pasted in, and sub-agents whose cost Pi leaves out of its own
totals.

Those pages are probably useful to anyone else reading either format, whatever they are building.

```
cmd/bough        the command
internal/agent   the boundary between bough and the agents it reads
  .../claude     reading Claude Code
  .../codex      reading OpenAI Codex CLI rollouts
  .../pi         reading Pi sessions
internal/segment prompts into tasks
internal/rollup  tasks into sittings, and the links between them
internal/metrics how long, how much, how hard
internal/graph   the finished structure, ready to serialise
internal/repo    the project's own git history, read to confirm its commits
internal/server  the local page, served on loopback only
internal/pick    the list you choose a project from
internal/banner  the mark it opens with
assets           the artwork, and the script that sizes it for the page
```

Nothing above `internal/agent` knows which agent the history came from, and a
test fails if that ever stops being true. That is what makes adding another agent
cheap.

Early. It works on the history it was built against, and the parts that are guesses are marked as guesses.

Two things worth knowing before you rely on it. The thresholds are fitted to one person's history, so your boundaries may fall in places you disagree with. The struggle score has been checked against one person's memory of their own work, on three projects, and it picked out the sittings they remembered as the hard ones. That is why it exists. It is one person checking a score fitted to their own history, which is why it is still off by default.

Claude Code, OpenAI Codex CLI and Pi are what bough reads, and they are the
whole of the focus for now. Getting a few agents right is worth more than
getting many roughly, and each new one has turned up defects in the ones before
it. The seam for adding one is documented in `internal/agent`.

Issues and pull requests are welcome, and questions are as useful as code at
this stage. See [CONTRIBUTING.md](https://github.com/nickelsec/bough/blob/main/CONTRIBUTING.md) for how to get set up and
the four rules that hold the design together.

MIT. See [LICENSE](https://github.com/nickelsec/bough/blob/main/LICENSE).
