Multiple AI terminals. All waiting. And I was at a carwash.
THROVE was mid-build on itself - it IS the fitness app. CRAFT was adding CI workflows, DARINBUILDS.COM was reviewing content, and three Directors were orchestrating them from a CMUX layer above them. All running Claude Code, all of them paused at different points asking me something. And I'm sitting there watching the brushes go, phone in hand, wondering why managing an AI fleet means being chained to a laptop.
For a while I'd been treating it like a building problem, I just needed some notification system, or an API layer, or some clever way to route claude's questions to my phone. More stuff to build....
But I was already living in Obsidian. I'd been using it for months as the knowledge graph behind Craft, notes linking decisions across every project. And Obsidian already gives me markdown files with checkboxes and a clean UI on my phone. So the question flipped. What if the system just talked to me through that? Checkboxes for decisions, tables for context, the terminals' running work wrapped up in the background the same way my notes already were.
I didn't need to build an interface - I was already standing in one.
A markdown file IS the message. Frontmatter handles the routing, checkboxes carry the options, and a Reply field catches anything I want to type back. Both sides just speak markdown, so there's no translation layer, no API, and nothing gets dumbed down for either of us.
That's the whole thing, everything else is just plumbing.
So I went home and built it that night.
Not a script - the whole thing. The watcher that wakes the fleet, the worker to director to CTO chain of command, the routing, the notes it writes back to my phone, the logic that tells a stalled terminal from a working one. One sitting, because once I saw the interface was already in my hands, it stopped being a building problem and turned into a one-night problem. The hard part wasn't the code, it was noticing. After that I just couldn't not make it.
One Word Woke Up the Fleet
I opened Obsidian on my phone and typed "pulse".
One word in a markdown file, dropped into CTO/outbox/. iCloud synced it over to my laptop a couple seconds later, where a watcher script had been sitting there doing nothing:
When a file lands, the loop exits. That's the wake - the CTO runs the pulse, writes its notes, and arms standby again, which restarts the loop.
No server. No webhook. Just a bash loop checking the outbox every 10 seconds, kept awake with caffeinate.
I tried fswatch first. Event-driven, elegant - and completely wrecked by iCloud. Every sync triggers metadata updates before the actual content lands. .DS_Store, extended attributes, partial writes. Three false wakes before the real event, and the race between wake and re-arm meant I'd miss the actual file while recovering from a ghost one.
So I threw it out and did the dumbest thing that works: check the folder every 10 seconds. No events, no debounce to tune, no race. It feels slow. But it's never wrong, and that matters more.
The elegant version lost to the boring one. That keeps happening in this whole thing, and I've stopped fighting it.
"Zero tokens while idle. Wakes within ten seconds when a file lands"
The AI Fleet Doesn't Read Every Screen
The first thing it does is run cmux list-notifications. One command, and it knows who's waiting, who finished, and who needs a decision from me. No tokens burned scanning seven terminals, it just gets a list of who actually needs attention.
Then it reads screens, but only for those. cmux read-screen --workspace workspace:10 --lines 50. CRAFT's last message was sitting there: "Want me to do a full read of the files I haven't covered yet?" That's my decision, not the machine's.
So the CTO writes me a note. I tried dumping the raw terminal output into it early on, and on a phone that's unreadable. A summary isn't the answer either because summaries decay - come back three hours later and you have no idea what "story 3" meant. The format that survived is bold labels, one fact per line, a recommendation, and checkbox options where each box maps to the exact text that gets typed into the terminal.
That note lands in CTO/inbox/CRAFT.md, iCloud syncs it to my phone, I check a box, and I move the file to CTO/outbox/. The move is the submit. No send button, no confirmation step, a file in the outbox is a sent message.
Stalled detection is the part that makes this actually useful instead of just clever.
The CTO sorts every terminal it reads into one of three buckets:
- Waiting:
cmux list-notificationsflagged it. The terminal needs input from me. - Stalled: quiet on notifications, but the screen shows an obvious next step. A terminal that creates a backlog story and then stops isn't done, it has unfinished work sitting right there and it stopped anyway. The CTO reads the screen, recognizes it, and suggests the next move.
- Working: in the middle of something. Leave it alone.
A dumb relay just forwards questions - the CTO reads the room. And it does that with stuff I already had, a notification list and a screen, not some judgment engine I had to invent. That's what makes this feel like management instead of babysitting.
Three Tiers, Adjacent Layers Only
The fleet has a chain of command:
Directors manage Workers, and the CTO only talks to Directors. When the pulse ran this morning it saw THROVE working and THROVE DIRECTOR idle. Totally fine, the Director is just letting the Worker work.
But what if THROVE stalls and THROVE DIRECTOR is still idle? That's a dropped ball. The CTO flags the Director, not the Worker, and it never reaches over a Director's head without asking me first.
Each layer talks to the layer next to it, that's the whole thing. No framework. The routing is YAML frontmatter, every message carries a type (pulse, kill, dm-message, feedback) and a to: for where it gets dispatched. Conventions on top of files I already had - not a system bolted on.
This Is What Shows Up on My Phone
This is a real note from today, exactly how it looks in Obsidian:
---
from: DARINBUILDS.COM DIRECTOR
workspace: workspace:5
project: darinbuilds.com
status: pending
created: 2026-03-29T18:25
type: pulse
to: DARINBUILDS.COM DIRECTOR
---
## DARINBUILDS.COM DIRECTOR - dm-handoff gap
**Fixed:** Director acknowledged the mistake, invoked craft-direct,
and is now spinning up a Worker terminal.
**Root cause:** The dm skill ends after conversation completes,
but never tells the Director to start craft-direct. Director
improvises - chose craft-story-new (do it myself) instead of
craft-direct (spawn a Worker and supervise).
**The gap:** No handoff step between "DM complete" and "start
directing implementation."
**My recommendation:** Add a Phase 4 to dm-handoff where CTO
sends craft-direct after processing dm-complete. Keeps
orchestration where it belongs.
---
- [ ] Fix in dm-handoff (sends `Update dm-handoff Phase 4`)
- [ ] Fix in dm skill (sends `Update dm skill instead`)
- [ ] Both (sends `Do both`)
**Reply:**
That's the root cause, a recommendation, and three options. Every checkbox shows you exactly what gets sent through cmux send. I can check a box, or type in Reply and it goes out word for word.
None of that is a custom UI. Those are just Obsidian's checkboxes (the same ones I'd been using in my notes for months). The interface was sitting there the whole time.
And what did I type to get that whole note? One word, "pulse."
Oh, and the Drag Story
I wanted to review next week's workout schedule. I dragged dm-message.md from CTO/create/ into the outbox and typed one line: "Review next week's generated workouts and send me the schedule."
I'm supposed to duplicate the template and leave the original in place. I never do. I drag every time, and every time the CTO wakes up, handles my message, checks CTO/create/, and the template is gone. So it recreates it.
That recreate step (check that every template exists, recreate anything missing) is only in the CTO's instructions because of me. The system built a step around my habit instead of making me fix it. lol. You can't design that up front, it shows up when you actually live in the system.
THROVE Director got the message, curated the workouts, and sent them back. I left notes on two that felt too grip-heavy back to back, approved the rest. Straight to production, all from my phone.
By the time the car was done, three terminals were unblocked and shipping code.
The Stack Is Boring on Purpose
iCloud is the file sync - but any sync works. The watcher is a 10-second bash polling loop. The terminal bridge is cmux. The routing is YAML frontmatter on markdown files.
Obsidian is the one piece I wouldn't swap though. It's a knowledge graph. Every decision note links back to the project that spawned it, every archived conversation is backlinked, so when the CTO writes me a recommendation it can search every past decision for that project first. Take the graph out and this whole thing is a message relay. The graph is why it gets smarter over time.
There's no server in any of this, no database, no API. Files in folders with conventions on top, that's the whole system. The crystallized agents I use to give the fleet eyes run the exact same way.
I wasn't trying to invent a protocol, that's the part I keep coming back to. Files are already a protocol. Claude understands markdown, I understand markdown. The insight wasn't technical - it was noticing something that was already there.
The whole system is a night's work, and it only went that fast because I stopped trying to build the interface and noticed I was already holding it. You're holding one too. A notes app, a sync folder, some tool you live in every day that the machine already understands. Pick it up and wire a terminal to it, then tell me what you think. DM me, for real - I could talk about this setup all day.
Resources
- Obsidian - The knowledge graph that powers the vault. Free for personal use, syncs via iCloud.
- cmux - Terminal multiplexer with workspace management, screen reading, and notification API.
- Claude Code - The AI terminals running in each workspace.
- THRØVE - Fitness coaching app built by the
THROVEterminal. Live at throve.fit.