agentsclimarketplace

Elevenlabs local dev loop

Skill ComeOnOliver/skillshub/skills/jeremylongshore/claude-code-plugins-plus-skills/elevenlabs-local-dev-loop

🧠 The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.

Install
npx -y skills add ComeOnOliver/skillshub --skill elevenlabs-local-dev-loop

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Configure local ElevenLabs development with mocking, hot reload, and audio testing. Use when setting up a dev environment for TTS/voice projects, configuring test workflows, or building a fast iteration cycle with ElevenLabs audio. Trigger: "elevenlabs dev setup", "elevenlabs local development", "elevenlabs dev environment", "develop with elevenlabs", "test elevenlabs locally".

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.7 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it

ElevenLabs Local Dev Loop

Overview

Set up a fast, cost-effective local development workflow for ElevenLabs audio projects. Includes SDK mocking to avoid burning character quota during development, audio output testing, and hot-reload patterns.

Prerequisites

  • Completed elevenlabs-install-auth setup
  • Node.js 18+ with npm/pnpm
  • vitest for testing (recommended)

Instructions

Step 1: Project Structure

my-elevenlabs-project/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ elevenlabs/
β”‚   β”‚   β”œβ”€β”€ client.ts       # Singleton client wrapper
β”‚   β”‚   β”œβ”€β”€ config.ts       # Environment-aware config
β”‚   β”‚   └── tts.ts          # TTS service layer
β”‚   └── index.ts
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ __mocks__/
β”‚   β”‚   └── elevenlabs.ts   # SDK mock for free testing
β”‚   β”œβ”€β”€ tts.test.ts
β”‚   └── fixtures/
β”‚       └── sample.mp3      # Known-good audio for comparison
β”œβ”€β”€ output/                  # Generated audio (git-ignored)
β”œβ”€β”€ .env.local               # Local API key (git-ignored)
β”œβ”€β”€ .env.example             # Template for team
└── package.json

Step 2: Environment Configuration

// src/elevenlabs/config.ts
export interface ElevenLabsConfig {
  apiKey: string;
  modelId: string;
  defaultVoiceId: string;
  outputFormat: string;
}

export function loadConfig(): ElevenLabsConfig {
  const env = process.env.NODE_ENV || "development";

  return {
    apiKey: process.env.ELEVENLABS_API_KEY || "",
    // Use cheaper/faster model in dev, high-quality in prod
    modelId: env === "production"
      ? "eleven_multilingual_v2"    // 1.0 credits/char, best quality
      : "eleven_flash_v2_5",       // 0.5 credits/char, ~75ms latency
    defaultVoiceId: process.env.ELEVENLABS_VOICE_ID || "21m00Tcm4TlvDq8ikWAM",
    outputFormat: "mp3_22050_32",  // Smaller files for dev
  };
}

Step 3: Mock the SDK for Unit Tests

// tests/__mocks__/elevenlabs.ts
// Avoids API calls (and character charges) during testing
import { vi } from "vitest";
import { readFileSync } from "fs";

const sampleAudio = readFileSync("tests/fixtures/sample.mp3");

export const mockElevenLabsClient = {
  textToSpeech: {
    convert: vi.fn().mockResolvedValue(
      new ReadableStream({
        start(controller) {
          controller.enqueue(sampleAudio);
          controller.close();
        },
      })
    ),
    stream: vi.fn().mockImplementation(async function* () {
      yield sampleAudio.subarray(0, 1024);
      yield sampleAudio.subarray(1024);
    }),
  },
  voices: {
    getAll: vi.fn().mockResolvedValue({
      voices: [
        { voice_id: "21m00Tcm4TlvDq8ikWAM", name: "Rachel" },
        { voice_id: "ErXwobaYiN019PkySvjV", name: "Antoni" },
      ],
    }),
  },
  user: {
    get: vi.fn().mockResolvedValue({
      subscription: {
        tier: "free",
        character_count: 500,
        character_limit: 10000,
      },
    }),
  },
};

Step 4: Development Scripts

{
  "scripts": {
    "dev": "tsx watch src/index.ts",
    "test": "vitest",
    "test:watch": "vitest --watch",
    "test:integration": "ELEVENLABS_INTEGRATION=1 vitest run tests/integration/",
    "generate": "tsx src/generate.ts",
    "quota": "tsx src/check-quota.ts"
  }
}

Step 5: Quota-Aware Development

// src/check-quota.ts β€” run before integration tests
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";

const client = new ElevenLabsClient();

async function checkQuota() {
  const user = await client.user.get();
  const { character_count, character_limit } = user.subscription;
  const remaining = character_limit - character_count;
  const pct = ((character_count / character_limit) * 100).toFixed(1);

  console.log(`Characters: ${character_count.toLocaleString()} / ${character_limit.toLocaleString()} (${pct}% used)`);
  console.log(`Remaining: ${remaining.toLocaleString()} characters`);

  if (remaining < 1000) {
    console.warn("WARNING: Low character quota. Use mocks for development.");
    process.exit(1);
  }
}

checkQuota().catch(console.error);

Step 6: Integration Test Guard

// tests/tts.test.ts
import { describe, it, expect, vi, beforeAll } from "vitest";
import { mockElevenLabsClient } from "./__mocks__/elevenlabs";

// Only hit real API when explicitly enabled
const useRealApi = process.env.ELEVENLABS_INTEGRATION === "1";

describe("TTS Service", () => {
  it("should generate audio from text (mocked)", async () => {
    const audio = await mockElevenLabsClient.textToSpeech.convert(
      "21m00Tcm4TlvDq8ikWAM",
      { text: "Test speech", model_id: "eleven_flash_v2_5" }
    );
    expect(audio).toBeDefined();
  });

  it.skipIf(!useRealApi)("should generate real audio (integration)", async () => {
    const { ElevenLabsClient } = await import("@elevenlabs/elevenlabs-js");
    const client = new ElevenLabsClient();
    const audio = await client.textToSpeech.convert("21m00Tcm4TlvDq8ikWAM", {
      text: "Integration test.",
      model_id: "eleven_flash_v2_5",
    });
    expect(audio).toBeDefined();
  });
});

Output

  • Working development environment with hot reload via tsx watch
  • Mock layer that avoids API calls and character charges during dev
  • Quota checker to prevent surprise billing
  • Integration test guard pattern (ELEVENLABS_INTEGRATION=1)
  • Environment-aware model selection (cheap in dev, quality in prod)

Error Handling

ErrorCauseSolution
MODULE_NOT_FOUNDSDK not installednpm install @elevenlabs/elevenlabs-js
Mock returns undefinedMock not wiredCheck vi.mock path matches import
Integration test failsNo API keySet ELEVENLABS_API_KEY in .env.local
Quota exceeded in devRunning real API callsUse mock layer; run npm run quota first

Resources

Next Steps

See elevenlabs-sdk-patterns for production-ready code patterns.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 327,132. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.