Even Realities G1: Build notes

BLE takeover architecture, display constraint discovery, Claude Code integration pipeline, display modes, and Mac companion app. Seven sections on replacing the phone.

01: Context

The phone was always in the loop.

I bought the G1 for one job: to know when Claude Code needs me without looking at a screen. Out of the box that is not what the glasses do. Even Realities ships them with a phone app that owns everything. Notifications pass through it. Weather passes through it. The AI assistant passes through it. The glasses are a peripheral of the phone, and the phone is always in the loop.

So the first decision was to take the phone out. Replace the companion app with a desktop-hosted runtime that owns the G1 over BLE, and let the glasses become a direct surface for whatever is running on the machine.

That gave the build a specific north star. The glasses answer one question, when can I give feedback or guidance? Live tool progress, stop notifications, and session state from Claude Code, with no phone in hand and no window switch.

02: The Constraint

Forty characters. Five lines. Green.

The G1 display is monochromatic green, roughly 488 pixels wide. That gives you about 40 characters per line and 5 lines per screen. No scrolling, no font weights, no color. The window sits in peripheral vision at a 20° field of view, so whatever appears has to be readable in under 300 milliseconds. Anything slower is a distraction.

Input is voice and a small touch surface on the temple arm. There is no tap target, no scroll gesture, no pointer. Most UI patterns do not transfer. The design question is what does, and what should never appear in the window at all.

The hardware splits too. Left and right arms are separate BLE connections, both paired, both synchronized: send to the left, wait for the ACK, then send to the right. Done naively that takes 1.6 seconds per frame, which for a glance is the same as never arriving.

40chars

Line width

Maximum characters per line on the monochromatic green display.

5lines

Screen depth

Total visible lines. No scrolling, no paging.

20°FOV

Field of view

Peripheral vision. Has to land in a glance.

2arms

Dual BLE

Left and right are separate connections; both must sync.

03: The D0 Probe

Co-opt. Don’t suppress.

The first assumption did not survive the first device probe. The stock firmware HUD (time, weather, date) cannot be fully hidden. The hide_dashboard command only repositions it. I had planned the whole display around a blank canvas, and there was no blank canvas.

So instead of fighting the firmware layer, I co-opted it. The 0x06 BLE command lets you feed the stock HUD your own data: your own time format, your own weather string. Set it to minimal mode so it takes as little room as possible, then take over the “Even AI” canvas, the second display layer, for everything that matters.

The result is a two-layer model. The firmware HUD carries ambient context at the bottom of the display. The custom canvas carries active content: tool progress, stop notifications, session state. The layers share the window, and that one discovery set the display strategy for everything after it.

Three-ring takeover

Ring 1: Own the companion connection (BLE pairing, bypass phone). Ring 2: Own the display (firmware co-option + custom canvas). Ring 3: Own the experience (attention tiers, context routing, voice).

Dual-layer display

Firmware HUD: ambient (clock, weather, battery) via 0x06. Custom canvas: active content (tool progress, notifications, state) via send_text/send_result. Two layers, one window.

04: The Build

Glasses as a coding surface.

The runtime is a Python FastAPI daemon on macOS. It holds persistent BLE connections to both arms, exposes an HTTP API for integrations, and runs display state through a mode machine: idle home, tool progress, stop notification, tilt dashboard.

Claude Code hooks are the primary integration. An on-tool hook fires on every tool use, file reads, edits, shell commands, and pushes live progress to the glasses. An on-stop hook fires when the agent stops and needs input, and the glasses show a summary frame: task count, tool count, and a “your turn” indicator. I stopped switching windows to check on it.

Transport was the hardest infrastructure problem. Sequential writes took 1.6 seconds per frame, and tool progress fires several times a second. Parallel dual-arm writes push the same content to both arms at once and bring that down to about 150ms. A SHA-256 content hash skips the write entirely when the display already shows the right frame.

01Hook

Claude fires event

on-tool or on-stop posts JSON to the local daemon.

02Format

40-char layout

Word-wrap, truncate, pad to the active display anchor position.

03Hash

Dedup check

SHA-256 content hash; skip the BLE write if the display is current.

04Push

Parallel BLE

Dual-arm write in ~150ms (vs 1.6s sequential).

05Display

Glance frame

Tool name + status on the 40×5 canvas. Readable at a glance.

06Tilt

Dashboard on gesture

Head-up triggers clock + weather + session state overlay.

05: Display Modes

Three stances for attention.

Once frames arrived fast enough, the harder question surfaced: what should the glasses say when nothing is happening? The idle state is most of the day. The state machine has three layout modes, selectable in configuration:

Collaboration

Readiness-first. Shows “G1 OS” header, last action with time-ago label, session stats (tasks/tools). The idle state answers: is anything happening, and do I need to look?

Zen

Single word when idle. Nothing else. For deep work where the glasses should disappear until an interrupt arrives.

Dev

Inline tool progress. Every file read, every edit, every shell command streams to the display as it happens. For pairing sessions where you want full visibility.

Active frames override all modes: tool progress shows a spinner animation with the current tool name (>> Edit, ✓ Read file.py, ✗ Edit). Stop notifications show a summary frame with an ASCII progress bar, task count, and “your turn” indicator. Head-tilt triggers a dashboard overlay regardless of mode.

06: Mac Companion

The control surface the phone app isn’t.

Display configuration needed a home once the phone app was gone, so a native macOS app took its place. The Even app uses a vertical “ladder picker” (positions 0–8) for display height; the Mac app mirrors that mental model exactly, then adds the controls the phone app does not expose: head-up angle (0–60°), display depth (1–9), text anchor position, and alignment.

Geometry changes use the Even app’s two-step preview and apply flow, because the glasses physically move the display and you need to confirm it feels right before committing. Brightness is a direct slider (0–41) with an auto-brightness toggle.

The app also shows daemon health: per-arm BLE state, Claude session activity, current display mode, and the last push timestamp. A live activity card mirrors what the glasses are showing, which makes layout debugging possible without wearing the device.

07: What’s Still Open

The hard problems are not display.

Display is solved enough to be useful. The problems I have not solved sit higher up the stack:

Attention tiers

Not everything deserves a glance. The system needs to tell interrupt (look now) from ambient (there if you look) from quiet (suppressed until asked). Today everything is “always notify,” which is the wrong default.

Voice input

The G1 mic sends LC3-encoded audio from the right arm only, never raw PCM, so decoding through liblc3 has to happen before Whisper can transcribe. Voice would close the loop: the glasses show state, and I answer without my hands.

Context at glance-scale

40 characters is enough for “Edit: server.py” and nowhere near enough for why. The system shows what is happening. Showing whether you should care needs inference the display layer does not have yet.

Failure at speed

Wrong at glance-scale is worse than no output. If the model produces something incorrect and I trust it because I only glanced, that is a harder failure than a phone screen, where there is time to verify. This is the problem the whole project is really about.