Neither setting did what it looked like it did, and the knowledge base had no page for either, so both were invisible until the operator asked. tools/neovim.md: the two entry points (vanilla `nvim`, `lazyvim` as an NVIM_APPNAME profile), the fresh-box install, the base16 wallpaper-palette hook with its SIGUSR1 contract, and the trap that matters — the official recipe clones over ~/.config/nvim and destroys the vanilla quick-edit path. tools/applications.md gets the editor row (Ghostty's row had lost its label) and Neovim's verified version. core/dankvoice.md gains the arming rule: arming is session-scoped, a silent session start is a config state, and the two checks — `/say status` then `pgrep -a pw-play` — prove the chain without blaming the endpoint. kb-lint 0 violations, index-coverage 0 issues.
4.4 KiB
type, title, description, tags, verified, timestamp
| type | title | description | tags | verified | timestamp | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| reference | dankvoice | Voice output ships as the dank/dankvoice package; this page keeps only the fleet integration facts and the cutover procedure. |
|
2026-10-19 | 2026-10-19 |
dankvoice
Voice output lives in the dank/dankvoice package:
pi install git:http://192.168.0.143:3000/dank/dankvoice.git. This page owns
only fleet integration and the cutover. The package README
(http://192.168.0.143:3000/dank/dankvoice) owns the /say command
reference, the settings/env knob list, the segmentation state machine, the
enhancer port, and mood control — never duplicate those facts here.
Fleet wiring
- TTS endpoint — resolved from the provider block whose model row carries
api: openai-speechin agent/models.yml: frank-tts on Dankclaw:7772. LAN-only — no Caddy vhost fronts it. - Narration humanizer — the harness
@tinyrole (modelRoles.tinyinagent/config.yml), on this fleet frank-zealot (Dankclaw:7771). - Hybrid-endpoint trap (load-bearing) — a raw
fetchto a thinking-by-default model spends the token budget onreasoning_contentand answerscontent: "". The package pinschat_template_kwargs: { enable_thinking: false }on the rewrite call; do not remove it. On a hybrid endpoint, empty content beside non-emptyreasoning_contentmeans the flag was ignored — that is a failed rewrite (fall back to the mechanical text), never the legitimate "nothing to say". - Voice contract — omitting
voiceis legal: frank-tts fills itsDEFAULT_VOICE(2026-10-18 voice-pack work).GET {base}/v1/audio/voicesanswers a bare JSON array; an unknown voice answers 400 withavailable_voices, which the package uses as roster fallback. On this shimGET /v1/voicesandGET /v1/modelsare 404.
Cutover (Refs #34)
The agent/extensions/dankvoice.ts drop-in and its 26-test bats suite are
retired here (the package suite is a strict superset; test names ported 1:1).
Per box:
pi install git:http://192.168.0.143:3000/dank/dankvoice.git/say status, then "Speak a test phrase" from the/saymenu — the audible proof a silent session needs.- Pull
main(the drop-in disappears with it) and restart the session.
Menu choices survive the cutover: both transports persist to the same
gitignored settings file, ~/.omp/cache/dankvoice.json
(DANKVOICE_CONFIG relocates it).
Why not the built-in vocalizer
The harness speak-aloud path (speech.enabled / speech.voice, omp say)
synthesizes with bundled Kokoro ONNX against a compile-time voice enum —
cloned voices can never reach it, and no setting routes it to frank-tts.
dankvoice is a second transport beside it, not a patch: Kokoro stays for
quick local speech, the package carries cloned-voice narration. The tts
tool / xd://tts device reach frank-tts too, but produce files, not audio
playback.
Arming auto-speak
Arming is session-scoped by design: /say on arms the running session and
is deliberately never persisted. A session that starts silent is a config
state, not a fault — set "auto": true in ~/.omp/cache/dankvoice.json (this
fleet does) or export DANKVOICE_AUTO=1 to start armed. Editing the settings
file mid-session does nothing; the plugin reads it at startup.
Two checks prove the chain, in order: /say status must report
auto-speak on with a real endpoint (not NO ENDPOINT), and pgrep -a pw-play
during a turn must show one player per spoken segment, --target set to the
saved sink. Thinking narration rides the same arming (thinking: true).
Limits
- Auto-speak narrates thinking and the final message only — mid-turn tool
chatter is never spoken; skipped in
print/jsonmodes so benches stay silent. - frank-tts deployment, voice packs and the registry are owned by the
serverAppConfigsrepo (serverAppConfigs-docs/Dankclaw/Frank TTS.md).
Citations
- Package repo
dank/dankvoice(README,docs/decisions/) — behaviour and knob truth. - Gitea issues #21, #23, #27, #32 (drop-in history) and #34 (this cutover)
on
dank/command-center. - Live endpoint probes 2026-10-18/19 documented in those issues.
See Also
- Core Documentation — the live harness configuration.
- Handy — offline speech-to-text, the input half of voice.