Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 4 min read

Building Claudeq: a touchscreen control surface for Claude Code

The problem: agents that stop and wait Claude Code is Anthropic's terminal-based coding agent. It's autonomous for stretches, but by design it periodically stops: a permission prompt before it touches something risky,

Building Claudeq: a touchscreen control surface for Claude Code

The problem: agents that stop and wait

Claude Code is Anthropic's terminal-based coding agent. It's autonomous for stretches, but by design it periodically stops: a permission prompt before it touches something risky, a clarifying question when it genuinely isn't sure what you want. That's a feature, not a bug β€” except when you're running several sessions across different projects, because then the failure mode isn't "the AI got something wrong," it's "I didn't notice it was waiting on me for twenty minutes."

I wanted a physical, glanceable answer to "which session needs me right now." That's Claudeq.

Real Claudeq device working, showing a prompt and user selecting an option

It's way faster than fiddling around with the Claude Code app in your phone, and still works if you forgot to start the /remote-control before leaving your desk.

What it is

Claudeq is a free, open-source (MIT), personal project β€” not a product, not a company, no monetization. It turns a Waveshare ESP32-S3-Touch-LCD-3.49 (a ~$30, 172Γ—640 portrait touchscreen) into a dedicated control surface for Claude Code:

  • Claude's AskUserQuestion prompts render on-screen β€” tap an option to answer. Multi-question prompts step through one at a time.
  • Every running session is a chip across the top; the one that needs you glows, and a new question auto-focuses whoever asked.
  • It discovers every bridge on your LAN via mDNS and, optionally, over a Tailscale tailnet β€” so sessions running on other machines merge into the same screen.
  • A macro deck fires a saved prompt or slash-command with one tap.
  • Tap-to-talk voice input, transcribed locally via whisper.cpp (no API key, nothing leaves your machine until you review the transcript and hit Send).
  • OTA firmware updates, pulled from GitHub over HTTPS, with automatic rollback if an update fails to boot.
  • On-device WiFi/Tailscale setup through a captive portal β€” no rebuilding firmware to change networks.

Architecture

 Claude Code A     Claude Code B     The claudeq command
   β”‚ hooks            β”‚ hooks        launches a tmux session
   β–Ό                  β–Ό
 bridge.mjs ─┐      bridge.mjs ─┐    Each advertises itself
   :8787     β”‚        :8787     β”‚    via mDNS, device discovers
             β”‚                  β”‚    & websocket to ALL bridges
             β”‚                  β”‚    (taps/focus/voice are
             └────▢ claudeq β—€β”€β”€β”€β”˜    routed back to source session)


The firmware is C on ESP-IDF v5.4.1 with LVGL for the UI. Each dev machine runs a small Node "bridge" that Claude Code's own hooks feed session events into (question asked, tool running, reply received); the bridge relays those over a JSON-over-WebSocket protocol to any connected device. A claudeq launcher script is the actual entry point end users touch: it wraps claude in a tmux session named after the project directory (so it shows up correctly as a chip), starts the bridge if it isn't already running, and otherwise gets out of the way β€” plain claude still works exactly as before.

Some implementation details worth sharing

OTA and the partition problem. Adding OTA support after the fact meant changing the flash partition table β€” which itself can't be done over the air. Anything flashed before OTA existed needs exactly one more USB flash to adopt the new layout; every update after that is wireless, with automatic rollback if a new image doesn't boot cleanly.

Zero-toolchain distribution. Release builds are served through a static page using ESP Web Tools (WebSerial), so installing doesn't require ESP-IDF, Python, or any CLI β€” plug in USB-C, open Chrome or Edge, click Install. A claudeq flash CLI command exists too, for anyone who does have the toolchain and just wants a shortcut.

Standby vs. lock. The backlight is the dominant power draw, so standby only turns off the screen β€” WiFi and the WebSocket stay connected, so the deck lights back up instantly on an incoming question or alert rather than needing to reconnect. Locking (long-press the BOOT button) is a separate, stronger state for "this is going in my pocket": screen dark, touch and incoming wake events both ignored, until another long-press unlocks it.

No auth yet. Worth stating plainly: the device↔bridge WebSocket has no authentication. It's fine on a home LAN or personal tailnet you trust; it is not meant to be exposed to anything untrusted. That's explicitly called out in the README and is next on the roadmap.

Installing it

  1. Flash from a browser (WebSerial, Chrome/Edge, no toolchain) β€” or claudeq flash if you have Node already.
  2. brew install Positronico/tap/claudeq β€” pulls in Node, tmux, ffmpeg, and puts claudeq on your PATH.
  3. Connect the device to WiFi via its own captive portal (Claudeq-setup hotspot on first boot).
  4. Run claudeq instead of claude in any project.

Building from source (only needed if you want to change the firmware or bridge) is documented in the README, including the ESP-IDF setup and the build-dist.sh packaging script.

Why share it

This started as a for-myself project β€” I use it daily now β€” but the underlying problem (many agent sessions, only one pair of eyes) doesn't seem specific to me. It's MIT-licensed and free; the project page (https://invisible.cat/claudeq) has the overview and links through to the GitHub repo, which has everything including a protocol doc and pinout reference if you want to poke at the firmware/bridge.

Links

Claudeq device showing the macros options
Claudeq device showing a session transcript
Claudeq device showing the settings screen
Claudeq device showing the voice/dictation option

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.