Skip to content

WillTaylorDev/opencode-voice

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

opencode-voice

Hold a hotkey anywhere on macOS, speak, and a Terminal window opens straight into an opencode TUI session with your voice as the first message.

Runs entirely on your machine. Microphone capture via sox, transcription via whisper.cpp. No API keys for transcription. The only network call is whatever opencode itself makes to your configured AI provider.

Demo

hold right-Option ── 🎙 recording overlay appears
speak (1-2s minimum)
release ─────────── overlay disappears
                    new Terminal window pops up showing "transcribing..."
                    whisper-cli runs (~1-2s)
                    Terminal cuts to the opencode TUI with your prompt
                    submitted as the first message

Everything works from any app: dictate prompts while you're in Slack, Spotify, your IDE, anywhere.

Requirements

  • macOS (tested on Apple Silicon)
  • Homebrew
  • opencode, authenticated with whatever provider you use

The installer pulls in everything else (Hammerspoon, whisper-cpp, sox, jq, plus a Whisper model).

Install

git clone git@github.com:WillTaylorDev/opencode-voice.git
cd opencode-voice
./install.sh

The installer is idempotent. It checks for Homebrew, installs the four packages it needs if they're missing, downloads the recommended Whisper model (ggml-large-v3-turbo-q5_0.bin, roughly 570MB), symlinks the runtime files into ~/.hammerspoon/ and ~/.local/share/voice-prompt/, and adds a managed block to ~/.hammerspoon/init.lua.

Re-run it any time. It detects what's already in place and skips the work.

Permissions

macOS will prompt for these the first time they're needed.

  1. Accessibility for Hammerspoon, so it can detect the global hotkey. Pre-grant under System Settings, Privacy & Security, Accessibility.
  2. Microphone for Hammerspoon, so sox can record. Auto-prompts on first recording.
  3. Automation control of Terminal.app, so the pipeline can open a window. Auto-prompts on first run.

Usage

Hold right-Option, speak, release. The recording overlay shows while you hold. The Terminal window opens immediately on release with a "transcribing..." spinner, then drops into the opencode TUI when whisper finishes.

Hold for at least 250ms. Anything shorter is rejected as a stray tap.

Configuration

Edit ~/.hammerspoon/voice-prompt-env.lua after install. The installer seeds this file from a template once and never touches it again.

Setting What it does
OPENCODE_DIR Working directory opencode runs in. Defaults to ~/voice-prompts.
OPENCODE_BIN Path to the opencode binary. Defaults to ~/.opencode/bin/opencode.
OPENCODE_MODEL Pin a specific model, e.g. "anthropic/claude-haiku-4-5" for cheap fast prompts. Leave commented to use opencode's default.
WHISPER_MODEL Switch to ggml-small.en.bin for roughly 2x faster but slightly worse transcription.

Reload Hammerspoon after editing. Click the menu bar icon, Reload Config, or from the shell:

hs -c "hs.reload()"

Hotkey alternatives

voice-prompt.lua ships with two trigger modes. The installer wires startHoldMode() (hold right-Option) by default. To switch to a toggle on cmd+shift+space, edit the managed block in ~/.hammerspoon/init.lua:

-- vp.startHoldMode()
vp.startToggleMode()

Hold mode feels natural for short prompts. Toggle mode is better if your keyboard lacks a separate right-Option key, or if you want to dictate long passages without holding a key the whole time.

Logs and debugging

Each invocation writes a log to ~/voice-prompts/YYYYMMDD-HHMMSS.log containing the raw whisper transcript and the opencode invocation.

Tail the latest:

tail -f "$(ls -t ~/voice-prompts/*.log | head -1)"

Test the pipeline without the hotkey:

sox -d -r 16000 -c 1 -b 16 /tmp/voice-prompt-test.wav trim 0 4
WAV_FILE=/tmp/voice-prompt-test.wav ~/.local/share/voice-prompt/pipeline.sh

If the hotkey isn't firing, open the Hammerspoon Console (menu bar icon, then Console) and watch for [voice-prompt] log lines while you press the key. The most common cause is missing Accessibility permission for Hammerspoon.

How it works

Hammerspoon (right-Option flagsChanged event tap)
  ├─ on key down: spawn `sox` recording to /tmp/voice-prompt-{timestamp}.wav
  └─ on key up:   stop sox, run ~/.local/share/voice-prompt/pipeline.sh

pipeline.sh
  ├─ open new Terminal window with a watcher script (immediate)
  ├─ run whisper-cli on the WAV
  └─ write the transcript to a temp file the watcher polls for

watcher (running in the new Terminal window)
  ├─ show a spinner while whisper runs
  └─ exec opencode --prompt "<transcript>" once the file appears

The window opens before whisper finishes so you see motion immediately rather than a delayed pop. opencode receives the prompt via the --prompt flag, which submits it as the first user message and starts processing inside the TUI.

File layout

opencode-voice/
├── install.sh                       Idempotent installer
├── README.md                        This file
├── LICENSE                          MIT
├── hammerspoon/
│   ├── voice-prompt.lua             Hotkey + sox recording
│   └── voice-prompt-env.lua.example Config template
└── share/
    ├── pipeline.sh                  whisper -> spawn Terminal
    ├── run-in-terminal.sh           Inner script that exec's into the opencode TUI
    └── stt-prompt.md                Optional LLM normalization prompt (unused by default)

After install, runtime files live at:

  • ~/.hammerspoon/voice-prompt.lua (symlink to hammerspoon/voice-prompt.lua)
  • ~/.hammerspoon/voice-prompt-env.lua (real file, your local config)
  • ~/.local/share/voice-prompt/pipeline.sh (symlink)
  • ~/.local/share/voice-prompt/run-in-terminal.sh (symlink)
  • ~/.local/share/voice-prompt/stt-prompt.md (symlink)

Comparison with opencode-voice plugin

There's a separate project, @renjfk/opencode-voice, that does voice input inside the opencode TUI bound to ctrl+r. That's a great fit when you're already in opencode. This project covers the case where you're in any other app and want to fire a prompt without switching first.

You can run both side by side. They share the same whisper-cli and sox binaries.

Uninstall

# remove symlinks
rm -f ~/.hammerspoon/voice-prompt.lua
rm -f ~/.local/share/voice-prompt/pipeline.sh
rm -f ~/.local/share/voice-prompt/run-in-terminal.sh
rm -f ~/.local/share/voice-prompt/stt-prompt.md

# remove the managed block from ~/.hammerspoon/init.lua manually,
# or delete the file if it only contains the opencode-voice block

# optional: remove your local config and work dir
rm ~/.hammerspoon/voice-prompt-env.lua
rm -rf ~/voice-prompts

# optional: remove the Whisper model (~570MB)
rm ~/.local/share/whisper-cpp/ggml-large-v3-turbo-q5_0.bin

# reload Hammerspoon
hs -c "hs.reload()"

The Homebrew packages (hammerspoon, whisper-cpp, sox, jq) are left alone since other tools may depend on them.

License

MIT. See LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors