Skip to main content

SDK-first Discord bot with chat, shitposts, and voice pipeline.

Project description

Clanker9000

SDK-first Discord bot with chat, voice pipeline, shitposts, and a standalone CLI.

Clanker9000 separates a reusable SDK (clanker) from its Discord host (clanker_bot). Build multi-personality bots with LLM chat, voice transcription, TTS output, and meme generation — all with pluggable provider abstractions. Use the SDK standalone via the CLI without any Discord infrastructure.

Features

  • Multi-Persona Support - YAML-configured bot personalities with custom system prompts and voice settings
  • Voice Pipeline - Real-time voice activity detection (Silero VAD), chunking, idle flush, and speech-to-text
  • Voice Resilience - Keepalive packets, automatic reconnection, and actor-based voice management
  • CLI Interface - Chat, speak, transcribe, and generate memes from the command line
  • Provider Architecture - Pluggable adapters for LLM (OpenAI, Anthropic), STT (Whisper), TTS (ElevenLabs), and image generation (Memegen)
  • Shitpost Generator - Context-aware meme generation with ephemeral preview/post/regenerate workflow
  • VC Monitoring - Auto-leave when alone, nudge-to-join when humans gather
  • Feedback Persistence - Track user interactions (accepted/rejected/regenerated) with SQLite via sqlc
  • Structured Logging - File-based rotation, JSON format, voice-specific log levels

Discord Commands

Command Description
/chat <prompt> Chat with Clanker
/speak <prompt> Chat with TTS audio response
/shitpost [n] [guidance] Generate meme previews with Post/Regenerate/Dismiss buttons
/join Join your voice channel for transcription
/leave Leave the current voice channel
/transcript Show recent voice transcripts (ephemeral)

CLI Commands

clanker chat "What is the meaning of life?"    # Chat with the LLM
clanker speak "Hello world" -o hello.mp3       # Generate TTS audio
clanker transcribe audio.wav                   # Transcribe audio file
clanker shitpost --guidance "programming"       # Generate a shitpost
clanker meme --guidance "cats"                  # Generate a meme image
clanker config show                            # Show active configuration

Use --config path/to/config.yaml and --persona <id> to control persona selection.

Installation

Prerequisites

  • Python 3.12+
  • uv package manager

Install from GitHub

# Install the CLI tool (lightweight — SDK + CLI only)
uv tool install git+https://github.com/safurrier/clanker.git

# Install as a library
uv pip install git+https://github.com/safurrier/clanker.git

# Install with Discord bot support
uv pip install "clanker9000[bot] @ git+https://github.com/safurrier/clanker.git"

# Install with everything (bot + voice)
uv pip install "clanker9000[bot,voice] @ git+https://github.com/safurrier/clanker.git"

Local Development Setup

# Install all dependencies (including bot, voice, dev)
make setup

# Run quality checks
make check

Environment Variables

# Required for LLM and STT (when using OpenAI provider)
export OPENAI_API_KEY="sk-..."

# Required for LLM (when using Anthropic provider)
export ANTHROPIC_API_KEY="sk-ant-..."

# Required for Discord bot
export DISCORD_TOKEN="..."

# Required for TTS
export ELEVENLABS_API_KEY="..."

# Optional
export CLANKER_CONFIG_PATH="./config.yaml"   # Custom config path
export VOICE_DEBUG=1                          # Enable voice debug capture
export VOICE_DEBUG_DIR="./voice_debug"        # Debug output directory
export LOG_DIR="./logs"                       # Enable file logging (JSON, rotated)
export LOG_LEVEL="INFO"                       # Base log level
export VOICE_LOG_LEVEL="INFO"                 # Voice-specific log level
export DATABASE_URL="sqlite:///data/clanker.db"  # Database path
export USE_VOICE_ACTOR=1                      # Enable actor-based voice management

Quick Start

SDK Usage

from clanker.models import Context, Message, Persona
from clanker.providers.openai.llm import OpenAILLM
from clanker.respond import respond

# Create a persona
persona = Persona(
    id="assistant",
    display_name="Helper",
    system_prompt="You are a helpful assistant.",
)

# Build context
context = Context(
    request_id="req-001",
    user_id=0,
    guild_id=None,
    channel_id=0,
    persona=persona,
    messages=[Message(role="user", content="Hello!")],
    metadata={},
)

# Generate response
llm = OpenAILLM(api_key="sk-...")
response, audio = await respond(context, llm=llm)
print(response.content)

Voice Transcription

from clanker.providers.openai.stt import OpenAISTT

stt = OpenAISTT(api_key="sk-...")

with open("audio.wav", "rb") as f:
    audio_bytes = f.read()

transcript = await stt.transcribe(audio_bytes)
print(transcript)

Run the Discord Bot

Requires the [bot] extra (included by make setup):

make run

# Or directly:
python -m clanker_bot.main

# With custom config:
CLANKER_CONFIG_PATH=./my-config.yaml make run

Configuration

Create a config.yaml file:

providers:
  llm: openai    # or: anthropic
  stt: openai
  tts: elevenlabs
  image: memegen

personas:
  - id: clanker
    display_name: Clanker9000
    system_prompt: |
      You are Clanker9000, a witty and slightly sarcastic Discord bot.
      Keep responses concise and entertaining.
    tts_voice: "Rachel"

  - id: helper
    display_name: Helper Bot
    system_prompt: |
      You are a helpful assistant. Be clear and informative.
    tts_voice: "Alice"

default_persona: clanker

Project Structure

src/
  clanker/                  # Core SDK (no Discord dependencies)
    config/                 # Configuration loading (YAML)
    providers/              # Pluggable provider adapters
      openai/               # LLM (GPT) and STT (Whisper)
      anthropic/            # LLM (Claude)
      elevenlabs/           # TTS
      memegen/              # Meme image generation
      audio_utils.py        # Stereo-to-mono, resampling
      base.py               # Protocol definitions (LLM, STT, TTS, ImageGen)
      factory.py            # Provider construction with lazy env-var resolution
    shitposts/              # Template-based meme content generation
    voice/                  # Voice processing pipeline
      vad.py                # Voice activity detection (Silero/Energy)
      chunker.py            # Audio chunking with idle flush
      formats.py            # AudioFormat abstraction
      worker.py             # Transcription orchestration
      debug/                # Debug capture system
    models.py               # Domain models (Context, Persona, Message)
    respond.py              # Core response orchestration

  clanker_cli/              # Click-based CLI (consumes SDK)
    commands/               # chat, speak, transcribe, shitpost, meme, config
    main.py                 # CLI entry point and shared context

  clanker_bot/              # Discord bot host
    command_handlers/       # /chat, /speak, /shitpost, /join, /leave, etc.
    cogs/                   # Discord cogs (vc_monitor)
    persistence/            # Feedback persistence (sqlc-gen-python + SQLite)
    views/                  # Discord UI views (shitpost preview)
    voice_actor.py          # Actor-based voice management
    voice_ingest.py         # Voice receive integration
    voice_resilience.py     # Keepalive and reconnection
    logging_config.py       # Structured logging setup
    commands.py             # Slash command registration
    health.py               # Health endpoint
    main.py                 # Bot entry point

tests/                      # Test suite
  cli/                      # CLI command tests (CliRunner + fakes)
  network/                  # Integration tests (require API keys)
  test_*.py                 # Unit tests

Development

make check    # Run all checks (lint, format, test, typecheck)
make test     # Run tests (excludes network tests)
make lint     # Ruff linting with auto-fix
make format   # Ruff formatting
make ty       # Type checking with ty
make setup    # Install all dependencies with uv
make run      # Run the Discord bot

Voice Support

Voice features require additional dependencies:

uv pip install -e ".[voice]"

Two VAD implementations are available:

Implementation Accuracy Dependencies Size
SileroVAD (default) High (ML-based) torch, numpy ~500MB
EnergyVAD (fallback) Moderate (RMS) Built-in Minimal

Docker

See docker/README.md for full documentation.

docker-compose up -d

Documentation

Detailed guides in agent_docs/:

  • Architecture - System design, data flows, design decisions
  • Testing - Testing strategy, fixtures, fakes, markers
  • Voice Pipeline - End-to-end voice processing and debugging
  • Providers - Provider system and adding new providers

Additional docs in docs/:

License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

clanker9000-0.3.0.tar.gz (2.3 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clanker9000-0.3.0-py3-none-any.whl (190.7 kB view details)

Uploaded Python 3

File details

Details for the file clanker9000-0.3.0.tar.gz.

File metadata

  • Download URL: clanker9000-0.3.0.tar.gz
  • Upload date:
  • Size: 2.3 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for clanker9000-0.3.0.tar.gz
Algorithm Hash digest
SHA256 64b56d6acc3d75612f2eb0233832b4bd790bd7c3e91371ab23cd5a125f3ea8f4
MD5 59c483e59f5d293e289816574464ae2f
BLAKE2b-256 6035cf48a0816b654d8b3df8700c0fc5cdda4aa0f30c6cb0fd30af83cf196b39

See more details on using hashes here.

Provenance

The following attestation bundles were made for clanker9000-0.3.0.tar.gz:

Publisher: publish.yml on safurrier/clanker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file clanker9000-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: clanker9000-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 190.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for clanker9000-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 92a605ee4ef0fd0dc49c3fa6488ba81ff19ce483b5a81fec1f4bdb19a3eb761b
MD5 5315b638fcc4b661c9c764808165ce42
BLAKE2b-256 8848b802e4052ace928769f0386cd85ee0eac3162ae7c0e3c67b6edb05c3d940

See more details on using hashes here.

Provenance

The following attestation bundles were made for clanker9000-0.3.0-py3-none-any.whl:

Publisher: publish.yml on safurrier/clanker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page