用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/tomc98/speak --skill speak命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | speak |
| description | Speak text aloud via ElevenLabs TTS. Voice is the primary communication channel. Audio queues sequentially across all agents. |
| allowed-tools | Bash, Read |
Paths below use
{base}as shorthand for this skill's base directory, which is provided automatically via the "Base directory for this skill" context injected at the top of the prompt when the skill loads. Construct the full path from that value — do NOT rely on environment variables.
Speak every turn. The user works on other things while you run — voice is how they know you need attention or are done.
Skip speaking only when:
{base}/scripts/say.sh "Your message here"
{base}/scripts/say.sh "Your message" --voice Claude
{base}/scripts/say.sh "Your message" --voice Adam --channel agent-1
{base}/scripts/say.sh "Urgent!" --priority
Queue operations:
{base}/scripts/say.sh --status
{base}/scripts/say.sh --skip
{base}/scripts/say.sh --clear
{base}/scripts/say.sh --pause
{base}/scripts/say.sh --resume
{base}/scripts/say.sh --history --limit 10
{base}/scripts/say.sh --replay <id>
Every spoken line is attributed on the dashboards as a stack: voice → session → agent.
say.sh from the Claude Code environment
($CLAUDE_JOB_DIR/state.json name, falling back to the session transcript's latest
title record). Renames are picked up on the next call, and subagents inherit the
environment, so their lines attribute to the parent session. No action needed;
--session "Name" overrides.--channel) — the main agent speaks with no --channel. Every spawned
subagent/teammate must be told its name in its spawn brief (see Team Voice
Assignment) so its lines carry the third stack line. Channels also drive
per-channel pause and filtering on the dashboards.ElevenLabs V3 supports freeform expressive tags in brackets. These direct how the voice performs — not what sounds it makes.
Works well:
[excited] [deadpan] [sarcastically] [conspiratorial] [smug][slowly, building intensity] [suddenly shouting] [composing herself, calm][old timey radio announcer] [valley girl voice] [deep movie trailer voice][singing softly] — surprisingly effective, can carry a tune[aside, whispering to audience] [back to announcer voice] [dramatic pause][whispering, conspiratorial] [speaking normally, laughs]Doesn't work:
[sound of keyboard clicking] [car driving by] [thunder rumbling] [door creaking] — the model cannot generate non-voice sounds[out of breath] — mostly ignored[even quieter] [normal volume] — unreliableTags direct voice acting, not audio production. Think stage directions, not foley.
Default assistant voice is Claude. The full roster is dynamic — query the daemon at session start rather than relying on a hardcoded list:
curl -s http://127.0.0.1:7865/voices
Each record has name, id, color, style, kind, and has_portrait. Pick a voice whose style description matches your role (e.g. a precise debugging agent → crystalline/deliberate; an exploration agent → young/energetic).
Selection order:
Claude (the default)kind fieldkind is an open enum describing where a voice came from. Known values:
default — the built-in rostercodex — voices intended for Codex-impersonating agentsuser — the user's own cloned voicecustom — any other user-added voiceUnless instructed otherwise, agents should pick from kind: "default". A Codex-impersonating agent should prefer kind: "codex" when one exists, falling back to default.
Some voices carry an in-character speaking style in their style field — for these, the style is a script direction to perform, not just a label. When you speak as one, write the spoken line as that character: follow every directive in the style, including the suggested audio tags and any phonetic respellings it specifies.
kind: "custom") — deadpan, blunt, broken English. Drop articles, keep sentences short and clipped, and respell words for his accent so the TTS leans in: this→dis, that→dat, they→dey, them→dem, then→den, with→wit, nothing→nutting, very→wery, what→wat. Lead with [deadpan] / [flat, monotone]. e.g. [deadpan] Dis is not good. Your app do nutting. My app is better.kind: "custom") — manic genius pickle scientist, ALWAYS AT FULL VOLUME. The voice only works shouted: open [shouting] L-LOOK, MORTY,, write most of the line in ALL CAPS, and pin the register with [suddenly shouting] / [yelling] / [manic]. Banned: [sighs], [muttering], calm asides, quiet trail-offs — any low-energy beat kills it. Mania mechanics stay, at volume: stammered restarts, em-dash self-interrupts, rapid concrete specifics, rhetorical question whose ANSWER is the payoff, pickle gloat, doubled repeat (IT'S JUST— IT'S JUST SCIENCE!), closer I'M [X] RIIICK!. Never open with meta-setup, slow name repetition, or the payoff itself; everyone is 'Morty' unless being singled out.The rule generalizes: if a voice's style reads like a persona/accent rather than a neutral descriptor, render the text in that persona before calling say.sh --voice <Name>.
Tom manages the roster through the macOS Voice Manager UI (under macos/ in this skill). The same operations are available on the daemon for scripted changes:
GET /voices — list voices (includes kind, has_portrait)POST /voices — add {name, id, color, style, kind?}PATCH /voices/{name} — partial update; changing name renames the voiceDELETE /voices/{name} — remove a voicePOST /portraits/{name}?frame=default|slight|open — upload a portrait frame (raw PNG body)The dashboard at http://127.0.0.1:7865 shows:
When spawning a team, the lead should curl -s http://127.0.0.1:7865/voices and assign each teammate a unique voice from the live roster (no hardcoded mapping). Match style to role when it fits. Include in every teammate's prompt:
Your voice is <Name>. When speaking, use: {base}/scripts/say.sh "message" --voice <Name> --channel <agent-name>
Speak at the end of every turn — voice is how you communicate completion and status.
--channel <agent-name> per teammate — it drives dashboard filtering and renders
as the agent line under the portrait, so the user can see which agent is talking.