English | 日本語
See your tmux session on Even Realities G2 smart glasses and talk back to it.
The web app mirrors a remote tmux pane onto the G2 display via the Even Hub SDK. Double-tap the temple to open the mic; speech is transcribed through a Whisper-compatible endpoint and piped into the pane with tmux send-keys. Native swipe on the temple scrolls; when you hit the top or bottom boundary, the app pages older/newer content in.
Built for ambient access to a long-running Claude Code (or any tmux-hosted TUI) session while away from the laptop.
┌──────────── your host (tmux session) ────────────┐
│ tmux-g2-bridge (FastAPI, :18820) │
│ ├─ WS /tmux snapshot push + input receive │
│ ├─ POST /asr Whisper-compatible proxy │
│ └─ GET /healthz │
└────────────────────┬─────────────────────────────┘
│ wss + https
┌────────────────────┴─────────────────────────────┐
│ Phone │
│ Even Realities app → WebView (tmux-on-g2) │
│ └ @evenrealities/even_hub_sdk │
└────────────────────┬─────────────────────────────┘
│ Bluetooth 5.2
┌────┴─────┐
│ Even G2 │
│ 576×288 │
└──────────┘
The app code runs on the phone as a WebView under the Even Realities companion app; only rendered frames and gestures cross the Bluetooth link. The bridge stays on your host, co-resident with the tmux server.
- Even Realities G2 + phone paired via the Even Realities app
- An Even Hub developer account (free, for sideloading builds) — see docs
- Node 18+ and
npmon the dev machine - A Linux host with
tmux, Python 3.10+, andsystemdfor the bridge - A Whisper-compatible ASR key (Groq default; OpenAI works too) unless you self-host
- Phone reachable to the bridge at runtime — Tailscale is the easy option; LAN or tunneled public HTTPS also work
Full walkthrough with troubleshooting lives in docs/SETUP.md. If you hit a specific error, docs/TROUBLESHOOTING.md has the symptom-first index.
On the Linux host that owns the tmux session you want to mirror:
git clone <this-repo> tmux-on-g2
cd tmux-on-g2/bridge
sudo ./install.sh
# edit /etc/tmux-g2-bridge.env — fill ASR_API_KEY, set ALLOWED_TARGETS, TMUX_USER, etc.
sudo systemctl restart tmux-g2-bridgeVerify:
curl -s http://localhost:18820/healthz # → ok
grep BRIDGE_TOKEN /etc/tmux-g2-bridge.env # copy this token for the appcd tmux-on-g2 # repo root
npm install
cp .env.example .env.local
# edit .env.local → point VITE_BRIDGE_URL at the bridge, paste VITE_BRIDGE_TOKEN
npm run dev # http://localhost:5173Preview in the simulator (renders the glass display on your desktop):
npm run simnpm run build
npm run pack # produces tmux-on-g2.ehpkUpload the .ehpk to the Even Hub developer portal. Flip the build's status from Private (draft) to Beta and add yourself as a tester — otherwise the tester invite link reports "テスト版の有効期限が切れました". Accept the invite promptly; links are time-limited.
After install, launch "Tmux Mirror" from the Even Realities app.
| Gesture | Action |
|---|---|
| Swipe up / down on the temple | Scroll (native firmware-handled) |
| Swipe past top | Page to older tmux lines |
| Swipe past bottom | Snap back to live tail |
| Double-tap | Toggle mic: first tap starts recording, second stops and transcribes |
tmux-on-g2/
├── src/ # Vite + TS web app
│ ├── config.ts # canvas size, rate limits, bridge URL/token
│ ├── tmux-stream.ts # WS client (reconnect, input send)
│ ├── glass-render.ts # SDK bridge wrapper + CC chrome trim heuristic
│ ├── asr.ts # PCM buffering, WAV, RMS-VAD, hallucination filter
│ ├── input-control.ts # gesture + audioPcm event parsing
│ └── main.ts # boot, wiring
├── bridge/ # Python bridge for the tmux host
│ ├── bridge.py # FastAPI app
│ ├── bridge.env.example
│ ├── tmux-g2-bridge.service # systemd unit
│ ├── requirements.txt
│ └── install.sh
├── app.json # Even Hub manifest
├── vite.config.ts
└── docs/
├── SETUP.md # step-by-step install + first run
├── ARCHITECTURE.md # data flow in detail
├── SDK-NOTES.md # Even Hub SDK invariants, gotchas, resolved traps
└── TROUBLESHOOTING.md # symptoms → fixes
| Var | Meaning |
|---|---|
VITE_BRIDGE_URL |
WebSocket URL of the bridge, e.g. ws://100.x.y.z:18820/tmux |
VITE_BRIDGE_TOKEN |
Value of BRIDGE_TOKEN from /etc/tmux-g2-bridge.env |
See bridge/bridge.env.example. Key settings:
BRIDGE_TOKEN— shared secretALLOWED_TARGETS— comma-separated tmux session names the bridge will mirrorTMUX_USER— OS user that owns the tmux server (bridge runs as root and usessudo -n -u <user>)ASR_BASE_URL/ASR_API_KEY/ASR_MODEL— any OpenAI-compatible transcription endpoint
- The bridge accepts bearer tokens via
Authorizationheader or?token=query param, compared withsecrets.compare_digest. ALLOWED_TARGETSgates which tmux sessions the WS endpoint will capture from; requests for other sessions are rejected.- The web app's
.env.localtoken is embedded in the Vite bundle at build time (Vite rule). That bundle ships inside the.ehpkto your own device. Treat the token like an API key — rotate if you share or publish the build. - The bridge has no rate limiter on
/asr; add one before exposing publicly. - Bind the bridge to
127.0.0.1+ put it behindtailscale serve(or equivalent) for TLS termination if reaching it over the public internet.
See docs/SDK-NOTES.md for the full list of Even Hub SDK 0.0.7 invariants the app was designed around. Highlights:
- 576×288 per eye, 4-bit greyscale, single LVGL firmware font — no font size API
- Max 1000 chars (startup) / 2000 chars (upgrade) per text container, ~400–500 chars fill the screen
- Gesture enum: click / double-click / swipe-top / swipe-bottom / foreground toggles; long-press is reserved by "Even AI"
- Audio: raw 16 kHz 16-bit LE mono PCM only; the companion app's built-in ASR is not exposed to apps
See CONTRIBUTING.md. PRs welcome — especially on Japanese Whisper accuracy, other TUI chrome heuristics (shells beyond Claude Code), and image-container rendering for custom font sizes.
MIT. See LICENSE.