npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@afterrealism/opencode-voice

v1.0.0

Published

Local voice dictation for OpenCode on Linux using whisper.cpp and Ollama

Downloads

60

Readme

@afterrealism/opencode-voice

Local, private voice dictation for OpenCode on Linux. It records from your microphone with ALSA, transcribes on-device with whisper.cpp, optionally cleans up the transcript with a loopback Ollama model, and appends the result to your OpenCode prompt. It never submits the prompt for you and it never sends audio or transcripts to the cloud.

Features

  • Push-to-toggle dictation from the OpenCode TUI (Ctrl+O by default).
  • /voice and /voice-cancel slash commands.
  • On-device transcription with whisper.cpp (whisper-cli).
  • Optional local transcript cleanup via a loopback Ollama endpoint.
  • Raw-transcript fallback when Ollama is unavailable or returns bad output.
  • Appends to the prompt only — you review and submit.
  • No runtime dependencies, no telemetry, no cloud calls, no install hooks.
  • opencode-voice doctor prerequisite checker that changes nothing.

Requirements

  • Linux with ALSA. This version supports Linux only; recording uses arecord from alsa-utils. macOS and Windows are not supported.
  • Node.js >= 22 (OpenCode already provides a compatible runtime; Node is only needed directly for the opencode-voice doctor CLI).
  • whisper.cpp providing the whisper-cli binary on your PATH.
  • A Whisper model file (see below); the large v3 Q5 model is recommended.
  • Ollama (optional) running on loopback for transcript cleanup.

Install

Install the plugin from npm:

npm install -g @afterrealism/opencode-voice

Installing globally puts the opencode-voice doctor CLI on your PATH. You may also let OpenCode manage the plugin from tui.json (see Configure OpenCode); OpenCode installs the package into its own plugin store. The package ships no install, build, or postinstall scripts and pulls in no runtime dependencies.

Install the ALSA recording utility for your distribution:

# Debian / Ubuntu
sudo apt-get install -y alsa-utils

# Fedora
sudo dnf install -y alsa-utils

arecord (from alsa-utils) must be on your PATH.

Install whisper.cpp

This plugin calls the whisper-cli binary from whisper.cpp. Your distribution may or may not package it, so build it from source. These instructions target whisper.cpp v1.9.1.

git clone --branch v1.9.1 --depth 1 https://github.com/ggml-org/whisper.cpp
cd whisper.cpp

Pick the CPU build or the NVIDIA CUDA build below, then put the resulting build/bin/whisper-cli on your PATH (for example, copy or symlink it into a directory such as ~/.local/bin).

CPU

A CPU build works everywhere and needs no GPU drivers:

cmake -B build
cmake --build build -j --config Release
# result: build/bin/whisper-cli

NVIDIA CUDA

A CUDA build is faster if you have an NVIDIA GPU and the CUDA toolkit installed. Enable CUDA and let the toolchain detect your GPU architecture rather than hardcoding one:

cmake -B build -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=native
cmake --build build -j --config Release
# result: build/bin/whisper-cli

native asks the CUDA compiler to target the architecture of the GPU in the build machine. If your CUDA toolkit is too old to support native, look up your GPU's compute capability (for example, 89 for an RTX 40-series Ada card) and pass it explicitly, e.g. -DCMAKE_CUDA_ARCHITECTURES=89. Do not copy another machine's architecture number blindly — it must match your card.

Download the Whisper model

The model file is user-supplied and referenced by an absolute path. The recommended model is large v3 Q5 (ggml-large-v3-q5_0.bin). Download it from the whisper.cpp model repository on Hugging Face:

mkdir -p ~/.local/share/whisper-models
curl -L -o ~/.local/share/whisper-models/ggml-large-v3-q5_0.bin \
  https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-q5_0.bin

Confirm the file is present and readable — the plugin and the doctor both check readability at the configured absolute path:

test -r ~/.local/share/whisper-models/ggml-large-v3-q5_0.bin && echo readable

Smaller models (for example ggml-base.en.bin) also work and are faster but less accurate; point whisperModelPath at whichever .bin you downloaded.

Configure Ollama

Ollama is optional. When it is running on loopback, the raw transcript is passed through a local model for light cleanup (punctuation, capitalization, obvious recognition fixes). Install Ollama from https://ollama.com, then pull the default model:

ollama pull qwen2.5:7b

Ollama serves an OpenAI-compatible API on http://127.0.0.1:11434 by default, which matches the plugin's default endpoint. If Ollama is not running, dictation still works and the plugin uses the raw transcript instead.

Run the doctor

opencode-voice doctor is a read-only prerequisite check. It records nothing, calls no cloud endpoint, and installs, downloads, or starts nothing.

opencode-voice doctor --model /absolute/path/to/ggml-large-v3-q5_0.bin

It checks, in order: Linux platform, arecord, whisper-cli, the model file's readability, the OpenCode version (if opencode is on PATH), and Ollama reachability plus the configured model.

Exit semantics:

  • Exit code 0 when no required check fails.
  • Exit code 1 when a required check fails (wrong platform, missing arecord/whisper-cli, or an unreadable model), or when the arguments are invalid.
  • A missing OpenCode binary and an unreachable or unconfigured Ollama are warnings, not failures: the plugin still transcribes, and an Ollama warning simply means normalization is skipped and the raw transcript is used.

Add --json to emit the machine-readable result. Run opencode-voice --help for all flags (--model, --ollama-model, --ollama-endpoint, --language, --shortcut, --json).

Configure OpenCode

Register the plugin in your OpenCode TUI config at ~/.config/opencode/tui.json. Use the npm tuple form — a [name, options] pair — with an absolute model path:

{
  "$schema": "https://opencode.ai/tui.json",
  "plugin": [
    [
      "@afterrealism/opencode-voice",
      {
        "whisperModelPath": "/home/you/.local/share/whisper-models/ggml-large-v3-q5_0.bin"
      }
    ]
  ]
}

Restart OpenCode after editing tui.json so it loads the plugin. On a successful load the plugin registers its commands and the toggle shortcut; on invalid options it shows one error toast and stays inactive.

Usage

  • Toggle recording: press Ctrl+O (or your configured shortcut), or run /voice. Press again to stop; transcription and optional cleanup run, then the text is appended to your prompt.
  • Cancel: run /voice-cancel to stop and discard the current dictation without inserting anything.
  • Review and submit: the plugin never submits the prompt. It only appends text; you press Enter yourself.
  • Recording stops automatically after 120 seconds.

Status toasts report each phase (Recording, Transcribing, Normalizing, Transcript added). If normalization fails, you get a warning and the raw transcript is inserted instead — your words are never lost.

Configuration

Options go in the second element of the plugin tuple in tui.json.

| Option | Required | Default | Notes | | ----------------- | -------- | -------------------------------------------- | ----- | | whisperModelPath| yes | — | Absolute path to a whisper.cpp .bin model. | | ollamaModel | no | qwen2.5:7b | Local Ollama model used for cleanup. | | ollamaEndpoint | no | http://127.0.0.1:11434/v1/chat/completions | Must be loopback (127.0.0.1, localhost, or ::1), HTTP/HTTPS, no credentials/query/fragment, path exactly /v1/chat/completions. | | language | no | en | auto or a 2–3 letter lowercase code passed to whisper.cpp. | | shortcut | no | ctrl+o | OpenCode key expression for the toggle. |

Unknown options are rejected to catch typos.

Notes:

  • Normalization is best-effort. If Ollama is unreachable, times out, or returns malformed output, the plugin falls back to the raw transcript and no prompt is submitted.
  • Shortcut conflicts. ctrl+o may collide with an existing OpenCode keybinding or a terminal/emulator binding. If the toggle does nothing, pick a free key via shortcut and avoid keys your terminal already intercepts.
  • Cloud endpoints are rejected. Only loopback Ollama hosts are accepted; there is no API-key or remote-endpoint support by design.

Privacy and security

  • Audio and transcripts stay on your machine. Nothing is sent to any cloud service. The only network call is to your configured loopback Ollama endpoint.
  • No telemetry, analytics, or crash reporting.
  • Recordings are written to a unique, mode-0700 temporary directory and deleted after the pipeline finishes or on cancel/shutdown.
  • Child processes (arecord, whisper-cli) are spawned with argument arrays, never a shell string, and only the exact spawned process is ever signalled — no process-name matching or pkill.
  • Logs contain state names and error categories only — never transcript text, model responses, audio, or secrets.
  • Output buffers and operation timeouts are bounded so a runaway process cannot exhaust memory or hang the plugin.

Troubleshooting

  • /voice or the shortcut does nothing. Confirm OpenCode was restarted after editing tui.json, then check for a shortcut conflict and set a different shortcut.
  • "Voice unavailable" preflight error. arecord or whisper-cli is not on PATH, or the model is not readable. Run opencode-voice doctor --model ... to see which check fails.
  • No speech detected. Recording was silent or too quiet; check your ALSA input device and microphone levels.
  • Transcription failed. Verify the model path is correct and the file is a valid whisper.cpp .bin, and that your whisper-cli version can read it.
  • Cleanup unavailable; using the raw transcript. Ollama is down or the model is not pulled. Start Ollama and run ollama pull qwen2.5:7b, or ignore it and keep using raw transcripts.
  • Plugin inactive after config change. An option is invalid (for example a relative whisperModelPath or a non-loopback endpoint). The error toast names the offending option.

Upgrade

npm install -g @afterrealism/opencode-voice@latest

If OpenCode manages the plugin from tui.json, update the version constraint there (or let it re-resolve) and restart OpenCode. Review the changelog for any option changes before upgrading across a major version.

Uninstall

npm uninstall -g @afterrealism/opencode-voice

Then remove the plugin tuple from ~/.config/opencode/tui.json and restart OpenCode. Whisper models, whisper.cpp, and Ollama are separate installs; remove them yourself if you no longer need them. The plugin leaves no temporary audio behind — recordings are deleted after each use.

Development

git clone https://github.com/afterrealism/opencode-voice
cd opencode-voice
npm install --ignore-scripts
npm test
npm run build
npm pack --dry-run

See CONTRIBUTING.md for the full contributor workflow and SECURITY.md for vulnerability reporting.

License

MIT © 2026 After Realism