A Chrome extension that uses Rust + WebAssembly to analyze YouTube and Twitch live chat in real-time. See what the conversation is really about — questions, sentiment, trending topics — without losing it in the scroll.
- Message Clustering: Automatically categorizes messages into Questions, Issues/Bugs, Requests, and General Chat using whole-word boundary matching to reduce false positives
- Semantic Clustering: When GPU is available, messages are classified by cosine similarity to prototype vectors using MiniLM embeddings — falls back silently to keyword matching
- Sentiment Analysis: Real-time mood indicator showing chat sentiment (excited, positive, angry, negative, confused, neutral) — positive/negative signals take priority over confusion markers
- Trending Topics: Word cloud of frequently mentioned terms, with special highlighting for emotes
- Session History: Save and review past session summaries with full sentiment breakdown and captured questions
- Smart Session Detection: Auto-prompts to save when stream chat goes inactive for 2+ minutes
- AI Summaries: Optional on-device chat summaries via Chrome's built-in AI (Gemini Nano); falls back gracefully to a rule-based "Basic mode" when unavailable
- Configurable Thresholds: Adjust analysis window size and inactivity timeout from the settings page
- Rust WASM Engine (
wasm-engine/): High-performance analysis compiled to WebAssembly- Message clustering (keyword-based fallback)
- Topic extraction with stop-word filtering
- Sentiment signal analysis
- Semantic AI Pipeline (
extension/sidebar/): In-browser ML for smarter clustering- MiniLM encoder via Transformers.js (WebGPU with WASM fallback)
- Cosine similarity routing to prototype vectors per category
- Automatic mode switching with "Semantic"/"Keyword" badge
- Chrome Extension (
extension/): Manifest V3 extension with sidebar UI- Real-time chat observation
- Mood indicator with theme-aware display
- Trending topics word cloud
- Automatic light/dark mode support (follows system theme)
- Build Scripts (
scripts/): Automated build pipeline from Rust → WASM → Extension
-
Build the WASM module:
chmod +x scripts/build.sh ./scripts/build.sh
-
Load extension in Chrome:
- Open
chrome://extensions/ - Enable Developer mode (top-right toggle)
- Click Load unpacked
- Select the
extension/folder
- Open
-
Test it:
- Navigate to a YouTube live stream or Twitch channel with active chat
- Click the extension icon to open the sidebar
- Watch the dashboard update in real-time:
- 🎭 Mood indicator shows overall chat sentiment
- 🏷️ Trending topics highlight what people are talking about
- 📊 Message clusters organize chat by type
- Click End Session to see a full summary with sentiment breakdown
- Switch to the History tab to view past sessions
chat-signal/
├── wasm-engine/ # Rust → WASM analysis engine
│ ├── Cargo.toml
│ └── src/lib.rs # Clustering, topics, sentiment
├── extension/ # Chrome extension (Manifest V3)
│ ├── manifest.json
│ ├── background.js # Service worker
│ ├── content-script.js # Chat DOM observer
│ ├── llm-adapter.js # Gemini Nano (Chrome built-in AI) + rule-based fallback
│ ├── storage-manager.js # Session history persistence
│ ├── options/ # Settings page
│ │ ├── options.html
│ │ ├── options.js
│ │ └── options.css
│ ├── settings-defaults.js # Shared default settings (single source of truth)
│ ├── sidebar/
│ │ ├── sidebar.html # Dashboard UI
│ │ ├── sidebar.css # Styling (light/dark theme support)
│ │ ├── sidebar.js # Main entry point, WASM loading
│ │ ├── encoder-adapter.js # MiniLM encoder (lazy-init, WebGPU/WASM)
│ │ ├── cosine-router.js # Semantic cosine classification
│ │ ├── routing-config.js # Seed phrases & thresholds
│ │ ├── modules/ # Modular components
│ │ │ └── gpu-scheduler.js # WebGPU mutex with priority scheduling
│ │ └── utils/ # Utility modules
│ │ ├── DOMHelpers.js # Safe DOM manipulation (DOMPurify)
│ │ ├── ValidationHelpers.js # Input validation & sanitization
│ │ └── FormattingHelpers.js # Text formatting utilities
│ └── wasm/ # (generated) WASM artifacts
├── docs/ # GitHub Pages site
│ ├── CNAME # Custom domain (chatsignal.dev)
│ ├── privacy-policy.md # Published privacy policy
│ ├── cws-justifications.md # CWS dashboard reference
│ ├── cws-store-listing.md # Store listing copy reference
│ └── store/ # CWS store assets
│ ├── promo-440x280.png # Promotional image
│ ├── screenshot-clusters.png # Screenshot: message clusters
│ ├── screenshot-mood.png # Screenshot: sentiment/mood
│ └── screenshot-topics.png # Screenshot: trending topics
├── tests/ # JavaScript tests
└── scripts/
├── build.sh # Build Rust → WASM → Extension
├── watch.sh # Dev mode with auto-rebuild
├── promo-image.mjs # Generate 440x280 promo image
└── screenshot.mjs # Generate 1280x800 CWS screenshots
-
Start watch mode:
chmod +x scripts/watch.sh ./scripts/watch.sh
-
Open a test stream (YouTube live or Twitch with active chat)
-
After code changes:
- Watch mode auto-rebuilds WASM
- Go to
chrome://extensions/ - Click reload icon on Chat Signal extension
- Refresh the stream page
-
Debugging:
- Check Chrome DevTools Console for validation errors and security warnings
- Logs are prefixed with module names:
[Encoder],[LLM],[Storage],[Sidebar] - Security blocks are logged when unsafe content is detected
Requires cargo-watch:
cargo install cargo-watchEdit wasm-engine/src/lib.rs and rebuild. The engine includes:
- Clustering: Keyword-based message categorization
- Topic Detection: Word frequency with smart stop-word filtering
- Sentiment Analysis: Lexicon-based mood detection
Word lists for emotes, stop words, and sentiment are defined at the top of lib.rs.
The extension uses a modular architecture with clear separation of concerns:
- Security-First Design: All DOM operations use safe helpers from
DOMHelpers.jswith XSS protection - Input Validation: Comprehensive validation of WASM data, user input, and stored settings via
ValidationHelpers.js - Session Persistence: Session summaries saved to
chrome.storage.localviastorage-manager.js - GPU Scheduling: Promise-chain mutex in
gpu-scheduler.jsprevents concurrent WebGPU access
- XSS Prevention: DOMPurify with explicit allowed tags/attributes; safe DOM helpers for all rendering
- Input Sanitization: All user input and WASM output is validated and sanitized
- Data Validation: Comprehensive validation for messages, analysis results, settings, and session data
- Restricted Resources: Web-accessible resources limited to YouTube and Twitch origins only
cd wasm-engine
cargo test18 unit tests cover clustering, topic extraction, sentiment analysis, and spam detection.
For extension logic tests:
npm run test:js42 tests across 10 suites covering content-script extraction, sidebar rendering, options persistence, LLM fallback, storage manager, validation helpers, and DOM helpers.
- Content Script observes YouTube/Twitch chat DOM
- Batches messages every 5 seconds
- Sends batch to Sidebar via
chrome.runtime - WASM engine runs combined analysis:
- Clusters messages by type (keyword-based)
- Extracts trending topics (5+ mentions)
- Computes sentiment signals
- Semantic pipeline (when encoder is ready) overrides cluster assignments:
- MiniLM encodes messages into 384-dim embeddings
- Cosine similarity routes each message to the nearest prototype vector
- Badge shows "Semantic" or "Keyword" to indicate active mode
- LLM Adapter (Gemini Nano, Chrome built-in AI) enhances sentiment and generates summaries from semantic clusters
- Keyword-scan parser tolerates model preamble
- Garbage-triggered fallback to rule-based mode with "Basic mode" UI indicator
- Sidebar UI displays:
- Mood indicator (emoji + label + confidence)
- Trending topics word cloud
- Categorized message clusters (semantic or keyword)
- AI summary (if LLM available)
| Mood | Emoji | Trigger |
|---|---|---|
| Excited | 🎉 | Strong positive signals (score > 30) |
| Positive | 😊 | Positive keywords (love, great, pog, etc.) |
| Neutral | 😐 | Few sentiment signals detected |
| Confused | 🤔 | Questions, "wait", "huh", etc. (only when no positive/negative signal) |
| Negative | 😔 | Negative keywords (bad, boring, etc.) |
| Angry | 😠 | Strong negative signals (score < -30) |
Sentiment requires at least 3 signal-bearing messages before showing a non-neutral mood. Positive and negative signals take priority over confusion markers — "this is awesome?" counts as positive, not confused.
MPL 2.0
Chat Signal processes everything locally in your browser. No chat content is sent to any server, and the extension makes no external network connections (connect-src 'self'): the MiniLM encoder (~23MB) is bundled in the extension package, and optional AI summaries run on Chrome's built-in Gemini Nano, which is managed by the browser.
Full privacy policy: chatsignal.dev/privacy-policy
PRs welcome! Some ideas for future improvements:
- User-configurable sentiment keywords
- Additional streaming platforms
- Historical trend graphs
- Export/share functionality
- Threshold calibration for semantic clustering per-category