Your private, local AI companion that helps you build better habits and stronger relationships
Running entirely on your machine — Zero cloud ☁️❌
- Why RaccBuddy
- Features
- Quick Start
- Usage
- Troubleshooting
- Deployment to Production
- Platform Integrations
- Skills & Extensibility
- Tech Stack
- Project Structure
- API Reference
- Configuration
- FAQ
- Roadmap
- Security & Privacy
- Getting Help & Community
- Contributing
- License
Privacy First: Everything runs locally on your machine — no cloud services, no data leaks, complete control over your personal data.
Smart & Efficient: Uses a layered ContextBuilder + pgvector semantic search to assemble up to 30,000 tokens of relevant context, delivering coherent, deeply personalised responses.
Proactive Care: Sends personalized nudges based on your habits and relationship patterns — helps you stay connected with those who matter.
Multi-Platform: Started with Telegram, now supports WhatsApp, and designed to integrate with more platforms via an extensible plugin system.
- Smart Memory System: Uses pgvector semantic search to retrieve relevant context efficiently
- Multi-LLM Support: Works with local Ollama models (llama3.2, qwen2.5) or cloud providers (xAI Grok)
- Function Calling: Advanced LLM providers can call tools autonomously (analyze contacts, get insights, schedule messages)
- ContextBuilder: A layered, token-budgeted context assembly pipeline (30,000 token default, fully configurable)
- Multi-turn Conversations: Proper user/assistant alternating message history for coherent dialogue (via
generate_chat()+ Ollama/api/chat)
- Telegram Bot: Full-featured bot with inline commands and natural conversation
- WhatsApp Integration: Node.js bridge service connects WhatsApp messages to the same AI pipeline
- REST API:
/api/messagesendpoint for adding new platform bridges (Signal, Discord, etc.)
Built-in nudge skills that trigger based on real data:
- Idle Detection: Checks in when you've been inactive after recent activity
- Contact Quiet: Reminds you to reach out when a regular contact goes silent
- Evening Check-in: End-of-day reflections and gentle reminders
- Habit Tracking: Monitors your custom habits and sends motivational nudges
When using advanced providers (xAI, OpenAI), Raccy can autonomously:
- Analyze contact relationships and communication patterns
- Retrieve relationship scores (0-100)
- Get conversation insights and sentiment analysis
- List all contacts across platforms
- Summarize historical conversations
- Schedule future messages
- Local transcription via OpenAI Whisper (configurable model size)
- Text-to-speech via Suno Bark for voice replies
- Audio format conversion handled transparently via ffmpeg
- Reply mode: text-only, voice-only, or both (configurable)
- Fully opt-in: set
VOICE_ENABLED=trueto activate
- LangGraph-based 4-node supervisor graph: ContextKeeper -> NudgePlanner -> Crafter -> Reflector
- Quality-gated nudges: the Reflector LLM evaluates each crafted nudge before delivery
- Checkpointed state: survives restarts via PostgreSQL or SQLite backend
- Observability: optional Langfuse tracing and Prometheus metrics
- Fully opt-in: set
AGENTIC_ENABLED=trueto activate
Chat Skills: Customize conversation behavior
- Inject system prompt fragments
- Expose custom tools to the LLM
- Pre/post-process messages
- See
skills/folder for examples
Nudge Skills: Create custom proactive reminders
- Pure data checks (no LLM unless triggered)
- Cooldown periods to avoid spam
- Dynamic context injection
- See
nudges/folder for examples
- Automatic contact discovery across platforms
- Dynamic relationship scoring using four weighted signals: message frequency, recency, sentiment, and reply rate
- Mood / sentiment detection on every message via lightweight LLM classification
- Habit detection combining frequency analysis and LLM pattern extraction
- Conversation summarization with semantic search
- Platform-agnostic contact management
- Score-change event history for tracking relationship trends over time
🚀 Beta Release: RaccBuddy is in active beta. Features are stable but expect occasional updates and improvements.
- Python 3.12+ (for local installation) or Docker (for containerized setup)
- Telegram account for bot interaction
- (Recommended) Ollama installed locally for LLM processing
- (Alternative) xAI API key for cloud-based LLM (with function calling support)
Easiest way to get started. Everything runs in containers.
git clone https://github.com/dcbert/raccbuddy.git
cd raccbuddy- Open Telegram and message @BotFather
- Send
/newbotand follow the prompts - Copy the bot token (looks like
1234567890:ABCdefGHIjklMNOpqrsTUVwxyz)
cp .env.example .env
nano .env # or use your preferred editorMinimal configuration (edit these in .env):
# Required: Your Telegram bot token from BotFather
TELEGRAM_BOT_TOKEN=your-bot-token-here
# LLM Provider: 'ollama' (local, private) or 'xai' (cloud, with function calling)
LLM_PROVIDER=ollama
# If using Ollama on your host machine (recommended):
OLLAMA_BASE_URL=http://host.docker.internal:11434# macOS / Linux: Download from https://ollama.ai
# Then pull the models:
ollama pull llama3.2:3b
ollama pull nomic-embed-textdocker compose up -dThis starts:
- PostgreSQL database with pgvector
- RaccBuddy bot and API server
- (Optional) WhatsApp bridge
- Open Telegram and find your bot (@your_bot_username)
- Send
/start— Raccy will introduce themselves! 🦝 - Start chatting naturally
Verify it's running:
# Check container logs
docker compose logs -f app
# Health check
curl http://localhost:8000/healthFor development or custom setups.
git clone https://github.com/dcbert/raccbuddy.git
cd raccbuddy
python3.12 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txtcp .env.example .env
nano .env # Edit with your settingsRequired settings for local setup:
TELEGRAM_BOT_TOKEN=your-bot-token-here
DATABASE_URL=postgresql+asyncpg://raccbuddy:raccbuddy@localhost:5432/raccbuddy
LLM_PROVIDER=ollama
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama3.2:3b
OLLAMA_EMBED_MODEL=nomic-embed-textdocker compose up -d db# Download from https://ollama.ai
ollama pull llama3.2:3b
ollama pull nomic-embed-textalembic upgrade headpython -m src.botOptional: Start the REST API (for WhatsApp/extensions)
# In a separate terminal:
uvicorn src.api:api --host 0.0.0.0 --port 8000# Run the test suite
pytest tests/ -v
# Check database connection
docker exec -it $(docker ps -qf "name=raccbuddy-db") psql -U raccbuddy -d raccbuddy -c "\dt"
# View logs (Docker)
docker compose logs -f app
# API health check
curl http://localhost:8000/healthOnce your bot is running, message it on Telegram:
/start— Initialize your account and meet Raccy/help— Show available commands (if implemented)- Just chat naturally! — Raccy remembers context and learns about you
- Find your bot on Telegram using the username you created with BotFather
- Send
/start— This registers you as the owner and locks the bot to your account - Start chatting — Ask questions, share updates, or just talk about your day
- Raccy will learn — As you chat, Raccy builds a memory of your relationships and habits
Docker:
docker compose down # Stop all services
docker compose down -v # Stop and remove data (warning: deletes database)Local Python:
# Press Ctrl+C in the terminal running the botDocker:
docker compose logs -f app # Follow bot logs
docker compose logs -f db # Follow database logsLocal:
# Logs appear in the terminal where you ran `python -m src.bot`Check if the bot is running:
# Docker
docker compose ps
# Local
# Look for the python process in your terminalCheck logs for errors:
# Docker
docker compose logs app
# Local - errors appear in terminalVerify your bot token:
# Test the token directly
curl https://api.telegram.org/bot<YOUR_TOKEN>/getMeEnsure PostgreSQL is running:
docker compose ps db
docker compose logs dbCheck if the port is available:
lsof -i :5432 # Should show postgres if runningRestart the database:
docker compose restart dbCheck if Ollama is running:
curl http://localhost:11434/api/tagsVerify models are pulled:
ollama list
# Should show llama3.2:3b and nomic-embed-textDocker can't reach host Ollama:
- Make sure you're using
http://host.docker.internal:11434in docker-compose.yml - This is already configured correctly in the default setup
Ensure dependencies are installed:
# Docker - rebuild the image
docker compose build app
# Local
source venv/bin/activate
pip install -r requirements.txtReset and rerun migrations:
# Warning: This deletes all data
docker compose down -v
docker compose up -d db
alembic upgrade headCheck if the WhatsApp service is running:
docker compose logs whatsappRescan QR code:
docker compose down whatsapp
docker volume rm raccbuddy_wa-session
docker compose up whatsapp
# Scan the new QR codeRaccBuddy includes automated scripts for deploying to production environments like Umbrel home servers.
On your development machine (Apple Silicon or any platform):
# Set your Docker Hub username
export DOCKER_USERNAME=your-dockerhub-username
# Run the deployment script
./scripts/deploy-to-dockerhub.shThis script will:
- Build multi-platform Docker images (linux/amd64, linux/arm64)
- Push images to Docker Hub
- Dump your PostgreSQL database
- Backup your WhatsApp session (to avoid re-scanning QR)
- Create a ready-to-use
docker-compose.ymlwith your image references - Save everything to
./backups/YYYYMMDD_HHMMSS/
-
Copy the backup directory to your Umbrel:
scp -r backups/20260223_120000/ umbrel@umbrel.local:~/raccbuddy/ -
On your Umbrel, navigate to the backup directory:
cd ~/raccbuddy/backups/20260223_120000/
-
Create a
.envfile with your secrets:cat > .env << EOF TELEGRAM_BOT_TOKEN=your-bot-token OWNER_TELEGRAM_ID=your-telegram-id OWNER_WHATSAPP_NUMBER=your-whatsapp-number EOF
-
Start the services (uses the docker-compose.yml from backup):
docker compose up -d
-
Restore your data:
# Wait for containers to be ready (30 seconds) sleep 30 # Run the restore script ../../../restore-from-backup.sh .
If you prefer to restore manually:
# Restore database
gunzip -c database.sql.gz | docker compose exec -T db psql -U raccbuddy raccbuddy
# Restore WhatsApp session (optional, to avoid re-scanning QR)
docker run --rm \
-v raccbuddy_wa-session:/data \
-v $(pwd):/backup \
alpine sh -c "cd /data && tar xzf /backup/whatsapp-session.tar.gz"
# Restart services
docker compose restartIf you just want to pull and use the latest images:
-
Update your
docker-compose.yml:app: image: your-dockerhub-username/raccbuddy-app:latest # Remove the 'build: .' line whatsapp: image: your-dockerhub-username/raccbuddy-whatsapp:latest # Remove the 'build: ./whatsapp-service' line
-
Start normally:
docker compose up -d
For production deployments, consider these additional settings:
# Production database (if using external PostgreSQL)
DATABASE_URL=postgresql+asyncpg://user:pass@db-host:5432/raccbuddy
# Use xAI with function calling for better results
LLM_PROVIDER=xai
XAI_API_KEY=your-xai-api-key
# Or use Ollama on Umbrel (if installed)
OLLAMA_BASE_URL=http://umbrel.local:11434
# Increase memory retention
OWNER_MEMORY_RETENTION_DAYS=365
# More frequent nudges
NUDGE_CHECK_INTERVAL_MINUTES=30To update your deployment with new code:
-
Rebuild and push on your dev machine:
./deploy-to-dockerhub.sh
-
On your server, pull latest and restart:
docker compose pull docker compose up -d
The primary interface. Just message your bot:
/start - Initialize and introduce Raccy
/help - Show available commands
Then chat naturally — Raccy remembers context and helps you stay connected.
Run the Node.js bridge service to connect WhatsApp:
cd whatsapp-service
npm install
npm start- A QR code will appear — scan it with WhatsApp (Linked Devices)
- Session is saved locally, so you only scan once
- All WhatsApp messages flow into the same AI pipeline as Telegram
With Docker:
docker compose up whatsappSee whatsapp-service/README.md for details.
Create a bridge that POSTs to the REST API. When API_SECRET_KEY is set,
include the key in every request:
POST /api/messages
Content-Type: application/json
X-API-Key: your-api-secret-key
{
"platform": "your_platform",
"chat_id": "unique_chat_id",
"from_id": "user_id",
"contact_name": "John Doe",
"text": "Hello!",
"timestamp": "2026-02-21T10:00:00Z",
"is_group": false
}Customize how Raccy responds in conversations. Create a file in skills/:
from src.core.skills.chat import BaseChatSkill, register_chat_skill
class CustomSkill(BaseChatSkill):
name = "custom_skill"
description = "My custom chat behavior"
system_prompt_fragment = (
"Always end responses with a raccoon fact."
)
@property
def tool_schemas(self):
# Optional: expose custom tools
return []
async def execute_tool(self, tool_name: str, args: dict):
# Handle custom tool calls
pass
register_chat_skill(CustomSkill())Create proactive reminders. Add a file in nudges/:
from src.core.skills.base import BaseNudgeSkill, NudgeCheck, register_skill
import datetime
class MorningMotivation(BaseNudgeSkill):
name = "morning_motivation"
trigger = "morning"
default_prompt = "Send a motivational morning message. Max 2 sentences."
@property
def cooldown_minutes(self):
return 24 * 60 # Once per day
async def should_fire(self, owner_id: int) -> NudgeCheck:
now = datetime.datetime.now()
if now.hour == 8: # 8 AM
return NudgeCheck(fire=True, reason="Morning time!")
return NudgeCheck(fire=False)
register_skill(MorningMotivation())Skills are automatically loaded at startup from skills/ and nudges/ folders.
Core
- Python 3.12 with full async/await (asyncio)
- python-telegram-bot v21+ for Telegram integration
- FastAPI for REST API endpoints
- SQLAlchemy 2.0 with async support
- Alembic for database migrations
Database & AI
- PostgreSQL 16 with pgvector extension
- Semantic embeddings for efficient context retrieval
- Owner memory deduplication (cosine similarity > 0.9 → merge)
- Ollama for local LLM inference (default: llama3.2:3b)
- xAI Grok API support for cloud inference with function calling
- Sentiment / mood analysis via Ollama
State & Persistence
- Persistent user & contact state (DB-backed, survives restarts)
- DB-backed scheduled jobs (restored on restart)
- In-memory write-through cache for low-latency state access
Platform Bridges
- Node.js + whatsapp-web.js for WhatsApp
- REST API for custom integrations
DevOps
- Docker & Docker Compose
- pytest for testing
- black + ruff for code formatting
raccbuddy/
├── src/
│ ├── bot.py # Telegram bot entrypoint
│ ├── api.py # REST API for external bridges
│ ├── summarizer.py # Background conversation summarizer
│ ├── core/
│ │ ├── auth.py # Owner authentication
│ │ ├── config.py # Settings management
│ │ ├── plugin_loader.py # Dynamic plugin loading
│ │ ├── db/
│ │ │ ├── models.py # SQLAlchemy models (pgvector)
│ │ │ ├── crud.py # Database queries
│ │ │ └── session.py # Engine & session factory
│ │ ├── agentic/
│ │ │ ├── __init__.py # Init/shutdown lifecycle
│ │ │ ├── checkpointer_registry.py # Pluggable LangGraph checkpointers
│ │ │ ├── engine.py # Proactive cycle orchestration
│ │ │ ├── graph.py # 4-node StateGraph (LangGraph)
│ │ │ ├── metrics.py # Prometheus counters/histograms
│ │ │ ├── state.py # AgenticState TypedDict
│ │ │ ├── tools.py # Skill/tool adapters for graph nodes
│ │ │ └── tracing.py # Langfuse tracing integration
│ │ ├── habits/
│ │ │ └── detector.py # Habit detection (frequency + LLM)
│ │ ├── llm/
│ │ │ ├── base.py # LLM provider interface
│ │ │ ├── interface.py # LLM facade
│ │ │ └── providers/
│ │ │ ├── ollama.py # Ollama provider
│ │ │ └── xai.py # xAI/Grok provider
│ │ ├── memory/
│ │ │ ├── base.py # PostgreSQL memory backend (pgvector)
│ │ │ └── context_builder.py # Layered, token-budgeted context assembly
│ │ ├── nudges/
│ │ │ └── engine.py # Nudge execution engine
│ │ ├── relationship/
│ │ │ └── manager.py # Dynamic relationship scoring
│ │ ├── scheduled/
│ │ │ └── jobs.py # DB-backed scheduled messages
│ │ ├── sentiment/
│ │ │ └── analyzer.py # Mood / sentiment analysis
│ │ ├── skills/
│ │ │ ├── base.py # Nudge skill base & registry
│ │ │ ├── chat.py # Chat skill system & registry
│ │ │ ├── loader.py # Skill auto-discovery
│ │ │ └── nudge.py # Built-in nudge skills
│ │ ├── state/
│ │ │ └── persistent.py # Persistent state management
│ │ ├── voice/
│ │ │ ├── __init__.py # Public API (voice_manager singleton)
│ │ │ ├── base.py # STT/TTS abstract base classes
│ │ │ ├── manager.py # VoiceManager orchestrator
│ │ │ └── providers/
│ │ │ ├── whisper_stt.py # Whisper STT provider
│ │ │ └── bark_tts.py # Bark TTS provider
│ │ └── tools/
│ │ └── registry.py # LLM function calling tools
│ ├── handlers/
│ │ ├── chat.py # Message handling + enrichment
│ │ ├── start.py # /start command
│ │ └── voice.py # Voice message handler
│ └── plugins/
│ └── base.py # Plugin base class
├── alembic/ # Database migration scripts
│ ├── env.py
│ └── versions/
├── skills/ # Custom chat skills (auto-loaded)
│ └── example_motivation.py
├── nudges/ # Custom nudge skills (auto-loaded)
│ └── example_weekend.py
├── plugins/ # Custom platform plugins (auto-loaded)
│ └── example_echo.py
├── scripts/
│ ├── deploy-to-dockerhub.sh # Multi-platform build + push + backup
│ └── restore-from-backup.sh # Restore DB + WhatsApp session from backup
├── whatsapp-service/ # WhatsApp bridge (Node.js)
│ ├── src/
│ │ ├── index.js # whatsapp-web.js setup
│ │ └── forwarder.js # Forward to Python API
│ └── Dockerfile
├── tests/ # Unit tests
├── alembic.ini # Alembic configuration
├── docker-compose.yml # PostgreSQL + WhatsApp service
├── requirements.txt
└── README.md
Receive messages from external platform bridges.
Authentication: When API_SECRET_KEY is set in .env, all requests must include an X-API-Key header matching the configured secret. Requests without the correct key receive 401 Unauthorized. Leave API_SECRET_KEY empty to disable auth (local/LAN use only).
Headers:
X-API-Key: your-api-secret-key
Content-Type: application/json
Request Body:
{
"platform": "whatsapp",
"chat_id": "1234567890@c.us",
"from_id": "0987654321@c.us",
"contact_name": "Alice",
"text": "Hey, how are you?",
"timestamp": "2026-02-21T10:30:00Z",
"is_group": false,
"group_name": null
}Response: 200 OK with {"status": "ok"}
Health check endpoint.
Response: {"status": "ok"}
Available when using advanced providers (xAI):
analyze_contact(contact_name)- Run relationship analysisget_insights(contact_name)- Get conversation insightsget_relationship_score(contact_name)- Get score (0-100)list_contacts()- List all contactssummarize_contact(contact_name, days)- Summarize recent historyschedule_message(contact_name, when, message)- Schedule future message
| Variable | Default | Description |
|---|---|---|
TELEGRAM_BOT_TOKEN |
(required) | Bot token from @BotFather |
OWNER_TELEGRAM_ID |
0 |
Your Telegram user ID (auto-set on /start) |
DATABASE_URL |
(required) | PostgreSQL connection string |
LLM_PROVIDER |
ollama |
ollama or xai |
OLLAMA_BASE_URL |
http://localhost:11434 |
Ollama server URL |
OLLAMA_MODEL |
llama3.2:3b |
Model for text generation |
OLLAMA_EMBED_MODEL |
nomic-embed-text |
Model for embeddings |
XAI_API_KEY |
(optional) | xAI API key (if using xAI) |
XAI_MODEL |
grok-4-1-fast-reasoning |
xAI model name |
MAX_CONTEXT_TOKENS |
30000 |
Maximum LLM context size (Ollama KV-cache + input budget) |
EMBED_DIMENSIONS |
768 |
Embedding vector dimensions (must match embed model) |
API_SECRET_KEY |
(empty) | X-API-Key secret for POST /api/messages; leave empty to disable auth |
MAX_SUMMARY_WORDS |
150 |
Summary length limit |
NUDGE_CHECK_INTERVAL_MINUTES |
60 |
How often to check for nudges |
SENTIMENT_MODEL |
llama3.2:3b |
Model used for mood classification |
MEMORY_RECENT_MESSAGES |
15 |
Number of recent messages included in every context window |
MEMORY_SEMANTIC_CHUNKS |
6 |
pgvector semantic chunks retrieved per query |
MEMORY_MAX_SUMMARIES |
3 |
Past daily summaries included in context |
REL_WEIGHT_FREQUENCY |
0.30 |
Weight for message frequency in relationship scoring |
REL_WEIGHT_RECENCY |
0.30 |
Weight for recency in relationship scoring |
REL_WEIGHT_SENTIMENT |
0.25 |
Weight for sentiment in relationship scoring |
REL_WEIGHT_REPLY_RATE |
0.15 |
Weight for reply rate in relationship scoring |
OWNER_MEMORY_RETENTION_DAYS |
90 |
Days before low-importance memories are pruned |
DB_POOL_SIZE |
10 |
SQLAlchemy connection pool size |
DB_MAX_OVERFLOW |
20 |
Maximum overflow connections |
MAX_TOOL_ROUNDS |
10 |
Max LLM tool-call loop iterations |
VOICE_ENABLED |
false |
Enable voice message handling (requires ffmpeg + torch) |
VOICE_REPLY_MODE |
text |
Reply mode for voice messages: text, voice, or both |
VOICE_LANGUAGE |
(empty) | Force transcription language (ISO-639-1, e.g. en); empty = auto-detect |
STT_PROVIDER |
whisper |
Speech-to-text provider |
STT_MODEL |
openai/whisper-small |
HuggingFace model ID for STT |
TTS_PROVIDER |
bark |
Text-to-speech provider |
TTS_MODEL |
suno/bark-small |
HuggingFace model ID for TTS |
TTS_VOICE_PRESET |
v2/en_speaker_6 |
Bark voice preset |
AGENTIC_ENABLED |
false |
Enable the proactive agentic cycle (LangGraph) |
CHECKPOINTER_BACKEND |
postgres |
LangGraph checkpointer: postgres or sqlite |
MAX_CYCLE_TOKENS |
8192 |
Token budget per agentic cycle |
AGENTIC_CYCLE_INTERVAL_MINUTES |
30 |
How often the agentic cycle runs |
LANGFUSE_ENABLED |
false |
Enable Langfuse tracing for agentic cycles |
LANGFUSE_PUBLIC_KEY |
(empty) | Langfuse public key |
LANGFUSE_SECRET_KEY |
(empty) | Langfuse secret key |
LANGFUSE_HOST |
http://localhost:3000 |
Langfuse server URL |
PROMETHEUS_ENABLED |
false |
Enable Prometheus metrics endpoint |
PROMETHEUS_PORT |
9090 |
Prometheus metrics HTTP server port |
XAI_ENABLE_BUILTIN_TOOLS |
false |
Enable Grok built-in tools (web/X/code search — data leaves machine) |
For 8GB+ RAM:
llama3.2:3b(default, fast)qwen2.5:7b(better quality)
For 16GB+ RAM:
llama3.1:8bmistral:7b
Q: Is RaccBuddy really private? A: Yes! By default, everything runs locally on your machine. Messages, relationships, and habits stay in your local PostgreSQL database. If you use Ollama (default), even LLM inference happens locally. Only if you choose to use xAI does data leave your machine (and only the conversation context assembled by ContextBuilder — never raw message archives or relationship data).
Q: How much does it cost to run? A: RaccBuddy is free and open source. If using local Ollama, there are zero ongoing costs (just electricity). If you opt for xAI Grok, you'll pay xAI's API rates.
Q: What hardware do I need? A:
- Minimum: 8GB RAM, any modern CPU (for llama3.2:3b)
- Recommended: 16GB RAM (for qwen2.5:7b or larger models)
- Storage: ~2GB for Docker images + models
Q: Can I use RaccBuddy on Windows? A: Yes! Docker works on Windows. For local Python setup, use WSL2 for the best experience.
Q: Does RaccBuddy work offline? A: The bot requires internet to receive Telegram/WhatsApp messages, but LLM processing can be 100% offline with Ollama. The database runs locally regardless.
Q: What platforms are supported? A: Currently Telegram (native) and WhatsApp (via bridge). Signal, Discord, and others are planned.
Q: Can multiple people use one instance?
A: Not yet. RaccBuddy currently locks to one owner (the first person to send /start). Multi-user support is on the roadmap.
Q: What languages does RaccBuddy understand? A: It depends on your LLM. Llama3.2 and Qwen2.5 support many languages. Raccy's personality prompts are in English, but it should respond in whatever language you use.
Q: Does it support voice messages?
A: Yes! Set VOICE_ENABLED=true in your .env. RaccBuddy transcribes voice notes locally via Whisper and can reply with synthesized speech via Bark. Requires ffmpeg and optional torch/transformers dependencies (see requirements.txt).
Q: Why PostgreSQL instead of SQLite? A: We use pgvector for semantic search on embeddings, which requires PostgreSQL. It's also more scalable for production use.
Q: Can I self-host this on a VPS? A: Absolutely! The Docker setup works on any Linux VPS. Just make sure to:
- Use strong passwords for PostgreSQL
- Configure firewall rules if exposing the API
- Consider using xAI instead of Ollama if the VPS has limited RAM
Q: How do I back up my data? A: Your data is in the PostgreSQL database. Backup options:
# Export database
docker exec $(docker ps -qf "name=raccbuddy-db") pg_dump -U raccbuddy raccbuddy > backup.sql
# Restore
cat backup.sql | docker exec -i $(docker ps -qf "name=raccbuddy-db") psql -U raccbuddy -d raccbuddyQ: Can I use OpenAI or Anthropic instead of Ollama/xAI?
A: Not built-in yet, but it's easy to add! Check src/core/llm/providers/ and implement a new provider following the base interface. PRs welcome!
Q: How does RaccBuddy manage context size?
A: RaccBuddy uses the ContextBuilder pipeline, which assembles up to 30,000 tokens (configurable) from multiple layers:
- Recent messages — last N messages for immediate conversational continuity
- Semantic search — pgvector retrieves only the most relevant past chunks
- Daily summaries — compressed long-term memory without raw message bloat
- Owner personal facts — deduplicated self-knowledge about the user
- Token budgeting — each layer has a configured fraction of the total budget, preventing runaway context growth
Q: Can I see what data is stored? A: Yes! Connect to your database:
docker exec -it $(docker ps -qf "name=raccbuddy-db") psql -U raccbuddy -d raccbuddyThen explore tables: \dt (list tables), SELECT * FROM messages LIMIT 10;, etc.
Q: How do I delete all my data? A:
docker compose down -v # Stops containers and deletes volumesQ: Can Telegram see my messages? A: Yes, Telegram delivers messages to your bot. If privacy is critical, consider hosting a Matrix bridge instead (fully self-hosted messaging).
Q: What's sent to xAI if I use that provider? A: Only:
- System prompt (Raccy's personality)
- Current conversation context assembled by ContextBuilder (up to
MAX_CONTEXT_TOKENS, default 30,000 — a budget-controlled subset of your data) - Tool schemas (function definitions) Never: full raw message history, raw embeddings, or relationship tables.
Q: How do I change Raccy's personality?
A: Edit the system prompt in src/core/llm/interface.py. Look for the main system prompt construction.
Q: Can I add custom commands?
A: Yes! Add command handlers in src/handlers/ and register them in src/bot.py.
Q: How do I create a custom nudge?
A: Create a new file in the nudges/ folder. See Skills & Extensibility and check nudges/example_weekend.py for a template.
Q: Can I disable certain features? A: Most features can be controlled via environment variables. Check Configuration.
Q: How do I contribute? A: See the Contributing section! We welcome PRs, bug reports, and feature requests.
Q: Where are the tests?
A: In the tests/ folder. Run with pytest tests/ -v.
Q: How do I add a new LLM provider?
A: Create a new provider class in src/core/llm/providers/ that implements the base interface. See ollama.py and xai.py for examples.
- MVP: Telegram bot with memory and summaries
- Phase 1: WhatsApp integration via Node.js bridge
- Phase 2: Multi-LLM provider support (Ollama + xAI)
- Phase 3: Skills system (chat + nudge)
- Phase 4: LLM function calling / tool use
- Phase 5: Persistent state, Alembic migrations, dynamic relationship scoring, mood detection, habit detection, owner memory deduplication
- Phase 6: Voice message support (Whisper STT + Bark TTS, local processing)
- Phase 6b: Agentic proactive core (LangGraph, quality-gated nudges, Langfuse/Prometheus)
- Phase 7: Multi-user support (family/team mode)
- Phase 8: Signal/Discord/Matrix integrations
- Phase 9: Web dashboard for insights and configuration
- Phase 10: Plugin marketplace with community skills
Want to influence the roadmap? Open a Discussion or Issue!
RaccBuddy is built with privacy as the foundation:
- All your data: Messages, contacts, relationships, habits, embeddings
- Database: Runs on your machine via Docker or local PostgreSQL
- LLM inference: Uses local Ollama by default (no data sent to cloud)
- Embeddings: Generated locally with
nomic-embed-text
If you choose to use LLM_PROVIDER=xai:
- Only the ContextBuilder-assembled context (up to
MAX_CONTEXT_TOKENS, default 30,000 — a token-budgeted subset) is sent to xAI - No raw message archives, no raw embeddings, no relationship tables
- You control what's shared via environment variables and budget ratios
- Never commit
.envto version control (already in.gitignore) - Rotate your Telegram bot token if exposed
- Use strong PostgreSQL passwords in production
- Run behind a firewall if exposing the REST API
- Review the code — it's open source for complete transparency
- Old conversation details are summarized to save space
- Owner memories are retained for 90 days by default (configurable via
OWNER_MEMORY_RETENTION_DAYS) - You can delete the database anytime:
docker compose down -v
Open an issue on GitHub Issues with:
- RaccBuddy version / commit hash
- Operating system
- Steps to reproduce
- Relevant logs (remove sensitive data!)
We'd love to hear your ideas! Open a GitHub Issue with the enhancement label.
- Check the Troubleshooting section above
- Review existing GitHub Issues
- Start a Discussion for questions
As a beta tester, your feedback is invaluable:
- Report bugs, no matter how small
- Share feature ideas and use cases
- Contribute improvements via pull requests
- Help us improve documentation
We welcome contributions! Here's how:
- Fork the repository on GitHub
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/raccbuddy.git cd raccbuddy - Create a branch:
git checkout -b feat/amazing-feature
- Set up your environment: Follow Installation Method 2
- Make your changes
- Run tests:
pytest tests/ -v
- Commit with conventional commits:
git commit -m "feat: add amazing new feature" - Push to your fork:
git push origin feat/amazing-feature
- Open a Pull Request on GitHub
- Read the project instructions: .github/copilot-instructions.md
- Python 3.12+ with full type hints
- Use
async/awaitfor I/O operations - Follow black + ruff formatting (run
black . && ruff check .) - Write tests for new features (see
tests/folder) - Use
ContextBuilderfor all LLM calls — never build prompts manually (uses summaries + semantic retrieval + token budgets) - Document your code with clear docstrings
We use Conventional Commits:
feat:— New featurefix:— Bug fixdocs:— Documentation changestest:— Adding or updating testsrefactor:— Code restructuringchore:— Maintenance tasks
- 🌐 Platform bridges: Signal, Discord, Matrix, iMessage
- 🎯 Nudge skills: More proactive reminder types
- 🔒 Privacy audits: Security reviews and pen testing
- ⚡ Performance: Token efficiency, query optimization
- 📚 Documentation: Tutorials, guides, API docs
- 🧪 Testing: Expand test coverage, integration tests
- 🎨 Design: Logo improvements, UI mockups for future web interface
Linting & Formatting:
black .
ruff check .Type Checking:
mypy src/Running Tests:
pytest tests/ -v --tb=short
pytest tests/test_memory.py -v # Single test fileDatabase Migrations:
# Create a new migration
alembic revision --autogenerate -m "description"
# Apply migrations
alembic upgrade head
# Rollback one migration
alembic downgrade -1MIT — see the LICENSE file for details.
Made with ❤️ in Trento, Italy
🦝 Stay connected. Stay mindful. Stay raccoon. 🦝