Skip to content
Development
Skill

/add-dictation

Use when the user runs /add-dictation or wants speech turned into text with Grok speech-to-text: a mic button that dictates into the composer, live captions, or transcribing recorded audio (files, uploads, URLs) with word timestamps, diarization, subtitles, meeting notes. STT,

From plugin
plugins
15k113 skills14 agents

Claude Code

$ npx -y skills add cursor/plugins --skill add-dictation --agent claude-code

SKILL.md

add-dictation.SKILL.md
name: add-dictation
description: >-
  Use when the user runs /add-dictation or wants speech turned into text with
  Grok speech-to-text: a mic button that dictates into the composer, live
  captions, or transcribing recorded audio (files, uploads, URLs) with word
  timestamps, diarization, subtitles, meeting notes. STT, transcribe,
  transcription. For a voice agent that talks back use /add-voice.

Add Dictation

Add Grok Speech to Text to an existing app: a mic button that dictates into the composer, live captions, or transcripts of recorded audio. Run on `/add-dictation`, typed **Dictate**, or clear “transcribe” intent. Cursor has no mic; wire the **app**, not the IDE.

Docs

  • https://docs.x.ai/developers/model-capabilities/audio/speech-to-text
  • Model selection (read first): https://docs.x.ai/developers/model-capabilities/audio/speech-to-text#model-selection
  • Pricing (cite docs only): https://docs.x.ai/developers/pricing

Model

Before any STT call, read the model-selection section and pass the **latest listed** model as `model`. Do not invent ids or reuse a stale one from this skill. REST: form field before `file`. Streaming: query param. Official examples currently send `grok-voice-transcribe-2.0`. Listed today: `grok-voice-transcribe-2.0` (best), `grok-voice-transcribe-1.0` (original; API default when `model` is omitted).

Pick the path

| Need | Path | | --- | --- | | Tap, speak, tap, text appears. Uploaded files. URLs. | **Batch** `POST https://api.x.ai/v1/stt` (default) | | Text appears while speaking: captions, long dictation, push-to-talk | **Streaming** `wss://api.x.ai/v1/stt` through a backend relay |

Batch is the default for a composer mic button: one request, no socket, the key never leaves the server. Go streaming only when the UX needs interim text.

Auth

  • Bearer `XAI_API_KEY`, server side only. The STT docs document no ephemeral-token flow, and browsers cannot set WebSocket headers, so browser streaming goes through your backend relay. Do not invent a token flow.
  • Never put the key in a client bundle. Do not paste keys in chat.

Steps

1. **Map the app**

  • Composer or input component, where the text should land (insert at cursor vs replace), server framework, package manager.
  • The **microphone icon belongs to dictation**. If `/add-voice` is installed, its waveform primary button stays as is; add the mic as a secondary ghost button beside it.
  • Existing mic capture? If `/add-voice` ran, its PCM capture can feed streaming STT; pass its rate as `sample_rate`. 16 kHz is the model’s native rate; other supported rates (8000, 16000, 22050, 24000, 44100, 48000) are resampled server side.

2. **Batch path (default)**

  • Client: `MediaRecorder` → `Blob` → `POST` to your own route. The endpoint auto-detects containers (WAV, MP3, OGG, Opus, FLAC, AAC, MP4, M4A, MKV, WebM), so send whatever `MediaRecorder` produces.
  • Server: forward as `multipart/form-data`. Option fields first, **`file` last**; fields after `file` may be ignored. `file` or `url`, max 500 MB. `model` from docs (latest listed).
// server (any runtime with fetch + FormData)
export async function transcribe(blob: Blob, filename: string) {
  const form = new FormData();
  form.append("model", "grok-voice-transcribe-2.0"); // latest from docs; re-read model-selection
  form.append("format", "true");     // written-form numbers/currency; requires language
  form.append("language", "en");
  // form.append("keyterm", "Acme"); // repeat per term, ≤100 terms × 50 chars
  form.append("file", blob, filename); // last
  const res = await fetch("https://api.x.ai/v1/stt", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.XAI_API_KEY}` },
    body: form,
  });
  if (!res.ok) throw new Error(`STT ${res.status}`); // 400 bad input, 413 >500 MB, 429 back off, 502 url fetch failed, 503 retry
  return (await res.json()) as {
    text: string; language: string; duration: number;
    words?: { text: string; start: number; end: number; speaker?: number }[];
    channels?: { index: number; text: string; words: unknown[] }[];
  };
}
// client
const mime = MediaRecorder.isTypeSupported("audio/webm;codecs=opus") ? "audio/webm;codecs=opus" : "audio/mp4";
const rec = new MediaRecorder(stream, { mimeType: mime });
const parts: BlobPart[] = [];
rec.ondataavailable = (e) => parts.push(e.data);
rec.onstop = async () => {
  const fd = new FormData();
  fd.append("file", new Blob(parts, { type: mime }), "dictation");
  const { text } = await (await fetch("/api/dictation", { method: "POST", body: fd })).json();
  insertAtCursor(text);
};
rec.start(); // second tap: rec.stop()

3. **Streaming path**

  • Relay: server holds the key, upgrades the browser socket, forwards binary frames and client control messages up, JSON events down. Build the query string server side. `model` from docs (latest listed).
import { WebSocketServer, WebSocket } from "ws";

new WebSocketServer({ port: 8788 }).on("connection", (client) => {
  const q = new URLSearchParams({ model: "grok-voice-transcribe-2.0", sample_rate: "16000", encoding: "pcm", interim_results: "true", language: "en" });
  const up = new WebSocket(`wss://api.x.ai/v1/stt?${q}`, { headers: { Authorization: `Bearer ${process.env.XAI_API_KEY}` } });
  up.on("message", (d) => client.send(d.toString()));                       // transcript.* and error events
  client.on("message", (d, isBinary) => up.readyState === WebSocket.OPEN && up.send(d, { binary: isBinary })); // audio + finalize/audio.done
  const end = () => { client.close(); up.close(); };
  up.on("close", end); up.on("error", end); client.on("close", end);
});
  • Browser capture: PCM16 little-endian, mono, 16 kHz, **100 ms frames = 3,200 bytes**, raw binary, no base64. Wait for `transcript.created` before sending. `MediaRecorder` output is a container, not raw frames; do not stream it.
const ws = new WebSocket(relayUrl); ws.binaryType = "ar
Read more
@cursor
Ships withplugins

Official Cursor plugins for popular developer tools, frameworks, and SaaS products. Each plugin is a standalone directory at the repository root with its own .cursor-plugin/plugin.json manifest.

15k113 skills14 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
15.0k
Star history of cursor/plugins on GitHub, a chart by star-history.com

Other skills on plugins.

advisor

advisor

Advisor mode. Consult a stronger (or different) model at key checkpoints: before major decisions, when stuck on an error, and…

@cursor@cursorInstall Skill
cli-for-agents

cli-for-agents

Designs or reviews CLIs so coding agents can run them reliably: non-interactive flags, layered --help with examples,…

@cursor@cursorInstall Skill
continual-learning

continual-learning

Orchestrate continual learning by delegating transcript mining and AGENTS.md updates to `agents-memory-updater`.

@cursor@cursorInstall Skill
create-plugin-scaffold

create-plugin-scaffold

Create a new Cursor plugin scaffold with a valid manifest, component directories, and marketplace wiring. Use when starting a new…

@cursor@cursorInstall Skill
review-plugin-submission

review-plugin-submissi…

Audit a Cursor plugin for marketplace readiness. Use when validating manifests, component metadata, discovery paths, and…

@cursor@cursorInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about add-dictation.

Which coding agents can use add-dictation?
add-dictation installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.