What if the algorithm stopped hiding and started explaining itself?
Every day, social media algorithms decide what you see — and they never tell you why.
This project is a small act of rebellion: a browser extension + desktop agent (Clippy, naturally) that sits with you while you browse, watches what the algorithm shows you, tells you the truth — and then clicks "Not interested" on your behalf.
- Watches your feed — YouTube, X/Twitter, Facebook, Instagram, TikTok, LinkedIn, Reddit, Threads
- Classifies every post into one of 9 categories (politics, sports, tech, etc.)
- Asks you with floating 👍/👎 buttons: "Are you interested in this?"
- Learns your preferences and adjusts its weight per category
- Acts — when you press 👎, Clippy automatically clicks "Not interested" / "Hide post" for real
- Auto-dismisses posts from categories you consistently dislike (configurable threshold)
- Shows you exactly what it learned — dismissed count, category weights, sentiment badges
| Feature | Status |
|---|---|
| Feed observer (YouTube, X, Facebook, Instagram, TikTok) | ✅ Working |
| 9-category brain classifier | ✅ Working |
| Clippy desktop agent (Electron) | ✅ Working |
| Clippy Chrome extension | ✅ Working |
| Floating 👍/👎 feedback buttons | ✅ Working |
| Action Engine — clicks "Not interested" | ✅ Working |
| Dismiss counter (persisted, shown in popup) | ✅ Working |
| Popup with 5 tabs (overview/categories/history/insights/settings) | ✅ Working |
| Settings tab — auto-dismiss toggle | ✅ Working |
| Weight badges per category (❤️/😐/😒/🚫) | ✅ Working |
| Chrome extension icons | ✅ Present |
| Landing page | ✅ Working |
| AI-powered dialogue layer (click Clippy to chat) | ✅ Working |
| TikTok action adapter | ✅ Working |
| YouTube InnerTube API integration | ✅ Working |
| LinkedIn / Reddit / Threads action adapter | ✅ Working (needs real-browser testing) |
| Web text analyzer (9 categories, Hebrew/EN/RU) | ✅ Working |
| 37 unit tests (brain, classifier, state, questions) | ✅ Passing |
teshuva-algorithm/
├── brain/ # Core intelligence
│ ├── brain-api.js # Public API: observe, positive, negative, recordDismiss, getStats
│ ├── categories.js # 9 categories with Hebrew labels + colors
│ ├── classifier.js # Keyword-based text classification
│ ├── state.js # Persisted weights, allTime, dismissed counters
│ ├── questions.js # When + how to ask the user
│ ├── intent.js # "Why are you seeing this?" explanations
│ ├── explanations.js # Human-readable summaries
│ └── adapters/
│ ├── chrome-adapter.js # chrome.storage.local
│ └── memory-adapter.js # In-memory (for tests/desktop)
│
├── mascot/
│ ├── mascot-controller.js # Brain ↔ Mascot ↔ User bridge
│ └── animations.js # Mood → Clippy animation mapping
│
├── extension/
│ ├── manifest.json # MV3, host permissions for 5 platforms
│ ├── content/
│ │ ├── bundle-entry.js # Content script entry + wiring
│ │ ├── bundle.js # Built bundle (esbuild output)
│ │ ├── action-engine.js # Platform "Not interested" click logic
│ │ ├── feedback-ui.js # Floating 👍/👎 buttons
│ │ ├── feed-observer.js # MutationObserver for new posts
│ │ └── site-adapters.js # CSS selectors per platform
│ ├── popup/
│ │ ├── popup.html # 5-tab popup UI
│ │ ├── popup-entry.js # Popup logic
│ │ └── popup.js # Built bundle
│ ├── background-entry.js # Service worker: storage + settings relay
│ └── api.js # Content ↔ Background message protocol
│
├── desktop/
│ ├── main.js # Electron window (340×340, always-on-top)
│ └── renderer-entry.js # Desktop Clippy logic + IPC
│
├── shared/
│ └── constants.js # Storage keys, message types, timing
│
├── agent/
│ └── dialogue.js # Conversational AI stub
│
├── web/ # Landing page & marketing site (Netlify)
│ ├── index.html # Main landing page (HE/EN/RU, dark/light)
│ ├── features.html # Features page
│ ├── pricing.html # Pricing page
│ ├── faq.html # FAQ page
│ ├── support.html # Support page
│ └── downloads/ # Extension zip for manual install
└── package.json
When the user presses 👎 or when the brain weight drops below 0.4 (configurable), Clippy automatically:
| Platform | Action | DOM Strategy |
|---|---|---|
| YouTube | "Not interested" | Hover reveal → ytd-menu-renderer → option click |
| X / Twitter | "Not interested in this post" | [data-testid="caret"] → menu item |
| "Hide post" | [aria-label="More options"] → menu item |
|
| "Not interested" | Three-dot button → dialog button |
import { createBrain } from './brain/brain-api.js'
import { createChromeAdapter } from './brain/adapters/chrome-adapter.js'
const brain = createBrain(createChromeAdapter())
await brain.load()
const categoryId = brain.observe('פוסט על פוליטיקה...') // → 'politics'
brain.positive('politics') // user liked it → weight +0.15
brain.negative('politics') // user disliked → weight -0.08
brain.recordDismiss('politics') // post was actually removed from feed
const { allTime, weights, dismissed, dismissedTotal } = brain.getStats()
// weights.politics < 0.4 → auto-dismiss threshold crossed- Run
npm install && npm run build - Open
chrome://extensions/ - Enable Developer mode
- Click Load unpacked → select the
extension/folder - Navigate to YouTube, X, Facebook, or Instagram
- Clippy appears bottom-right
npm install
npm start
# Or double-click: "הפעל קליפי.bat"| Tab | Content |
|---|---|
| סקירה | Visits, social, dismissed banner |
| קטגוריות | Category bars with ❤️/😐/😒/🚫 badges |
| היסטוריה | Hour-of-day chart, top domains |
| תובנות | Weekly insights |
| ⚙️ הגדרות | Auto-dismiss toggle, reset preferences |
- v0.4.0 — Improved YouTube selector (InnerTube API)
- v0.5.0 — TikTok action adapter
- v0.6.0 — AI dialogue via Claude API (ask Clippy "why?")
- v1.0.0 — Category blocklist, export preferences, multi-language
"האלגוריתם הזה לא מסתיר כלום ממך"
MIT License · GitHub