I closed the previous post with a promise: that the development style behind this blog, and the OSS I've been shipping — a harness for steering AI coding agents — deserved their own write-up. This is that write-up.
The project is basou. In one line: it's a harness — a full set of tack — for steering AI coding agents. A "saddle" you declare once per repository to say how the project should be driven; "reins" that carry intent from one session to the next; and, underneath both, a replayable record of what the agent actually did. All of it as plain files, in a .basou/
directory right next to your code. Local-first: nothing leaves your machine.
Once agents write most of the code, the scarce resource isn't typing — it's control. The more I leaned on agents, the more the pain narrowed to three things.
One: the "why" evaporates between sessions. The answer to "what does this code do" lives in the code; even a read-only assistant can reconstruct it. What can't be reconstructed is the living context around a decision — what you intended, which path you rejected, how far you got. That has to be captured in the moment, and what you capture is worthless unless it survives to the next session.
Two: the cost of re-explaining. Because it wasn't captured, every session starts with a human re-narrating the context by mouth. Run three projects in parallel and you pay that tax three times over.
Three: you can't audit it. What an agent did is buried inside vendor-specific log formats, or nowhere at all. "That change last week — why did we do it that way?" has no answer you can verify after the fact.
basou is my answer to those three. Not a dashboard you glance at, not an audit log you file away — tack you keep in your hands the whole time you're working. The name comes from basou (馬装), the Japanese word for tacking up a horse: fitting the saddle and the reins.
You declare each repository's nature once — public or private, what language it's in, where the canonical copy of the agent-instruction file (AGENTS.md
) lives — in a manifest. Then basou project
derives the rest: which roots to record, the wiring of AGENTS.md
/ CLAUDE.md
/ Copilot instruction files, the .gitignore
that keeps a private canonical file out of a public repo's history, and a workspace view that bundles multiple repositories. Humans edit the declaration; basou maintains the plumbing.
Every generating command is dry-run by default (--apply
is what actually writes), and additive and non-destructive. How to consolidate the ever-multiplying pile of instruction files is a whole post on its own, so I'll save it for another time.
basou orient
answers "where is the work right now, and what's next" from the record, not from memory. Recent decisions, open tracks, the recorded next step, and a note on whether the record itself has gone stale.
The decision record has a trick to it. A decision made mid-conversation with an agent — the reasoning, the alternatives, and why you rejected them — normally dies with the chat log. basou decision capture
makes the agent itself, while it still holds the conversation in context, emit the decision as structured data, and basou writes it down deterministically. basou never runs an LLM of its own. So the record is yours, verifiable, and works offline.
basou note
leaves a one-line "pick up here next." basou handoff generate
regenerates a handoff document for the next session — or the next teammate.
The two foundations sit on a simple, inspectable base.
.basou/sessions/<session_id>/events.jsonl
and basou verify
..basou/handoff.md
and .basou/decisions.md
are regenerated from the event log (you can hand-edit them too). Review them in an editor, or right in a PR diff.basou run claude-code
wraps a process from the outside and records it; basou import claude-code
/ basou import codex
derive sessions after the fact from the logs each tool leaves behind. basou refresh
does ingestion and Markdown regeneration in one pass, and basou view
shows the whole thing in a local web UI bound to 127.0.0.1 only.Keep exactly one source of truth and regenerate the human-facing copies from it — that stance is the "one source, many uses" discipline from twenty years of designing business systems, carried straight into the agent era.
I use basou every day, across all of my projects. The repository behind the blog you're reading is one of them. What follows isn't a staged sample — it's a real excerpt from that repository's own .basou/
(some paths and identifiers are masked; the Japanese working notes are translated here for readability).
First, the current position basou orient
returned when I resumed work. Behind it, handoff.md
holds the same content.
> Generated at 2026-07-08T13:20:50Z from ses_01KVZAFJT0..ses_01KX0Y6TPT
## Current state
- Last session: claude-code 2026-07-07: 110 commands, 11 files (imported) [ses_01KX0Y6TPR]
- Last task: (no tasks recorded yet)
## Recently changed files
- src/components/MermaidRenderer.astro
- src/layouts/BaseLayout.astro
- src/pages/ja/index.astro
- …
## Recent decisions
- Use the existing static image for the shared header avatar [decision_01KWYHFVDE]
Next, one decision made during that work, recorded like this — with the reasoning and the road not taken.
## Render Mermaid diagrams as SVG on the client
- date: 2026-07-07
- rationale: Build-time rendering (rehype-mermaid and friends) depends on headless
Chromium, which risks breaking Cloudflare's build pipeline. Instead, load mermaid.js
in the browser and swap the Shiki-highlighted pre[data-language=mermaid] for SVG.
- alternatives: Pre-generate the SVG at build time (SSG) with a headless browser
- rejected_reason: Adding a headless-Chromium dependency to the build makes builds
fragile; that operational risk outweighs the "no JS required" benefit.
- linked_files: src/components/MermaidRenderer.astro, src/styles/global.css
And beneath all of it, the event log and its verification.
{"schema_version":"0.1.0","session_id":"ses_01KW0J3F…","type":"session_started","prev_hash":"1e4d0428…e34dc37"}
{"schema_version":"0.1.0","session_id":"ses_01KW0J3F…","type":"session_status_changed","from":"initialized","to":"running","prev_hash":"e3108afa…efb2bc9"}
{"schema_version":"0.1.0","session_id":"ses_01KW0J3F…","type":"session_ended","exit_code":0,"prev_hash":"9d11ac73…b4b29f0e"}
$ basou verify
ses_01KW0J3F… verified (5 events)
Markdown is easy to read, but it's only a copy. The source of truth is the hash-chained JSONL — which is why a machine can answer "has this record been tampered with?"
.basou/
directory next to your code. Nothing leaves the machine..basou/
, and generating commands are dry-run by default and non-destructive. Adopting it — or backing out — is low-risk.
npm install -g @basou/cli
cd /path/to/your/project
basou init
basou task new --title "Refactor login form"
basou session note --body "Starting from a look at auth.ts"
basou handoff generate && cat .basou/handoff.md
basou refresh
basou view # local UI, 127.0.0.1 only
A walkthrough with sample output and the usual gotchas is at basou.dev/quickstart/.
One more thing: if basou is the side that records what an agent did, there's a companion project, Kozou, for the side that tells an agent what a database means. I'll introduce that one separately too.
The repository is github.com/basou-dev/basou; the docs are at basou.dev. If something trips you up on 0.x, I'd be grateful for an issue.
The Japanese version of this post — its "paired" article — is already live.