{"id":48963868,"url":"https://github.com/paperfoot/elevenlabs-cli","last_synced_at":"2026-04-20T05:09:29.003Z","repository":{"id":350107511,"uuid":"1205351305","full_name":"paperfoot/elevenlabs-cli","owner":"paperfoot","description":"Agent-friendly Rust CLI for the ElevenLabs AI audio platform. One static binary replaces the MCP server. TTS, STT, sound effects, voice cloning, music, conversational AI agents — all JSON-envelope and semantic exit codes out of the box.","archived":false,"fork":false,"pushed_at":"2026-04-17T20:43:02.000Z","size":333,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-18T03:34:51.439Z","etag":null,"topics":["agent-friendly","ai-agents","ai-audio","ai-tools","audio-processing","cli","cli-tool","conversational-ai","elevenlabs","elevenlabs-api","mcp-alternative","rust","rust-cli","sound-effects","speech-to-text","text-to-speech","tts","voice-ai","voice-cloning","voice-generation"],"latest_commit_sha":null,"homepage":"https://github.com/199-biotechnologies/elevenlabs-cli","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paperfoot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-08T22:08:56.000Z","updated_at":"2026-04-17T20:43:06.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/paperfoot/elevenlabs-cli","commit_stats":null,"previous_names":["199-biotechnologies/elevenlabs-cli","paperfoot/elevenlabs-cli"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/paperfoot/elevenlabs-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paperfoot%2Felevenlabs-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paperfoot%2Felevenlabs-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paperfoot%2Felevenlabs-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paperfoot%2Felevenlabs-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paperfoot","download_url":"https://codeload.github.com/paperfoot/elevenlabs-cli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paperfoot%2Felevenlabs-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32033761,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T00:18:06.643Z","status":"online","status_checked_at":"2026-04-20T02:00:06.527Z","response_time":94,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-friendly","ai-agents","ai-audio","ai-tools","audio-processing","cli","cli-tool","conversational-ai","elevenlabs","elevenlabs-api","mcp-alternative","rust","rust-cli","sound-effects","speech-to-text","text-to-speech","tts","voice-ai","voice-cloning","voice-generation"],"created_at":"2026-04-18T03:04:37.864Z","updated_at":"2026-04-20T05:09:28.996Z","avatar_url":"https://github.com/paperfoot.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"./assets/banner.svg\" alt=\"elevenlabs-cli — agent-friendly Rust CLI for the ElevenLabs AI audio platform\" width=\"100%\"/\u003e\n\n# `elevenlabs-cli`\n\n**One Rust binary. Every [ElevenLabs](https://elevenlabs.io) endpoint. No MCP server, no Python runtime, no drift.**\n\nTTS • STT • Sound Effects • Voice Cloning • Voice Design • Conversational Agents • Music Generation • Phone Calls — all from your terminal, all machine-readable.\n\n[![Star this repo](https://img.shields.io/github/stars/paperfoot/elevenlabs-cli?style=for-the-badge\u0026logo=github\u0026label=%E2%AD%90%20Star%20this%20repo\u0026color=yellow)](https://github.com/paperfoot/elevenlabs-cli/stargazers)\n\u0026nbsp;\n[![Follow @longevityboris](https://img.shields.io/badge/Follow_%40longevityboris-000000?style=for-the-badge\u0026logo=x\u0026logoColor=white)](https://x.com/longevityboris)\n\n[![crates.io](https://img.shields.io/crates/v/elevenlabs?style=for-the-badge\u0026logo=rust\u0026color=orange)](https://crates.io/crates/elevenlabs)\n[![Downloads](https://img.shields.io/crates/d/elevenlabs?style=for-the-badge\u0026logo=rust\u0026color=orange)](https://crates.io/crates/elevenlabs)\n[![CI](https://img.shields.io/github/actions/workflow/status/paperfoot/elevenlabs-cli/ci.yml?style=for-the-badge\u0026logo=github-actions\u0026label=CI)](https://github.com/paperfoot/elevenlabs-cli/actions/workflows/ci.yml)\n[![MIT License](https://img.shields.io/badge/License-MIT-blue?style=for-the-badge)](LICENSE)\n[![MSRV 1.85+](https://img.shields.io/badge/MSRV-1.85%2B-orange?style=for-the-badge\u0026logo=rust)](https://www.rust-lang.org/)\n[![PRs Welcome](https://img.shields.io/badge/PRs-Welcome-brightgreen?style=for-the-badge)](#contributing)\n\n[Install](#install) • [Quick start](#quick-start) • [Recipes](#recipes) • [Commands](#commands) • [Why](#why-a-cli-instead-of-an-mcp-server) • [For agents](#for-ai-agents) • [Config](#configuration) • [**Contributing**](CONTRIBUTING.md) • [**AGENTS.md** (for LLM contributors)](AGENTS.md)\n\n\u003c/div\u003e\n\n---\n\n## What it does\n\nA single ~5 MB Rust binary that exposes the entire ElevenLabs platform on the command line:\n\n```bash\nelevenlabs tts \"Hello, world\"                                        # Text → speech\nelevenlabs tts \"sync me\" --with-timestamps --save-timestamps t.json  # Per-character alignment\nelevenlabs stt voicenote.m4a --timestamps character --format srt     # Transcribe + SRT\nelevenlabs sfx \"rain on a tin roof\" --duration 28                    # Sound effects (0.5-30s)\nelevenlabs voices clone \"My Voice\" sample1.wav sample2.wav\nelevenlabs voices design \"a gruff old lighthouse keeper\" --model eleven_ttv_v3 --seed 42\nelevenlabs audio isolate noisy.mp3                                   # Extract clean speech\nelevenlabs audio convert me.mp3 --voice \"Rachel\" --stability 0.6     # Voice-to-voice\nelevenlabs music compose \"lofi chill for a rainy sunday\" --length-ms 120000\nelevenlabs agents create \"triage-bot\" --system-prompt \"You are a friendly support agent...\"\nelevenlabs phone call agent_xxx --from-id phnum_yyy --to +14155551234\n```\n\nEvery command auto-switches between **coloured human output** (terminal) and **JSON envelopes** (piped / `--json`). Exit codes are semantic (`0=ok, 1=transient, 2=config, 3=bad input, 4=rate limited`). Errors carry a machine-readable `code` and an actionable `suggestion` an AI agent can follow literally.\n\n**Grounded against the official [elevenlabs-js v2.43 SDK](https://github.com/elevenlabs/elevenlabs-js)** — every request/response type in this CLI was verified against the Fern-generated schema that ElevenLabs ships for their own SDK.\n\n---\n\n## Install\n\n```bash\n# cargo (Linux, macOS, Windows)\ncargo install elevenlabs          # crate name is `elevenlabs`, binary name is `elevenlabs`\n\n# Homebrew (macOS, Linux)\nbrew tap 199-biotechnologies/tap\nbrew install elevenlabs\n\n# Prebuilt binaries — Linux, macOS (x86_64 + arm64), Windows\ncurl -L https://github.com/paperfoot/elevenlabs-cli/releases/latest/download/elevenlabs-$(uname -s)-$(uname -m).tar.gz | tar xz\nsudo mv elevenlabs /usr/local/bin/\n```\n\nSelf-update once installed:\n\n```bash\nelevenlabs update --check\nelevenlabs update\n```\n\n---\n\n## Quick start\n\n```bash\n# 1. Save your API key (recommended — wins over any ambient env var)\nelevenlabs config init --api-key sk_...\nelevenlabs config check                     # confirms the key + reports voices available\n\n# 2. Generate speech (+ character-level timings for subtitles / karaoke)\nelevenlabs tts \"The quick brown fox\" -o fox.mp3\nelevenlabs tts \"Per-character timings\" --with-timestamps --save-timestamps t.json -o out.mp3\n\n# 3. Transcribe with character-level accuracy and speaker diarization\nelevenlabs stt interview.m4a --timestamps character --diarize --detect-speaker-roles\n\n# 4. Browse voices — /v2/voices so search/sort actually works\nelevenlabs voices list\nelevenlabs voices library --gender female --accent british --page 1\n\n# 5. Install the skill so Claude / Codex / Gemini discover the CLI automatically\nelevenlabs skill install\n\n# 6. Bootstrap an agent with the full capability manifest\nelevenlabs agent-info | jq '.commands | keys'\n```\n\n---\n\n## Recipes\n\nReal workflows you can paste straight into a shell:\n\n```bash\n# ── Lyric-sync subtitle file from any song ────────────────────────────────\n# Get per-character start/end times, then let the API produce the SRT.\nelevenlabs stt song.mp3 \\\n  --model scribe_v2 \\\n  --timestamps character \\\n  --format srt --format-include-timestamps --format-max-chars-per-line 42 \\\n  --format-out-dir ./subs\n\n# ── Karaoke-style alignment from generated speech ──────────────────────────\n# TTS with per-character alignment JSON (audio + timings.json).\nelevenlabs tts \"The quick brown fox jumps over the lazy dog\" \\\n  --with-timestamps --save-timestamps fox.timings.json \\\n  --seed 42 -o fox.mp3\n# fox.timings.json → { alignment: { characters, character_start_times_seconds, character_end_times_seconds } }\n\n# ── Deterministic voice clone for A/B testing ─────────────────────────────\nelevenlabs tts \"Consistent output every run\" \\\n  --seed 42 --apply-text-normalization on --voice \"Rachel\" -o take.mp3\n\n# ── Call-centre transcript with PII redaction + speaker roles ──────────────\nelevenlabs stt call.wav \\\n  --multi-channel --diarize --detect-speaker-roles \\\n  --detect-entities pii --redact-entities pii --redaction-mode entity_type \\\n  --format segmented_json --format-out-dir ./transcripts\n\n# ── YouTube / TikTok transcript without downloading first ──────────────────\nelevenlabs stt --source-url \"https://youtu.be/…\" --timestamps word \\\n  --keyterm \"ElevenLabs\" --keyterm \"scribe_v2\" --save-words words.json\n\n# ── Designed voice with reproducibility ───────────────────────────────────\nelevenlabs voices design \"a gruff old lighthouse keeper with a warm tone\" \\\n  --model eleven_ttv_v3 --seed 7 --enhance --output-dir ./previews\nelevenlabs voices save-preview \u003cgenerated_id\u003e \"Lighthouse Keeper\" \"gruff, warm\"\n\n# ── Long-form music from a composition plan ────────────────────────────────\nelevenlabs music plan \"cinematic build then drop\" --length-ms 90000 \u003e plan.json\nelevenlabs music compose --composition-plan plan.json --respect-sections-durations -o track.mp3\n\n# ── Pipe into jq and other tools ──────────────────────────────────────────\nelevenlabs voices list --json | jq '.data[] | select(.category==\"cloned\") | .voice_id'\nelevenlabs history list --source TTS --after $(date -v-7d +%s) --json | jq '.data.history | length'\n```\n\n---\n\n## Commands\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eSpeech synthesis \u0026amp; transcription\u003c/b\u003e\u003c/summary\u003e\n\n```bash\n# Text-to-speech — routes to convert / stream / with-timestamps based on flags\nelevenlabs tts \u003ctext\u003e [-o path] [--voice NAME | --voice-id ID] [--model ID]\n                     [--format mp3_44100_128] [--stability 0.5] [--similarity 0.75]\n                     [--style 0.0] [--speed 1.0] [--speaker-boost true] [--language en]\n                     [--stream]                                  # route to /stream endpoint\n                     [--with-timestamps [--save-timestamps PATH]] # per-character alignment JSON\n                     [--seed 0..4294967295] [--optimize-streaming-latency 0..4]\n                     [--previous-text STR] [--next-text STR]     # continuity across splits\n                     [--previous-request-id ID (repeatable x3)] [--next-request-id ID]\n                     [--apply-text-normalization auto|on|off] [--apply-language-text-normalization]\n                     [--no-logging]                              # zero-retention (enterprise)\n                     [--use-pvc-as-ivc] [--stdout]\n\n# Speech-to-text — default model scribe_v2; character-level timings for karaoke/lyric sync\nelevenlabs stt [FILE] [--from-url URL | --source-url URL]        # local | HTTPS | YouTube/TikTok\n              [-o TEXT_PATH] [--save-raw JSON] [--save-words JSON]\n              [--model scribe_v2|scribe_v1] [--language ISO]\n              [--timestamps none|word|character]                 # 'character' for lyric video sync\n              [--diarize] [--num-speakers 1..32] [--diarization-threshold 0..1]\n              [--detect-speaker-roles]                           # auto-label agent/customer\n              [--audio-events | --no-audio-events] [--no-verbatim]   # no-verbatim = scribe_v2 only\n              [--multi-channel] [--pcm-16k]\n              [--temperature 0..2] [--seed 0..2147483647]\n              [--keyterm WORD (repeatable, up to 1000)]          # vocabulary biasing\n              [--detect-entities TYPE] [--redact-entities TYPE]  # PII: all|pii|phi|pci|...\n              [--redaction-mode redacted|entity_type|enumerated_entity_type]\n              [--format srt|txt|segmented_json|docx|pdf|html (repeatable)]\n              [--format-include-speakers] [--format-include-timestamps]\n              [--format-segment-on-silence S] [--format-max-segment-duration S]\n              [--format-max-segment-chars N] [--format-max-chars-per-line N]\n              [--format-out-dir DIR]\n              [--no-logging] [--webhook [--webhook-id ID] [--webhook-metadata JSON]]\n\n# Sound effects (0.5-30s per official API)\nelevenlabs sfx \u003cprompt\u003e [-o path] [--duration 0.5..30] [--prompt-influence 0.3]\n                       [--loop] [--format mp3_44100_128] [--model eleven_text_to_sound_v2]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eVoices (library, search, clone, design)\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nelevenlabs voices list [--search TERM] [--sort name|created_at_unix] [--direction asc|desc]\n                      [--limit N] [--show-legacy]\nelevenlabs voices show \u003cvoice_id\u003e\nelevenlabs voices search \u003cquery\u003e\n\n# Public shared voice library — page is 1-indexed\nelevenlabs voices library [--search TERM] [--page 1] [--page-size 20]\n                         [--category professional|high_quality|famous]\n                         [--gender female] [--age young|middle_aged|old] [--accent british]\n                         [--language en] [--locale en-US] [--use-case narration]\n                         [--featured] [--min-notice-days N] [--include-custom-rates]\n                         [--include-live-moderated] [--reader-app-enabled]\n                         [--owner-id ID] [--sort cloned_by_count|usage_character_count_1y]\n\nelevenlabs voices clone \u003cname\u003e \u003cfiles...\u003e [--description \"...\"]\n\n# Voice design — per the elevenlabs-js v2.43 SDK schema\nelevenlabs voices design \u003cdescription\u003e [--text \"read this\"] [--output-dir ./previews]\n                        [--model eleven_multilingual_ttv_v2|eleven_ttv_v3]\n                        [--loudness -1.0..1.0] [--seed N] [--guidance-scale F]\n                        [--enhance] [--stream-previews] [--quality F]\n\nelevenlabs voices save-preview \u003cgenerated_voice_id\u003e \u003cname\u003e \u003cdescription\u003e\n\n# Destructive: requires explicit --yes (deletion is irreversible)\nelevenlabs voices delete \u003cvoice_id\u003e --yes    # alias: rm\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eAudio transforms\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nelevenlabs audio isolate \u003cfile\u003e [-o path] [--pcm-16k]\n\n# Speech-to-speech voice conversion — full voice_settings override\nelevenlabs audio convert \u003cfile\u003e [--voice NAME | --voice-id ID] [--model ID] [-o path]\n                               [--format mp3_44100_128]\n                               [--stability 0..1] [--similarity 0..1] [--style 0..1]\n                               [--speaker-boost true|false] [--speed 0.7..1.2]\n                               [--seed N] [--remove-background-noise]\n                               [--optimize-streaming-latency 0..4] [--pcm-16k] [--no-logging]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eMusic generation\u003c/b\u003e\u003c/summary\u003e\n\n```bash\n# length_ms: 3000-600000 per the official API\nelevenlabs music compose [prompt] [--length-ms 3000..600000] [-o path] [--format FMT]\n                        [--composition-plan FILE]          # mutually exclusive with prompt\n                        [--model music_v1] [--seed N] [--force-instrumental]\n                        [--respect-sections-durations] [--store-for-inpainting] [--sign-with-c2pa]\n\nelevenlabs music plan \u003cprompt\u003e [--length-ms 3000..600000] [--model music_v1]\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eConversational AI agents\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nelevenlabs agents list                  # alias: ls\nelevenlabs agents show \u003cagent_id\u003e        # alias: get\nelevenlabs agents create \u003cname\u003e\n    --system-prompt \"...\"\n    [--first-message \"Hi, how can I help?\"]\n    [--voice-id ID] [--language en] [--llm gemini-2.0-flash-001]\n    [--temperature 0.5] [--model-id eleven_turbo_v2]\nelevenlabs agents delete \u003cagent_id\u003e      # alias: rm\nelevenlabs agents add-knowledge \u003cagent_id\u003e \u003cname\u003e (--url URL | --file PATH | --text \"...\")\n\nelevenlabs conversations list [--agent-id ID] [--page-size 30] [--cursor TOKEN]\nelevenlabs conversations show \u003cconversation_id\u003e\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003ePhone calls (outbound via Twilio/SIP)\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nelevenlabs phone list\nelevenlabs phone call \u003cagent_id\u003e --from-id \u003cphone_number_id\u003e --to +14155551234\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cb\u003eUser, history, framework\u003c/b\u003e\u003c/summary\u003e\n\n```bash\nelevenlabs user info\nelevenlabs user subscription\nelevenlabs history list [--page-size 20] [--start-after ID] [--voice-id ID]\n                       [--model-id ID] [--before UNIX] [--after UNIX]\n                       [--sort-direction asc|desc] [--search TERM] [--source TTS|STS]\nelevenlabs history delete \u003cid\u003e\n\nelevenlabs config show | path | set \u003ckey\u003e \u003cvalue\u003e | check | init --api-key sk_...\nelevenlabs skill install | status\nelevenlabs update [--check]\nelevenlabs agent-info          # JSON capability manifest (alias: info)\n```\n\n\u003c/details\u003e\n\n---\n\n## For AI agents\n\nThis CLI is built to be called by autonomous agents. It follows the [Agent CLI Framework](https://github.com/paperfoot/agent-cli-framework) patterns:\n\n- **`agent-info`** returns a complete capability manifest as JSON — no MCP server required, no schema file to fetch.\n- **Dual output**: terminal users get colour + tables, piped/`--json` callers get a stable `{version, status, data|error}` envelope.\n- **Semantic exit codes**: `0=ok, 1=transient, 2=config/auth, 3=bad input, 4=rate limited`. Agents use these to pick retry, fix-and-retry, or escalate.\n- **Errors have suggestions**: every error envelope includes a `suggestion` field with a concrete next command, not vague advice.\n- **No interactive prompts** — every flag has an environment or config fallback. Scripts never hang.\n- **Installable skill**: `elevenlabs skill install` drops `SKILL.md` into `~/.claude/skills/`, `~/.codex/skills/`, and `~/.gemini/skills/` so agents discover the tool automatically.\n\nExample agent usage:\n\n```bash\n# Bootstrap: what can this tool do?\nelevenlabs agent-info | jq '.commands | keys'\n\n# Call it, parse structured output, preserve exit code\nif output=$(elevenlabs tts \"status update\" --json -o /tmp/out.mp3); then\n  path=$(echo \"$output\" | jq -r '.data.output_path')\nelse\n  rc=$?\n  code=$(echo \"$output\" | jq -r '.error.code')         # e.g. auth_failed, rate_limited\n  suggestion=$(echo \"$output\" | jq -r '.error.suggestion')\n  # 1=transient retry, 2=fix config, 3=fix args, 4=wait then retry\n  [ \"$rc\" -eq 4 ] \u0026\u0026 sleep 30 \u0026\u0026 continue\nfi\n```\n\n**Auth model for agents (v0.1.6+)**: run `elevenlabs config init --api-key sk_...` once per machine. The saved key wins over `ELEVENLABS_API_KEY` so a stale env var in some other tool's `.env` never silently breaks your CLI calls. `elevenlabs config show --json` reports which source is in use and whether an env var is set-but-ignored.\n\n---\n\n## Why a CLI instead of an MCP server?\n\nThe [official ElevenLabs MCP server](https://github.com/elevenlabs/elevenlabs-mcp) runs as a stdio subprocess per session, burns context on tool definitions, requires a Python runtime, and drifts from the API. This CLI does the opposite:\n\n|                              | MCP server           | `elevenlabs-cli`              |\n|------------------------------|----------------------|-------------------------------|\n| Install                      | Python, `uvx`, MCP client | Single ~5 MB static binary    |\n| Context cost per tool        | ~550-1400 tokens     | 0 (one shell exec)            |\n| Context cost to bootstrap    | ~55k tokens (typical)| One `agent-info` call         |\n| Scriptable                   | No                   | Yes (pipes, shell, make, CI)  |\n| Works without MCP host       | No                   | Yes                           |\n| Offline from first install   | No (needs runtime)   | Yes                           |\n| Cold start                   | ~200 ms+             | **\u003c10 ms**                    |\n| Memory                       | ~50-80 MB            | **~7 MB**                     |\n\nBenchmarks in the wild: [MCP vs CLI (Scalekit)](https://www.scalekit.com/blog/mcp-vs-cli-use) measured a 32× token overhead for MCP on 75 real tasks. [Speakeasy](https://www.speakeasy.com/blog/how-we-reduced-token-usage-by-100x-dynamic-toolsets-v2) reduced token usage by ~100× by moving agents off MCP onto CLIs. GitHub Copilot [dropped from 40 tools to 13](https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/) and got better results.\n\nLLMs already know how to drive CLIs — the grammar of `tool subcommand --flag value` is baked into their weights. Give them a tool, not a pamphlet about tools.\n\n---\n\n## Configuration\n\nConfig lives in a TOML file at:\n\n| OS      | Path                                                           |\n|---------|----------------------------------------------------------------|\n| macOS   | `~/Library/Application Support/elevenlabs-cli/config.toml`      |\n| Linux   | `~/.config/elevenlabs-cli/config.toml`                         |\n| Windows | `%APPDATA%\\elevenlabs-cli\\config.toml`                         |\n\nExample:\n\n```toml\napi_key = \"sk_...\"\n\n[defaults]\nvoice_id = \"oaGwHLz3csUaSnc2NBD4\"\nmodel_id = \"eleven_multilingual_v2\"\noutput_format = \"mp3_44100_128\"\noutput_dir = \"~/Desktop\"\n\n[update]\nenabled = true\nowner = \"199-biotechnologies\"\nrepo = \"elevenlabs-cli\"\n```\n\n### API-key precedence (v0.1.6+)\n\n1. **`api_key` in config.toml** — the value you explicitly saved with `config init`\n2. `ELEVENLABS_API_KEY` env var — fallback, used when no file key is saved\n3. (none) → `auth_missing` error\n\nWhy file wins over env: a stale `ELEVENLABS_API_KEY` left exported in `~/.zshrc`, a project `.env` file, or a shell session previously used to be silently \"promoted\" over a freshly-saved CLI key and produced confusing `Invalid API key` errors. Now the explicit, scope-specific key you saved via `elevenlabs config init` is always what ships on the wire. CI and container setups are unaffected — they don't ship a `config.toml`, so the env var is still picked up as the only source.\n\nOther flags / env vars still apply in the usual order: explicit command-line flags → config → env → defaults.\n\n\u003e **Upgrading from ≤0.1.5**: if you relied on `ELEVENLABS_API_KEY` in your shell overriding a saved config, either delete the `api_key` line from `config.toml`, or overwrite it with `elevenlabs config set api_key \u003cvalue\u003e`. `elevenlabs config show` now reports which source is being used and calls out the env-var-is-set-but-ignored case.\n\nSecrets are masked in `config show`. The config file is chmod `0600` on Unix.\n\n**Useful env vars**\n\n| Variable | Purpose |\n|---|---|\n| `ELEVENLABS_API_KEY` | API key used as a fallback when `config.toml` has no `api_key`. |\n| `ELEVENLABS_API_BASE_URL` | Override the API base URL (default `https://api.elevenlabs.io`). Use for staging / mock servers. |\n| `ELEVENLABS_CLI_CONFIG` | Full path override for `config.toml`. Handy for tests and CI. |\n\n---\n\n## Output contract\n\n**Success** (stdout, piped or `--json`):\n```json\n{\n  \"version\": \"1\",\n  \"status\": \"success\",\n  \"data\": {\n    \"voice_id\": \"oaGwHLz3csUaSnc2NBD4\",\n    \"output_path\": \"/tmp/hello.mp3\",\n    \"bytes_written\": 46437\n  }\n}\n```\n\n**Error** (stderr, piped or `--json`):\n```json\n{\n  \"version\": \"1\",\n  \"status\": \"error\",\n  \"error\": {\n    \"code\": \"auth_missing\",\n    \"message\": \"API key not configured\",\n    \"suggestion\": \"Set your API key: elevenlabs config init --api-key \u003csk_...\u003e  or: export ELEVENLABS_API_KEY=sk_...\"\n  }\n}\n```\n\n---\n\n## Building from source\n\n```bash\ngit clone https://github.com/paperfoot/elevenlabs-cli\ncd elevenlabs-cli\ncargo build --release\n./target/release/elevenlabs --version\ncargo test\n```\n\nRequires Rust 1.85+ (2024 edition).\n\n---\n\n## Contributing\n\nPRs welcome. Keep commits focused, follow the existing patterns, and run `cargo fmt \u0026\u0026 cargo clippy \u0026\u0026 cargo test` before pushing.\n\n---\n\n## License\n\nMIT © 2026 [199 Biotechnologies](https://github.com/199-biotechnologies). See [LICENSE](LICENSE).\n\n---\n\n\u003cdiv align=\"center\"\u003e\n\nBuilt by [Boris Djordjevic](https://github.com/longevityboris) at [199 Biotechnologies](https://github.com/199-biotechnologies) using the [Agent CLI Framework](https://github.com/paperfoot/agent-cli-framework).\n\n**If this saves you context or setup time:**\n\n[![Star this repo](https://img.shields.io/github/stars/paperfoot/elevenlabs-cli?style=for-the-badge\u0026logo=github\u0026label=%E2%AD%90%20Star%20this%20repo\u0026color=yellow)](https://github.com/paperfoot/elevenlabs-cli/stargazers)\n\u0026nbsp;\n[![Follow @longevityboris](https://img.shields.io/badge/Follow_%40longevityboris-000000?style=for-the-badge\u0026logo=x\u0026logoColor=white)](https://x.com/longevityboris)\n\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaperfoot%2Felevenlabs-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaperfoot%2Felevenlabs-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaperfoot%2Felevenlabs-cli/lists"}