μœ λŒ€μ„ 
← ν”„λ‘œμ νŠΈλ‘œ
Β·μ—…λ°μ΄νŠΈΒ·1 λΆ„

Cockpit gets a voice: speak commands on the phone, launch it from the web app

Two usability wins for the terminal cockpit: a 🎀 voice-input button (Web Speech API live-transcription into the compose bar, with a graceful keyboard-mic fallback on iOS Safari), and a 'open cockpit' button in the web dashboard whose token-bearing URL is stored ONLY in the browser's localStorage β€” never synced to the cloud.

Typing on a phone to drive a terminal is misery. So the cockpit grew two things.

Voice in

A 🎀 button in the compose bar. Where the browser has the Web Speech API (Chrome, Android, newer Safari), tapping it starts live transcription straight into the box β€” interim words stream in as you speak; tap again to stop, then 보내기. A ν•œ/EN toggle switches recognition language (Korean intent vs English shell verbs). Where SpeechRecognition is absent (older iOS Safari), 🎀 just focuses the box so the OS keyboard's own mic is one tap away β€” the reliable fallback, honestly labelled.

Deliberately no auto-send: a misheard word must never fire a terminal command blind. Voice fills the box; a glance and one tap sends it. For talking to Claude (natural language) that's plenty fast; for raw shell it's a needed safety beat.

Launch from the dashboard, token stays local

The web dashboard now has a "πŸ–₯ 콕핏 μ—΄κΈ°" button. The catch: the cockpit URL carries its access token, and the web app talks to Supabase. So the rule is strict β€” the URL is stored only in this browser's localStorage, never written to Supabase, never synced. The web app is purely a launcher; the live terminal connection still terminates at the Mac. The settings panel says so in plain words.

This keeps the architecture honest: data lives in the cloud, the live terminal lives on your Mac, and the secret that bridges them never leaves your device.

tsc clean (web), cargo build green (cockpit). The voice loop's live behavior is the owner's to confirm on his phone (browser speech support varies by device).