Skip to content

Voice as a Clayde capability: shared transport layer under voice-walk / voice-command / quick-command / ntfy-ping #101

Description

@ClaydeCode

Problem

Voice I/O is spread across four skills that each re-solve a slice of the same transport:

  • voice-walk — browser page, Web Speech API in, speechSynthesis out, persistent headless session
  • voice-command — Pebble watch, speech-to-text in, ntfy JSON envelope out
  • quick-command — one-shot headless dispatch, text only
  • ntfy-ping — push notification out

Each owns its own answer to: how does speech become text, how does text become audio, how is a session addressed and kept alive, how does a link or reply reach the phone. Fixing any one of those fixes it for exactly one skill.

The first real voice-walk field test (2026-07-15) made the cost concrete. Six of seven defects were transport, not brainstorm logic, and none were specific to walking:

  1. TTS dies on screen lock. The page speaks via SpeechSynthesisUtterance; Chrome Android suspends the Web Speech API when the tab backgrounds. Not a setting — the API itself. Phone must stay awake and foregrounded, defeating the premise. Proper fix is server-side TTS → <audio> + MediaSession, which is architecture, not a patch.
  2. Long-press on the record button selects its text. Hold-to-talk fights Android's own long-press gesture. Toggle removes the conflict.
  3. Truncated dictation, two independent causes. The selection popup fires pointercancel instead of pointerup, which nothing handles. Separately, the send path waits a hardcoded 250ms after rec.stop() before reading the transcript — a race with a magic number that silently drops the tail when the final result finalizes slower. Should send on rec.onend.
  4. Missing space makes TTS read punctuation aloud. Text deltas are joined with "".join(chunks), so when a tool_use block sits between two text blocks the texts concatenate with no separator and TTS pronounces doing.Confirmed as "doing dot Confirmed".
  5. Greeting is discarded. The warm-up turn loads context and greets, then throws the output away, so the first real turn is wasted and the greeting has to be re-asked. Should be a Start button.
  6. Session link is not tappable in the ntfy app — long-press copies the whole message. (ntfy likely has click/action headers for this; unverified.)
  7. Latency was fine (~1.3s warm turns), which is where most of the original design effort went.

Result: zero brainstorm content captured. The whole transcript is the user fighting the tool.

Proposal

Design a shared voice capability for Clayde — the transport layer the skills sit on top of, so a fix lands once. Rough scope, to be settled in design:

  • Audio out — server-side TTS, MediaSession, survives screen lock. Replaces per-skill speechSynthesis.
  • Speech in — capture semantics (toggle vs hold), reliable end-of-utterance, jargon handling.
  • Session lifecycle — warm session, addressing, start/stop, crash recovery, transcript persistence.
  • Delivery — how a session link or a reply reaches a phone or a watch, tappably.

Per-skill concerns stay per-skill: what the agent is for (brainstorm an issue, run a command), its system prompt, its artifact handling.

Notes

Not scheduled — deferred deliberately as a larger design task. Filing so the field-test evidence and the capability argument aren't lost.

Item 1 alone changes the architecture, so this wants a design pass, not seven patches to voice-walk.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions