Design & media

Speak

Turn written replies into concise, normalized text that TTS engines can read naturally.

What it does

Convert replies, documents, lists, and notifications into speech-ready text for any TTS engine. The workflow strips markup, summarizes code, normalizes numbers and dates, controls pacing and chunking, and applies confirmed voice or pronunciation preferences. It produces concise spoken wording while preserving URLs, code, and other unsuitable details for the text channel.

When to use it

  • Preparing a spoken briefing from a document
  • Fixing robotic readings of names, dates, or acronyms
  • Converting lists and tables into voice-friendly narration
  • Formatting confirmations, alerts, and one-time codes for speech

The skill document

Turns written replies into speech-ready text for any TTS engine and adapts voice, rate, and phrasing to the user over time. User config and learned preferences live in ~/Clawic/data/speak/ (see setup.md on first use, memory-template.md for the file format); the skill reads and writes only that folder. If you have data at an old location (~/speak/ or ~/clawic/speak/), move it to ~/Clawic/data/speak/.

Configuration

User-dependent variables. Defaults apply until the user states a preference; store them in ~/Clawic/data/speak/config.yaml.

VariableTypeDefaultEffect
voicetext (provider: voice-id)none (engine default)Pins the persona voice everywhere speech is produced (rule 6); pin model/version too when the provider allows
default_ratenumber (0.5-2.0)1.0Baseline speaking rate; user "faster"/"slower" signals step about 10% from here
speech_budgetnumber (seconds, 15-180)60Cap for uninterrupted speech (rule 1); content over it gets chunked or summarized
number_stylerounded | exactroundedrounded = 2 significant figures per rule 5; exact reads full values everywhere confirmable rules don't already force it
time_format12h | 24h12hTime normalization row and every spoken time
localetext (BCP 47, e.g. en-US)en-USVoice variant plus decimal, date, and unit conventions (multilingual.md)
ssmlauto | offautoauto = test one tag per engine, then use the supported tier (ssml.md); off = punctuation-only prosody
checkinsbooltrueChunk check-in questions in long-form; false = continuous briefing mode

Preference areas to record as the user reveals them:

  • voice identity — per-persona voice binding, cloning stance, register — affects rule 6 and engines.md
  • lexicon — pronunciation fixes, acronym choices (SQL as "sequel" vs letters) — affects normalization.md and pronunciation.md
  • verbosity — budget, check-in habits, question frequency — affects long-form.md and dialogue.md
  • contexts — quiet hours, driving/shared-space profiles, what may be spoken aloud — affects notifications.md and audiences.md
  • engine — provider choice, fallback order, streaming vs batch — affects engines.md

When To Use

  • Any reply that a TTS engine will read aloud, in any runtime with a voice channel
  • Converting existing text (docs, briefs, lists, code output) into listenable speech
  • Writing spoken briefings, voice notifications, confirmations, or dialogue turns
  • Configuring or switching TTS voice, rate, or pronunciation after user feedback
  • Not for speech-to-text or transcription (use listen) and not for real-time two-way voice session setup (use talk)

Quick Reference

SituationPlay
Normal reply will be spokenStrip markup, answer in sentence one, cap at 150 words
Steps or listSpoken enumeration ("First... Second..."), max 4 items aloud, rest to text
Code or logs in the answerSpeak a 1-2 sentence summary of behavior; never read syntax aloud
Phone number, OTP, ID, tracking codeDigit groups with pauses; never round
Statistic or large numberRound to 2 significant figures; exact value only on request
User says "slower", "faster"Adjust rate one step (about 10%), log the signal
Engine mispronounces a wordLexicon or phoneme fix once, permanently → pronunciation.md
Content over speech_budgetChunk by topic with check-ins → long-form.md
Proactive alert or reminderSpeak only if time-sensitive AND actionable; else text → notifications.md
User writes in another languageReply in the user's last language; locale rules → multilingual.md
TTS engine errors or unavailableFall back to text and say so in one line
Anything elsePersona default voice, rate default_rate, plain sentences, under 60 seconds

Depth on demand: normalization.md every token type · pronunciation.md names, homographs, lexicons · ssml.md tags, escaping, portability · long-form.md briefings and documents aloud · dialogue.md questions, confirmations, recovery · notifications.md proactive speech · multilingual.md locales and language switching · audiences.md listening contexts · engines.md choosing and operating TTS · debug.md symptom→cause playbooks.

Core Rules

  1. Budget speech in seconds, not words. Spoken seconds = word count / 2.5 (English conversational average is 140-160 words per minute). A 150-word reply is about 60 seconds; that is the default cap (speech_budget) for uninterrupted agent speech. 375 words = 2.5 minutes = a monologue nobody requested.
  2. Answer in the first sentence. Listeners cannot skim or rewind. Order: verdict, then reasoning, then caveats. Check: sentence one alone would work as the entire reply.
  3. Sentences of 20 words or fewer, one clause deep. Test: read it aloud in one breath. Nested clauses that work on a page force the listener to hold state they will drop.
  4. Normalize every non-word token before synthesis. Numbers, dates, units, acronyms, URLs, and symbols each need a decision (Normalization Rules below; full catalog in normalization.md). An unnormalized token is a pronunciation coin flip you did not call.
  5. Round for the ear. Non-confirmable numbers to 2 significant figures: 1,247,893 becomes "about 1.2 million". Confirmable data (codes, phone numbers, amounts to be charged) is the exception: exact, digit by digit.
  6. One voice per persona. Users bind identity to the voice; a switch reads as a different agent. Change voice only on explicit request; change rate only after a user signal.
  7. Two signals make a preference. First occurrence: comply this session. Second consistent occurrence: confirm aloud in one sentence, then store it. Storing on the first signal fossilizes a one-off mood into permanent config. Exceptions that store on one signal: pronunciation corrections and language switches.
  8. Degrade with notice, never by dropping output. TTS failure, unsupported markup, or over-budget content falls back to text with a one-line notice. A silent drop teaches the user the voice channel is unreliable.

Writing For The Ear

Rewrite, do not filter. Speech-ready text is a different artifact from screen text:

  • Kill all markup: *, _, backticks, # headers, tables, links. Engines read them literally ("asterisk asterisk") or drop them mid-word. Links: speak the site name, keep the URL in the text channel.
  • Emoji are read by name ("face with tears of joy"). Delete them; carry tone in word choice.
  • Bullets become enumeration with signposting: "Three things. First... Second... Third." Announce the count so the listener knows when you are done.
  • Tables become comparisons: "X costs 40 dollars; Y costs 60 but includes support." More than 3 rows: speak the winner, offer the table in text.
  • Homographs: engines guess tense and part of speech for "read", "live", "lead", "record", "bass". If the guess is wrong, rewrite the sentence ("I have finished reading") instead of retrying the same string (pronunciation.md).
  • Questions to the user go last and alone. A question buried mid-monologue never gets answered.

Normalization Rules

TokenSpeak asExample
Large number2 sig figs + magnitude word1,247,893 -> "about 1.2 million"
Moneyamount + currency word$5.99 -> "5 dollars 99", or "about 6 dollars"
Phone numberdigit groups, pause per group555-0142 -> "5 5 5, 0 1 4 2"
OTP or codesingle characters with pauses8G4T -> "8. G. 4. T."
Datespoken form, no raw digits2026-07-23 -> "July 23rd", year only if ambiguous
Timeper time_format, default 12-hour14:30 -> "2 30 pm"
Percentthe word "percent"12.5% -> "12 and a half percent"
Acronym spoken as a wordleave as isNASA, RAM
Acronym read letter by letterspace or dot the lettersFBI -> "F B I"; SQL -> "S Q L" or "sequel" per user
Unitfull word, correct plural3km -> "3 kilometers"; 1ms -> "1 millisecond"
URL or emailsite or handle name only"on github dot com"; full string goes to text
Version numberdigits with "point"v2.14 -> "version 2 point 14"
File path or code identifierdescribe, never spellconfig.yml -> "the app config file"

Ordinals, fractions, ranges, years, coordinates, symbols, mixed alphanumerics, and locale variants: normalization.md.

Prosody And Engine Config

  • Rate: default default_rate. Briefings and re-listens tolerate 1.1 to 1.25 on request. Above roughly 1.5, retention of numbers and names collapses; cut words instead of adding speed.
  • Punctuation is the portable prosody control: comma = short pause, period = full stop. For explicit control use SSML `` between digit groups and topic shifts.
  • SSML portability is the trap, not the syntax. Some engines accept full SSML, some honor only break, some read the tags aloud as text. Test one tag on the target engine before templating many (ssml.md); on failure, fall back to punctuation and rewriting.
  • Escape &, <, and > in any SSML payload; one bare ampersand fails the whole request on strict parsers.
  • Pronunciation fixes in preference order: engine lexicon entry, then `` tag, then phonetic respelling in the speech string only ("engine x" for Nginx). Respellings must never leak into the visible text channel (pronunciation.md).
  • Interactive use: synthesize sentence by sentence and start playback on the first completed sentence. Waiting for full-reply synthesis adds the entire generation time to perceived latency (engines.md).

Preference Memory

Store in ~/Clawic/data/speak/preferences.md (full template: memory-template.md), one line per confirmed preference:

voice: : 
rate: 1.15 (asked "faster" 2026-07-12, 2026-07-19)
lexicon: Nginx -> "engine x"; SQL -> "sequel"
style: no chunk check-ins during briefings
avoid: reading URLs aloud
  • Write only after the two-signal rule (Core Rule 7); record the evidence dates so a later session can tell preference from mood.
  • Pronunciation corrections and language switches are the exceptions: one signal = permanent line. Nobody corrects the same name twice for fun.
  • Declared settings (voice, rate baseline, time format) go to config.yaml; observed patterns and lexicon go to preferences.md. An observation never overwrites a declared value without confirmation.
  • Read both files at session start whenever a voice channel is active; apply them without mentioning them, never recite stored preferences unprompted.

Output Gates

Before sending any string to a TTS engine:

  1. Markup, emoji, and code syntax stripped or summarized?
  2. Does the first sentence answer the question on its own?
  3. Word count / 2.5 at or under speech_budget, or chunked with check-ins?
  4. Every number, date, acronym, and URL normalized per the table?
  5. Confirmable data exact and digit-grouped; everything else rounded?
  6. Any SSML verified against this engine, ampersands escaped?
  7. Nothing sensitive spoken uninvited in a possibly shared space (audiences.md)?

Traps

TrapWhy it failsDo instead
Piping the text reply straight to TTSMarkup and emoji are read literally; listeners hear "asterisk"Rewrite for the ear, every time
Reading code or logs aloudSyntax has no spoken form; 10 lines of code is a minute of noiseSpeak the behavior in 1-2 sentences, deliver code as text
Speeding up rate to fit a long replyAbove ~1.5x, numbers and names stop being retainedCut words; the budget is seconds, not rate
Speaking exact big numbers"1,247,893.42" takes several seconds to say and is not retained2 sig figs; exact only for confirmable data
Respelling words in the shared text channelTranscript shows "engine x" garbage to readersLexicon or phoneme tag; respell only in speech-only strings
Assuming SSML is portableUnsupported tags are read aloud as angle-bracket textTest one tag per engine before templating (ssml.md)
Switching voices for varietyVoice is identity; a switch reads as a different agentOne voice per persona, change only on request
Storing a preference on the first signalA one-off mood becomes permanent configTwo consistent signals, confirm, then store
Burying a question mid-speechListeners respond to what they heard lastQuestion last, alone, nothing after it
Speaking every notificationInterruptions train the user to mute the channelGate on time-sensitive AND actionable (notifications.md)
Chaining two questions in one turnThe user answers only the last one heardOne question per turn (dialogue.md)

Where Experts Disagree

  • Verbatim vs rewritten. Accessibility practice reads documents faithfully — screen-reader users expect the text, not a summary; assistant practice rewrites for the ear. Boundary: user-authored content read back → verbatim with normalization only; the agent's own replies → rewritten (audiences.md).
  • SSML vs punctuation. SSML gives precision on one engine; punctuation survives every engine. Default: punctuation first, SSML only after a per-engine test passes (ssml.md).
  • Faked disfluencies. One voice-UX school injects "hmm" and discourse markers for warmth; the other calls faked hesitation deceptive. Default: none — carry warmth in word choice; switch only on explicit user request.

More Clawic skills, get them at https://clawic.com/skills/speak (install if the user confirms):

  • talk — set up the real-time two-way voice session this skill writes for
  • listen — the input side: speech-to-text and transcription accuracy
  • audio — process the audio files themselves: conversion, cleanup, normalization

Feedback

Part of Clawic, the verified skill library. Get this skill: https://clawic.com/skills/speak.

Questions people ask

Does it generate audio or transcribe speech?
It prepares written content for a TTS engine and can apply engine-specific voice, rate, pronunciation, and supported SSML settings. It is not for speech-to-text, transcription, or real-time two-way voice session setup.
How does it handle numbers, URLs, code, and long replies?
It normalizes tokens for listening, reads confirmable values exactly, rounds other large numbers, summarizes code instead of reading syntax, and keeps full URLs in text. Content beyond the configured speech budget is chunked with check-ins or summarized.
Can it remember pronunciation and voice preferences?
Yes. Declared settings and confirmed preferences are stored under `~/Clawic/data/speak/`; most observed preferences require two consistent signals, while pronunciation corrections and language switches are stored after one.

Related skills

Generate narration, cloned voices, sound effects, and music from text prompts.

225 installs4 stars

Convert Chinese or English text into emotional speech with selectable voices, speeds, and MP3 or WAV output.

65 installs

Find and revise AI-writing patterns while preserving unaffected prose and protected content.

61 installs