14 KiB
Configuration Guide
Complete reference for configuring RedditBot.
Table of Contents
- Configuration Overview
- Configuration Storage
- Environment Variables
- Application Settings
- Runtime Configuration
- Configuration Validation
- Troubleshooting
Configuration Overview
RedditBot uses a layered configuration approach:
┌──────────────────────────────────────────────────────────────┐
│ Priority Order (High → Low) │
├──────────────────────────────────────────────────────────────┤
│ 1. Environment Variables │
│ (OPENROUTER_API_KEY, WEB_DASHBOARD_TOKEN) │
│ │
│ 2. config.yaml │
│ (Primary configuration file) │
│ │
│ 3. Defaults │
│ (Hardcoded defaults in code) │
└──────────────────────────────────────────────────────────────┘
Configuration is loaded at startup by loadConfig() in src/config/index.ts, which:
- Reads the singleton
app_configrecord from SQLite - Imports
config.yamlonly when upgrading an existing database that has no settings record - Validates the entire configuration tree using Zod
- Returns a strongly-typed
Configobject
Application-owned settings are edited from the dashboard and saved to SQLite. OPENROUTER_API_KEY, WEB_DASHBOARD_TOKEN, and DATABASE_PATH remain environment-owned bootstrap values and are never stored in app_config.
Configuration Storage
Legacy config.yaml
config.yaml is retained temporarily as a one-time migration source for existing installations. Once every deployed database contains an app_config row, it can be removed in a follow-up release.
RedditBot/
├── config.yaml # ← Main configuration
├── package.json
├── tsconfig.json
└── src/
Data Directory
Runtime data is stored in data/ (created automatically):
data/
├── reddit-bot.db # SQLite database
├── browser/ # Browser session data (cookies, storage)
├── media/ # Downloaded media files
│ ├── index.json # Media index (SHA-1 → filename)
│ ├── abc123.jpg # Media file 1
│ └── def456.png # Media file 2
└── chats/ # Cached conversation JSON files
├── chat_abc123.json
└── chat_def456.json
Environment Variables
Environment variables provide secrets and bootstrap settings that are intentionally excluded from SQLite.
| Variable | Required | Type | Description | Example |
|---|---|---|---|---|
OPENROUTER_API_KEY |
Yes | string | OpenRouter API key for AI services | sk-or-v1-abc123... |
WEB_DASHBOARD_TOKEN |
Yes when dashboard enabled | string | Dashboard access token | long-random-secret |
DATABASE_PATH |
No | string | SQLite database location | ./data/reddit-bot.db |
Setting Environment Variables
Option 1: .env file (recommended for development)
Create a .env file in the project root:
OPENROUTER_API_KEY=sk-or-v1-abc123...
WEB_DASHBOARD_TOKEN=long-random-secret
Note
: Add
.envto.gitignore- never commit credentials.
Option 2: Shell export
export OPENROUTER_API_KEY=sk-or-v1-abc123...
export WEB_DASHBOARD_TOKEN=long-random-secret
Option 3: Docker
Pass via docker-compose.yml or Docker CLI:
environment:
- OPENROUTER_API_KEY=sk-or-v1-abc123...
- WEB_DASHBOARD_TOKEN=long-random-secret
Application Settings
Use Settings in the dashboard for monitoring, rate limits, dry-run behaviour, subreddits, models, prompts, filtering, media sync, and strategy configuration. The advanced JSON editor exposes settings that do not yet have dedicated controls; its payload is validated by the server before it is saved.
The YAML examples below document the legacy field layout used during one-time migration.
Complete reference for every configuration option.
Reddit Settings
reddit:
# Subreddits to monitor for new posts
subreddits:
- gonewild
- ratemyboobs
- HomemadeNsfw
- realgirls
- plussize_gonewild
# ... add or remove subreddits
# Minutes between polling cycles
pollInterval: 15
# Target gender for image analysis filtering
# Options: "F" (female), "M" (male)
targetGender: "F"
# Keywords used to detect sellers/spam profiles
# Posts from users matching these keywords are skipped
sellerKeywords:
- seller
- onlyfans
- link in bio
- check my profile
- promo
- discount
- affiliate
OpenRouter AI Settings
openrouter:
# OpenRouter API key (can also be set via OPENROUTER_API_KEY env var)
apiKey: "sk-or-v1-abc123..."
# Primary AI model for image analysis
# Models must be available on OpenRouter
model: "meta-llama/llama-3.2-90b-vision-preview"
# Fallback models tried if the primary model refuses or fails
fallbackModels:
- "google/gemini-2.0-flash-001"
- "meta-llama/llama-3.2-11b-vision-instruct"
# Quick detection model (cheaper/faster, used for gender pre-filter)
quickModel: "google/gemini-2.0-flash-lite-001"
# System prompt for image analysis
# The AI will describe the image and detect gender
systemPrompt: |
Analyze this image and provide:
1. Gender detected (F or M)
2. Detailed description of the image content
3. Notable features (hair color, clothing, setting, etc.)
Return as JSON: {"gender": "F", "description": "...", "features": [...]}
# System prompt for message generation
# Used when crafting DMs to post authors
messagePrompt: |
Generate a natural, friendly DM for this Reddit post.
Image analysis: {description}
Post title: {title}
Strategy: {strategy}
Guidelines:
- Be complimentary but not creepy
- Reference something specific from the image
- Keep it under 2 sentences
- Sound like a genuine person, not a bot
- Do NOT ask for anything in return
Rate Limiting
rateLimit:
# Minimum delay between messages (milliseconds)
# Higher values reduce detection risk
minDelayMs: 30000
# Maximum messages per hour
# Bot will pause when this limit is reached
maxMessagesPerHour: 20
# Random jitter added to delay (milliseconds)
# Adds unpredictability to timing
jitterMs: 15000
Timing example with defaults:
Minimum delay: 30,000ms (30 seconds)
Jitter: 0 to 15,000ms (0-15 seconds)
Effective delay: 30-45 seconds between messages
Max messages: 20 per hour
Browser Settings
browser:
# Persistent managed-browser data populated only by verified imports
sessionDir: "./data/browser-session"
dryRun: false
Browser session persistence:
data/browser/
├── Default/
│ ├── Cookies # Reddit session cookies
│ ├── Local Storage # Local storage data
│ └── Preferences # Browser preferences
├── Login Data # Saved login info
└── Preferences # Browser state
Important
: Keep this directory intact. Deleting it requires re-login.
Database Settings
database:
# Path to SQLite database file
path: "./data/reddit-bot.db"
The database is auto-created on first run. Migrations run automatically on startup.
Media Sync Settings
mediaSync:
# Enable periodic media synchronization
enabled: true
# Interval between sync cycles (minutes)
intervalMinutes: 30
Sync behavior:
- Incremental sync (automatic): Downloads media from top 10 conversations
- Full sync (manual via dashboard): Downloads media from all conversations
Auto-Reply Settings
autoReply:
# Enable automatic chat replies
enabled: true
# Auto-send replies (true) or mark as pending for approval (false)
autoSend: false
# Minutes between checking for new messages
checkInterval: 10
Reply modes:
| autoSend | Behavior |
|---|---|
true |
Bot sends AI-generated replies automatically |
false |
Bot suggests replies, user approves via dashboard |
Strategy Variants (A/B Testing)
strategyVariants:
# Variant 1: Compliment-based
- name: "compliment"
prompt: |
Write a friendly compliment about the person's appearance.
Be genuine and specific. Keep it short and natural.
enabled: true
# Variant 2: Question-based
- name: "question"
prompt: |
Write a friendly message that includes a question.
Engage them in conversation naturally.
enabled: true
# Variant 3: Casual observation
- name: "observation"
prompt: |
Write a casual observation about the photo or setting.
Sound like you're commenting to a friend.
enabled: true
Web Dashboard Settings
web:
# Port for the web dashboard
port: 3000
Global Settings
# Global dry run mode
# When true, all actions are logged but not actually performed
dryRun: false
# Number of successful message examples to include in prompts
fewShotExamples: 3
# Minimum responses needed before trusting strategy stats
minStrategySamples: 10
# Exploration rate for A/B testing (0.0 to 1.0)
# 0.15 = 15% of messages use random variants (exploration)
explorationRate: 0.15
Runtime Configuration
The following settings can be modified via the web dashboard without restarting the bot:
| Setting | Endpoint | Type | Description |
|---|---|---|---|
rateLimit.minDelayMs |
PUT /api/config |
number | Message delay |
rateLimit.maxMessagesPerHour |
PUT /api/config |
number | Hourly cap |
rateLimit.jitterMs |
PUT /api/config |
number | Jitter range |
reddit.pollInterval |
PUT /api/config |
number | Poll frequency |
dryRun |
PUT /api/config |
boolean | Dry run mode |
Updating Runtime Config
Via dashboard:
- Open the settings modal
- Modify desired values
- Click "Save"
Via API:
curl -X PUT http://localhost:3000/api/config \
-H "Content-Type: application/json" \
-d '{
"rateLimit": {
"minDelayMs": 45000,
"maxMessagesPerHour": 15,
"jitterMs": 20000
},
"dryRun": true
}'
Note
: Runtime changes are in-memory only. They are lost when the bot restarts. To make changes persistent, update
config.yaml.
Configuration Validation
All configuration is validated using Zod at startup. Invalid configuration will cause the bot to exit with a descriptive error.
Validation Rules
| Field | Validation |
|---|---|
reddit.subreddits |
Must be non-empty array of strings |
reddit.pollInterval |
Must be positive integer |
reddit.targetGender |
Must be "F" or "M" |
openrouter.apiKey |
Must be non-empty string |
openrouter.model |
Must be non-empty string |
openrouter.fallbackModels |
Must be non-empty array |
rateLimit.minDelayMs |
Must be positive integer |
rateLimit.maxMessagesPerHour |
Must be positive integer |
rateLimit.jitterMs |
Must be non-negative integer |
browser.sessionDir |
Must be non-empty string |
browser.dryRun |
Must be boolean |
database.path |
Must be non-empty string |
mediaSync.enabled |
Must be boolean |
mediaSync.intervalMinutes |
Must be positive integer (if enabled) |
autoReply.enabled |
Must be boolean |
autoReply.autoSend |
Must be boolean |
autoReply.checkInterval |
Must be positive integer (if enabled) |
strategyVariants |
Must be array with name + prompt |
web.port |
Must be integer 1-65535 |
dryRun |
Must be boolean |
Common Validation Errors
Error: Invalid config: openrouter.apiKey must be a string
Fix: Set OPENROUTER_API_KEY environment variable or add apiKey to config.yaml
Error: Invalid config: reddit.subreddits must be a non-empty array
Fix: Add at least one subreddit to reddit.subreddits in config.yaml
Error: Invalid config: browser.sessionDir must be a string
Fix: Ensure browser.sessionDir is set in config.yaml
Troubleshooting
Configuration Not Loading
Symptom: Bot fails to start with validation errors.
Steps:
- Verify
config.yamlis in the project root - Check YAML syntax (use a YAML linter)
- Verify environment variables are set correctly
- Check bot logs for specific validation errors
Account Authentication Not Working
Symptom: Account work remains paused.
Steps:
- Sign in to Reddit in local Chrome
- Open Reddit Chat and wait for the extension badge to show
OK - Export and upload a fresh combined session dump
- Check dashboard logs for Reddit or Matrix identity verification errors
AI Not Working
Symptom: Image analysis fails or returns errors.
Steps:
- Verify
OPENROUTER_API_KEYis valid - Check API key has sufficient balance
- Verify
openrouter.modelis available on OpenRouter - Check fallback models are set correctly
- Review logs for specific AI errors
Browser Session Expired
Symptom: Bot stops with "Browser session expired" error.
Steps:
- Open Reddit Chat in the local Chrome profile containing the extension
- Export and upload a fresh session dump
- Delete the downloaded dump after verification
Port Already in Use
Symptom: Dashboard fails to start with "Port already in use".
Steps:
- Change
web.portinconfig.yaml - Or kill the process using the port:
lsof -i :3000