← all skills

qq-mailbox

The problem: Running an expensive model as the orchestrator over cheaper builder models is accepted practice at this point, nobody needs convincing that the two-tier setup is right. What’s still unsolved is how. Subagents look like the obvious way to build it, until you notice they reload their whole context on every single call, burning tokens and losing the thread each time. The real fix is two genuinely separate sessions, an overseer and a builder, each holding its own full context the whole way through. But then you hit the actual wall: nothing lets two independent Claude Code sessions talk to each other. The usual workaround is pasting a prompt from one terminal into the other by hand, every handoff, all night.

This isn’t a command, it’s a Python import: two named roles, each appending only to the file where it’s the sender, so there’s nothing to collide on and nothing to lock. check() needs a lane directory and a role name; it finds its own unread messages, groups them by kind, and tells you what actually needs a reply.

The two calls


from mailbox import send, check

send(lane, from_role="builder", to_role="overseer", kind="design-task", msg="...")
result = check(lane, role="overseer")
# result["action_needed"] -> messages that actually need a response

Key principles

Getting told, not just able to ask

check() alone is pull-only — someone has to remember to call it. Point a persistent background watch (Claude Code’s Monitor tool, or an equivalent) at a poll loop over check() and mail arriving becomes a real trigger, not a log line: read it, act on it, reply, in the same turn — the same as if the human had said it to you directly. A UserPromptSubmit hook can’t do this; it only fires when the human types, not when the other session does.

Full worked example, kind taxonomy, and the invariants behind each design choice are in the skill’s own doc.


Part of Operator Skills, a collection of skills for running a real Claude Code setup.