Value-first Reddit reply assistant with Telegram approval flow.
Scans Reddit communities for relevant conversations, drafts helpful replies via AI, and sends candidates to Telegram for human approval before posting. Named after Cyrano de Bergerac — the original reply guy.
Forked from OutreachPilot, rewritten with Claude, Telegram, and PRAW.
config/projects/{name}/
personality.yml Your voice, tone, project info
subreddits.yml Communities to monitor
filters.yml Pre-filters + AI scoring preferences
|
v
┌─────────────────────────────┐
│ Reddit scanner │ Public JSON API, rate-limited
└─────────────────────────────┘
|
v
┌─────────────────────────────┐
│ Pre-filter (zero AI cost) │ Keywords, score, age, flairs
└─────────────────────────────┘
|
v
┌─────────────────────────────┐
│ Pass 1: Haiku scoring │ Yes / Maybe / No + why
└─────────────────────────────┘
| (only Yes/Maybe continue)
v
┌─────────────────────────────┐
│ Pass 2: Sonnet drafting │ Full reply in your voice
└─────────────────────────────┘
|
v
┌─────────────────────────────┐
│ Telegram approval card │ [Approve] [Edit] [Skip] [No Plug]
└─────────────────────────────┘
|
v
┌─────────────────────────────┐
│ Post via PRAW │ From your Reddit account
└─────────────────────────────┘
Every reply is human-approved. The AI drafts; you decide.
git clone https://github.com/KerryJones/cyrano.git
cd cyrano
python3 -m venv .venv
source .venv/bin/activate
pip install -e .Copy and fill in your credentials:
cp .env.example .envRequired in .env:
ANTHROPIC_API_KEY— for Claude via LiteLLMTELEGRAM_BOT_TOKEN— from @BotFatherTELEGRAM_CHAT_ID— your personal chat IDREDDIT_CLIENT_ID,REDDIT_CLIENT_SECRET,REDDIT_USERNAME,REDDIT_PASSWORD— for posting
python -m cyrano scan # One-shot scan, log actionable signals
python -m cyrano scan --project X # Scan one project only
python -m cyrano run # Scheduler + Telegram bot (production)
python -m cyrano bot # Telegram bot only (test approval flow)Each project gets its own directory under config/projects/:
config/projects/
├── matcha/
│ ├── personality.yml # Voice, bio, project info, plug criteria
│ ├── subreddits.yml # Communities to monitor
│ └── filters.yml # Pre-filters + AI preferences
├── rowcraft/
│ └── ...
└── dealcred/
└── ...
Cyrano scans all projects on each cycle. Telegram cards are tagged with the project name.
Defines your voice and when to mention your project:
name: "Kerry"
bio: "Software engineer who rows on a Concept2 daily..."
project:
name: "RowCraft"
description: "Structured Concept2 workouts with BLE coaching"
plug_when:
- someone is asking for a Concept2 workout app
tone:
style: "fellow rower who's also an engineer"
dos:
- Share specific workout recommendations with splits
donts:
- Never lead with the app — always lead with advice
example_comments:
- "For a 2K, your target should be roughly your steady state pace minus 6-8 splits..."Pre-filters run before any AI calls (zero cost). AI preferences guide the Yes/Maybe/No scoring:
thresholds:
min_score: 2
max_comments: 300
max_age_hours: 24
ai_preferences:
prefer_topics:
- asking for help or recommendations
avoid_topics:
- memes with no substance
engagement_notes: >
Value-first. Only mention the project if it directly solves their problem.Cost optimization: most signals are "No" and never hit the expensive model.
| Pass | Model | Purpose | Cost |
|---|---|---|---|
| 1 | Haiku | Relevance scoring (Yes/Maybe/No + why) | ~$0.001/signal |
| 2 | Sonnet | Full reply drafting (only for Yes/Maybe) | ~$0.01/signal |
For 2-3 projects with 15 subreddits, 2 scans/day: **$4-5/month**.
Runs scans automatically during configured hours:
SCAN_CRON=*/30 8-20 * * * # Every 30 min, 8am-8pm
TIMEZONE=America/New_YorkDocker + Dokploy (or any Docker host):
docker compose up --build -d# docker-compose.yml
services:
cyrano:
build: .
env_file: .env
volumes:
- ./data:/app/data
- ./config:/app/config
restart: unless-stoppedcyrano/
├── cyrano/
│ ├── __main__.py # CLI: scan / run / bot
│ ├── pipeline.py # Scan orchestration
│ ├── models.py # ScoredSignal dataclass
│ ├── config.py # Settings + multi-project loading
│ ├── scheduler.py # APScheduler cron runner
│ ├── scanners/
│ │ ├── base.py # Scanner protocol + data models
│ │ └── reddit.py # Reddit JSON API scanner
│ ├── analyzers/
│ │ ├── pipeline.py # Two-pass analysis (Haiku + Sonnet)
│ │ ├── llm_client.py # LiteLLM wrapper
│ │ └── base.py # Analysis dataclass
│ ├── telegram/
│ │ ├── bot.py # Approval flow + callback handlers
│ │ └── formatter.py # Message rendering + keyboards
│ ├── reddit/
│ │ └── poster.py # PRAW posting with rate limiting
│ ├── filters/
│ │ ├── rule_filter.py # Pre-filter (keywords, score, age)
│ │ └── dedup.py # Cross-day deduplication
│ ├── personas/
│ │ └── prompt_builder.py # LLM prompt construction
│ └── storage/
│ ├── signals.py # Daily signal JSON files
│ ├── approvals.py # Approval decision records
│ ├── post_history.py # Posted reply audit trail
│ └── progress.py # Checkpoint/resume
├── config/
│ └── projects/ # Per-project YAML configs
├── Dockerfile
├── docker-compose.yml
├── pyproject.toml
└── .env.example
AGPL-3.0 — Free to use, modify, and self-host.
Forked from OutreachPilot by Saurabh Singh.