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

opencode-speaker

v1.0.7

Published

Speaker plugin for opencode — speaks agent events through pluggable TTS providers.

Downloads

126

Readme

opencode-speaker

npm version CI License: MIT

A speaker plugin for opencode that speaks agent activity out loud through pluggable text-to-speech providers.

Hear what your agent is doing while you work on something else — session summaries, errors, permission requests, and todo completions, narrated by an LLM and spoken by a TTS model.

Supports OpenAI (default) and ElevenLabs for TTS, with OpenAI or Anthropic for the LLM narrator. Powered by the Vercel AI SDK.


Requirements

  • Node.js ≥ 20
  • An API key for your chosen provider (OpenAI by default; ElevenLabs and/or Anthropic optional)
  • On Linux, a TTS/audio provider — see Troubleshooting

Install

1. Add the plugin to opencode.json

Your global opencode config file is usually located at ~/.config/opencode/opencode.json. If you use a project-local opencode config, add the same plugin entry there instead.

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": ["opencode-speaker"]
}

2. Set your OpenAI API key

For the current terminal session:

export OPENAI_API_KEY=sk-...

To make it available every time you open a terminal, add it to your shell startup file:

# zsh, macOS default
echo 'export OPENAI_API_KEY=sk-...' >> ~/.zshrc

# bash
echo 'export OPENAI_API_KEY=sk-...' >> ~/.bashrc

If you use fish:

set -Ux OPENAI_API_KEY sk-...

Restart your terminal after adding the variable, or run source ~/.zshrc / source ~/.bashrc for the current session.

That's it. Start opencode and you'll hear a short greeting confirming the plugin is ready.

By default, the plugin uses:

  • TTS model: openai/gpt-4o-mini-tts
  • Narrator model: openai/gpt-4.1-mini

And out of the box, you'll hear:

  • Session starts, idle summaries, errors, and compactions
  • Permission requests and replies
  • Tool starts and finishes
  • File edits and executed commands
  • Reasoning deltas while the assistant is thinking
  • Todo item completions and “all todos complete” summaries

Using ElevenLabs instead

Configure the plugin using the tuple form in the plugin array (per-plugin config goes as the second tuple element — not as a top-level key):

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": [
    ["opencode-speaker", {
      "tts": {
        "model": "elevenlabs/eleven_turbo_v2_5",
        "voice": "EXAVITQu4vr4xnSDxMaL"
      }
    }]
  ]
}

Then set your API key:

export ELEVENLABS_API_KEY=...

The voice field takes an ElevenLabs voice ID.

Note: The narrator (LLM summarizer) is separate from TTS. You can mix and match — e.g., narrate with Anthropic, speak with ElevenLabs.


Configuration

All options go inside the tuple's second element: ["opencode-speaker", { ... }].

Full example

{
  "plugin": [
    ["opencode-speaker", {
      "greeting": "opencode speaker ready",
      "tts": {
        "model": "openai/gpt-4o-mini-tts",
        "voice": "nova",
        "rate": 1.0
      },
      "narrator": {
        "model": "openai/gpt-4.1-mini",
        "timeoutMs": 5000,
        "minIntervalMs": 3000
      },
      "events": {
        "tool.execute.before": { "enabled": true }
      }
    }]
  ]
}

TTS providers

| Provider | Model slug example | Voices | Env var | |---|---|---|---| | OpenAI (default) | openai/gpt-4o-mini-tts, openai/tts-1, openai/tts-1-hd | alloy, ash, coral, echo, fable, onyx, nova, sage, shimmer | OPENAI_API_KEY | | ElevenLabs | elevenlabs/eleven_turbo_v2_5 | ElevenLabs voice ID | ELEVENLABS_API_KEY |

Narrator (LLM) providers

| Provider | Model slug example | Env var | |---|---|---| | OpenAI (default) | openai/gpt-4.1-mini | OPENAI_API_KEY | | Anthropic | anthropic/claude-haiku-4 | ANTHROPIC_API_KEY |

The plugin resolves provider/model slugs internally — no imports needed.

Events

Each event is independently configurable.

Verbosity

Use verbosity to choose a default event profile, then override individual events as needed.

| Value | Behavior | |---|---| | minimal | Speaks only session idle summaries, session errors, permission requests, and all-todos-complete summaries. | | normal | Current default event profile. | | verbose | Same as normal today; reserved for future high-detail defaults while preserving a stable option name. |

{
  "plugin": [
    ["opencode-speaker", {
      "verbosity": "minimal",
      "events": {
        "tool.execute.before": { "enabled": true }
      }
    }]
  ]
}

| Event | Default | Mode | |---|---|---| | session.idle | on | narrate (LLM summary) | | session.error | on | template, urgent | | session.compacted | on | template | | session.created | on | template | | permission.asked | on | template, urgent | | permission.replied | on | template | | tool.execute.before | on | template, chatty | | tool.execute.after | on | template, chatty | | file.edited | on | template, chatty | | command.executed | on | template | | message.reasoning.delta | on | verbatim, chatty | | message.text.delta | off | verbatim, chatty | | message.updated | off | verbatim | | todo.completed.item | on | template, chatty | | todo.completed.all | on | narrate |

Override per event:

{
  "events": {
    "tool.execute.before": { "enabled": true, "mode": "template" }
  }
}

Modes:

  • template — fixed phrasing (fast, no LLM)
  • narrate — LLM-generated summary (concise but covers what happened, blockers, next steps)
  • verbatim — speak the raw text as-is

The narrator is rate-limited by minIntervalMs and falls back to a template if the call fails or is throttled.

Greeting

A short startup line, spoken once when the plugin is ready. Default: "Welcome to OpenCode Speaker!".

{ "greeting": "welcome back" }

Set to "" to disable. Skipped automatically when startMuted: true or OPENCODE_VOICE_MUTE=1.

Custom providers

Runtime provider selection is currently built in. TTS slugs route openai/* and elevenlabs/*; narrator slugs route openai/* and anthropic/*.

The opencode-speaker/api entrypoint exports provider-related TypeScript types for integrations, but it does not register custom providers at runtime. To add a provider today, fork the model resolver in src/ai-sdk/models.ts or open an issue.


Troubleshooting

No audio on Linux: install speech-dispatcher (sudo apt install speech-dispatcher) or espeak. For cloud-provider audio playback, install pulseaudio-utils (paplay), alsa-utils (aplay), or ffmpeg (ffplay).

Windows blocked by execution policy: run PowerShell once with Set-ExecutionPolicy -Scope CurrentUser RemoteSigned.

Plugin disabled with a toast on startup: the toast carries a short summary (invalid config, missing API key, TTS init failure). The full structured detail is in opencode's log file — opencode-speaker errors are logged at error / warn level.

TTS quota exceeded toast: if speech synthesis fails because the configured provider API key has no remaining quota, the plugin shows one error toast and disables speech for the current opencode session to avoid repeated failed API calls. Check your provider plan and billing details, then restart opencode.

Startup TTS failure toast: if the startup greeting fails because the provider rejects the request, the API key is invalid, the network fails, or audio playback fails, the plugin shows one error toast and disables speech for the current opencode session. Check the opencode log for the full provider error.

Unrecognized key: voice schema error: you put options at the top level. Use the tuple form: "plugin": [["opencode-speaker", { ... }]], not "voice": { ... }.


Development

Six runnable demo scripts exercise each feature without booting opencode (all use tsx):

| Script | Validates | |---|---| | npm run demo:say -- "text" | Synthesis + playback. Override TTS with --model=elevenlabs/eleven_turbo_v2_5 --voice=<id>. | | npm run demo:queue | Speech queue priority + dedup behavior. | | npm run demo:event -- <event.type> | Full event-to-audio pipeline. E.g. session.idle, permission.asked --tool=write. | | npm run demo:narrator -- --assistant-text="..." --tool=bash | LLM narrator handler. | | npm run demo:config -- '{...}' or --file=path.json | Validate a config block against the Zod schema. | | npm run demo:greet | Startup greeting via the full plugin. |

Standard commands:

npm test          # full unit + integration suite
npm run typecheck # TypeScript validation
npm run build     # produce dist/

To restart opencode against a local build:

rm -rf ~/.cache/opencode/node_modules/opencode-speaker && npm run build

License

MIT.