Shipped v0.7.0 and v0.8.0 in the same day. That kind of pace only happens when the plumbing is already right and you’re just opening valves.
The big piece: MCP server with 6 tools over stdio. One implementation that serves Claude Code, Cursor, Windsurf, Gemini CLI, Kilo Code, Continue, Codex — no per-tool CLI wrappers. timbers serve fires up, handlers call directly into internal/ packages, and that’s it. The filter functions had to move into internal/ledger/ so both CLI and MCP could share them, which was a surprisingly hefty chunk of plumbing, but the payoff is clean. Tagged v0.7.0 and moved on.
Then v0.8.0: the --notes field. This one has a clear philosophy behind it — why captures the verdict, notes captures the journey. Alternatives weighed, dead ends explored, the “thinking out loud” that usually evaporates. The coaching follows the same pattern that worked for why: guide by question, not by structure. BAD/GOOD examples in the prime text. The field tucks away in verbose display (truncated), gets its own section in show, and templates can pull from it in draft.
The interesting thing about
notesis that it immediately made the existing example artifacts look thin. Old examples were generated from 30 backfilled entries with shallowwhyfields. Regenerating from 55 real entries with actual notes content produced dramatically better decision-log output. The old version had 9 ADRs; the new one has 6 — but every single one has genuine fork-in-the-road context. Quality over quantity, and it’s not close.
The registry pattern work was satisfying. Debated registry vs switch for the AgentEnv interface. Switch would centralize everything but mean touching multiple files every time you add Gemini or Codex support. Registry means one file per environment, self-contained, registers via init(). Adding a new agent env becomes a single-file task. The interface methods — Detect, Install, Remove, Check — mirror exactly what doctor, setup, and init already needed. ClaudeEnv wraps the existing functions, --no-claude becomes --no-agent (deprecated alias kept), doctor iterates AllAgentEnvs(), uninstall gathers all detected envs. Clean.
A couple of test fixes that were small but satisfying in the “stop being annoyed” sense. TestCommitFiles was running against the live repo’s HEAD, which breaks when HEAD is a merge commit because diff-tree returns empty. Fix: give the test its own temp repo with two commits so it always owns its state. TestRepoRoot was hardcoding a directory name, which fails in worktrees. Fix: check absolute paths instead. Both were pre-existing landmines.
And some CI housekeeping — switched the devblog pipeline from weekly to daily (matching actual commit frequency), killed a stale git-notes fetch step that was left over from before timbers moved to .timbers/ directory storage. That ref never existed on the remote. Classic dead code in CI: invisible until it isn’t.
Documentation got a pass too. --notes shipped in v0.8.0 but only the prime coaching mentioned it. README, tutorial, spec, agent-reference — all still showed the old what/why/how-only pattern. Fixed across five docs, consistently framing why as verdict, notes as journey.
This post was drafted with AI assistance from development log entries.