Your agent lives on your glasses and your phone stays in your pocket. That is OcuClaw in one line. The glasses are Even Realities’ G2: a small display projected into each lens, the two combining into a single floating screen in front of you, driven by a ring on your finger that swipes, scrolls, and taps. OcuClaw is the app that puts an AI agent on them. An agent, not a chatbot, and the difference is the point. A chatbot can only talk. An agent can use tools, work through a multi-step job on its own, and come back with the result. So you get an answer with your hands full, or capture a thought mid-walk and have it filed somewhere real before you are home, or check how a coding job is going, all without taking your phone out. It began as a client for OpenClaw, an open runtime for that kind of agent, and it now speaks Hermes Agent too. It ships on Even Hub, Even Realities’ app store for the glasses, and it is built by Matthew Ford, an independent developer who was among the twenty selected for the pilot program that opened the platform up.
The interesting part is what it takes to build. An agent that lives on a pair of glasses is not something you can test by running a program and looking at it. The whole stack has to be alive at once, with glasses on the other end of it, before anything you see means anything. That is a lot of computer to point at a single branch, and Ford, working alone, wanted several branches moving at once. So each branch got a computer of its own.
What is the “Fleet Control Center” specifically, and how is it different from just using OcuClaw on its own?
OcuClaw is the product. The Fleet Control Center is the factory. An OcuClaw change isn’t one program to test; it’s a Kotlin app, an OpenClaw plugin, a Hermes Agent plugin, and a relay that all have to be exercised together through a G2 simulator before you can trust it. The Fleet Control Center manages a fleet of “boxes,” each one a complete, isolated copy of that whole stack living in its own Sprite. From one screen, or from my phone, or my glasses, I can wake a box, hand it a task, watch its live glasses render, or park it back to sleep.
Each box is built to serve a pair of smart glasses. Most days that’s the G2 simulator it carries, its render streamed out of the box to my screen; when I want the real thing, my actual glasses connect to the box instead. Same box, same branch, either client.
The site mentions Overview mode, Cockpit mode, and a Phone lane. Can you describe what each one is for, in the words you’d use with a new user?
Overview is the fleet at a glance. Every box is a tile: parked ones sit cold, armed ones show a live thumbnail of whatever their glasses display is rendering right now. It’s the “is anything on fire, is anything done” screen.
Cockpit is climbing inside one box. You get the live glasses render and the app UI side by side, with real input. Your taps and swipes become actual input on that box’s simulator, so you’re driving the stack as if it were running natively on your phone/glasses.
The Phone lane flips the roles. The box’s simulator steps aside and your physical phone becomes the client, connected over a private tunnel. Now you’re testing the real phone-plus-glasses experience against whatever branch that box is running. Real taps on the ring, real voice input, real agent, through the lens.
Who is this actually for? How many people or teams use it today?
One human, plus a fleet of AI agents. That’s not an embarrassing admission, it’s the whole point. I’m a solo developer who works like a team. I dispatch coding tasks to boxes, each box’s agent writes and builds and validates in the simulator on its own, and I review the PRs that come back. And the fleet does more than feature work. Agents on the boxes pull in user-submitted bug reports and come back with proposed fixes that are already e2e-tested in the simulator (ocuclaw.com/triage). Others monitor the OpenClaw and Hermes Agent release logs, check each release against my code, and hand me an “act / check / watch” list per release so I can keep up with the pace of both projects. OcuClaw itself has beta testers on real hardware, but the fleet is my personal factory.
Before this system existed, how did you build and test G2 glasses apps? What did the day-to-day look like?
One laptop, one simulator, one OpenClaw client, and everything queued behind them. Every change went through the same serialized loop. For example: build the app, rebuild the plugin, restart the runtime, drive a real agent turn, look at the render. That’s fine when only one thing is in flight. But agents have gotten good enough to carry long-running tasks on their own, and the moment I wanted more than one moving, it fell apart: every agent needed the same simulator and the same runtime as me. The bottleneck was never the work; it was the machine. And it took a real toll: I could feel my excitement for an idea wax and wane while it sat queued behind something else, and my todo list grew until it was overwhelming. Sprites fixed all of that. Now work starts when the idea does, not when the machine frees up.
You call out three specific pains. Can you tell the story of a real time each of those bit you?
Waiting for the simulator: the sim is a lock in my tooling, because two things driving one simulator produce garbage. So an agent would finish its code changes and then just sit there, waiting for the sim to free up so it could validate, usually while I also wanted the sim to check something by hand. With two or three tasks in flight, most of everyone’s time was spent waiting for a turn.
One client, two plugin versions: I confirmed this one the hard way. An OpenClaw instance runs one OcuClaw plugin version at a time, and merely attaching a second client rotated the live session out from under the first. Poof, gone. So “just run two copies locally” was never an option. Testing branch A against branch B meant tearing one down and standing the other up, every single time. When I caught myself designing scaffolding to juggle multiple OpenClaw instances on one machine, that’s when I started looking at remote boxes.
Manual cycles: this one never bit in one dramatic moment, it bit on every single change. The agents could write code, build it, test it. What they couldn’t do was own the loop end to end, because closing the loop still meant my hands on the shared machine. The story here is death by a thousand cuts.
Did you try anything else before landing on the current architecture?
Three things, in escalating order of effort. First, scaffolding on the local machine: locks so tasks could queue instead of collide. A build lock first, then a lock on the simulator, then on the OpenClaw plugin runtime. Each one helped, and each was another lock layered on top of the last: an increasingly elaborate queueing system around a machine that fundamentally couldn’t be shared. Second, multiple isolated “lanes” through one local relay. I killed that once I actually traced the code: single-tenant assumptions run all the way down, and making that layer multi-tenant would’ve meant rewriting the very thing I was trying to test. Third, I priced up alternatives: a flat-rate dedicated server, and (briefly) just building a second machine, an idea that survived right up until I saw what RAM costs these days. Sprites won on the shape of my usage, which is bursty. A flat-rate machine bills for every quiet hour; my fleet spends most of its life parked, then lights up several boxes at once for an afternoon. I need many boxes available, not many boxes running.
Why a Sprite per box rather than containers, a shared VM, or local machines? What did that isolation buy you?
Because each box has to be a computer, not a process. The stack inside is stateful and assumes it owns the machine: an agent runtime holding real credentials, a simulator on its own virtual display, logins for two coding engines, a checked-out repo, warm build caches earned by a real build, a Tailscale identity, and the box-side half of the fleet machinery, the dispatch harness, the watchdog, and the heartbeat telemetry that vouches for it all. A Sprite is a real Linux VM where you get root, with a persistent filesystem, and it wakes exactly as I left it. Park it Tuesday, wake it Friday, and the gateway is still logged in and the branch is still checked out. Could I have rebuilt all that from containers? Probably, piece by piece. But stop a container and it comes back cold (the disk can survive, the running state doesn’t) while a recently-parked Sprite comes back mid-thought: process state survives the suspension, and the tunnels just reconnect. Even a long-cold one comes back with its whole environment intact and its services restarting themselves. A shared VM would’ve just rebuilt the single-tenant problem one level up. And local machines don’t scale past the desk.
What does each box run inside it, and why does that whole stack living inside one Sprite matter?
Each box runs the OpenClaw/Hermes Agent gateways & relays, the G2 simulator rendering to a virtual display that streams live out of the box, a dev server for the app build, an on-demand shim that lets the cockpit drive the sim, the Codex and Claude Code CLIs logged in and ready for dispatch, the ~4,100-test validation suite, and the box-side fleet machinery (dispatch harness, watchdog, heartbeat) riding its own Tailscale tunnel. It all lives in one Sprite because the value of a box is end-to-end truth. When a box says a branch is good, that verdict went through a real gateway, a real relay, and a real render in the sim. The only stand-in on that path is the simulator, and when I need real hardware, my glasses connect to the box instead.
Talk me through the networking model: loopback-only core services, per-box Tailscale tunnels, and temporary *.sprites.app doors for static builds.
Three layers, each closing a different door. The agent runtime on each box runs real, billed agent turns with real credentials, so it binds to loopback and is never web-fronted, full stop. Nothing about “it’s just a dev box” makes an agent runtime safe to expose.
Two kinds of traffic still need in: the control plane (my browser or agents managing the fleet) and the phone lane (my actual phone and glasses acting as a box’s client). Both come in privately: a home-lab server runs 24/7 on my tailnet, hosts the fleet backend, and proxies into each box over loopback tunnels. My browser only ever talks to that backend. The home-lab server is the one piece that never sleeps: idling at about 25 watts, it’s what lets a dispatch wake a Sprite at 3am with no human and no laptop involved.
The *.sprites.app URLs exist for one job: getting a static app build to someone outside the tailnet. One standing public box fronts the static app build and nothing else. The best use of those is a beta tester reproducing their own bug: I serve an instrumented build, they open it on their own device while I watch the live trace, and then the box and the door are torn down together. The live runtime is never behind that door.
The “single client rule” says a box answers to exactly one client at a time. Why was that constraint necessary, and what broke before you enforced it?
It’s the session-rotation surprise from earlier, promoted to law. What broke was never a crash. That’s what made it dangerous. Attach a second client and the runtime silently rotates the live session over to it, so the first client keeps rendering a conversation that no longer exists. I’d be driving the sim from the cockpit, connect my glasses to “just check something,” and suddenly the cockpit was a museum exhibit: agent still working, answers landing in a session nobody was watching. You lose minutes to that before you even suspect it, because nothing looks wrong.
Rather than rewrite the session layer, I made the constraint something the tooling enforces instead of something I remember. Each box has exactly one armed lane at a time, its own simulator under the cockpit, or my phone and glasses over the tunnel, and arming a second lane is refused until the first is disarmed. The failure mode moved from silent switch to loud no. Read-only taps don’t count: the Overview thumbnails watch the render without ever touching the session. Once the rule lived in the tooling, that whole class of confusion stopped, not because I got more careful, but because I no longer had to be.
Where do fast checkpoints and restores actually matter? What does a developer feel when it’s that fast versus, say, ten seconds?
Less as a pain relieved, more as a hesitation removed. I can’t claim sub-second restore rescued me from some ten-second nightmare, because I never lived one. What I can tell you is what it makes effortless. An agent iterating on a problem can snap back to a known-good savepoint and go again, instead of rebuilding a stack, and because savepoints are cheap to take, there’s always one worth going back to. And when I get a whim to try a few approaches at once, I fan out boxes and they’re all working before I’ve finished typing the prompts. At ten seconds those things would still be possible; they just wouldn’t be reflexes. At sub-second, “park it” and “spin another” are muscle memory, and the fleet stays cold by default without me spending any discipline on it.
Idle cost is described as roughly $0. How does that change how you work? Do people leave boxes armed that they wouldn’t have kept running otherwise?
Yes, though what I keep around isn’t running boxes, it’s parked ones. Waking one takes a couple of seconds, so nothing stays armed just in case. I have three primary boxes plus one serving the public app build, provisioned 24/7 with the gateway, the sim, and all the logins already set up, and scratch boxes on top as needed. Parked, each costs a few dollars a year, so there’s usually one sitting around holding a half-finished experiment and I don’t think twice about it. On a billed VM I’d have deleted it the same day, and realistically never rebuilt it. So the fleet mostly just sits there, like tools on a shelf.
The shelf works without me, too. Waking a box isn’t a human act in this system; it’s just a dispatch. When a user-submitted bug report needs triage, or a fresh OpenClaw or Hermes Agent release needs checking against my code, a box wakes, does the work against the real stack, reports back, and parks. The fleet earns its keep in the background without a cent spent on standby.
The cross-engine auto-review has Codex and Claude reviewing each other’s work. How did that come about, and how much do you trust it?
It came from a simple observation: an agent reviewing its own work has the same blind spots twice. Two models from two different labs disagree, and the disagreements are where the bugs are. So every dispatched task ends with the other engine reviewing the diff and writing a review.txt that travels with the DONE report. It pulls its weight. The reviewer always starts in a clean context, looking only at the diff, so it carries none of the writer’s assumptions, and it goes hunting for the edge cases the writer was too close to see. Then the two work the branch together, round after round, until they’re both happy. To me it’s just the natural extension of writing code at all: after it’s written, it gets checked, and never by the hand that wrote it.
How much do I trust it? As a filter, a lot. As a substitute for me, not at all; I still read every PR. It also taught me a lesson about automated verdicts: early on, a healthy-looking review summary turned out to be an error dump from a misconfigured reviewer, and my pipeline had been counting lines instead of checking success. Now the verdicts verify the artifact, and every verdict carries a harness signature: a DONE report that arrives without one gets quarantined, not counted. Trust the mechanism you’ve audited, not the green checkmark.
How many boxes does a typical developer run in parallel? What’s the most you’ve seen armed at once?
Day to day, one or two awake at a time. The most I’ve had going at once is five, and I expect that number to climb as I roll out more autonomous agent loops. But the count is the wrong thing to watch, and low numbers aren’t underuse. The point was never to run many boxes, it’s to have many available: I get the whole benefit of the fleet for almost no cost, one or two most days, five when I want it, and any number I need only ever a moment away, with nothing billed for the boxes sitting parked in between.
Are there numbers you can share: task throughput, time saved per cycle, cost before versus after, region choices, box specs?
- A full end-to-end smoke test (fresh runtime install, gateway up, sim rendering, one real billed agent turn) cost $0.22 in compute. A real dispatched task, including a mid-run course correction, came to $0.64.
- Parked cost is measured at tens of cents per box per month.
- A fresh box building its whole stack to fully-serving is about 27 seconds, measured. That’s separate from waking an already-built box: a recently-parked (warm/suspended) box is the sub-second path, and one that’s gone fully cold (stopped) is back in a second or two, with its services restarting themselves from there.
- Boxes are the standard Sprite spec: 8 vCPU, autoscaling memory (2 to 16 GB), 100 GB.
- Region: Fly has Sydney, and I ping it at sub-50ms. That’s just over half the time it takes Bluetooth to get an ack from my phone to the glasses sitting on my face. A datacenter that replies faster than my own glasses is not a latency problem I need to manage.
“Time saved per cycle” is hard to reduce to one number. The real change is that several validation loops now run at once, unattended, where one used to run at a time with me watching it. And the saving compounds, because the queue is gone: work never sits waiting for the simulator to free up, so every loop I add is pure parallel time, not another job in line.
What was the most frustrating part of building this on Sprites? What fought you?
The biggest surprise was architectural: I assumed I’d bake one perfect box and clone a fleet from it, and at the time there was no cross-Sprite restore, so that plan died on day one. Instead, every box is built up from scratch by a provisioning script, and that script quietly became the foundation of the whole system. I’ve since noticed forking land in the release notes, but I haven’t gone back to it. The script turned out to be the right shape anyway: versioned, repeatable, and honest in a way a golden image never is. But I arrived there by having my first plan refused.
Was there anything about Sprites or Fly.io that was missing, surprising, or that you had to work around? We like to talk about the friction alongside the wins.
Two stories. The first is what actually holds a box awake. Background services don’t keep a Sprite from suspending, which is correct but surprising, while a forgotten console session or an open proxy tab absolutely does. My number one “why is this box still awake” culprit turned out to be a lingering session somewhere, so my status tooling now lists exactly what’s holding each box up.
The second: for a stretch, boxes would occasionally freeze mid-run, with the heartbeat and the build stopping together while the API still said “running.” Credit where it’s due: Fly support moved me over to the newer I/O platform, and since the fleet was recreated there it’s been quiet. My telemetry caught those freezes because I’d long since stopped trusting any single liveness signal; fusing platform status, box heartbeats, and responsiveness is what flagged “machine running, guest unresponsive.”
If you started over tomorrow, what would you do differently?
Less than you’d think. Most of what fought me pushed me somewhere better. Losing the golden-image plan handed me a provisioning script that’s more honest than any image, and here’s the part I didn’t expect: I gave up nothing for it. The script builds each box the long way, versioned and readable top to bottom, and the Sprite snapshot keeps the warm result, so I get an image’s speed with none of its amnesia. Best of both. The freezes, similarly, forced telemetry I now couldn’t work without. The one detour I’d genuinely cut is the shared machine. I kept teaching one laptop to share itself, compile, sim, plugin runtime, an elaborate queue around something that couldn’t be shared. The day I stopped asking “how do I share this box” and started asking “why is there only one box” was the day it fell into place. I’d ask it weeks earlier.
What’s the one thing this setup lets you do that genuinely wasn’t possible before?
Running experiments I expect to fail. That’s new. When trying a theory cost a day of the machine, every run had to justify itself, which meant I was betting, not experimenting. Now a full e2e run to failure costs 64 cents, and failure teaches me something instead of costing me something. OcuClaw’s best features are experiments I didn’t expect to survive.
If you had to explain to another glasses-app developer in a single sentence why this architecture is worth copying, what would you say?
I don’t prioritize anymore. An idea gets its own stack the moment it lands, three paths at once if I’m torn, dispatched mid-walk from the glasses and coming back to my face as a finished branch, with no laptop wedged open and no meter I can hear ticking.