# derp - Backlog ## Core - [x] Multi-server support (per-server config, shared plugins) - [x] Stable plugin API (versioned, breaking change policy) - [x] Paste overflow (auto-paste long output to FlaskPaste) - [x] URL shortener integration (shorten URLs in subscription announcements) - [x] Webhook listener (HTTP endpoint for push events to channels) - [x] Granular ACLs (per-command: trusted, operator, admin) ## LLM Bridge Goal: let an LLM agent interact with the bot over IRC in real-time, with full machine access (bash, file ops, etc.). ### Architecture Owner addresses the bot on IRC. A bridge daemon reads addressed messages, feeds them to an LLM with tool access, and writes replies back through the bot. The bot already has `owner` config (`[bot] owner` hostmask patterns) to gate who can trigger LLM interactions. ``` IRC -> bot stdout (addressed msgs) -> bridge -> LLM API -> bridge -> bot inbox -> IRC ``` ### Approach options (ranked) 1. **Claude Code Agent SDK** (clean, non-trivial) - Custom Python agent using `anthropic` SDK with `tool_use` - Define tools: bash exec, file read/write, web fetch - Persistent conversation memory across messages - Full control over the event loop -- real-time IRC is natural - Tradeoff: must implement and maintain tool definitions 2. **Claude Code CLI per-message** (simple, stateless) - `echo "user said X" | claude --print --allowedTools bash,read,write` - Each invocation is a cold start with no conversation memory - Simple to implement but slow startup, no multi-turn context - Could pass conversation history via system prompt (fragile) 3. **Persistent Claude Code subprocess** (hack, fragile) - Long-running `claude` process with stdin/stdout piped - Keeps context across messages within a session - Not designed for this -- output parsing is brittle - Session may drift or hit context limits ### Bot-side plumbing needed - `--llm` CLI flag: route logging to file, stdout for addressed msgs - `_is_addressed()`: DM or nick-prefixed messages - `_is_owner()`: only owner hostmasks trigger LLM routing - Inbox file polling (`/tmp/llm-inbox`): bridge writes ` ` - `llm-send` script: line splitting (400 char), FlaskPaste overflow - Stdout format: `HH:MM [#chan] text` / `HH:MM --- status` - Only LLM-originated replies echoed to stdout (not all bot output) ### Previous attempt (reverted) The `--llm` mode was implemented and tested (commit ea6f079, reverted in 6f1f4b2). The stdout/stdin plumbing worked but Claude Code CLI cannot act as a real-time daemon -- each tool call is a blocking round-trip, making interactive IRC conversation impractical. The code is preserved in git history for reference. ## Plugins -- Security/OSINT - [x] `emailcheck` -- SMTP VRFY/RCPT TO verification - [x] `canary` -- canary token generator/tracker - [x] `virustotal` -- hash/URL/IP/domain lookup (free API) - [x] `abuseipdb` -- IP abuse confidence scoring (free tier) - [x] `jwt` -- decode tokens, show claims/expiry, flag weaknesses - [x] `mac` -- OUI vendor lookup (local IEEE database) - [x] `pastemoni` -- monitor paste sites for keywords - [x] `internetdb` -- Shodan InternetDB host recon (free, no API key) ## Plugins -- Utility - [x] `paste` -- manual paste to FlaskPaste - [x] `shorten` -- manual URL shortening - [x] `cron` -- scheduled bot commands on a timer ## Teams - [x] Microsoft Teams adapter via outgoing webhooks - [x] TeamsBot + TeamsMessage (duck-typed with IRC Message) - [x] HMAC-SHA256 webhook validation - [x] Permission tiers via AAD object IDs - [x] Route `send()` through SOCKS5 proxy (bug fix) - [ ] Adaptive Cards for richer formatting - [ ] Graph API integration for DMs - [ ] Teams event handlers (member join/leave) ## Telegram - [x] Telegram adapter via long-polling (no SDK) - [x] TelegramBot + TelegramMessage (duck-typed with IRC Message) - [x] All HTTP through SOCKS5 proxy - [x] Message splitting at 4096-char limit - [x] @botusername suffix stripping in groups - [x] Permission tiers via user IDs - [ ] Inline keyboard support for interactive replies - [ ] Markdown/HTML formatting mode toggle - [ ] Webhook mode (for setWebhook instead of getUpdates) ## Discord - [ ] Discord adapter via WebSocket gateway + REST API (no SDK) - [ ] DiscordBot + DiscordMessage (duck-typed with IRC Message) - [ ] Gateway intents for message content - [ ] Message splitting at 2000-char limit - [ ] Permission tiers via user/role IDs - [ ] Slash command registration (optional) ## Matrix - [ ] Matrix adapter via long-poll `/sync` endpoint (no SDK) - [ ] MatrixBot + MatrixMessage (duck-typed with IRC Message) - [ ] Room-based messaging (rooms map to channels) - [ ] Power levels map to permission tiers - [ ] E2EE support (optional, requires libolm) ## XMPP - [ ] XMPP adapter via persistent TCP + XML stanzas (no SDK) - [ ] XMPPBot + XMPPMessage (duck-typed with IRC Message) - [ ] MUC (Multi-User Chat) support -- rooms map to channels - [ ] SASL authentication - [ ] TLS/STARTTLS connection ## Performance - [x] Iterative `_extract_videos` in alert.py (replaced 51K-deep recursion) - [x] Bypass SOCKS5 for local services (SearXNG `proxy=False`) - [x] Connection pool tuning (30 pools / 8 connections) - [ ] Async HTTP client (aiohttp + aiohttp-socks) to avoid blocking executors - [x] Connection pooling via urllib3 SOCKSProxyManager - [x] Batch OG fetch via ThreadPoolExecutor - [x] HTTP opener caching at module level - [x] Per-backend error tracking with exponential backoff ## Mumble - [x] Mumble adapter via TCP/TLS + protobuf control channel (no SDK) - [x] MumbleBot + MumbleMessage (duck-typed with IRC Message) - [x] Text chat only (no voice) - [x] Channel-based messaging - [x] Minimal protobuf encoder/decoder (no protobuf dep) - [x] pymumble transport rewrite (voice + text) - [x] Music playback (yt-dlp + ffmpeg + Opus) - [x] Voice STT/TTS (Whisper + Piper) - [x] Multi-bot with per-bot plugin filtering - [x] Configurable voice profiles (voice, FX chain) - [x] Self-mute support (auto mute/unmute around audio) - [x] Bot audio isolation (ignore own bots in sound callback) - [x] Pause/unpause with position tracking, stale stream re-download, rewind + fade-in - [x] Autoplay continuous radio (random kept track, silence-aware, configurable cooldown) - [x] Periodic resume state persistence (survives hard kills) - [x] Track duration in `!np` (ffprobe), optional `!announce` toggle - [x] Direct bot addressing (`merlin: say `) - [x] Self-deafen on connect - [ ] Per-channel voice settings (different voice per channel) - [ ] Voice activity log (who spoke, duration, transcript) ## Music Discovery - [x] Last.fm integration (API key, free tier) - [x] `!similar` command -- find similar artists/tracks via Last.fm - [x] `!tags` command -- show genre/style tags for current track - [x] Auto-discover similar tracks during autoplay via Last.fm/MusicBrainz - [x] MusicBrainz fallback for `!similar` and `!tags` (no API key required) ## Slack - [ ] Slack adapter via Socket Mode WebSocket (no SDK) - [ ] SlackBot + SlackMessage (duck-typed with IRC Message) - [ ] OAuth token + WebSocket for events - [ ] Channel/DM messaging - [ ] Permission tiers via user IDs ## Mattermost - [ ] Mattermost adapter via WebSocket API (no SDK) - [ ] MattermostBot + MattermostMessage (duck-typed with IRC Message) - [ ] Self-hosted Slack alternative - [ ] Channel/DM messaging ## Bluesky - [ ] Bluesky adapter via AT Protocol firehose + REST API (no SDK) - [ ] BlueskyBot + BlueskyMessage (duck-typed with IRC Message) - [ ] Mention-based command dispatch - [ ] Post/reply via `com.atproto.repo.createRecord` ## Testing - [x] Plugin command unit tests (encode, hash, dns, cidr, defang) - [x] CI pipeline (Gitea Actions)