A message arrived in one of my sessions from another one of my sessions. I read it, did what it asked, and thought absolutely nothing of it for the better part of a week.
Which, when it finally landed, was the odd bit. Nobody had built that. I certainly hadn’t.
The feature I was using without noticing
It turns out Claude Code grew cross-session messaging a fortnight or so before any of this, and it’s about as simple as a feature gets: a session can list the others running on the machine and write to one of them by name. Plain text, no history and no files, over a socket that never leaves the box. Nothing to enable and nothing to configure, which is exactly why I never noticed it arrive. My sessions started talking to each other, I read what they said and carried on, because a message from a session that knows what it’s on about looks a lot like a session doing its job.
My first real thought wasn’t “what a nice feature”, though. It was that if they can reach each other, something a good deal more interesting than status updates is on the table!
Because the estate is spread across a lot of repositories and the work stubbornly refuses to respect that. A change to the CI components drags three consumers behind it. A convention that lands in the framework wants backporting into four modules. An encryption decision touches the signing tool, the infra that provisions the key, and the docs describing both. Cross-project initiatives, if you want the tidy phrase, and every one of them had been coordinated by me, in my head, across ten terminals, badly.
That was the ambition. Underneath it sits a narrower problem I’d been misdiagnosing for months, because running ten sessions presents as a capacity problem: ten of something, one of you, so the constraint must be throughput. Except the throughput is fine and the estate ships. What fails is that I lose track of which ones need me, and in what order… and a session waiting on me does nothing whatever while looking exactly like a session that’s busy. Everything’s moving, nothing’s on fire, and if you ask me what any one of them is doing I’ll tell you inside thirty seconds. Ask me which one is stuck and I’ve no idea, because the only way to find out was to cycle through eleven tmux panes reading the last few lines of each, which I did more mornings than I’d care to count.
I called it a coordinator, and that was the first thing I got wrong
The word I reached for was coordinator, and the genre online reaches for much the same: chief of staff, orchestrator, team lead. I didn’t want any of it, and not out of squeamishness about hierarchy. It’s that the hierarchy isn’t there. Read a week of the traffic and not one message reads as an instruction handed down from a superior; it’s peers correcting each other, occasionally with a retraction and an apology attached, once with a session telling another its reasoning was better and withdrawing its own suggestion. Put a coordinator on top of that and you’ve described something that isn’t happening… and a metaphor describing the wrong thing will, given long enough, build the wrong thing.
So it became a standup. A ceremony you attend rather than a rank you hold, and one that assigns nothing to anybody.
The obvious approach is the wrong one
My first instinct, and I’d guess yours, is to message every session and ask how it’s getting on: the software equivalent of walking the floor, and cheap and friendly and obviously correct. Every skill I found in this genre does exactly that, and for eleven sessions it’s eleven turns and eleven interruptions. What comes back is a summary written to reassure, composed by a session with every reason to present its own state as under control.
The alternative had been sat in front of me the whole time. Every message these sessions have sent each other is already written down, both sides of it, in the transcripts, on the machine, right now. Nothing has to be woken up so I can read it, and sweeping the whole estate took three and a half seconds. It also hands you what neither participant has, because a session only ever sees its own side: it knows what it said and what came back, and hasn’t a clue the same question is being settled differently two repos over.
So I built that, ran it, and produced a rather pleasing report of who was doing what.
Then I checked, and my report was wrong
The report said keryx needed me, quoting its own words back: “write the report to the wiki, park the spike in a project snippet, delete it from the tree, then draft the superseding spec. Shall I carry on?” Four steps held behind one yes. It said cicd was waiting on a merge request. And it filed krites and sigillum as safe to leave.
Then I did the expensive thing and actually asked them.
keryx had moved on hours before and shipped v0.12.0. The merge request cicd was waiting on had already been merged. And the two I’d filed as safe to leave were both blocked on me, one of them badly: krites had a v0.9.0 tag out in the world with no release files behind it, so anybody running krites update (which is, you know, the point of shipping it) was getting nothing at all. It needed one job re-run. It had needed it for hours.
Three wrong out of five, and they were wrong in one direction, which is the part that matters. Not noise.
The sweep hadn’t malfunctioned, mind. It did precisely what I built it to do: it read the past, accurately, and I was the one who picked that up and treated it as a picture of the present. A session that finished at five still looks, in the transcripts, exactly like the session that was mid-sentence at five, and nothing about a transcript was ever going to tell me the difference. That’s my error and it’s a fairly basic one.
And underneath that, the bit worth carrying away. A session blocked on me has no reason to message a peer at all. No other session can approve an implementation, or re-run a release job on my behalf, or make a call that was always going to be mine. There’s nobody to write to. It writes to nobody, then, and generates not one byte of traffic, and my clever free sweep sees a session with no outbound messages and files it as fine… which is kinda the whole problem in one sentence.
The wire tells you who is talking. It cannot tell you who is stuck, because being stuck on a human is exactly the state that produces no evidence… which is the same shape as the fourteen tickets only a person can close, wearing a different coat, and by now I doubt that’s a coincidence.
Now, the tempting move here is to pick one. Drop the sweep because it lies, or drop the check because it costs, and have a single clean mechanism. There isn’t one. The cheap thing is always going to be stale and the accurate thing is always going to interrupt, and no amount of cleverness collapses that into a free lunch… so it wants to be both, with the difference between them understood.
A sweep that reads what already happened, run every time, because it costs nothing and wakes nobody. And a check that asks every live session to describe its own state, which interrupts all of them and is therefore something you call rather than something that runs. Put a standup on a timer and the judgement about whether the interruption is worth it stops being made at all, which automates away the only part that needed a person.
Two messages, and no others
Which brings me to the rule I was least sure about, and the one my own data settled.
I’d assumed a coordinator ought to be able to nudge: chase a stalled thread, stand down work that’s been overtaken, pass on a warning. Then I went and counted what the sessions had actually been doing. Nineteen threads. Six were opened because I spotted a connection between two sessions and routed it, and those six carry sixty-three of the hundred-and-one messages, one of them running to forty-seven across three repos, settling a design question and catching a real bug before it shipped. The other thirteen are self-started, and every one is short and reactive: a collision, a heads-up, a stand-down, a retraction.
That split is structural rather than behavioural, and once you see it the design writes itself. Sessions are perfectly good at spotting their own hazards and send those warnings unprompted, so relaying them adds nothing but a hop where a claim travels unchecked. No session can spot a connection between two other sessions, because none of them sees sideways. Only I could… and my name is in the first paragraph of all six of the deep ones because of it.
So the standup sends exactly two things. An introduction, which says “you two are circling the same question, go and talk”, carries the pointer and the provenance and never once the finding itself, and states plainly what it hasn’t checked. And a progress check, which asks a session to describe its own state in its own words. That’s the entire list, and everything I wanted to add to it over the following week turned out on inspection to be a bad idea.
Everything reactive stays with whoever owns the fact. Nullius in verba, as the Royal Society has had it for three hundred and fifty years, which is a very grand way of saying go and check it yourself. The temptation to relay is strong, because the coordinator is right there and can see everything, and I have the receipt for what that costs: one session told another a build target took sixty-three minutes, the second reasoned from it in good faith for a quarter of an hour, and then the first came back with a retraction and an apology for handing over a bad number. That was between two sessions that owned their own facts. Add a well-meaning middleman and you’ve built a machine for laundering unverified claims into confident ones, at speed, across an entire estate.
An introduction is safe for a boring, specific reason: it carries no claim. It says who said what and when, admits what it hasn’t checked, and gets out of the way so the two of them can verify between themselves. Which they’re better at than I am.
Where it leaves me
Not with fewer decisions, which is the thing I’d half hoped for. The decisions are the residue and they were never going anywhere.
Granted, I’ve no idea what any of this looks like at thirty sessions. It works at eleven because eleven is a number I can still read in a sitting, and the whole apparatus rests on that being true. I’m not in a hurry to find out where it breaks.
What changes is that they arrive on a list, rather than arriving because I happened to glance at the right terminal at the right moment. If you’re running a few of these yourself, that’s the bit I’d steal. And krites, sitting on a broken release all morning, silently, not bothering a soul, gets to be the line at the top of it.
That’s a small thing to have spent a morning on. It’s also the difference between eleven sessions working and eleven sessions running.





