Gemini Wrote a New OS for My Google Glass. Now It Talks to Meta Muse.
Gemini Wrote a New OS for My Google Glass. Now It Talks to Meta Muse. In February 2014 I bought a Google Glass Explorer Edition. Explorers collected theirs in person, so on February 28 I sat for a fitting at Google's San Francisco office, 350 The Embarcadero, and carried the future home on the plan

In February 2014 I bought a Google Glass Explorer Edition. Explorers collected theirs in person, so on February 28 I sat for a fitting at Google's San Francisco office, 350 The Embarcadero, and carried the future home on the plane. I wore it for a couple of years, it filmed a road trip through Iceland, and then, like almost everyone else's, it went into a drawer. It was still in the drawer in September 2023, when Google ended support for Glass entirely, and it was still there last week, when I took it out and gave it a new operating system.
Pickup day, San Francisco, February 28, 2014, drawn from my own photograph of the moment: the glasses were three hours old, and the camera that took the original picture was the Glass itself, pointed at a hotel mirror.
Not a ROM. Not a launcher. A Linux system we wrote ourselves, on top of the kernel Google shipped, with no Android anywhere in it. On top of that, the glasses now pair with Meta's Muse app over Bluetooth and hold live voice conversations with an AI, through the bone-conduction speaker behind my ear. As far as a careful search could find, no published project had done either of those last two things with this hardware.
And the code was written by a Google AI. We'll get to that.
The whole arc in 34 seconds: the voice HUD, the full-screen avatar, the camera card. Click through for the version with audio.
Glass's final firmware, XE24, shipped in December 2019 and is usually described as the shutdown notice. Read it more carefully and it's an emancipation proclamation. Google removed the Google account. Google removed the backend connection. What they left behind is a complete, self-contained computer: a 640×360 prism display, a touchpad, an inertial sensor, Wi-Fi, Bluetooth, a microphone, a camera, and a bone-conduction transducer, running a Linux kernel whose source Google had published, on a bootloader that unlocks with a standard fastboot command.
Dead as a product. Intact as a machine. Those are very different things, and the difference is the whole project.
Before writing anything, I did the research properly, because "first" claims are where projects like this go to embarrass themselves. The hardware truth, layer by layer: everything from the kernel up is rewriteable. The display is a plain framebuffer device, the touchpad and IMU are ordinary I2C citizens with in-tree drivers. The bootloaders have no public source and are treated as untouchable. The camera pipeline runs on closed firmware and, on the early evidence, doesn't survive a minimal system. (That last one turned out to be wrong in the best way. Patience.)
My prior-art check came back with a correction I needed: I was not the first person to put Linux on Glass, and it wasn't close. postmarketOS ported Glass itself back in 2017. And three weeks before I started, same month, a builder named Lasimeri published glass-xec-mainline, an Alpine Linux system for Glass that he daily-drives, with nearly every peripheral working. His project is MIT licensed, this one learned its platform layer from it, and both facts are credited in my repo, where they belong.
What the check did clear, with actual searched-empty evidence: no published work had turned Glass into a voice endpoint for a modern AI assistant through a public gadget SDK. Meta's Muse Gadget SDK had itself only opened on October 2, 2026, and nothing in its world targeted glasses. And no published operating system for Glass had been authored by an AI coding agent. So that's the project I built. Credit where it's due, claims only where they're earned.
I wrote the build as a milestone contract: M0, a reproducible boot-image pipeline (stock XE24 kernel, verified by hash, our own Alpine initramfs, inside the 8 MB boot partition). M1, first boot from RAM, nothing flashed. M2, Wi-Fi and modern TLS on a 2014 kernel. M4, a live voice call. And in the middle, M3, the cliff: Bluetooth LE pairing with the Muse phone app, from a 3.4-series kernel, a thing with no public precedent. The brief ordered the builder to stop and report if pairing failed, because that answer would decide the architecture.
The contract also carried safety rules that were not negotiable. Some partitions are never written, ever: the bootloaders and the display FPGA have no public source and no recovery path. The factory image was archived and hash-verified before anything else happened. Every new image gets tested from RAM before it is allowed anywhere near flash.
Then I handed the contract to Google's Gemini 4 Argon, through Antigravity. I even wound down my other Antigravity workers for the evening to bank its usage quota for the run. A Google AI, a dead Google product, and a quota cleared in its honor: if you're going to do a thing, do it with the symmetry on.
The first milestone needed no hardware at all, which was just as well, because at that point the glasses were still in a drawer somewhere in my house. The pipeline unpacks Google's factory image, keeps the stock kernel byte for byte (its SHA-256 is checked before and after every repack), and builds our Alpine userland around it. Two traps defined the work. The boot partition is exactly 8 MiB, and a modern TLS stack does not naturally fit in the space left over; the build ended at about 300 KB under the ceiling, with the crypto libraries packed and unpacked into RAM at boot. And modern ARM toolchains assume a 64-bit time_t, which silently changes the size of kernel structures on a 2014 kernel that expects 32 bits. Every native binary is compiled with that assumption explicitly switched off.
When the unit finally came out of the drawer, the first job was not technical. The battery in a Glass is a sealed 570 mAh cell, and this one had been sitting for over a decade. Swelling check first, supervised charging second, heroics later. It passed. M1 was a RAM boot, fastboot boot and nothing written: our init ran, and the prism lit up with our own framebuffer card where Google's interface used to be. M2 followed: the BCM4330 radio associated on 2.4 GHz Wi-Fi (it has no 5 GHz; some constraints are forever), picked up a modern CA store, and completed a TLS 1.3 handshake from a kernel Google shipped in 2014.
Then we arrived at the cliff the whole brief had been organized around.
BlueZ would not pair. That's the short version, and it was the expected failure: a decade of userspace Bluetooth assumptions stacked against a kernel from 2014.
The longer version is three walls, hit in order. The Bluetooth firmware loader wanted its patchfile under a name the stock system used and our userland didn't. The modern BlueZ advertising manager interface the SDK's pairing flow expects simply does not exist in a form the old kernel can support. And at the L2CAP layer, the address type the stack presented was not the one the SDK's expectations are built on.
The wall, as diagnosed in the build session: the manager interface the pairing flow needs was added to the kernel a full release generation after this one shipped.
The build went underneath all of it. If the GATT stack won't advertise, advertise without it: the pairing service falls back to raw HCI commands, the four standard Bluetooth 4.0 LE commands, issued directly, broadcasting the MuseGadget service UUID exactly as the phone app expects. The L2CAP mismatch closed with a small shim, and the ATT MTU pinned to 23, what the old radio reliably supports.
Then the phone app answered: pairing_confirmed.
The real trace from the build's results log, lightly redacted: five numbered steps from subscription to an encrypted Wi-Fi scan, ending in the two words the whole milestone hung on.
I keep coming back to the shape of that result. The silicon was never the problem. The BCM4330 in a 2014 pair of glasses does Bluetooth Low Energy perfectly well. The gap was entirely in software written after it, which means it was closable in software written now.
One mismatch remained between the glasses and the SDK. The voice client is strict: WAV in and out, 16-bit mono at exactly 24 kHz, and it will not resample for you. The Glass codec speaks 48 kHz stereo. And the 3.4 kernel's ALSA ioctl numbers predate the modern ABI, so a contemporary audio library is quite literally speaking the wrong protocol numbers into the kernel.
The answer is a small C program that translates all three at once. It issues the old ioctl values directly, upsamples the 24 kHz mono reply to 48 kHz stereo for the TWL6040 codec and the bone-conduction transducer, and decimates microphone capture the other way. It later learned a second trick, decoding streamed MP3 in-process, which the camera section below needed. Hold that thought.
The first full voice turn was deliberately small. I asked the glasses, in one sentence, to describe a lighthouse. The reply came back through the bone behind my ear, seven seconds of it, while the prism showed the call live and an animated avatar kept time with the words:
"It's a tall tower throwing a steady sweeping beam across dark water to warn ships and point them to safe passage."
There's a recording of a full turn in the repo, question and reply, if you want to hear a dead platform talk.
The same call twice: first as the wearer sees it on the prism, then the avatar full-screen, lip-synced to the reply.
One precision, because it matters to me: the glasses are an endpoint. The conversation lives in my Muse account and terminates at Meta's cloud service; nothing about the voice path touches my home servers. A pair of Google glasses, running a Linux system Google never shipped, talking to Meta's AI through Meta's gadget SDK. The 2014 future took a strange route, but it arrived.
Remember the camera that "doesn't survive"? The prior art had already proven otherwise. Lasimeri's build drives it through the Ducati coprocessor from C, and our M5 milestone made it a feature: pressing the physical camera button on the top frame snaps a 640×360 frame, renders a live viewfinder thumbnail (or a full-screen picture-in-picture card) alongside the avatar on the prism, uploads the image directly into the active Meta Muse conversation thread, and streams the assistant's spoken description back through the bone-conduction transducer in MP3 with real-time lip-sync. The conversation on the glasses and the conversation on the phone are the exact same conversation.
The shutter-press flow as recorded on the device: snap, viewfinder card, upload into the same thread.
Two engineering details made that work, and both are the kind you only find by doing. The Ducati coprocessor's firmware has to be fed to it through a legacy sysfs loader in roughly the first minute after boot, or the camera device never appears; the boot scripts now start that feed in the first second. And converting a camera frame from NV12 to something uploadable took about 3.8 seconds in Python on the Glass's Cortex-A9. The same conversion in C takes about 2 milliseconds. On hardware this old, the language you choose is a feature.
Everything above was proven on a bench, with the glasses plugged into a computer. A wearable that only works on a cable is a demo, so the next phase was unglamorous and essential: untethered operation, and surviving a reboot.
Unplugging surfaced two bugs that no bench test could have caught. The Glass shares its micro-USB port between data and an audio earpiece through a switch chip, and the stock kernel reports the headset state as the literal string "None" when nothing is latched; our audio routing was checking for "0", so the mux stayed on USB and the bone-conduction path stayed silent until the routing learned to treat "None", and an unplugged cable, as the signal to switch. The second bug was worse.
Before the clock syncs, the glasses' clock can sit far enough off that the SDK's token logic concluded the pairing token was stale, tried to refresh it, got a refusal, and deleted the perfectly valid pairing file. The fix is a patch to refresh only when the service itself actually reports the token dead. Pairing survived reboots after that, which is fortunate, because re-pairing is the one trick in this project I never want to do twice.
Heat got a pass of its own. The HUD's render loop was comparing frames against uncached video memory every 80 milliseconds, which kept the processor pinned at 600 MHz doing nothing, at 13% CPU, forever. Comparing against a cached shadow buffer instead, slowing the idle refresh, and letting the CPU governor drop to a 300 MHz floor took idle CPU to 2% and the board temperature down by about four degrees. On a 570 mAh battery worn against your temple, that difference is the product.
The finale of this phase was the step the safety rules had been protecting all along. The whole system, userland, credentials, pairing state and all, was synced to the internal storage over Wi-Fi, and the boot image was written to the boot partition over Wi-Fi too, by an on-device updater that verifies the stock kernel's hash inside the image before writing, then reads the entire partition back and verifies what it wrote. The glasses now cold-boot into our system on their own.
No cable, no fastboot, no bench. I could finally pick them up and walk away from the desk, which produced exactly one more bug: I picked them up by the temple arm, my thumb rested on the touchpad, and the glasses interpreted the hold as a command and switched systems on me. The gesture that summons the system chooser now requires two fingers.
Grabbing your glasses like glasses should never be an input event.
Somewhere in that phase the project stopped being a firmware image and became a platform. The glasses now run a small authenticated HTTP daemon that serves screenshots of the prism, telemetry, archived voice and camera turns, and controls for cards, brightness, audio routing, camera, voice turns, and updates. On the host side, an MCP server wraps that daemon in twenty-three tools, so an AI assistant with MCP access can check the glasses' health, take a screenshot, snap a photo, record a short clip, ask the glasses a question and hear the answer spoken, read their sensors, change their settings, speak a sentence aloud through them, trigger a Wi-Fi heal when the radio hangs, or reboot them into the other system they dual-boot. (A second, local system shares the same hardware layer and the same boot chooser; it is a different project with its own story, and it will get its own article.)
The glasses also grew a settings card of their own along the way: volume, brightness, audio output, desk sleep, and the OS switch, all driven from the temple touchpad, with the physical back button as its shortcut. And the voice path has since gone fully realtime. Microphone and reply now stream in both directions at once, and the transcripts appear on the prism word by word as they are spoken, which is a strange and lovely thing to watch on a display from 2014.
I did not plan for the control plane to be the point. It turned out to be the point. Once a 2014 wearable exposes the same tool interface as everything else on my desk, it stops being a museum piece with a clever trick and becomes a device you can build on.
The reusable lesson isn't about Glass. It's that "the platform is dead" usually means "the vendor left," and those are different diagnoses with different prognoses. XE24 cut Glass loose from Google, and in doing so accidentally made it the most hackable it had ever been: no accounts, no backend, no one's permission required. A sealed battery and a decade in a drawer were the real risks, and they're inspected for, not theorized about.
The other lesson is about the division of labor. An AI agent wrote an operating system here: planned it, built the pipeline, diagnosed a Bluetooth stack older than some of its training data's authors, and went under it when the documented path failed. A human wrote the contract, set the safety rules, found the glasses, checked the battery, and pressed the buttons that needed pressing. That split, agent builds, human directs and verifies, is the story under the story, and I think it's the part that generalizes.
The hardware layer is now stable enough to build on, and the project record lays out a set of prototype systems that share it. First up is the one the camera work was clearly always heading toward: point the glasses at the world, snap, and have the conversation understand what you're looking at, with translations, explanations, and read-aloud a swipe away. After that, a glance-and-nod remote for the other gadgets on my desk, hands-free checklists, a kitchen mode with timers that live on the device, and a remote-expert mode where someone else can see what you see and talk you through a repair. Each one is small, because the hard part, a living machine with an eye, an ear, and a voice, is done.
Everything is public: the firmware, the build pipeline, the milestones with their evidence, the screenshots and recordings, and the full results log including the dead ends: github.com/niclydon/metamuse-glass. The factory firmware isn't redistributed; the repo documents the hashes so you can extract what you need from Google's image yourself. The platform layer owes its start to Lasimeri's glass-xec-mainline and, before it, postmarketOS; the gadget path is Meta's Muse Gadget SDK; the code was created with Google's Gemini 4 Argon via Antigravity, directed and hardware-tested by me.
The drawer is empty now. That was the point.