Chatter
A Rust CLI tool that wraps Qwen3-TTS from Hugging Face to provide text-to-speech capabilities with voice profile management. Users can design custom voices from natural language descriptions, clone voices from audio samples, and generate speech from text or documents — all from the terminal with progress feedback.
Core Value: Users can create reusable voice profiles and generate high-quality speech from text or documents without leaving the command line.
- Tech stack: Rust CLI with PyO3 for Python interop — required because model is Python-only
- Hardware: Apple Silicon (MLX/MPS) or CUDA-capable GPU required for local inference
- Distribution:
brew install chattermust work out of the box. Chatter manages its own Python venv at~/.local/share/chatter/venv/with auto-setup on first run. Users do NOT manually install Python packages. - Dependencies: Python 3.13 runtime (Homebrew formula declares
depends_on "python@3.13").qwen-ttsis auto-installed into the managed venv on first run. Python 3.13 aligns ChatterBox (chatterbox-tts) with NumPy 2.x pins (PyPI allows NumPy 2.x only for Python ≥3.13). - Audio: MP3 output (requires encoding from WAV produced by model)
| Technology | Version | Purpose | Why | Confidence |
|---|---|---|---|---|
| Rust (edition 2024) | 1.85+ | Language | Systems-level performance, strong type system, excellent CLI ecosystem. PyO3 0.28 requires Rust >= 1.83. | HIGH |
| PyO3 | 0.28.2 | Python embedding | The only mature Rust-Python interop crate. Actively maintained (released 2026-02-18). Enables calling qwen_tts Python package directly from Rust without subprocess overhead. Use auto-initialize feature. |
HIGH |
| clap | 4.5+ | CLI argument parsing | De facto standard for Rust CLIs. Derive macro API eliminates boilerplate. Powers ripgrep, bat, fd. | HIGH |
| Technology | Version | Purpose | Why | Confidence |
|---|---|---|---|---|
| hound | 3.5.1 | WAV reading | Standard Rust WAV library. 7.5M+ downloads. Reads WAV output from qwen-tts model inference before MP3 encoding. | HIGH |
| mp3lame-encoder | 0.2.2 | WAV-to-MP3 encoding | High-level safe Rust bindings to LAME. Statically links LAME so no runtime dependency. The most ergonomic MP3 encoding option in Rust. | MEDIUM |
| Technology | Version | Purpose | Why | Confidence |
|---|---|---|---|---|
| pdf-extract | 0.10.0 | PDF text extraction | Purpose-built for text extraction (not PDF manipulation). Simpler API than lopdf for our read-only use case. | MEDIUM |
| pulldown-cmark | 0.13.3 | Markdown parsing | CommonMark-compliant, streaming parser. Very fast, no AST allocation needed -- we just need to strip markup and extract plain text. Released 2026-03-22. | HIGH |
| Technology | Version | Purpose | Why | Confidence |
|---|---|---|---|---|
| indicatif | 0.18.4 | Progress bars | The standard Rust progress bar library. Supports bounded bars (file processing) and spinners (model loading). MultiProgress for concurrent operations. Released 2026-02-14. | HIGH |
| console | 0.15+ | Terminal utilities | Sister crate to indicatif (same console-rs org). Handles terminal width detection, styling, and ANSI support. |
HIGH |
| owo-colors | 4.x | Colored output | Zero-allocation, no_std-compatible terminal coloring. Respects NO_COLOR/FORCE_COLOR env vars. Recommended by Rust CLI best practices guide over colored crate. |
HIGH |
| Technology | Version | Purpose | Why | Confidence |
|---|---|---|---|---|
| serde | 1.x | Serialization framework | De facto standard. Required by every config/data format crate. Use derive feature. |
HIGH |
| serde_json | 1.x | JSON serialization | Voice profile metadata storage format. Human-readable, easy to debug. | HIGH |
| toml | 0.8+ | TOML config files | Optional: if app-level config is needed beyond voice profiles. Idiomatic in Rust ecosystem. | HIGH |
| directories | 6.0.0 | XDG directory paths | Cross-platform (Linux/macOS/Windows) standard directory resolution. Returns ~/.config/chatter/ on Linux, ~/Library/Application Support/ on macOS. Actively maintained under xdg-rs org. |
HIGH |
| Technology | Version | Purpose | Why | Confidence |
|---|---|---|---|---|
| anyhow | 1.x | Application error handling | For main.rs and top-level CLI code. Ergonomic error context with .context(). Standard for Rust CLI apps. |
HIGH |
| thiserror | 2.x | Typed error definitions | For internal library modules (PyO3 bridge, audio encoding). Gives callers structured error types to match on. | HIGH |
| Technology | Version | Purpose | Why | Confidence |
|---|---|---|---|---|
| Python | 3.13 | Runtime for qwen-tts + ChatterBox | Shared venv uses NumPy 2.3 with SciPy 1.16; chatterbox-tts requires Python 3.13+ for NumPy 2.x. PyO3 0.28 supports CPython 3.7+. |
HIGH |
| qwen-tts | 0.1.1 | TTS model inference | Official Python package from Qwen team. Wraps Qwen3-TTS models. Depends on PyTorch, transformers, soundfile. | HIGH |
| Category | Recommended | Alternative | Why Not |
|---|---|---|---|
| Python interop | PyO3 (embedding) | std::process::Command (subprocess) |
Subprocess has higher latency per call, no shared state between calls, harder error handling, no progress callbacks. PyO3 keeps Python alive in-process. |
| Python interop | PyO3 (embedding) | Rewrite model inference in Rust | Qwen3-TTS depends on PyTorch + transformers. Rewriting in Rust would be a massive effort with no clear benefit. |
| MP3 encoding | mp3lame-encoder | symphonia |
Symphonia is primarily a decoder. No MP3 encoding support. |
| MP3 encoding | mp3lame-encoder | FFmpeg subprocess | External dependency, harder to distribute, more failure modes. LAME static linking is cleaner. |
| PDF parsing | pdf-extract | lopdf | lopdf is a PDF manipulation library (read/write/edit). We only need text extraction. pdf-extract is purpose-built for this. |
| PDF parsing | pdf-extract | pdf-rs/pdf |
Less mature, fewer downloads. pdf-extract is the established choice for text extraction. |
| Markdown parsing | pulldown-cmark | comrak | comrak builds a full AST and supports GFM extensions. We only need to strip markup to get plain text -- pulldown-cmark's streaming approach is lighter and faster. |
| Progress bars | indicatif | pbr |
pbr is unmaintained. indicatif is the ecosystem standard. |
| Colored output | owo-colors | colored |
colored allocates strings. owo-colors is zero-allocation and respects NO_COLOR standard. |
| Directory paths | directories | dirs |
dirs is the low-level sibling. directories provides ProjectDirs which gives us app-scoped paths (config, data, cache) in one call. |
| Config format | JSON (serde_json) | TOML / YAML | Voice profiles are data, not human-edited config. JSON is simpler, universally understood, and has the best tooling. TOML for app config if needed later. |
- System must have Python 3.13 development headers (
python3-devon Ubuntu) pyo3-build-config(transitive dep) auto-detects Python at build time- Set
PYO3_PYTHON=python3.13env var if multiple Python versions installed
| Technology | Why Not |
|---|---|
tokio / async-std |
This is a synchronous CLI tool. Model inference is blocking (GPU-bound). Async adds complexity with zero benefit here. |
reqwest / ureq |
No network requests needed. Local-only inference, local profiles. |
rusqlite / sqlx |
Profiles are individual JSON files, not a database. SQLite is overkill for < 100 profiles. |
crossterm / ratatui |
No TUI needed. This is a straightforward CLI, not an interactive terminal app. |
rodio / cpal |
No audio playback. Generate-to-file only (out of scope per PROJECT.md). |
image / resvg |
No image processing needed. |
| Python virtualenv management | Out of scope. User is responsible for having qwen-tts installed. Document the prerequisite, don't automate it. |
- PyO3 0.28.2 on docs.rs - Verified version 0.28.2 (2026-02-18)
- PyO3 User Guide - Embedding patterns, auto-initialize feature
- PyO3 GitHub - Rust 1.83+ requirement
- clap on crates.io - CLI framework
- indicatif 0.18.4 on docs.rs - Verified version (2026-02-14)
- mp3lame-encoder on crates.io - MP3 encoding
- pdf-extract 0.10.0 on docs.rs - Verified version (2025-10-03)
- pulldown-cmark 0.13.3 on docs.rs - Verified version (2026-03-22)
- directories 6.0.0 on docs.rs - Verified version (2025-01-12)
- hound 3.5.1 on docs.rs - WAV library
- qwen-tts 0.1.1 on PyPI - Verified version (2026-02-06)
- Qwen3-TTS GitHub - Model documentation
- owo-colors on lib.rs - Terminal coloring
- Rain's Rust CLI Recommendations - Color management best practices
- anyhow / thiserror best practices - Error handling patterns
Conventions not yet established. Will populate as patterns emerge during development.
Architecture not yet mapped. Follow existing patterns found in the codebase.
Before using Edit, Write, or other file-changing tools, start work through a GSD command so planning artifacts and execution context stay in sync.
Use these entry points:
/gsd:quickfor small fixes, doc updates, and ad-hoc tasks/gsd:debugfor investigation and bug fixing/gsd:execute-phasefor planned phase work
Do not make direct repo edits outside a GSD workflow unless the user explicitly asks to bypass it.
Profile not yet configured. Run
/gsd:profile-userto generate your developer profile. This section is managed bygenerate-claude-profile-- do not edit manually.