VCode home

Point dictation at another service, or turn it off

Agents: claude, codex, opencode · On: desktop · optional

VCODE_STT_URL is the only coupling between VCode and whatever transcribes a clip. Point it at a GPU box, at a hosted service that speaks the OpenAI shape, or leave it empty and dictation is off.

Why you would use it

The machine running VCode is a laptop and the GPU is elsewhere. Or the sidecar is fine but you want it off on this box. One env line decides.

How to use it

  1. Edit ~/.config/v-code/env (mode 0600) — see environment-variables.

  2. Set VCODE_STT_URL to the origin of the service. The route always posts /v1/audio/transcriptions on it, so a base URL with a path still lands on the service root.

    VCODE_STT_URL=http://10.0.0.4:3446
    
  3. To turn dictation off, set it to nothing:

    VCODE_STT_URL=
    
  4. Restart VCode from a real terminal or over ssh, never from inside a VCode thread: systemctl --user restart v-code.service.

install.sh voice only adds the key when it is absent, so a value you set by hand survives every later install and update.

What you see

With a value, /health reports voice: true and the mic appears. With an empty value, /health reports voice: false, the server refuses a clip with voice is not configured on this server, and no mic is drawn — the composer is exactly as it was.

A value that is not an http(s) URL fails the boot with one line: VCODE_STT_URL must be an http(s) URL, got "ftp://x": …. That is deliberate: a typo stops the service rather than 502-ing every tap.

Options and settings

Option Default What it changes
VCODE_STT_URL empty The service origin. Empty is voice off; a non-http(s) value fails the boot
What is posted — multipart POST /v1/audio/transcriptions, field file, field model=parakeet, and one VCode request header
What is expected back — JSON with a string text. An empty string is a valid answer
Timeout 60 s REQUEST_TIMEOUT_MS in lib/voice.js
Clip size 25 MB The largest clip the server accepts from the phone

A service that never heard of that header ignores it, so an OpenAI-shaped endpoint works unchanged.

Limits and known gaps