cd /news/artificial-intelligence/sloth-recap-wake-up-to-2-lines-inste… · home › topics › artificial-intelligence › article
[ARTICLE · art-153689] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=↑ positive

Sloth Recap: wake up to 2 lines instead of 200 group-chat messages (EmbeddingGemma, 100% in your browser)

A developer built Sloth Recap, a browser-only web app that condenses a group-chat export into a two-line recap plus a list of messages that need the user's attention. The app runs Google's open-weight EmbeddingGemma 300M model locally via transformers.js in a Web Worker, using WebGPU when available and WASM CPU otherwise, and falls back to TF-IDF keyword vectors if the model fails to load. On the built-in 38-message sample, the pipeline reduced the chat to two lines plus three flagged messages, and the developer reports the 4-bit model export ran roughly 3x slower than the 8-bit file on WASM.

by read5 min views1 publishedOct 20, 2026

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

Sloth Recap is a small web app for one very lazy moment: waking up and finding 200 new messages in a group chat.

You drop in the chat export (WhatsApp "Export chat" .txt or .zip, or just paste the text), type your name once, and press 🦥 Catch me up. You get:

Group chats never sleep. In the morning you scroll through "lol", "😂", "ok" and three conversations happening at the same time, just to find the one question somebody asked you. Sloth Recap does that scrolling for you, so whoever reads the group last in the morning gets to be the lazy one.

One design rule I care about: Sloth Recap only quotes real messages. It picks them, it never writes new text, so it can't invent a plan nobody made. When the recap says "Technician comes Wednesday between 9 and 12", someone really wrote that.

👉 Live demo: https://asosa933.github.io/sloth-recap/

Click one of the two sample chats (🏠 English flatmates or ⚽ Italian football group), then Catch me up. The first AI run downloads the model once (about 175 MB with WebGPU or about 310 MB on CPU) and then the browser keeps it cached. If you don't want the download, untick "Use local AI" and you get the simple keyword mode instantly.

The result for the flatmates chat: 38 new messages became 2 lines, plus the 3 messages that actually need me.

It also works in Italian (and on mixed-language chats), because the model is multilingual:

Wake up to 2 lines, not 200 group-chat messages.

Sloth Recap reads a group chat export (WhatsApp .txt or .zip, or pasted text) and gives you:

Everything runs in your browser. The open-weight model EmbeddingGemma runs locally with transformers.js. There is no server, no account and no API key, and your chat is never uploaded.

👉 Live demo: https://asosa933.github.io/sloth-recap/ (click a sample chat, then "Catch me up")

Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 3: "Slow and Steady". The project was created during the Week 3 window (October 2026).

On the built-in "Flat 3B" sample, 38 messages arrived…

It's plain HTML, CSS and JavaScript: no build step, no backend, hosted for free on GitHub Pages. The pipeline looks like this:

chat export → parser → "messages after my last one" → drop "ok/lol/👍"
            → EmbeddingGemma vectors (Web Worker) → pick key messages → group the rest
            → 2 lines + "needs you" + topics

The open-weight model: EmbeddingGemma. In a Web Worker I load onnx-community/embeddinggemma-300m-ONNX with transformers.js. It runs on WebGPU when the browser has it and on the CPU (WASM) otherwise. Every new message becomes a vector, using EmbeddingGemma's task: sentence similarity prompt. Then:

The 🙋 Needs you list is intentionally not AI. It's simple rules: your name as a whole word or @name, plus question patterns in English and Italian. For "did someone ask me something?" I want rules that are 100% predictable.

Deterministic fallback. If the model can't load (or you turn it off), the exact same pipeline runs on TF-IDF keyword vectors. I tested this by blocking Hugging Face in headless Chrome: the app showed "Local AI: failed to load" and still produced the recap in simple mode.

Making it fast on a normal laptop CPU was the part I learned the most from. On my CPU-only test machine (headless Chrome, 38 messages):

The 4-bit export is the smaller download, but on WASM it was about 3x slower than the 8-bit file. I don't know exactly which operator is the slow one, but the measurement was clear, so the app uses 8-bit on CPU (and 4-bit only on WebGPU). Multi-threading needs a "cross-origin isolated" page, and GitHub Pages can't set those headers. So I added a tiny service worker (sw.js, about 20 lines) that adds them to the site's own files. After the first load, the model can use several CPU threads (4 on my test machine).

Testing.

npm test: 11 unit tests with node:test (WhatsApp Android/iPhone formats, US/EU dates, multi-line messages, fillers, "needs you", the fallback digest, reading a .zip). eval/eval-model.mjs runs the real model in Node on 5 small chats I wrote and labelled by hand (the 2 demo chats plus 3 held-out ones, one of them mixed Italian/English):

EmbeddingGemma TF-IDF fallback
nearest message is about the same topic 67/88 (76%) 64/88 (73%)
real topics covered by the top 3 lines 14/15 14/15
messages grouped under the right line 72/81 (89%) 64/78 (82%)
mixed-language chat, grouped right 11/13 9/13

To be honest: it's a tiny dataset that I wrote myself, so it's a sanity check, not a benchmark. Both modes pick good lines on these chats. The model's advantage shows when it groups messages, especially short replies and messages that switch language ("The heating in my room is not working" / "Anche da me il termosifone è freddo").

AI disclosure: I'm a beginner from Italy and I built this with a lot of help from an AI coding assistant (code, tests, debugging, measurements). The idea, the "never write new text" rule, the choices about what is AI and what is rules, and the testing are mine. I made sure I understand every file.

For this project, open weights are the whole point:

src/model-worker.js. If a better small open embedding model comes out next month, I can try it in an afternoon, and the TF-IDF fallback means the app never depends on any single model. Measured by the app itself on the built-in flatmates chat:

A busier group means more reading time, but the recap is still 2 lines. 🦥

Thanks for reading! If your group chat export breaks the parser (there are many date formats out there), please open an issue with a fake example and I'll fix it. 🦥

── more in #artificial-intelligence 4 stories · sorted by recency
── more on @sloth recap 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/sloth-recap-wake-up-…] indexed:0 read:5min 2026-10-20 · —