Skip to content

Telegram 3-Bot Fleet: Build Plan

Created: 2026-04-23 Owner: Claude Code (this session) Context: Justin asked for dedicated bots for UPDATES (push-driven roundups + 2-way replies) and INBOX (voice/text quick capture with smart routing), alongside the existing @GregTwoPointO chat bot. This plan supersedes notify.sh for user-facing alerts.


Target State

Bot Role Context Model Cost Profile
@GregTwoPointO_Bot Conversation, architecture, deep work INFINITE (persistent session, auto-compact) Opus/Sonnet on demand
@ForgeUpdates_Bot (NEW) Morning roundup + scheduled pushes + reactive replies WINDOWED (24h rolling via session restart) Haiku composer + Sonnet for replies
@ForgeInbox_Bot (NEW) Voice/text capture → Whisper → intent route → execute EPHEMERAL (fresh Haiku per message) Near-zero per message

What Pushes to @ForgeUpdates_Bot

Morning Roundup (07:30 daily)

Single composed summary containing: - 📧 Pressing emails, business accounts only (Nova, JWVR, Gus Outdoor, Wiebelhaus, Sip-N-Serve). Top 3 w/ sender + one-line summary. NEVER personal Gmail (hard security rule). - 📰 News roundup, 3 bullets curated for Justin's interests (Shopify/e-com, AI, Austin tech, outdoor/overland) - 🎯 Yesterday's wins, parsed from memory/daily/YYYY-MM-DD.md checkpoints - 😴 Sleep, score, HRV, stages from Eight Sleep Context API - 💪 Wellness: HRV trend, readiness, stress from Garmin Context API - 📅 Today's schedule, next 12h from Google Calendar - 🏠 Home state, presence, temp, anomalies from HA Context API - 🔧 Fleet health, one-line status (green/yellow/red counts)

Event-Driven Pushes

  • Sleep score on wakeup (Eight Sleep poller threshold trigger)
  • Wellness alerts (HRV crash, high stress)
  • Security events (Frigate object detections at unusual hours, camera offline)
  • Fleet health critical (disk >90%, service down, failed workers)
  • Scheduled nudges from inbox bot ("ping me at 6pm about X")

Evening Recap (22:00 daily)

  • Today's accomplishments (synthesized from day's checkpoints)
  • Tomorrow's schedule preview
  • Wellness summary

What @ForgeInbox_Bot Captures

Text or voice note → Whisper transcribes → intent router dispatches:

Intent Example utterance Action
TODO "remind me to sign up for Austin marathon" TickTick API create
CALENDAR "haircut next Friday at 2pm" Google Calendar event
NOTE "save idea: rebuild JWVR landing with video hero" Append to memory/general/ideas.md
NUDGE "ping me at 6pm about calling mom" Scheduled Telegram push via cron + at
SHOPPING "add oat milk to grocery list" TickTick shopping list
QUESTION "how's Plex doing" Spawn chat-style reply (reroute to @GregTwoPointO context)

Reply with ✅ + one-line confirmation so Justin knows it landed.


Build Phases

PHASE 1: Retire notify.sh + build Updates Bot foundation (45 min)

1.1 New bots via BotFather - Justin creates @yourname_updates_bot and @yourname_inbox_bot - Pastes tokens → I save to ~/.forge-secrets/telegram-updates.env + ~/.forge-secrets/telegram-inbox.env

1.2 telegram-push helper (replaces notify.sh for user-facing pushes) - scripts/integrations/telegram/push.sh <bot> <priority> <title> <body> - bot ∈ {chat, updates, inbox} - Direct Telegram sendMessage, no Claude involvement - Retire notify.sh (or leave dormant, no dependencies break)

1.3 Updates bot plugin attach - Separate TELEGRAM_STATE_DIR=~/.claude/channels/telegram-updates/ - Launch a dedicated Claude Code session (Sonnet) bound to Updates bot via --channels plugin:telegram@claude-plugins-official - Systemd unit forge-claude-updates.service to keep it running - Session restarts nightly via systemd timer → gives the "24h rolling context" effect

PHASE 2: Morning Roundup Worker (1 hr)

2.1 Build scripts/integrations/roundup/morning.sh - Haiku claude -p with structured prompt - Ingests from: - curl http://127.0.0.1:7358/context?about=all&window=24h (wellness + home) - Grep last checkpoint from memory/daily/$(date -d yesterday +%F).md - Google Calendar API (need to wire OAuth, see 2.2) - Gmail API (business accounts only, see 2.3) - News via scripts/news/fetch.sh (new, simple RSS aggregator) - Composes markdown summary - Calls push.sh updates info "Morning Roundup" "$summary"

2.2 Google Calendar wiring - Create Google Workspace OAuth app (business workspace, NOT personal) - Store token at ~/.forge-secrets/google-calendar.env - Helper scripts/integrations/gcal/list.py --window today

2.3 Gmail business wiring - Per business account (Nova, JWVR, etc.), separate OAuth per account - Tokens at ~/.forge-secrets/gmail-{brand}.env - Helper scripts/integrations/gmail/pressing.py --account nova --limit 3 - Hard guard: script aborts if account domain is @gmail.com for justinwieb personal

2.4 News aggregator - scripts/news/fetch.sh: RSS from ~5 curated feeds (TechCrunch, Shopify blog, Austin Business Journal, outdoor/overland, AI news) - Haiku pass: pick top 3 most relevant to Justin's active projects

2.5 Cron trigger - 30 7 * * * /home/justinwieb/forge/scripts/integrations/roundup/morning.sh

PHASE 3: Inbox Bot (1.5 hr)

3.1 Standalone bot service - New: scripts/integrations/telegram/inbox_bot.py - Own systemd unit forge-telegram-inbox.service - Long-poll, single authorized user, auto-pair first /start

3.2 Voice pipeline - Telegram voice note → getFile download → mp3/ogg - Whisper transcription. Two options: - Local: faster-whisper via uv venv, CPU-only (slower but private, free) - Cloud: OpenAI Whisper API (fast, ~$0.006/min, not on Max plan) - Recommend: local for privacy + free

3.3 Intent router - claude -p --model haiku with JSON-output prompt - Input: transcribed text - Output: {intent, payload, confidence} - Handler dispatches per intent table above

3.4 Action handlers - TickTick: OAuth app + scripts/integrations/ticktick/create.py - Google Calendar: reuse 2.2 helper - Notes: append to memory/general/ideas.md - Nudges: write file to ~/scheduled-nudges/, cron watches + fires via push.sh

PHASE 4: Plumbing + polish (30 min)

4.1 Event-driven pushes wired - Eight Sleep poller on score change → push.sh updates - Wellness threshold monitor → push.sh updates - Frigate unusual-hours detection (new monitor) → push.sh updates - fleet-status monitor critical → push.sh updates

4.2 MEMORY.md updates - Register all new scripts + services - Update Telegram Fleet Bot reference with 3-bot topology

4.3 Tests - Fire test morning roundup manually - Record a voice note to inbox bot, watch TickTick entry appear - Verify chat bot unchanged


Security Checklist

  • Personal Gmail NEVER touched (hard-coded abort if account email matches)
  • All tokens in ~/.forge-secrets/ (outside repo, chmod 600)
  • Each bot has its own allowlist, only Justin's Telegram user ID
  • Voice notes deleted after transcription (no audio retention)
  • OAuth scopes minimized (Calendar: read events only; Gmail: read metadata + subject only for roundup, NOT full message body)
  • Intent router has allowlist of intents, unknown intents refused, not executed

Open Questions for Justin

  1. Which bots, preferred names? @j_updates_bot, @jw_inbox_bot, etc.?
  2. Which business email accounts should roundup cover? (Nova, JWVR, Gus Outdoor, Wiebelhaus, Sip-N-Serve, pick)
  3. TickTick, does he already have account? Needs premium for API access.
  4. Local Whisper vs OpenAI API for voice? (Recommend local.)
  5. News feeds, wants me to pick defaults, or give a list?
  6. Morning roundup time, 07:30 default, or different? (Garmin/Eight Sleep poller already runs 07:30.)
  7. Evening recap, opt in? (Might be noise.)

Estimated Timeline

  • Phase 1: 45 min (blocked on token creation, 2 min from Justin)
  • Phase 2: 1 hr (blocked on Google OAuth if not already set up)
  • Phase 3: 1.5 hr (blocked on TickTick API key)
  • Phase 4: 30 min

Total work: ~4 hours active spread across sessions, but Phase 1+2 can land today if tokens arrive. Phase 3 (inbox) works standalone and can be deferred.


Rollback

If anything goes wrong: - All bots are independent, killing one doesn't affect others - systemctl stop forge-claude-updates or forge-telegram-inbox to disable - crontab -e to remove morning roundup trigger - notify.sh stays in tree as fallback (not removed, just retired)