Files
RedditBot/docs/configuration.md
T

16 KiB

Configuration Guide

Complete reference for configuring RedditBot.


Table of Contents

  1. Configuration Overview
  2. Configuration Storage
  3. Environment Variables
  4. Application Settings
  5. Runtime Configuration
  6. Configuration Validation
  7. 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:

  1. Reads the singleton app_config record from SQLite
  2. Imports config.yaml only when upgrading an existing database that has no settings record
  3. Validates the entire configuration tree using Zod
  4. Returns a strongly-typed Config object

Application-owned settings are edited from the dashboard and saved to SQLite. OPENROUTER_API_KEY, WEB_DASHBOARD_TOKEN, REDDIT_BOT_AGENT_READ_TOKEN, REDDIT_BOT_AGENT_CONTROL_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
REDDIT_BOT_AGENT_READ_TOKEN No string Least-privilege GET/SSE agent access separate-read-secret
REDDIT_BOT_AGENT_CONTROL_TOKEN No string Read access plus /api/v1 controls/jobs separate-control-secret
REDDIT_BOT_API_URL MCP only URL HTTP base URL used by npm run mcp http://127.0.0.1:3000
REDDIT_BOT_AGENT_TOKEN MCP only string Token selected for the MCP process separate-read-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
REDDIT_BOT_AGENT_READ_TOKEN=separate-read-secret
REDDIT_BOT_AGENT_CONTROL_TOKEN=separate-control-secret

Note

: Add .env to .gitignore - never commit credentials.

Option 2: Shell export

export OPENROUTER_API_KEY=sk-or-v1-abc123...
export WEB_DASHBOARD_TOKEN=long-random-secret
export REDDIT_BOT_AGENT_READ_TOKEN=separate-read-secret
export REDDIT_BOT_AGENT_CONTROL_TOKEN=separate-control-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
  - REDDIT_BOT_AGENT_READ_TOKEN=separate-read-secret
  - REDDIT_BOT_AGENT_CONTROL_TOKEN=separate-control-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

Each subreddit also has a conversation behaviour in the dashboard:

  • legacy preserves the existing three-turn media-request flow.
  • r4r continues general conversation autonomously and never requests media.
  • r4r-media continues general conversation for rapportTurnsBeforeMediaAsk, makes one optional non-explicit image request, and never repeats it.
  • manual records the reply for human handling without sending an automated response.

maxAutomatedTurns is configurable for r4r and r4r-media up to 20. In hybrid mode, rapportTurnsBeforeMediaAsk must be lower than maxAutomatedTurns. A conversation snapshots these values when its first verified reply arrives, so later settings changes affect new conversations only.

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:

  1. Open the settings modal
  2. Modify desired values
  3. 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:

  1. Verify config.yaml is in the project root
  2. Check YAML syntax (use a YAML linter)
  3. Verify environment variables are set correctly
  4. Check bot logs for specific validation errors

Account Authentication Not Working

Symptom: Account work remains paused.

Steps:

  1. Sign in to Reddit in local Chrome
  2. Open Reddit Chat and wait for the extension badge to show OK
  3. Export and upload a fresh combined session dump
  4. Check dashboard logs for Reddit or Matrix identity verification errors

AI Not Working

Symptom: Image analysis fails or returns errors.

Steps:

  1. Verify OPENROUTER_API_KEY is valid
  2. Check API key has sufficient balance
  3. Verify openrouter.model is available on OpenRouter
  4. Check fallback models are set correctly
  5. Review logs for specific AI errors

Browser Session Expired

Symptom: Bot stops with "Browser session expired" error.

Steps:

  1. Open Reddit Chat in the local Chrome profile containing the extension
  2. Export and upload a fresh session dump
  3. Delete the downloaded dump after verification

Port Already in Use

Symptom: Dashboard fails to start with "Port already in use".

Steps:

  1. Change web.port in config.yaml
  2. Or kill the process using the port: lsof -i :3000