The Closing Window
A Notes Plugin for People Redlining Their Agent Sessions image
Photo by Amanda Jones on Unsplash

A Notes Plugin for People Redlining Their Agent Sessions

AI Insights

Before the post, a word about how it was written

This post was written mostly by an AI. I want to say that up front, because I keep seeing outlets ban AI-generated content outright, and I think that's a mistake.

I'm an engineer, not a writer. Writing takes me real effort. Most of the time I do it anyway because I enjoy it and because it forces me to think a topic through properly, which is its own payoff. It brings me clarity. But that's a few hours I don't always have.

So the choice in front of me this week wasn't "good post or AI post." It was "AI post or no post." I found something genuinely useful, almost by accident, and I've seen it mentioned in exactly one newsletter. Nowhere else. If the price of sharing that is admitting a model helped me put the sentences in order, fine.

The blanket ban treats "AI-generated" as a proxy for "worthless." Sometimes it is. There's a lot of garbage being pumped out for clicks and I'm not defending any of it. But the proxy is bad. What matters is whether there's something real underneath: a discovery, a bug you actually hit, a thing you actually built. Judge that. I'm not doing this for engagement numbers. I'm doing it because I think three or four people reading this will go install this thing and be glad they did.

Anyway. On to the important part.


TL;DR

Kept wanting to leave myself notes inside an agent session. No good way to do it. Researched the options, most of them bad. Then an agent IDE called bb turned up in a newsletter and it was the one tool where I could just build the missing feature myself. Twenty minutes, give or take. Plugin's here, MIT.

The actual problem: notes that survive, context that doesn't

If you work with coding agents all day you already know this one.

You point Claude at a task. It works through it, and it finishes. The task is genuinely done.

And then, right there in the same breath, it tells you about three other things. A function that's wrong but was out of scope. A config value that contradicts the docs. A test that's been skipped since March. All real, all related to what you just did, none of them the thing you asked for. Good agents surface these. Claude surfaces a lot of them.

The timing is the problem. That moment is already the busiest one in the whole cycle. The work is sitting in a worktree, so I still have to look at what actually changed, run it, decide whether I believe it, and get the branch merged back into main. That's the live obligation, and it has my attention.

So three genuine findings arrive at precisely the moment I have the least room for them, and they compete with a merge for the same slice of my head. Whatever happens to them next has to happen in about a minute, because after that I'm in the diff.

For a long time what happened next was a task app, or a plain-text todo file I'd open in something else. I lived in Warp for a while, then Superset, always juggling three terminal windows across at least as many projects.

And I kept those lists. One per project, worked meticulously, every item followed up eventually. Nothing got dropped.

It was still the wrong system, for two reasons that took me a while to surface.

The first is that writing the note cost me the session. Capturing a thought meant leaving the thing I was in the middle of, switching to another application, typing it in, and coming back. Call it fifteen seconds. Fifteen seconds is plenty. That's the window where I'm still holding the shape of what the agent just did, and every round trip punches a small hole in it. Do that six times in an afternoon and the afternoon goes to recovering your place. Maintaining the list was never the hard part. The interruption it demanded, every single time, was.

The second is worse, and it's the one that actually drove this. A task in another app has no way to carry its context with it. I'd write "check the retry logic in the sync handler," and a half day and 1 million tokens later I'd read it back and the sentence would be technically clear and practically useless. Why did I flag it? What was Claude doing when it came up? What was in the output that made me think it mattered? That was a thousand lines up in a scrollback I'd long since closed.

I tried writing longer notes. That just meant summarizing a session I was still standing in the middle of, which costs more than the note is worth.

So the note would survive and its meaning wouldn't. I'd end up reconstructing the reasoning from scratch, or worse, sitting there half-remembering the context and usually leaning on Claude to help me fill in the holes.

What I wanted was small and specific: leave a note attached to the exact turn where the thing came up, without leaving the session to do it, so that when I come back the surrounding conversation comes back with it. Not a note about the context. A note that lives in the context.

In practice that means the note hangs off the message where Claude listed its findings. Which is the message that already contains the reasoning, the file names, and everything I'd otherwise be trying to compress into a task title at the worst possible moment.

What I looked at first

I spent a few days on this before building anything, and I'll summarize the whole search here because the shape of the answer is more useful than my conclusion.

Everything turned out to hinge on one question: does the agent have to keep running in a terminal?

If yes, the options are thin. iTerm2 is the only terminal that genuinely does this. It has a real annotation feature that anchors a note to a range of text in your scrollback, and because it's a GUI action rather than shell input, it works fine while Claude Code owns the terminal. That's a legitimate off-the-shelf answer and if you want to stop reading here and go use it, that's a reasonable outcome. Warp, which I was using at the time, has bookmarks that carry no text at all, so they're navigation markers and nothing more. Its own docs say they vanish when the session closes. kitty and WezTerm have position markers or scripting hooks but no annotation. Ghostty has neither. tmux has nothing built in, but it's the best substrate if you want to assemble something yourself with a popup and a side pane.

Claude Code's own features get you partway and then stop. Hooks can print markers into the transcript, but they fire on Claude's events, not when I notice something. # and /memory write to CLAUDE.md, which is durable long-term memory and the exact opposite of what I wanted. Slash commands need the prompt, which I can't reach mid-turn. Session transcripts are JSONL on disk and you can append to them out of band, but nothing renders live. And the various scratchpad MCP servers are side stores: the note goes in, but it isn't anchored to anything, so it reproduces the exact problem I was trying to escape.

One thing to actively avoid. If you're thinking "just inject the text into the running terminal from outside," don't. That path runs through TIOCSTI, which has such a long history of being used in privilege escalation attacks that Linux disabled it by default in 6.2 and OpenBSD removed it years earlier. Writing directly to the TTY device is worse. Those bytes land in the middle of whatever the agent is currently drawing, and the screen turns to garbage.

The result of all that was a fork in the road. Every one of those limitations is a property of terminals, not of agents. Output is a byte stream into a TTY, a foreground process owns the input, scrollback rolls over, and nothing has a stable ID. There is no object to attach a note to, so every workaround is really an attempt to fake one.

Which meant the honest options were: use iTerm2 and accept its model, or find something where the session is made of addressable objects instead of bytes. I had no candidate for the second one. Then I got lucky.

The accident

Halfway through those days, bb showed up in Ben's Bites, one of the AI newsletters I subscribe to.

The mention was short. Something to the effect of: it's an agent IDE, and it's extremely customizable. That was enough, mostly because of when it arrived. I was already deep in a problem where "customizable" was the entire answer I was looking for. On any other week I'd have skimmed past it.

I want to be clear about how much luck was involved. There are new agentic coding tools, terminals, orchestrators, and wrappers appearing every week now. Nobody can evaluate all of them. I didn't find bb through diligence. It landed on my desk the week I happened to have a problem shaped like it, and I only recognized it because I'd spent a couple of days getting the shape clear.

Why it fit

bb gets filed under "IDE," which is misleading, because you don't edit files in it. It orchestrates: it runs coding agents (Claude Code, Codex, Cursor, and anything speaking ACP) inside named threads, each with its own git worktree, and it's MIT-licensed and runs entirely on your own machines using subscriptions you already pay for.

Two things about my setup made this land harder than it might for other people.

The homelab. I run jobs across several machines on my local network. One box does the always-on agent work, another has the GPU, the Mac Mini is the daily driver. Coordinating that used to be a pile of SSH sessions and a lot of remembering which window was which. bb handles this properly: each machine runs an actual client daemon that connects back to the server on my main machine. That's a meaningful difference from SSH. The daemon knows about projects, environments, and providers, so I can start a thread and say "run this over there" and the worktree gets created on that host with its own environment. Each machine also carries a permission ceiling, so my sandbox box can sit at full access while my laptop stays locked down and nothing I do in a thread can raise it.

The two modes I work in. During the day I'm an AI engineer, and that job still involves writing a lot of software. After hours I'm what people have started calling a builder, which mostly means I have too many projects going at once. Both modes are "many concurrent agent sessions, several machines, easy to lose the thread." bb is built for exactly that.

The features that actually keep me in flow

I'll skip the tour and name the four things that changed how a day goes.

Tasks that become threads. I can capture a task in the app and turn it into a running agent thread with a click. Sounds like a small thing. The gap between "I noticed something" and "an agent is working on it" is where my ideas used to stall out, and collapsing that gap to one click means the backlog lives where I'm already working instead of in Vikunja or Jira, waiting for me to come back to it.

Forking a thread. You can fork a session at any point in its history. The fork clones the actual provider session, not just a transcript, so the agent genuinely remembers everything up to that point. This is the "wait, what if we did it the other way" button. I use it constantly. Claude Code allows you to do the same thing natively, but not as smoothly as you can with bb.

Side chat. You can run a quick side conversation off the main thread without disturbing it. Claude notices a "gate" not closed, or a sub-item of a spec forgotten, mid-run, or I need to check something adjacent, and the main thread's context stays clean.

Notes on turns. That's the one that didn't exist. So I built it.

The plugin

bb's plugin API is not a plugin API in the usual "we exposed six hooks" sense. A plugin is TypeScript that extends the server directly: its own SQLite database, HTTP and RPC endpoints, background jobs, settings that render in the UI, React components in the app, and its own bb subcommand that works like any built-in one. Nearly everything bb ships is built this way, which is the real proof that the API is honest.

The whole thing took fifteen, maybe twenty minutes.

What it does: hover any message in a thread, click "Add note," and a Notes tab opens in the side panel with a box already anchored to that message. Write, save with Cmd+Enter. Never leave the session, which was half the point.

The other half is what comes back later. Notes list in timeline order, so reading the panel top to bottom walks the session in order. Each one carries a fragment of the message it's attached to, and the note is still sitting at its own position in a thread I can scroll. So I don't have to summarize the context at capture time. I just point at it and keep going, and the reasoning is still there when I return, because I never separated the note from the conversation that produced it.

There's also a bb note add command, so a script or a hook can drop a marker.

What it refuses to do

The notes never reach the model. They're never injected into context, never sent to a provider, never influence a turn. They're mine.

The value of these notes is that they're my running commentary on what the agent is doing. The second they become model input, they stop being observations and start being instructions, and I lose the one place in the workflow that's just me thinking.

One honest exception: registering the CLI command means an agent can discover that note-taking exists and write one. Contents still never come back to it, but it can write. Rather than hide that, notes created that way are labelled "via bb note" instead of "You," so I can always tell which ones I wrote.

Rough edges

The notes render in a side panel rather than inline underneath the message, which is what I'd originally hoped for.

You can only annotate user and assistant messages, not tool calls or their output. The API types it that way. The CLI is the escape hatch when I need one.

And bb is at 0.38.0 and moving fast. Anything I say about its plugin surface has a shelf life. Budget for that if you build something.

The part that generalizes

Normally, wanting a small feature means filing a request and waiting, if you even get that far. Maybe it lands, probably it doesn't, and either way the decision belongs to someone whose priorities aren't yours. That's not anyone's fault. It's just what happens when one product serves a hundred thousand people with a hundred thousand different workflows.

That trade used to be unavoidable, because building the feature yourself cost more than living without it. That's the part that's changing. The cost of "just build it" has fallen far enough that for a genuinely small feature with outsized benefits, the waiting is now the expensive option.

Which means it's turning into a choice. And the people who keep waiting for the feature request will increasingly be choosing to wait.

If you want to keep feeling the thrill of redlining your agents, get tools that fit how you work.


I wrote the Session Notes plugin. I did not write bb, and I'm not affiliated with it. bb is MIT-licensed and free, at getbb.app. The plugin is MIT too, at github.com/pablooliva/bb-ide-session-notes-plugin. Versions as of writing: bb 0.38.0, plugin SDK 0.4.6.

Powered by Buttondown.