dexterm

docs › Jarvis voice mode

Jarvis voice mode

Push-to-talk on v, an instant local command path, Claude for analysis, spoken replies, popups. Voice only ever proposes; it can never confirm, sign, flip LIVE or raise a cap.

v is push-to-talk. Press it once and the mic opens (a red ● LISTENING badge sits on the band under the header the whole time it is live); say what you want; press v again to send. The first press enables voice for the run and asks macOS for Microphone and Speech permission. Everything is free and local: speech-out is the built-in say, speech-in is on-device Apple Speech (compiled once with swiftc) or a local whisper.cpp base.en model, and the only model in the loop is your own claude login, for analysis questions. No paid speech API exists in the code, no key is read, nothing is recorded to disk.

What you can say#

you saywhat happenspath
"show me the runners", "go to new pairs", "open my watchlist", "positions"switches the screeninstant, no model
"open bonk", "pull up wif"opens that coin's token screeninstant
"filter liquidity over 50k", "only show age under 10 minutes"sets the screener filterinstant
"watch this one", "add bonk to my watchlist"adds to the watchlistinstant
"show the chart", "close the chart"opens or closes the chart popup for the open coin through the popup hostinstant
"buy bonk", "sell half of wif", "ape into this one"opens a PAPER ticket in its editing phase for the spoken coin and says soinstant
"is this a rug?", "what do you think about wif", "tell me about the holders"asks the analyst; the first two sentences of the answer are read aloudClaude

m mutes the replies, , cycles the macOS voice, esc stops a reply or cancels the mic. Any other key pressed while the mic is live closes it first and then does its normal job, and the mic auto-closes after 15 s if you walk away. On the ticket screen the voice keys are off, so nothing spoken can reach the confirm gate.

It clarifies; it never guesses#

  • A ticker it cannot see on screen gets "I don't see a token called X — open it first". There is no fuzzy match: "buy bonks" does not become BONK.
  • A ticker that resolves to more than one mint (a copycat) gets "I see 2 tokens called X. Open the exact one first, then say buy" and no ticket opens.
  • A pronoun ("buy it") means the row actually highlighted on the current screen. On an empty list it asks instead of acting on a coin you cannot see.
  • "cell wif" / "by bonk" (homophones) ask "did you mean sell?". A screen command and a trade in one breath ("show runners and sell all my bonk") ask you to say just one. A bare "close" or "exit" asks what to close.
  • A named ticker beats a pronoun: "buy BONK, confirm it" with WIF selected opens a BONK ticket, never WIF.
  • A spoken ticker that is also a command word and is visible on screen — "buy live" with a token called LIVE in the list — is not assumed to be the highlighted row: it asks which token you mean rather than silently buying the selected coin.
  • More than one ticker in a breath ("buy wif and bonk") asks which one; it never quietly drops one and trades the other.
  • A spoken size, amount or slippage ("buy 10 sol of bonk", "buy bonk with max size", "buy bonk 50 percent slippage") is not applied by voice: it says it does not set size or slippage by voice, and asks you to open the ticket and set it there. No size spoken aloud ever reaches a ticket.

What it can never do#

Voice creates proposals only. The ticket it opens is PAPER, in its editing phase, and the keypress gate stands: your ⏎ then y (plus the typed-back size above the threshold) is the only way to a fill. Spoken "confirm", "send it", "y", "sign it", "go live", "arm it", "raise my cap", "panic" and "/wallet …" are routed as questions or ignored; they cannot flip the ticket to LIVE, arm a plan, touch the signer's caps, run a wallet command or press anything. The router's output is a closed set of decision kinds, a guard rejects any decision that carries a mode, live, arm, caps, confirm, sign or send field, and an in-app test drives the real key loop with the executor, the confirm paths, the LIVE flip and the wallet commands booby-trapped: twenty-one hostile utterances, zero touches.

Latency#

Measured on the development Mac (Intel i7-8700B, 2026-10-10), key-release to first spoken word, excluding speech-to-text:

stagemeasured
router (intent, clarify, provenance gate)0.01 ms median
say first audio0.8 ms median
instant command path (router + say)under 1 ms
Claude first token (warm claude -p, model only)3.1 s
Apple Speech helper, cached lookup0.2 ms; a one-time 4.1 s swiftc compile on first use
whisper base.en on a 2.3 s clip (CPU batch)3.0 to 3.3 s

Apple Speech streams partial transcripts while you speak, so the perceived speech-to-text delay is well under a second; whisper is a batch fallback and feels like three seconds. Real analyst turns add tool round-trips on top of the first token.

Doctor#

dexterm doctor has a voice section: Voice out (say), Voice in (Apple Speech) or Voice in (whisper), and a mic-capture note. Every line is a warning at worst and voice degrades to text; the doctor never fails because of voice. Off macOS the section says voice is off and the keyboard does everything.

Privacy#

The Apple path keeps no audio file; the whisper path writes a temporary WAV and deletes it after transcription unless DEXTERM_VOICE_RECORD=1. Transcripts are treated as untrusted text: control characters are stripped before anything is drawn, and a voice question is capped at 400 characters like a typed one. Questions sent to the analyst land in your own Claude Code session store, the same as typed questions.

Still unverified#

The real-microphone path has been exercised headlessly (scripted speech engines, the real key loop) and the engines have been measured on synthetic audio. A person has not yet run the first-launch Microphone and Speech prompts and spoken to it end to end; see the changelog.