> ## Documentation Index
> Fetch the complete documentation index at: https://docs.60db.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Codex Skills

> Drop 60db voice into Claude Code, OpenAI Codex, OpenCode, or any agent with a skills directory — triggered by /60db.

# 60db Agent Skills

Bring 60db's full voice stack — **text-to-speech, speech-to-text, voice cloning, voice management, and the LLM core** — directly into your coding agent. Install it once and call it with `/60db` from [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [OpenAI Codex](https://developers.openai.com/codex), [OpenCode](https://opencode.ai), or any agent that reads a skills directory.

It's a single **zero-dependency** Python CLI (stdlib only, Python 3.8+) — no SDK, no `pip install`, no version drift.

<CardGroup cols={3}>
  <Card title="Claude Code" icon="comments" color="#4A3228">
    Native skill — `/60db` and `/setup-60db`
  </Card>

  <Card title="OpenAI Codex" icon="robot" color="#4A3228">
    Same skill folders, copied into `~/.codex/skills`
  </Card>

  <Card title="OpenCode & others" icon="terminal" color="#4A3228">
    Plain markdown + stdlib Python runs anywhere
  </Card>
</CardGroup>

<Info>
  Source repository: [github.com/60db-ai/60db.ai-skills](https://github.com/60db-ai/60db.ai-skills) — Apache-2.0.
</Info>

***

## Why a Skill, Not Just the SDK

The skill **encodes the behavior that's actually true** against the live API, so you never relearn the gotchas. It's stdlib-only, so it keeps working regardless of SDK or doc drift. The five mistakes it pins for you:

<AccordionGroup>
  <Accordion title="REST /tts-synthesize returns NDJSON, not one JSON blob">
    Concatenate each line's `result.audioContent` (base64 LINEAR16 PCM). The CLI does this for you.
  </Accordion>

  <Accordion title="Only 8000 / 16000 / 24000 / 48000 Hz are accepted">
    `44100` is rejected with a `400`.
  </Accordion>

  <Accordion title="The output_format flag is ignored">
    The API always returns raw PCM — wrap it as WAV yourself (the CLI does).
  </Accordion>

  <Accordion title="Sample rate ≠ fidelity">
    The model is band-limited at \~8 kHz, so 48 kHz is upsampled headroom. `enhance` and `60db-quality` do not raise the ceiling.
  </Accordion>

  <Accordion title="The voice id field is voice_id, not id">
    Language and gender live under `labels` — confirmed by live inspection.
  </Accordion>
</AccordionGroup>

***

## How It Works

One CLI — `skills/60db/scripts/sixtydb.py` — fronts every 60db use case against `https://api.60db.ai`.

```
/60db
  1. Setup once     →  user runs `init`: hidden key prompt → config (mode 600)
  2. Ask if unclear →  prompt for: use case · voice · model · kHz · format
  3. Route          →  tts / stt / voices / clone / chat / langs / doctor
  4. Verify         →  `doctor` reports key presence + resolved defaults (never the key)
```

Every setting resolves the same way, so you can override per-call or store defaults once:

```
CLI flag  >  env SIXTYDB_*  >  config file  >  built-in default
```

<Note>
  **Setup is the user's job.** The API key is never typed by the agent, never passed on the command line, never printed, never committed. The user runs `init` (a hidden prompt) or sets `SIXTYDB_API_KEY`. In a chat session where a hidden prompt isn't reachable, the agent scaffolds defaults with `init --no-key` and hands the key step back to the user.
</Note>

***

## Use Cases

What you can build with `/60db` without leaving your coding agent:

<CardGroup cols={2}>
  <Card title="Narration & voiceovers" icon="microphone" color="#4A3228">
    Turn a script, blog post, or `.txt` file into studio-quality audio for videos, podcasts, or demos — `tts script.txt --voice <id> --out vo.wav`.
  </Card>

  <Card title="Transcription & subtitles" icon="closed-captioning" color="#4A3228">
    Convert recordings, calls, or meetings into text with speaker labels and word timings, then build SRT/VTT — `stt rec.mp4 --diarize --timestamps --json`.
  </Card>

  <Card title="Voice agents & bots" icon="robot" color="#4A3228">
    Wire `stt` (ears) + `chat` (brain) + `tts` (mouth) into a conversational loop for support, reception, or IVR-style flows.
  </Card>

  <Card title="Custom brand voices" icon="user-pen" color="#4A3228">
    Clone a voice from a few samples and reuse it across all your audio — `clone --name "Brand VO" --sample a.wav --sample b.wav`.
  </Card>

  <Card title="Accessibility" icon="universal-access" color="#4A3228">
    Add read-aloud audio to docs, articles, and apps for visually impaired or on-the-go users.
  </Card>

  <Card title="Multilingual content" icon="language" color="#4A3228">
    Generate speech and transcribe audio across 30+ languages — check `langs` / `langs --stt` for coverage.
  </Card>
</CardGroup>

### Who it's for

<AccordionGroup>
  <Accordion title="Developers building voice features">
    Add TTS/STT to an app without learning the SDK or fighting the docs — the skill drives one stdlib-only CLI that already pins the API's real behavior.
  </Accordion>

  <Accordion title="Creators & content teams">
    Produce voiceovers and dubbed audio straight from a script file, with a consistent brand voice via cloning.
  </Accordion>

  <Accordion title="Support & operations teams">
    Prototype phone/voice bots from the `stt + chat + tts` parts, and transcribe call recordings for QA or summaries.
  </Accordion>

  <Accordion title="Anyone in a coding agent">
    If you live in Claude Code, Codex, or OpenCode, `/60db` lets you ship audio without context-switching to a dashboard or another tool.
  </Accordion>
</AccordionGroup>

### A typical workflow

<Steps>
  <Step title="Set up once">
    Run `/setup-60db` to store your API key and defaults (voice, model, sample rate).
  </Step>

  <Step title="Pick a voice">
    Run `voices` to list available voice IDs (add `--mine` for your cloned voices).
  </Step>

  <Step title="Generate or transcribe">
    Call `tts` to make audio or `stt` to make text — the skill asks for anything it needs.
  </Step>

  <Step title="Iterate or chain">
    Adjust `--speed` / `--stability`, or chain `stt → chat → tts` for a full voice-agent turn.
  </Step>
</Steps>

***

## The Two Skills

| Skill          | Trigger       | What it does                                                               |
| -------------- | ------------- | -------------------------------------------------------------------------- |
| **60db**       | `/60db`       | The worker — routes every voice use case to the CLI                        |
| **setup-60db** | `/setup-60db` | First-run onboarding: collects the key privately, picks defaults, verifies |

The worker drives one CLI with **9 subcommands**:

| Subcommand     | What it does                                                           | Status                   |
| -------------- | ---------------------------------------------------------------------- | ------------------------ |
| `init`         | Hidden key prompt → config (mode 600); `--no-key` stores defaults only | ✅                        |
| `doctor`       | Diagnose setup — key presence (never revealed), resolved defaults      | ✅                        |
| `tts`          | Text or `.txt` → WAV (REST NDJSON; `--ws` for legacy WebSocket)        | ✅ verified               |
| `stt`          | Audio → transcript (`--diarize`, `--timestamps`, `--json`)             | ✅ verified               |
| `voices`       | List voice ids (built-in + your cloned), `--mine`, `--json`            | ✅ verified               |
| `clone`        | Train a new voice from samples (`--sample` / `--sample-url`)           | ⚠️ doc-only — test first |
| `delete-voice` | Hard-delete one of your custom voices                                  | ⚠️ doc-only              |
| `langs`        | Supported languages (`--stt` for STT's 39)                             | ✅                        |
| `chat`         | LLM core (`60db-tiny`) you pair with stt+tts for a voice agent         | documented               |

***

## Install

<Steps>
  <Step title="Add the skill">
    **Claude Code (recommended):**

    ```bash theme={null}
    npx skills add 60db-ai/60db.ai-skills
    ```

    **Codex / OpenCode / other agents** — copy the two skill folders into that agent's skills directory:

    ```bash theme={null}
    git clone https://github.com/60db-ai/60db.ai-skills.git
    cp -r 60db.ai-skills/skills/60db 60db.ai-skills/skills/setup-60db ~/.codex/skills/
    ```
  </Step>

  <Step title="Restart your agent session">
    Skills are only picked up on session start — this is an agent-platform limitation, not a bug.
  </Step>

  <Step title="Run setup once">
    Run `/setup-60db`, or directly:

    ```bash theme={null}
    E=skills/60db/scripts/sixtydb.py
    python3 $E init      # hidden prompt for your API key → config (mode 600)
    python3 $E doctor    # verify (reports key presence without revealing it)
    ```

    Get a key at **app.60db.ai → Settings → Developer → API Keys**.
  </Step>
</Steps>

<Warning>
  The API key is **yours to enter** — never paste it into the agent chat (chat history is retained by the platform). It's stored locally at `~/.config/60db/config.json` (mode 600) or read from `SIXTYDB_API_KEY`, and `.gitignore` keeps it out of git.
</Warning>

***

## Run It

```bash theme={null}
E=skills/60db/scripts/sixtydb.py

python3 $E tts "Hello there." --out out/hello.wav        # text → WAV (48 kHz, 60db-quality)
python3 $E tts script.txt --voice <id> --out out/vo.wav
python3 $E stt recording.mp3 --diarize --timestamps      # audio → transcript
python3 $E voices                                        # list voice ids
python3 $E langs --stt                                    # 39 STT languages
python3 $E chat "One-line summary of attachment theory."  # LLM core for agents
python3 $E doctor                                        # diagnose setup
```

Store defaults once so you stop repeating flags:

```bash theme={null}
python3 $E init --no-key --voice <id> --model 60db-quality --sample-rate 48000
```

***

***

## Quick Decision Guide

| I want to...                             | Use                                                                    |
| ---------------------------------------- | ---------------------------------------------------------------------- |
| Narration / voiceover from text          | `tts "..." --out out/vo.wav`                                           |
| Read a script file aloud                 | `tts script.txt --voice <id> --out out/vo.wav`                         |
| Transcribe audio with speaker labels     | `stt rec.mp3 --diarize --timestamps`                                   |
| See which voices I can use               | `voices` (then `voices --mine`)                                        |
| Use a specific language                  | `langs` / `langs --stt`                                                |
| Clone my own brand voice                 | `clone --name "Brand VO" --sample a.wav --sample b.wav` *(test first)* |
| Build a phone/voice bot                  | `chat` as the brain + `stt` ears + `tts` mouth                         |
| Figure out why audio sounds "compressed" | `doctor` → troubleshooting                                             |
| Set up for the first time                | `/setup-60db`                                                          |

***

## Examples

<CodeGroup>
  ```bash Voiceover from text theme={null}
  python3 $E tts "Welcome to the show." --voice <id> --out out/intro.wav
  # wrote out/intro.wav  (412160 B PCM, ~4.3s @ 48000Hz, REST, model=60db-quality)
  ```

  ```bash Narrate a script file theme={null}
  python3 $E tts episode.txt --voice <id> --out out/ep.wav --speed 0.95 --stability 65
  ```

  ```bash Transcribe with speakers + timings theme={null}
  python3 $E stt interview.m4a --diarize --timestamps --out interview.txt
  # [English, 42.7s] So the first thing we noticed was the latency...
  ```

  ```bash Structured JSON for subtitles theme={null}
  python3 $E stt talk.mp4 --timestamps --confidence --json > talk.json
  # talk.json → words[] each with {word, start, end} → build SRT/VTT
  ```

  ```bash One voice-agent turn: ears → brain → mouth theme={null}
  USER=$(python3 $E stt caller.wav --json | python3 -c 'import json,sys;print(json.load(sys.stdin)["text"])')
  REPLY=$(python3 $E chat "$USER" --system "Concise support agent." --chat-id call-42 | head -1)
  python3 $E tts "$REPLY" --voice <id> --out out/reply.wav
  ```
</CodeGroup>

***

## Gotchas That Bite Everyone

| Symptom                           | Cause                                               | Fix                                                                |
| --------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------ |
| Audio sounds a touch "compressed" | Model is \~16 kHz-native, band-limited to \~8 kHz   | Expected; `enhance` / `60db-quality` don't lift it                 |
| Garbled / truncated audio         | REST returns **NDJSON**, not one JSON blob          | Concatenate every line's `result.audioContent` (the CLI does this) |
| `400` on synthesize               | Sample rate `44100` (or anything off-menu)          | Use `8000 / 16000 / 24000 / 48000` only                            |
| Format flag seems ignored         | `output_format` **is** ignored — always raw PCM     | Wrap the PCM as WAV yourself (the CLI does)                        |
| Long script cut off               | TTS caps at **5000 chars** per request              | Split, synthesize, concatenate WAVs                                |
| `voices` prints `None` for the id | Field is `voice_id`; language/gender under `labels` | The CLI already handles this                                       |
| `no API key found`                | Key not in config or env                            | Run `init`, or export `SIXTYDB_API_KEY`                            |

***

## Coverage

| Use case                           | Command        | Status                             |
| ---------------------------------- | -------------- | ---------------------------------- |
| Text-to-speech (REST + WS)         | `tts`          | ✅ verified                         |
| Speech-to-text (batch + streaming) | `stt`          | ✅ endpoint verified                |
| List voices                        | `voices`       | ✅ verified (`voice_id` / `labels`) |
| Voice cloning                      | `clone`        | ⚠️ doc-only — test first           |
| Update / delete voice              | `delete-voice` | ⚠️ doc-only                        |
| Languages                          | `langs`        | ✅                                  |
| LLM chat (voice-agent core)        | `chat`         | documented; no native calling API  |

***

## How It Helps

<CardGroup cols={2}>
  <Card title="Zero setup friction" icon="bolt" color="#4A3228">
    Stdlib-only Python — no SDK, no `requests`, no version drift. Only `python3` 3.8+ required.
  </Card>

  <Card title="Truth over docs" icon="shield-check" color="#4A3228">
    Every endpoint is annotated verified vs. doc-only; live-API findings win over the published docs.
  </Card>

  <Card title="Voice agents from parts" icon="phone" color="#4A3228">
    No native telephony API — build a voice agent from `stt` (ears) + `chat` (brain) + `tts` (mouth).
  </Card>

  <Card title="Secure by design" icon="lock" color="#4A3228">
    The key is never typed by the agent, never printed, never committed.
  </Card>
</CardGroup>

***

## FAQ

<AccordionGroup>
  <Accordion title="How do I install it the fastest way?">
    `npx skills add 60db-ai/60db.ai-skills`, then restart your agent and run `/setup-60db`.
  </Accordion>

  <Accordion title="Where does my API key go? Is it safe?">
    Into a local config at `~/.config/60db/config.json` (mode 600), or the `SIXTYDB_API_KEY` env var. It's never passed on the command line, never printed, and `.gitignore` keeps it out of git. The agent never types it for you.
  </Accordion>

  <Accordion title="My voice sounds slightly compressed at 48 kHz. Bug?">
    No. The model is \~16 kHz-native and band-limited to \~8 kHz, so 48 kHz is upsampled headroom. `enhance` and `60db-quality` don't raise the ceiling.
  </Accordion>

  <Accordion title="Which sample rates are allowed?">
    `8000`, `16000`, `24000`, `48000` only. `44100` is rejected.
  </Accordion>

  <Accordion title="Can 60db make or receive phone calls?">
    There is no native calling/telephony API. You build a voice agent from the parts: `stt` (ears) + `chat` (brain, `60db-tiny`) + `tts` (mouth).
  </Accordion>

  <Accordion title="Does it work outside Claude Code?">
    Yes — it's markdown + stdlib Python. Copy the two skill folders into Codex's or OpenCode's skills directory. Only the onboarding prompt is Claude-specific and degrades gracefully.
  </Accordion>

  <Accordion title="Do I need the SDK or requests?">
    No. Only `python3` 3.8+. The single optional dependency is `websockets`, used solely by the legacy `--ws` TTS path.
  </Accordion>
</AccordionGroup>

<Note>
  Full command reference, recipes, and the complete troubleshooting list live in the repo's [GUIDE.md](https://github.com/60db-ai/60db.ai-skills/blob/main/GUIDE.md) and [references/](https://github.com/60db-ai/60db.ai-skills/tree/main/skills/60db/references).
</Note>
