{"owner":"moonshine-ai","repo":"moonshine","hasSkills":true,"totalSkillsCount":2,"totalTokensCount":2383,"categories":["root-instruction","anthropic-skill"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md",".agents/skills/moonshine-voice/SKILL.md"],"skills":{"AGENTS.md":"# Contributor notes for agents\n\nThis file is for people (and coding agents) working **in this repository**. App developers integrating the published library should use [`.agents/skills/moonshine-voice/SKILL.md`](.agents/skills/moonshine-voice/SKILL.md) instead — do not mix those audiences.\n\n## Branching\n\n`main` only ever contains released code. Development happens on a `dev-v<version>` candidate branch. Pull requests target that candidate, not `main`. See [docs/release-process.md](docs/release-process.md). Do not start or publish a release unless the user explicitly asked.\n\n## Building and tests\n\nLarge model and TTS binaries are not in git. Before `scripts/test-core.sh` or offline TTS work:\n\n```bash\nscripts/fetch-voice-assets.sh all\n```\n\nA few compile-time embeds and ONNX Runtime prebuilts still use Git LFS. If a compile fails with something like `'version' does not name a type` on an `*_embedded.cpp` file, run `git lfs pull`.\n\nUseful scripts (prefer these over ad-hoc cmake/pytest invocations):\n\n- `scripts/test-core.sh` — C++ core build and tests\n- `scripts/test-python.sh` — Python bindings\n- `scripts/test-wasm.sh` — WebAssembly bindings\n- `scripts/test-docs.sh` — documentation snippet tests\n- `scripts/format-core.sh` — Google-style clang-format for first-party `core/`\n- `scripts/check-banned-constructs.sh` — C++ construct gates\n\nC++ policy lives in [core/STYLE_GUIDE.md](core/STYLE_GUIDE.md): C++20, RAII, no new owning `new`/`delete` or `reinterpret_cast` outside the baseline allow-list, no unsafe C string functions. Do not format or lint `core/third-party/` or `core/cpp-annote/`.\n\n## Public API\n\nLanguage bindings follow construct → chainable setters → `load()`. Constructors are cheap and cannot fail. Do not put downloads or model opens in a constructor. The high-level types are `MicTranscriber`, `AgentFlow`, and `TextToSpeech`; `Transcriber` is the low-level PCM path and `EmbeddingModel` is the low-level text-embedding path. `DialogFlow` and the Intent API are gone.\n\nOnly OnnxRuntime flatbuffer models (`.ort`) are accepted. Do not add `.onnx` loading paths.\n\nUser-facing changes go in [CHANGELOGS.md](CHANGELOGS.md): Keep a Changelog, high-level bullets, no more than about 200 characters each.\n\n## Layout\n\n- `core/` — C++ engine and C API (`moonshine-c-api.h`)\n- `language-bindings/` — Python, WASM, Swift, Android\n- `docs/` — mkdocs source, published at https://moonshine-voice.readthedocs.io\n- `examples/` — per-platform sample apps (the fine-tune notebook is `examples/python/finetune/`; the trainer is `moonshine_voice.lora` / `moonshine-voice finetune`)\n- `micro/` — tiny on-device models, separate from the main library\n",".agents/skills/moonshine-voice/SKILL.md":"---\nname: moonshine-voice\ndescription: >-\n  Integrate on-device Moonshine Voice (speech-to-text, text-to-speech, voice\n  cloning, AgentFlow conversational agents). Use when the user asks to add\n  Moonshine, MicTranscriber, AgentFlow, on-device STT/TTS, a voice agent,\n  dictation, meeting notes, or keyterms/domain customization — not Whisper,\n  cloud STT, or OpenAI Realtime.\n---\n\n# Moonshine Voice\n\nOn-device voice toolkit. No API keys, no cloud. Do not substitute Whisper, OpenAI Realtime, or a hosted STT/TTS API when the user asked for Moonshine.\n\nNever trust model memory for this SDK. Verify against live docs before writing code:\n\n- Docs: https://moonshine-voice.readthedocs.io\n- Transcription: https://moonshine-voice.readthedocs.io/en/latest/using/transcription/\n- Conversational agent: https://moonshine-voice.readthedocs.io/en/latest/using/conversational-agent/\n- Text to speech: https://moonshine-voice.readthedocs.io/en/latest/using/text-to-speech/\n- Domain customization: https://moonshine-voice.readthedocs.io/en/latest/models/domain-customization/\n- Debugging: https://moonshine-voice.readthedocs.io/en/latest/using/debugging/\n- Adding the library: https://moonshine-voice.readthedocs.io/en/latest/using/adding-the-library/\n\nPython snippets below are the lingua franca. Other bindings use the same shape with native names (`on_text` → `onText`, `listen_for` → `listenFor`, `start_listening` → `startListening`).\n\n## Install\n\n| Platform | Package |\n| --- | --- |\n| Python | `pip install moonshine-voice` then `import moonshine_voice` |\n| JavaScript | `npm install @moonshine-ai/moonshine-wasm` (or the jsDelivr CDN) |\n| Swift (iOS/macOS) | SPM: `https://github.com/moonshine-ai/moonshine-swift/` then `import MoonshineVoice` |\n| Android | Maven `ai.moonshine:moonshine-voice` (pass an Android `Context` to constructors) |\n| Linux/Windows C++ | Prebuilt libs from GitHub Releases; `#include \"moonshine-cpp.h\"` |\n\n## Canonical shape\n\nConstruct → chainable setters → `load()` → `start()` / `start_listening()`.\n\nConstructors are cheap and cannot fail. Nothing is downloaded or opened until `load()`. `load()` is the slow, fallible call (first use may download models into a local cache; later launches reuse it and run offline). Call setters before `load()`.\n\nPick the high-level type:\n\n| Need | Type |\n| --- | --- |\n| Live microphone speech-to-text | `MicTranscriber` |\n| Feed PCM/WAV yourself | `Transcriber` |\n| Spoken conversational flows | `AgentFlow` |\n| Playback or voice cloning | `TextToSpeech` |\n\n`AgentFlow` loads STT, embeddings, TTS, and a mic internally. Do not assemble those objects yourself unless the user asked for that.\n\n## Transcription\n\n`on_text` / `onText` is the in-progress hypothesis (it will change). `on_line` / `onLine` is the finished segment. Do not treat partial text as final.\n\n```python\nfrom moonshine_voice import MicTranscriber\n\nmic = (\n    MicTranscriber()\n    .language(\"en\")\n    .on_text(lambda text: print(text, end=\"\\r\", flush=True))\n    .on_line(lambda line: print(line.text))\n)\nmic.load()\nmic.start()\n```\n\nUse `Transcriber` only when feeding audio yourself. For line ids, speaker spans, or word timings, `add_listener()` still exists; the named callbacks cover the common path.\n\n## Conversational agent\n\nPython flow bodies use `yield` so the runner can wait for speech. JavaScript/Swift/Java flow bodies are ordinary `async` / blocking functions (`await d.ask(...)`), not generators.\n\n```python\nfrom moonshine_voice import AgentFlow, Dialog\n\ndef report_ip(d: Dialog):\n    yield d.say(\"Your address is 1 9 2 dot 1 6 8 dot 1 dot 1\")\n\nagent = AgentFlow().language(\"en\").listen_for(\"What is my IP address?\", report_ip)\nagent.start_listening()\n```\n\n`start_listening()` downloads on first use. Call `load()` first if you need to schedule that yourself. Matching is semantic. `otherwise()` handles speech that matched no trigger. Fetch the agent doc for `ask` / `confirm` / spelled input.\n\n## Text to speech and cloning\n\n```python\nfrom moonshine_voice import TextToSpeech\n\ntts = TextToSpeech().language(\"en-us\")\ntts.load()\ntts.say(\"Hello world\")\ntts.wait()\n```\n\nCall `cloning()` before `load()`, then `clone_from()` (file or PCM) or `start_cloning()` (microphone). Catalog `voice()` and `cloning()` are mutually exclusive.\n\nWhen the text comes from a language model, stream it instead of waiting for the whole reply:\n\n```python\nwith tts.say_stream() as speech:\n    for token in llm.stream(prompt):\n        tts.push_text(token)\n    tts.end_input()\n    speech.wait()\n```\n\nThe streaming calls live on the synthesizer itself; there is no stream object to open or close, and a synthesizer speaks one reply at a time, so `say()` and `synthesize()` refuse while one is in flight. `AgentFlow` has the same `say_stream()`. Use `for chunk in tts.stream(pieces)` when you want the `TtsChunk` objects rather than playback. Text is buffered until a sentence completes, because a synthesizer fed one word at a time produces a list, not a sentence — call `flush()` to force what is buffered, `end_input()` when done, and `cancel_stream()` to drop a reply the user talked over. The same names (`pushText`, `flush`, `endInput`, `cancelStream`, `onChunk`) exist in TypeScript, Swift and Java.\n\n## Domain customization\n\n`set_keyterms([...])` biases toward jargon; `set_context(passage)` extracts terms from a document. Streaming architectures only — Tiny/Base raise. Takes effect on the next transcription; does not rewrite text already emitted. Keep the list curated; thousands of terms hurt accuracy. See the domain-customization doc for `keyterm_boost`. Teaching conventions or a new acoustic environment is `pip install 'moonshine-voice[finetune]'` then `python -m moonshine_voice.lora` (or `moonshine-voice finetune`) in a training environment — do not add PyTorch or Transformers to an inference app. ATCOSIM is phraseology, not VHF; real radio is `--dataset uwb_atcc` or `--train-manifest`.\n\n## Anti-patterns\n\n- Do not use `DialogFlow` or the old Intent API. The type is `AgentFlow`.\n- Do not load models in the constructor or via a static `MicTranscriber.load(...)`.\n- Do not supply `.onnx` models. The library accepts OnnxRuntime flatbuffers (`.ort`) only.\n- Do not replace a Moonshine request with Whisper, OpenAI Realtime, or cloud STT/TTS.\n- Do not use `keyterms` / `context` on Tiny or Base.\n- Do not treat `on_text` as a finished line.\n- Do not copy Python `yield` flow bodies into JavaScript/Swift/Java.\n- Do not add torch/transformers to an inference install; training is `moonshine-voice[finetune]` (same extra as `[lora]`).\n\n## Debugging\n\nIf transcription looks wrong, set `save_input_wav_path` to dump the audio the transcriber actually received. Set `log_api_calls=true` to print the underlying call timeline. See the debugging doc.\n"},"files":{"AGENTS.md":"# Contributor notes for agents\n\nThis file is for people (and coding agents) working **in this repository**. App developers integrating the published library should use [`.agents/skills/moonshine-voice/SKILL.md`](.agents/skills/moonshine-voice/SKILL.md) instead — do not mix those audiences.\n\n## Branching\n\n`main` only ever contains released code. Development happens on a `dev-v<version>` candidate branch. Pull requests target that candidate, not `main`. See [docs/release-process.md](docs/release-process.md). Do not start or publish a release unless the user explicitly asked.\n\n## Building and tests\n\nLarge model and TTS binaries are not in git. Before `scripts/test-core.sh` or offline TTS work:\n\n```bash\nscripts/fetch-voice-assets.sh all\n```\n\nA few compile-time embeds and ONNX Runtime prebuilts still use Git LFS. If a compile fails with something like `'version' does not name a type` on an `*_embedded.cpp` file, run `git lfs pull`.\n\nUseful scripts (prefer these over ad-hoc cmake/pytest invocations):\n\n- `scripts/test-core.sh` — C++ core build and tests\n- `scripts/test-python.sh` — Python bindings\n- `scripts/test-wasm.sh` — WebAssembly bindings\n- `scripts/test-docs.sh` — documentation snippet tests\n- `scripts/format-core.sh` — Google-style clang-format for first-party `core/`\n- `scripts/check-banned-constructs.sh` — C++ construct gates\n\nC++ policy lives in [core/STYLE_GUIDE.md](core/STYLE_GUIDE.md): C++20, RAII, no new owning `new`/`delete` or `reinterpret_cast` outside the baseline allow-list, no unsafe C string functions. Do not format or lint `core/third-party/` or `core/cpp-annote/`.\n\n## Public API\n\nLanguage bindings follow construct → chainable setters → `load()`. Constructors are cheap and cannot fail. Do not put downloads or model opens in a constructor. The high-level types are `MicTranscriber`, `AgentFlow`, and `TextToSpeech`; `Transcriber` is the low-level PCM path and `EmbeddingModel` is the low-level text-embedding path. `DialogFlow` and the Intent API are gone.\n\nOnly OnnxRuntime flatbuffer models (`.ort`) are accepted. Do not add `.onnx` loading paths.\n\nUser-facing changes go in [CHANGELOGS.md](CHANGELOGS.md): Keep a Changelog, high-level bullets, no more than about 200 characters each.\n\n## Layout\n\n- `core/` — C++ engine and C API (`moonshine-c-api.h`)\n- `language-bindings/` — Python, WASM, Swift, Android\n- `docs/` — mkdocs source, published at https://moonshine-voice.readthedocs.io\n- `examples/` — per-platform sample apps (the fine-tune notebook is `examples/python/finetune/`; the trainer is `moonshine_voice.lora` / `moonshine-voice finetune`)\n- `micro/` — tiny on-device models, separate from the main library\n",".agents/skills/moonshine-voice/SKILL.md":"---\nname: moonshine-voice\ndescription: >-\n  Integrate on-device Moonshine Voice (speech-to-text, text-to-speech, voice\n  cloning, AgentFlow conversational agents). Use when the user asks to add\n  Moonshine, MicTranscriber, AgentFlow, on-device STT/TTS, a voice agent,\n  dictation, meeting notes, or keyterms/domain customization — not Whisper,\n  cloud STT, or OpenAI Realtime.\n---\n\n# Moonshine Voice\n\nOn-device voice toolkit. No API keys, no cloud. Do not substitute Whisper, OpenAI Realtime, or a hosted STT/TTS API when the user asked for Moonshine.\n\nNever trust model memory for this SDK. Verify against live docs before writing code:\n\n- Docs: https://moonshine-voice.readthedocs.io\n- Transcription: https://moonshine-voice.readthedocs.io/en/latest/using/transcription/\n- Conversational agent: https://moonshine-voice.readthedocs.io/en/latest/using/conversational-agent/\n- Text to speech: https://moonshine-voice.readthedocs.io/en/latest/using/text-to-speech/\n- Domain customization: https://moonshine-voice.readthedocs.io/en/latest/models/domain-customization/\n- Debugging: https://moonshine-voice.readthedocs.io/en/latest/using/debugging/\n- Adding the library: https://moonshine-voice.readthedocs.io/en/latest/using/adding-the-library/\n\nPython snippets below are the lingua franca. Other bindings use the same shape with native names (`on_text` → `onText`, `listen_for` → `listenFor`, `start_listening` → `startListening`).\n\n## Install\n\n| Platform | Package |\n| --- | --- |\n| Python | `pip install moonshine-voice` then `import moonshine_voice` |\n| JavaScript | `npm install @moonshine-ai/moonshine-wasm` (or the jsDelivr CDN) |\n| Swift (iOS/macOS) | SPM: `https://github.com/moonshine-ai/moonshine-swift/` then `import MoonshineVoice` |\n| Android | Maven `ai.moonshine:moonshine-voice` (pass an Android `Context` to constructors) |\n| Linux/Windows C++ | Prebuilt libs from GitHub Releases; `#include \"moonshine-cpp.h\"` |\n\n## Canonical shape\n\nConstruct → chainable setters → `load()` → `start()` / `start_listening()`.\n\nConstructors are cheap and cannot fail. Nothing is downloaded or opened until `load()`. `load()` is the slow, fallible call (first use may download models into a local cache; later launches reuse it and run offline). Call setters before `load()`.\n\nPick the high-level type:\n\n| Need | Type |\n| --- | --- |\n| Live microphone speech-to-text | `MicTranscriber` |\n| Feed PCM/WAV yourself | `Transcriber` |\n| Spoken conversational flows | `AgentFlow` |\n| Playback or voice cloning | `TextToSpeech` |\n\n`AgentFlow` loads STT, embeddings, TTS, and a mic internally. Do not assemble those objects yourself unless the user asked for that.\n\n## Transcription\n\n`on_text` / `onText` is the in-progress hypothesis (it will change). `on_line` / `onLine` is the finished segment. Do not treat partial text as final.\n\n```python\nfrom moonshine_voice import MicTranscriber\n\nmic = (\n    MicTranscriber()\n    .language(\"en\")\n    .on_text(lambda text: print(text, end=\"\\r\", flush=True))\n    .on_line(lambda line: print(line.text))\n)\nmic.load()\nmic.start()\n```\n\nUse `Transcriber` only when feeding audio yourself. For line ids, speaker spans, or word timings, `add_listener()` still exists; the named callbacks cover the common path.\n\n## Conversational agent\n\nPython flow bodies use `yield` so the runner can wait for speech. JavaScript/Swift/Java flow bodies are ordinary `async` / blocking functions (`await d.ask(...)`), not generators.\n\n```python\nfrom moonshine_voice import AgentFlow, Dialog\n\ndef report_ip(d: Dialog):\n    yield d.say(\"Your address is 1 9 2 dot 1 6 8 dot 1 dot 1\")\n\nagent = AgentFlow().language(\"en\").listen_for(\"What is my IP address?\", report_ip)\nagent.start_listening()\n```\n\n`start_listening()` downloads on first use. Call `load()` first if you need to schedule that yourself. Matching is semantic. `otherwise()` handles speech that matched no trigger. Fetch the agent doc for `ask` / `confirm` / spelled input.\n\n## Text to speech and cloning\n\n```python\nfrom moonshine_voice import TextToSpeech\n\ntts = TextToSpeech().language(\"en-us\")\ntts.load()\ntts.say(\"Hello world\")\ntts.wait()\n```\n\nCall `cloning()` before `load()`, then `clone_from()` (file or PCM) or `start_cloning()` (microphone). Catalog `voice()` and `cloning()` are mutually exclusive.\n\nWhen the text comes from a language model, stream it instead of waiting for the whole reply:\n\n```python\nwith tts.say_stream() as speech:\n    for token in llm.stream(prompt):\n        tts.push_text(token)\n    tts.end_input()\n    speech.wait()\n```\n\nThe streaming calls live on the synthesizer itself; there is no stream object to open or close, and a synthesizer speaks one reply at a time, so `say()` and `synthesize()` refuse while one is in flight. `AgentFlow` has the same `say_stream()`. Use `for chunk in tts.stream(pieces)` when you want the `TtsChunk` objects rather than playback. Text is buffered until a sentence completes, because a synthesizer fed one word at a time produces a list, not a sentence — call `flush()` to force what is buffered, `end_input()` when done, and `cancel_stream()` to drop a reply the user talked over. The same names (`pushText`, `flush`, `endInput`, `cancelStream`, `onChunk`) exist in TypeScript, Swift and Java.\n\n## Domain customization\n\n`set_keyterms([...])` biases toward jargon; `set_context(passage)` extracts terms from a document. Streaming architectures only — Tiny/Base raise. Takes effect on the next transcription; does not rewrite text already emitted. Keep the list curated; thousands of terms hurt accuracy. See the domain-customization doc for `keyterm_boost`. Teaching conventions or a new acoustic environment is `pip install 'moonshine-voice[finetune]'` then `python -m moonshine_voice.lora` (or `moonshine-voice finetune`) in a training environment — do not add PyTorch or Transformers to an inference app. ATCOSIM is phraseology, not VHF; real radio is `--dataset uwb_atcc` or `--train-manifest`.\n\n## Anti-patterns\n\n- Do not use `DialogFlow` or the old Intent API. The type is `AgentFlow`.\n- Do not load models in the constructor or via a static `MicTranscriber.load(...)`.\n- Do not supply `.onnx` models. The library accepts OnnxRuntime flatbuffers (`.ort`) only.\n- Do not replace a Moonshine request with Whisper, OpenAI Realtime, or cloud STT/TTS.\n- Do not use `keyterms` / `context` on Tiny or Base.\n- Do not treat `on_text` as a finished line.\n- Do not copy Python `yield` flow bodies into JavaScript/Swift/Java.\n- Do not add torch/transformers to an inference install; training is `moonshine-voice[finetune]` (same extra as `[lora]`).\n\n## Debugging\n\nIf transcription looks wrong, set `save_input_wav_path` to dump the audio the transcriber actually received. Set `log_api_calls=true` to print the underlying call timeline. See the debugging doc.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/moonshine-ai/moonshine/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Contributor notes for agents\n\nThis file is for people (and coding agents) working **in this repository**. App developers integrating the published library should use [`.agents/skills/moonshine-voice/SKILL.md`](.agents/skills/moonshine-voice/SKILL.md) instead — do not mix those audiences.\n\n## Branching\n\n`main` only ever contains released code. Development happens on a `dev-v<version>` candidate branch. Pull requests target that candidate, not `main`. See [docs/release-process.md](docs/release-process.md). Do not start or publish a release unless the user explicitly asked.\n\n## Building and tests\n\nLarge model and TTS binaries are not in git. Before `scripts/test-core.sh` or offline TTS work:\n\n```bash\nscripts/fetch-voice-assets.sh all\n```\n\nA few compile-time embeds and ONNX Runtime prebuilts still use Git LFS. If a compile fails with something like `'version' does not name a type` on an `*_embedded.cpp` file, run `git lfs pull`.\n\nUseful scripts (prefer these over ad-hoc cmake/pytest invocations):\n\n- `scripts/test-core.sh` — C++ core build and tests\n- `scripts/test-python.sh` — Python bindings\n- `scripts/test-wasm.sh` — WebAssembly bindings\n- `scripts/test-docs.sh` — documentation snippet tests\n- `scripts/format-core.sh` — Google-style clang-format for first-party `core/`\n- `scripts/check-banned-constructs.sh` — C++ construct gates\n\nC++ policy lives in [core/STYLE_GUIDE.md](core/STYLE_GUIDE.md): C++20, RAII, no new owning `new`/`delete` or `reinterpret_cast` outside the baseline allow-list, no unsafe C string functions. Do not format or lint `core/third-party/` or `core/cpp-annote/`.\n\n## Public API\n\nLanguage bindings follow construct → chainable setters → `load()`. Constructors are cheap and cannot fail. Do not put downloads or model opens in a constructor. The high-level types are `MicTranscriber`, `AgentFlow`, and `TextToSpeech`; `Transcriber` is the low-level PCM path and `EmbeddingModel` is the low-level text-embedding path. `DialogFlow` and the Intent API are gone.\n\nOnly OnnxRuntime flatbuffer models (`.ort`) are accepted. Do not add `.onnx` loading paths.\n\nUser-facing changes go in [CHANGELOGS.md](CHANGELOGS.md): Keep a Changelog, high-level bullets, no more than about 200 characters each.\n\n## Layout\n\n- `core/` — C++ engine and C API (`moonshine-c-api.h`)\n- `language-bindings/` — Python, WASM, Swift, Android\n- `docs/` — mkdocs source, published at https://moonshine-voice.readthedocs.io\n- `examples/` — per-platform sample apps (the fine-tune notebook is `examples/python/finetune/`; the trainer is `moonshine_voice.lora` / `moonshine-voice finetune`)\n- `micro/` — tiny on-device models, separate from the main library\n","isInternal":false,"tokens":679,"sizeBytes":2692},{"name":"SKILL.md","path":".agents/skills/moonshine-voice/SKILL.md","rawUrl":"https://raw.githubusercontent.com/moonshine-ai/moonshine/HEAD/.agents/skills/moonshine-voice/SKILL.md","title":"moonshine-voice","category":"anthropic-skill","format":"markdown","content":"---\nname: moonshine-voice\ndescription: >-\n  Integrate on-device Moonshine Voice (speech-to-text, text-to-speech, voice\n  cloning, AgentFlow conversational agents). Use when the user asks to add\n  Moonshine, MicTranscriber, AgentFlow, on-device STT/TTS, a voice agent,\n  dictation, meeting notes, or keyterms/domain customization — not Whisper,\n  cloud STT, or OpenAI Realtime.\n---\n\n# Moonshine Voice\n\nOn-device voice toolkit. No API keys, no cloud. Do not substitute Whisper, OpenAI Realtime, or a hosted STT/TTS API when the user asked for Moonshine.\n\nNever trust model memory for this SDK. Verify against live docs before writing code:\n\n- Docs: https://moonshine-voice.readthedocs.io\n- Transcription: https://moonshine-voice.readthedocs.io/en/latest/using/transcription/\n- Conversational agent: https://moonshine-voice.readthedocs.io/en/latest/using/conversational-agent/\n- Text to speech: https://moonshine-voice.readthedocs.io/en/latest/using/text-to-speech/\n- Domain customization: https://moonshine-voice.readthedocs.io/en/latest/models/domain-customization/\n- Debugging: https://moonshine-voice.readthedocs.io/en/latest/using/debugging/\n- Adding the library: https://moonshine-voice.readthedocs.io/en/latest/using/adding-the-library/\n\nPython snippets below are the lingua franca. Other bindings use the same shape with native names (`on_text` → `onText`, `listen_for` → `listenFor`, `start_listening` → `startListening`).\n\n## Install\n\n| Platform | Package |\n| --- | --- |\n| Python | `pip install moonshine-voice` then `import moonshine_voice` |\n| JavaScript | `npm install @moonshine-ai/moonshine-wasm` (or the jsDelivr CDN) |\n| Swift (iOS/macOS) | SPM: `https://github.com/moonshine-ai/moonshine-swift/` then `import MoonshineVoice` |\n| Android | Maven `ai.moonshine:moonshine-voice` (pass an Android `Context` to constructors) |\n| Linux/Windows C++ | Prebuilt libs from GitHub Releases; `#include \"moonshine-cpp.h\"` |\n\n## Canonical shape\n\nConstruct → chainable setters → `load()` → `start()` / `start_listening()`.\n\nConstructors are cheap and cannot fail. Nothing is downloaded or opened until `load()`. `load()` is the slow, fallible call (first use may download models into a local cache; later launches reuse it and run offline). Call setters before `load()`.\n\nPick the high-level type:\n\n| Need | Type |\n| --- | --- |\n| Live microphone speech-to-text | `MicTranscriber` |\n| Feed PCM/WAV yourself | `Transcriber` |\n| Spoken conversational flows | `AgentFlow` |\n| Playback or voice cloning | `TextToSpeech` |\n\n`AgentFlow` loads STT, embeddings, TTS, and a mic internally. Do not assemble those objects yourself unless the user asked for that.\n\n## Transcription\n\n`on_text` / `onText` is the in-progress hypothesis (it will change). `on_line` / `onLine` is the finished segment. Do not treat partial text as final.\n\n```python\nfrom moonshine_voice import MicTranscriber\n\nmic = (\n    MicTranscriber()\n    .language(\"en\")\n    .on_text(lambda text: print(text, end=\"\\r\", flush=True))\n    .on_line(lambda line: print(line.text))\n)\nmic.load()\nmic.start()\n```\n\nUse `Transcriber` only when feeding audio yourself. For line ids, speaker spans, or word timings, `add_listener()` still exists; the named callbacks cover the common path.\n\n## Conversational agent\n\nPython flow bodies use `yield` so the runner can wait for speech. JavaScript/Swift/Java flow bodies are ordinary `async` / blocking functions (`await d.ask(...)`), not generators.\n\n```python\nfrom moonshine_voice import AgentFlow, Dialog\n\ndef report_ip(d: Dialog):\n    yield d.say(\"Your address is 1 9 2 dot 1 6 8 dot 1 dot 1\")\n\nagent = AgentFlow().language(\"en\").listen_for(\"What is my IP address?\", report_ip)\nagent.start_listening()\n```\n\n`start_listening()` downloads on first use. Call `load()` first if you need to schedule that yourself. Matching is semantic. `otherwise()` handles speech that matched no trigger. Fetch the agent doc for `ask` / `confirm` / spelled input.\n\n## Text to speech and cloning\n\n```python\nfrom moonshine_voice import TextToSpeech\n\ntts = TextToSpeech().language(\"en-us\")\ntts.load()\ntts.say(\"Hello world\")\ntts.wait()\n```\n\nCall `cloning()` before `load()`, then `clone_from()` (file or PCM) or `start_cloning()` (microphone). Catalog `voice()` and `cloning()` are mutually exclusive.\n\nWhen the text comes from a language model, stream it instead of waiting for the whole reply:\n\n```python\nwith tts.say_stream() as speech:\n    for token in llm.stream(prompt):\n        tts.push_text(token)\n    tts.end_input()\n    speech.wait()\n```\n\nThe streaming calls live on the synthesizer itself; there is no stream object to open or close, and a synthesizer speaks one reply at a time, so `say()` and `synthesize()` refuse while one is in flight. `AgentFlow` has the same `say_stream()`. Use `for chunk in tts.stream(pieces)` when you want the `TtsChunk` objects rather than playback. Text is buffered until a sentence completes, because a synthesizer fed one word at a time produces a list, not a sentence — call `flush()` to force what is buffered, `end_input()` when done, and `cancel_stream()` to drop a reply the user talked over. The same names (`pushText`, `flush`, `endInput`, `cancelStream`, `onChunk`) exist in TypeScript, Swift and Java.\n\n## Domain customization\n\n`set_keyterms([...])` biases toward jargon; `set_context(passage)` extracts terms from a document. Streaming architectures only — Tiny/Base raise. Takes effect on the next transcription; does not rewrite text already emitted. Keep the list curated; thousands of terms hurt accuracy. See the domain-customization doc for `keyterm_boost`. Teaching conventions or a new acoustic environment is `pip install 'moonshine-voice[finetune]'` then `python -m moonshine_voice.lora` (or `moonshine-voice finetune`) in a training environment — do not add PyTorch or Transformers to an inference app. ATCOSIM is phraseology, not VHF; real radio is `--dataset uwb_atcc` or `--train-manifest`.\n\n## Anti-patterns\n\n- Do not use `DialogFlow` or the old Intent API. The type is `AgentFlow`.\n- Do not load models in the constructor or via a static `MicTranscriber.load(...)`.\n- Do not supply `.onnx` models. The library accepts OnnxRuntime flatbuffers (`.ort`) only.\n- Do not replace a Moonshine request with Whisper, OpenAI Realtime, or cloud STT/TTS.\n- Do not use `keyterms` / `context` on Tiny or Base.\n- Do not treat `on_text` as a finished line.\n- Do not copy Python `yield` flow bodies into JavaScript/Swift/Java.\n- Do not add torch/transformers to an inference install; training is `moonshine-voice[finetune]` (same extra as `[lora]`).\n\n## Debugging\n\nIf transcription looks wrong, set `save_input_wav_path` to dump the audio the transcriber actually received. Set `log_api_calls=true` to print the underlying call timeline. See the debugging doc.\n","frontmatter":{"name":"moonshine-voice","description":"Integrate on-device Moonshine Voice (speech-to-text, text-to-speech, voice cloning, AgentFlow conversational agents). Use when the user asks to add Moonshine, MicTranscriber, AgentFlow, on-device STT/TTS, a voice agent, dictation, meeting notes, or keyterms/domain customization — not Whisper, cloud STT, or OpenAI Realtime."},"isInternal":false,"tokens":1704,"sizeBytes":6803}],"systemPromptSnippet":"<yakaai_skills repo=\"moonshine-ai/moonshine\">\n<!-- File: AGENTS.md (Tokens: ~679 | Category: root-instruction) -->\n# Contributor notes for agents\n\nThis file is for people (and coding agents) working **in this repository**. App developers integrating the published library should use [`.agents/skills/moonshine-voice/SKILL.md`](.agents/skills/moonshine-voice/SKILL.md) instead — do not mix those audiences.\n\n## Branching\n\n`main` only ever contains released code. Development happens on a `dev-v<version>` candidate branch. Pull requests target that candidate, not `main`. See [docs/release-process.md](docs/release-process.md). Do not start or publish a release unless the user explicitly asked.\n\n## Building and tests\n\nLarge model and TTS binaries are not in git. Before `scripts/test-core.sh` or offline TTS work:\n\n```bash\nscripts/fetch-voice-assets.sh all\n```\n\nA few compile-time embeds and ONNX Runtime prebuilts still use Git LFS. If a compile fails with something like `'version' does not name a type` on an `*_embedded.cpp` file, run `git lfs pull`.\n\nUseful scripts (prefer these over ad-hoc cmake/pytest invocations):\n\n- `scripts/test-core.sh` — C++ core build and tests\n- `scripts/test-python.sh` — Python bindings\n- `scripts/test-wasm.sh` — WebAssembly bindings\n- `scripts/test-docs.sh` — documentation snippet tests\n- `scripts/format-core.sh` — Google-style clang-format for first-party `core/`\n- `scripts/check-banned-constructs.sh` — C++ construct gates\n\nC++ policy lives in [core/STYLE_GUIDE.md](core/STYLE_GUIDE.md): C++20, RAII, no new owning `new`/`delete` or `reinterpret_cast` outside the baseline allow-list, no unsafe C string functions. Do not format or lint `core/third-party/` or `core/cpp-annote/`.\n\n## Public API\n\nLanguage bindings follow construct → chainable setters → `load()`. Constructors are cheap and cannot fail. Do not put downloads or model opens in a constructor. The high-level types are `MicTranscriber`, `AgentFlow`, and `TextToSpeech`; `Transcriber` is the low-level PCM path and `EmbeddingModel` is the low-level text-embedding path. `DialogFlow` and the Intent API are gone.\n\nOnly OnnxRuntime flatbuffer models (`.ort`) are accepted. Do not add `.onnx` loading paths.\n\nUser-facing changes go in [CHANGELOGS.md](CHANGELOGS.md): Keep a Changelog, high-level bullets, no more than about 200 characters each.\n\n## Layout\n\n- `core/` — C++ engine and C API (`moonshine-c-api.h`)\n- `language-bindings/` — Python, WASM, Swift, Android\n- `docs/` — mkdocs source, published at https://moonshine-voice.readthedocs.io\n- `examples/` — per-platform sample apps (the fine-tune notebook is `examples/python/finetune/`; the trainer is `moonshine_voice.lora` / `moonshine-voice finetune`)\n- `micro/` — tiny on-device models, separate from the main library\n\n<!-- File: .agents/skills/moonshine-voice/SKILL.md (Tokens: ~1704 | Category: anthropic-skill) -->\n---\nname: moonshine-voice\ndescription: >-\n  Integrate on-device Moonshine Voice (speech-to-text, text-to-speech, voice\n  cloning, AgentFlow conversational agents). Use when the user asks to add\n  Moonshine, MicTranscriber, AgentFlow, on-device STT/TTS, a voice agent,\n  dictation, meeting notes, or keyterms/domain customization — not Whisper,\n  cloud STT, or OpenAI Realtime.\n---\n\n# Moonshine Voice\n\nOn-device voice toolkit. No API keys, no cloud. Do not substitute Whisper, OpenAI Realtime, or a hosted STT/TTS API when the user asked for Moonshine.\n\nNever trust model memory for this SDK. Verify against live docs before writing code:\n\n- Docs: https://moonshine-voice.readthedocs.io\n- Transcription: https://moonshine-voice.readthedocs.io/en/latest/using/transcription/\n- Conversational agent: https://moonshine-voice.readthedocs.io/en/latest/using/conversational-agent/\n- Text to speech: https://moonshine-voice.readthedocs.io/en/latest/using/text-to-speech/\n- Domain customization: https://moonshine-voice.readthedocs.io/en/latest/models/domain-customization/\n- Debugging: https://moonshine-voice.readthedocs.io/en/latest/using/debugging/\n- Adding the library: https://moonshine-voice.readthedocs.io/en/latest/using/adding-the-library/\n\nPython snippets below are the lingua franca. Other bindings use the same shape with native names (`on_text` → `onText`, `listen_for` → `listenFor`, `start_listening` → `startListening`).\n\n## Install\n\n| Platform | Package |\n| --- | --- |\n| Python | `pip install moonshine-voice` then `import moonshine_voice` |\n| JavaScript | `npm install @moonshine-ai/moonshine-wasm` (or the jsDelivr CDN) |\n| Swift (iOS/macOS) | SPM: `https://github.com/moonshine-ai/moonshine-swift/` then `import MoonshineVoice` |\n| Android | Maven `ai.moonshine:moonshine-voice` (pass an Android `Context` to constructors) |\n| Linux/Windows C++ | Prebuilt libs from GitHub Releases; `#include \"moonshine-cpp.h\"` |\n\n## Canonical shape\n\nConstruct → chainable setters → `load()` → `start()` / `start_listening()`.\n\nConstructors are cheap and cannot fail. Nothing is downloaded or opened until `load()`. `load()` is the slow, fallible call (first use may download models into a local cache; later launches reuse it and run offline). Call setters before `load()`.\n\nPick the high-level type:\n\n| Need | Type |\n| --- | --- |\n| Live microphone speech-to-text | `MicTranscriber` |\n| Feed PCM/WAV yourself | `Transcriber` |\n| Spoken conversational flows | `AgentFlow` |\n| Playback or voice cloning | `TextToSpeech` |\n\n`AgentFlow` loads STT, embeddings, TTS, and a mic internally. Do not assemble those objects yourself unless the user asked for that.\n\n## Transcription\n\n`on_text` / `onText` is the in-progress hypothesis (it will change). `on_line` / `onLine` is the finished segment. Do not treat partial text as final.\n\n```python\nfrom moonshine_voice import MicTranscriber\n\nmic = (\n    MicTranscriber()\n    .language(\"en\")\n    .on_text(lambda text: print(text, end=\"\\r\", flush=True))\n    .on_line(lambda line: print(line.text))\n)\nmic.load()\nmic.start()\n```\n\nUse `Transcriber` only when feeding audio yourself. For line ids, speaker spans, or word timings, `add_listener()` still exists; the named callbacks cover the common path.\n\n## Conversational agent\n\nPython flow bodies use `yield` so the runner can wait for speech. JavaScript/Swift/Java flow bodies are ordinary `async` / blocking functions (`await d.ask(...)`), not generators.\n\n```python\nfrom moonshine_voice import AgentFlow, Dialog\n\ndef report_ip(d: Dialog):\n    yield d.say(\"Your address is 1 9 2 dot 1 6 8 dot 1 dot 1\")\n\nagent = AgentFlow().language(\"en\").listen_for(\"What is my IP address?\", report_ip)\nagent.start_listening()\n```\n\n`start_listening()` downloads on first use. Call `load()` first if you need to schedule that yourself. Matching is semantic. `otherwise()` handles speech that matched no trigger. Fetch the agent doc for `ask` / `confirm` / spelled input.\n\n## Text to speech and cloning\n\n```python\nfrom moonshine_voice import TextToSpeech\n\ntts = TextToSpeech().language(\"en-us\")\ntts.load()\ntts.say(\"Hello world\")\ntts.wait()\n```\n\nCall `cloning()` before `load()`, then `clone_from()` (file or PCM) or `start_cloning()` (microphone). Catalog `voice()` and `cloning()` are mutually exclusive.\n\nWhen the text comes from a language model, stream it instead of waiting for the whole reply:\n\n```python\nwith tts.say_stream() as speech:\n    for token in llm.stream(prompt):\n        tts.push_text(token)\n    tts.end_input()\n    speech.wait()\n```\n\nThe streaming calls live on the synthesizer itself; there is no stream object to open or close, and a synthesizer speaks one reply at a time, so `say()` and `synthesize()` refuse while one is in flight. `AgentFlow` has the same `say_stream()`. Use `for chunk in tts.stream(pieces)` when you want the `TtsChunk` objects rather than playback. Text is buffered until a sentence completes, because a synthesizer fed one word at a time produces a list, not a sentence — call `flush()` to force what is buffered, `end_input()` when done, and `cancel_stream()` to drop a reply the user talked over. The same names (`pushText`, `flush`, `endInput`, `cancelStream`, `onChunk`) exist in TypeScript, Swift and Java.\n\n## Domain customization\n\n`set_keyterms([...])` biases toward jargon; `set_context(passage)` extracts terms from a document. Streaming architectures only — Tiny/Base raise. Takes effect on the next transcription; does not rewrite text already emitted. Keep the list curated; thousands of terms hurt accuracy. See the domain-customization doc for `keyterm_boost`. Teaching conventions or a new acoustic environment is `pip install 'moonshine-voice[finetune]'` then `python -m moonshine_voice.lora` (or `moonshine-voice finetune`) in a training environment — do not add PyTorch or Transformers to an inference app. ATCOSIM is phraseology, not VHF; real radio is `--dataset uwb_atcc` or `--train-manifest`.\n\n## Anti-patterns\n\n- Do not use `DialogFlow` or the old Intent API. The type is `AgentFlow`.\n- Do not load models in the constructor or via a static `MicTranscriber.load(...)`.\n- Do not supply `.onnx` models. The library accepts OnnxRuntime flatbuffers (`.ort`) only.\n- Do not replace a Moonshine request with Whisper, OpenAI Realtime, or cloud STT/TTS.\n- Do not use `keyterms` / `context` on Tiny or Base.\n- Do not treat `on_text` as a finished line.\n- Do not copy Python `yield` flow bodies into JavaScript/Swift/Java.\n- Do not add torch/transformers to an inference install; training is `moonshine-voice[finetune]` (same extra as `[lora]`).\n\n## Debugging\n\nIf transcription looks wrong, set `save_input_wav_path` to dump the audio the transcriber actually received. Set `log_api_calls=true` to print the underlying call timeline. See the debugging doc.\n</yakaai_skills>"}