Show HN: Bough, Visualize your vibe coded project: progress, time, cost and more Nickelsec released Bough, an open-source tool that reads Claude Code, OpenAI Codex CLI and Pi session history to visualize what a developer built and what each piece of work cost in tokens and dollars. Bough groups sessions into sittings and tasks, links tasks to git commits by hash and message, and serves its diagram locally from 127.0.0.1 with published model rates built into the binary so it runs offline. It installs via Homebrew (brew install nickelsec/tap/bough) or curl/irm install scripts for Linux, macOS and Windows, and its commit counts may differ from git log because it counts what the agent did rather than what survived. 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 .