Skip to content

Installation

Prerequisites

  • uv
  • libopus for Discord voice (brew install opus, apt install libopus0, dnf install opus, or pacman -S opus)
  • A Discord application + bot token (portal) with the message_content, messages, and voice_states intents enabled
  • An OpenRouter API key
  • (optional, voice only) One of: Azure Cognitive Services key + region, a Cartesia API key, or a Google Gemini API key
  • (optional, voice only) A Deepgram API key for speech transcription

Environment variables

Create a .env in the repo root (loaded automatically on startup). Only install-wide secrets and the active-familiar selector live here; everything tunable about the familiar — LLM model per call site, TTS voice, chattiness — lives in data/familiars/<id>/character.toml.

# required
DISCORD_BOT=<discord bot token>
OPENROUTER_API_KEY=<openrouter key>

# pick the familiar to load (or pass --familiar on the CLI)
FAMILIAR_ID=aria

# TTS credentials — set the one matching [tts].provider in character.toml

# Azure Speech (default provider):
AZURE_SPEECH_KEY=<azure cognitive services key>
AZURE_SPEECH_REGION=<azure region, e.g. eastus>

# Cartesia (provider="cartesia"):
CARTESIA_API_KEY=<cartesia key>

# Google Gemini TTS (provider="gemini"):
GOOGLE_API_KEY=<google ai studio key>

# optional — Deepgram speech transcription (voice channels only)
DEEPGRAM_API_KEY=<deepgram key>

Per-familiar model choice

LLM model selection is per-call-site and lives in the familiar's character.toml under one [llm.<slot>] table per call site: main_prose, post_process_style, reasoning_context, history_summary, memory_search, and interjection_decision.

The checked-in reference profile at data/familiars/_default/character.toml fills in every slot with sensible defaults. A user's own character.toml only needs to override the fields it wants to change — missing slots inherit from the default profile on load. Copy the default to start a new familiar:

cp -r data/familiars/_default data/familiars/my-familiar
# then edit data/familiars/my-familiar/character.toml

Good slot-level starting points for cheap / fast models (everything except main_prose):

  • openai/gpt-4o-mini — cheapest OpenAI, fast, honours the name field, strong structured-output for the content-search TOOL/ANSWER protocol.
  • anthropic/claude-3.5-haiku — similar tier / price on the Anthropic side.
  • meta-llama/llama-3.1-8b-instruct — very cheap via OpenRouter, decent for simple summarisation.

The startup log prints each slot's resolved model on every launch.

Start

uv sync --dev
uv run familiar-connect run
uv run familiar-connect run --familiar aria
uv run familiar-connect -vv run --familiar aria

The run subcommand resolves the active familiar via --familiar first, then FAMILIAR_ID. -v / -vv / -vvv tune logging verbosity — -vv is the sweet spot for smoke tests.

CLI reference

The help text below is generated at build time from the argparse parser in src/familiar_connect/cli.py. Run uv run familiar-connect --help locally to get the same output.

usage: familiar-connect [-h] [--version] [-v] {run,version,metrics} ...

familiar-connect CLI tool

positional arguments:
  {run,version,metrics}
                        Available commands
    run                 Start the Discord bot
    version             Display package version
    metrics             View performance metrics collected by the bot

options:
  -h, --help            show this help message and exit
  --version             show program's version number and exit
  -v, --verbose         Increase verbosity (can be repeated: -v, -vv, -vvv)
usage: familiar-connect run [-h] [--familiar ID]

Start the familiar and connect to Discord

options:
  -h, --help     show this help message and exit
  --familiar ID  Folder name of the character to run (under data/familiars/).
                 Overrides FAMILIAR_ID.

Once the bot is online, see Slash commands for the smoke-test surface.