A Discord bot that hangs out in your voice channel. It hears what people say, talks back like a friend, and remembers the conversation. Everything runs locally on your machine.
Bobby is a regular person in the call. Casual, short replies, no assistant-speak. It knows who's talking and won't call you by the wrong name.
Wake words. Say "Bobby" (or "robot", "ai", "clanker") and it will answer. Calling it a "clanker" is an insult, so it claps back rudely. It also chimes into the flow of conversation on its own, just not constantly.
It remembers. Facts people mention stick around, compressed as the
conversation grows. /forget wipes it clean.
Multiple servers. It can hang out in several servers at the same time.
Each server gets its own conversation memory, its own /say cooldown, and
its own voice connection. Work is spread across worker threads so one busy
server doesn't make it go quiet in another.
- Node.js 20 or newer
ffmpegon your PATH- Ollama running with a model pulled:
ollama pull qwen3.5:2b
- Create a bot at https://discord.com/developers/applications (New Application, then the Bot tab, reset the token).
- No privileged intents needed. Invite it with the
botandapplications.commandsscopes, and theConnect+Speakpermissions. - Copy the config and paste your token:
cp .env.example .env- Start it:
npm install
npm startOn the first run it downloads the speech models (a few hundred MB total) into
./.cache and ./models. You'll see [bot] logged in as Bobby#4089 when it's
ready.
| Command | What it does |
|---|---|
/join |
Joins your voice channel and starts listening |
/leave |
Leaves and stops listening |
/say text |
Makes it say something out loud. It remembers having said it. Has a 30 second cooldown per server. |
/forget |
Clears its memory for this server |
/status |
Shows connection state, memory size, and which model it uses |
you speak -> captured audio -> tiny Whisper checks if it's for Bobby (~0.4s)
-> bigger Whisper transcribes properly, but only
when Bobby is actually going to answer
-> Ollama (qwen3.5:2b) writes a reply
-> eSpeak says it out loud
Each stage runs off the main thread so one server's load doesn't stall another: transcription runs in dedicated Whisper workers, speech synthesis in its own worker, and every server gets its own turn queue.
A few details worth knowing:
- Hearing. Silero VAD filters out music, clicks, and game audio before Whisper ever runs, so it doesn't hallucinate words from noise. Whisper-tiny does fast detection, and whisper-base only runs when a reply is coming.
- Thinking. Replies are capped to a couple of short sentences. The model can't loop on phrases (repeat penalty), won't repeat itself, gets nudged if it fixates on one topic, and never ends a reply on a question.
- Memory. The last 6 messages stay raw. Older ones get compressed into
short fact lines and keywords. It only remembers what people said, not its
own rambling. Saved to
data/memory.json, so it survives restarts. - Talking. eSpeak is a basic robotic voice on purpose: it costs almost nothing to run. The text is cleaned up first, so abbreviations like "idk" are said properly.
Everything is in .env, with comments in .env.example. The most useful
knobs:
BOT_NAME,BOT_ALIASES(defaultBobbyplusrobot,ai,clanker)UNNAMED_COOLDOWN_MS(how often it chimes in on its own, default 20s)CONTINUATION_WINDOW_MS(how long after speaking it stays in the flow)LLM_MODEL(swap to a bigger or smaller model anytime)STT_MODEL(transcription accuracy vs speed)STT_MAIN_WORKERS(how many quality transcription workers; raise it when the bot is in several servers at once)SYSTEM_PROMPT(rewrite its whole personality)
npm run selftestThis tests the whole pipeline without Discord: speak with TTS, transcribe it back, check the wake word, hit Ollama, verify memory. Good for checking nothing broke after a change.
[llm] Ollama not reachable-> start Ollama and pull the model.- It doesn't respond -> check the log.
not addressedmeans it decided the message wasn't for it,throttledmeans the cooldown is active,nothing intelligiblemeans it heard noise it couldn't make sense of. - It responds to noise -> the VAD handles most of it. If game audio slips
through, raise
VAD_MIN_CONFIDENT_FRAMES. - Replies feel slow -> the delay is mostly transcription. Lower
SILENCE_DURATION_MSor switchSTT_MODELtoonnx-community/whisper-tiny.en.
- The voice is eSpeak via
mespeak, which is GPL. Deliberately basic, and swappable insrc/tts.jsif you want something nicer. - The models are small on purpose so it runs on a normal laptop. That means
transcripts and replies are occasionally weird. Upgrading
LLM_MODELorSTT_MODELis the easiest way to get better results.