Crank Warden

Drive Claude Code with a crank.

Crank Warden turns a Playdate into a pocket remote for your coding agent. Crank to read what it's doing, press A to approve, and hold the d-pad to talk your next instruction. The agent keeps working on your laptop while you're on the sofa, in the garden or in the coffee queue.

  1. Pick a sessionThe bridge lists the Claude Code sessions on your Mac. A opens one.
  2. Crank to readTurn the crank back to scroll up through what Claude did, then forward to return. One turn is about 15 lines.
  3. Answer its questionClaude asks a multiple-choice question. Down and up move the ❯ pointer, and A picks.
  4. Watch it workNew output slides up as it arrives. The view stays at the bottom until you touch the crank.
  5. Hold ◀ and talkYour voice streams to the bridge. Words appear as they're recognised, and earlier words get corrected as it hears more.
  6. Send itWhen you let go, the text goes into Claude Code's input line. Check it, then A sends.
  7. Stick to the bottomThe reply streams in character by character. The view sticks to the newest line and scrolls a pixel at a time.
  8. Crank back to hold your placeThe view stays put while text keeps arriving below, and the status bar counts the new lines. Crank forward past the end to rejoin the live bottom.
0:00

Three pieces. Claude Code doesn't change.

Claude Code keeps running as normal in a terminal on your computer. A small bridge watches that terminal and presses keys for you. The Playdate is a remote control that happens to have a crank and a microphone.

on the device

Playdate app

  • Shows the session's screen, scrolled with the crank
  • D-pad, A and B act as arrow keys, Enter and Esc
  • Streams audio from the mic (C API)
  • Lua interface, C audio module
Wi-Fi
HTTPS + TCP
on your Mac or PC

Bridge

  • Runs or attaches to Claude Code in a terminal it controls
  • Reads the screen and sends only what changed
  • Turns device buttons into key presses
  • Speech-to-text on your machine (whisper.cpp)
  • Pairing, per-device tokens, network allow-list
pseudo-terminal
tmux / ConPTY
unchanged

Claude Code

  • The normal interactive CLI
  • Your settings, MCP servers, skills and permissions
  • You can open it in your own terminal at the same time

Every key Claude Code needs, on a handheld.

The bridge draws the session 64 columns wide, so Claude Code lays out its own text to fit the 400×240 screen in a 6×12 pixel font. Menus and prompts look the way they do in the terminal. On a 1-bit screen, the selected option is shown in reverse video.

The same screen as the device above, at its real 400×240 pixels, enlarged. Black on silver, like the Playdate's reflective LCD.

Crank
Smooth, pixel-by-pixel scrolling through the screen and its history
Crank folded
Follow mode: the view stays on the newest output
✚ up / down
Arrow keys: move through menus and prompts
✚ right
Tab: autocomplete, toggle an option
Hold ✚ left
Push to talk. When you let go, the text goes into the input line without being sent
A
Enter: confirm a choice, send the input line
B
Esc: stop Claude, close a menu, discard a recording
B + A
Shift+Tab: cycle the permission mode (plan, accept edits…)
Menu
System menu items: Sessions, Clear input, Settings

A quiet app on your Mac or PC.

The bridge sits in the macOS menu bar or the Windows system tray. It does what the Playdate can't: it emulates the terminal, transcribes speech and keeps the connection secure. You pair a device once with a six-digit code.

macOS: menu bar and dashboard

Crank Warden
Sessions
Devices
Voice
Security
Log
skywarden~/projects/SkyWarden · tmux cw-skywarden
on device
podwarden-hub~/projects/podwarden · background session
needs you
crank-warden~/projects/crank-warden · idle 14 min
idle
Pair a new Playdate: enter this code on the device
482 913
192.168.1.42:7433
expires in 4:51

Windows: tray app and settings

Crank Warden
Sessions
Devices
Voice
Security
Log
Speech enginewhisper.cpp · base.en · runs on this PC
ready
Live transcript on devicewords appear on the Playdate as you speak
on
Vocabulary hintspdc, Lua, PodWarden, kubectl, SkyWarden
edit
Terminal backendConPTY + headless terminal emulator
built in
PS> cw run --name api claude ✓ session "api" started, shown on 1 device PS> cw attach api
podwarden-hub needs approvalBash: kubectl rollout restart … Answer on the device or here.
ENG14:32

macOS: tmux

cw run starts claude in a named tmux session. The bridge reads it with capture-pane and types with send-keys. Run tmux attach to use the same session at your desk.

Windows: ConPTY

Windows has no native tmux, so the bridge hosts claude in a ConPTY pseudo-console and feeds it to a headless terminal emulator. cw attach shows the session in your own terminal too.

Speech stays local

Streaming whisper.cpp runs on your CPU or GPU, so your voice stays on your own network. A cloud speech service is an option for slower machines.

What's official, and what's a workaround.

Claude Code has no public way for an outside device to see a running session's screen and press keys in it. Remote Control only works with Anthropic's own apps. So the bridge drives the terminal directly, and uses official hooks where they help.

FeatureHowKind
Pick a sessiontmux list-sessions or the bridge's own terminals, plus claude agents --json for background sessionsworkaround official
Stream the screencapture-pane -p -S -2000 or the emulator's buffer, checked about every 200 ms; only changed lines are sentworkaround
Fit the screenThe session's terminal is 64 columns wide, so Claude Code wraps its own text to fitworkaround
Menus and promptssend-keys Up/Down/Enter/Escape/Tab. Covers permission prompts, multiple-choice questions and plan approvalworkaround
Esc / interruptA real Esc key pressworkaround
DictationThe transcript is typed with send-keys -l (literal) and not sent. A presses Enterworkaround
“Needs you” alertsNotification and Stop hooks POST to the bridge, and the device beepsofficial
Approvals without the screenA PermissionRequest hook holds the request until the device answers allow or deny (optional)official
Cloud sessionsNo public API for listing or streaming claude.ai/code sessions. claude -p --cloud <id> can only queue a messagenot possible

Device ↔ bridge protocol (sketch)

GET /v1/sessions GET /v1/s/:id/screen?since=rev changed lines + rev POST /v1/s/:id/keys {"k":"Up"} POST /v1/s/:id/text {"t":"…","enter":false} TCP :7434 PCM16 @ 16 kHz → ← partial text GET /v1/events needs-you, done

Playdate details

  • Networking uses playdate.network HTTP and TCP, available since Playdate OS 2.7. The device asks permission once per server.
  • The mic streams through setMicCallback in C. The Lua recordToSample only returns a finished clip.
  • Audio is downsampled to 16 kHz, about 32 KB/s. Game sound is muted while recording, because the speaker sits next to the mic.
  • setAutoLockDisabled(true) keeps the screen awake. Only one app runs at a time, so the controller stays open.

The bridge can run code on your machine

It types into an agent that runs shell commands, so anyone who can reach it can act as you. It needs pairing codes, a separate token for each device, listening only on your local network, HTTPS, and an allow-list of networks. Every key press is logged.

Shipped in three turns of the crank.

Each phase is useful on its own, and each one de-risks the next.

  1. Phase 1 · a weekend

    Basic controller

    Python bridge on tmux with HTTP polling. Lua app with the text view, crank scrolling and button-to-key mapping. Bridge address and token are set by hand.

  2. Phase 2 · a week

    Voice

    C mic module and a TCP audio stream. whisper.cpp in streaming mode, with live text on the device while you talk, typed into the input line when you let go.

  3. Phase 3 · ongoing

    Polish and Windows

    Pairing screen, session picker, hook alerts, sending only changed lines, reverse-video highlighting. ConPTY backend and a tray app for Windows.