This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
I have a confession. Most mornings I open GitHub, see the notification count, and close the tab. Then I feel guilty about it all day. Somewhere in that pile is a person waiting on my review, sitting right next to three dependency bumps and someone offering me free stars.
So I built Snooze Desk, a lazy developer's overnight desk.
While I sleep, it does the boring part:
- A durable Temporal workflow pulls my GitHub notifications.
- A local Gemma model running in Ollama sorts each one into
needs-you,can-waitorignore. - For the ones that need me, it drafts a reply that quotes real details from the notification, like the line number in a stack trace or the number of changed components in a PR.
- It writes a short morning digest, so the first thing I read is three lines, not forty tabs.
In the morning I open one dark screen. Red means something needs my attention. Green means it is handled. For each draft I can approve, edit, reject or snooze. Snoozing starts a Temporal durable timer with a live countdown, and the item comes back when the timer fires. The timer lives in Temporal, not in a browser tab.
Who gets to be lazier: anyone with a noisy GitHub inbox. During Hacktoberfest, that is probably you.
Demo
Code
RockingThor
/
snooze-desk
Lazy developer's overnight desk: local Gemma, Temporal and Sentry triage your GitHub notifications while you sleep. DEV Hacktoberfest 2026 entry.
Snooze Desk π
The lazy developer's overnight desk β Process GitHub notifications with local AI while you sleep.
A Hacktoberfest 2026 Open-Source AI Challenge project (Week 3: "Slow and Steady").
What It Does
Snooze Desk runs a durable Temporal workflow that processes your GitHub notifications overnight using a local Gemma model. Wake up to:
- A 3-line morning digest summarizing what needs your attention
- Smart classification: needs-you (red), can-wait (gray), or ignore
- AI-drafted replies for issues and PRs that need a response
- One-click actions: approve, edit, snooze, or reject each draft
- Durable snoozing: workflow sleeps for hours or days, survives restarts
Everything runs locally. Your notifications never leave your machine. Zero API costs.
Why Open-Source AI?
- Privacy: All processing happens on your laptop. No data leaves your machine.
- Zero cost: No API keys, no usage fees. Run it forever for free.
- Offline-capable: Works without internetβ¦
How I Built It
The stack is Next.js for the desk, the Temporal TypeScript SDK for the overnight job, Ollama running Gemma for the thinking, Octokit for GitHub, and Sentry for tracing every model call.
Temporal does the waiting
The whole night is one Temporal workflow. Fetching notifications, classifying each one, writing the digest and posting an approved reply are all activities. That matters because a local model is a flaky dependency. With Temporal, a failed step gets retried, and the workflow picks up where it left off instead of starting over.
Snooze is a Temporal timer too. When I say "not now", the workflow just sleeps. It is the most relatable code I have ever written.
Gemma does the sorting
The classifier sends each notification to Gemma and asks for strict JSON back. My first prompt was simple. It turned out to be too simple, and Sentry is how I found out.
Sentry shows me what actually happened
Every model call is a Sentry span with op ai.inference, named classify_notification or generate_digest_summary. Each span carries the model name, the prompt version, input and output token counts, Ollama's load and eval durations, and the Temporal workflow id and attempt number. The Ollama HTTP call shows up as a child span.
On October 22 I did 7 live runs on a Linux box with 8 CPU cores and no GPU. I used six sample notifications that I know the right answers for: three that need me, a dependency bump and a friendly praise thread that can wait, and one spam message. Sentry accepted every envelope, 54 out of 54.
Here is what the traces told me:
| Model | Prompt | Classify mean ms, min to max | Input tokens, mean | Output tokens, mean | Tokens per second | Digest ms | Correct |
|---|---|---|---|---|---|---|---|
gemma3:1b |
v1 | 1734, 1502 to 2081 | 215 | 71 | 44.3 | 1390 | 3 of 6 |
gemma3:1b |
v2 | 2926, 2417 to 3276 | 351 | 88 | 45.9 | 1991 | 3 of 6 |
gemma4:e4b |
v1 | 58123, 41556 to 71342 | 222 | 428 | 7.8 | 56679 | 5 of 6 |
gemma4:e4b |
v2 | 49195, 37485 to 65936 | 358 | 414 | 8.8 | 53766 | 6 of 6 |
Finding one: the small model says yes to everything. gemma3:1b is fast, under 3 seconds per notification on CPU. It also labelled all six notifications needs-you. That includes one titled "FREE GITHUB STARS! Click here now!!!". So it scored 3 of 6, and only because three of them really did need me.
I assumed my prompt was bad, so I wrote a v2:
- clear rules for each label, including "spam stays ignore even when it mentions you"
- five few shot examples
- the reason first, then the label
- a JSON schema that only allows the three labels
- temperature 0
On gemma3:1b this changed nothing. Still 3 of 6, still excited about free stars. At that point it is not a prompt problem, it is a model size problem.
Finding two: Gemma 4 gets it, and the better prompt makes it faster. gemma4:e4b got 5 of 6 with my original prompt. The one miss was the praise thread, which it thought needed me. With v2 it got 6 of 6, and the mean classify time dropped from 58.1 seconds to 49.2 seconds.
Finding three: Gemma 4 thinks more than it says. It produced around 400 output tokens for a JSON answer that is only a few lines long. That suggests hidden reasoning tokens. On a CPU at about 8 tokens per second, those extra tokens are where the time goes. A full run of six notifications plus the digest used 5205 tokens.
So the final setup is gemma4:e4b with prompt v2 for sorting, where being right matters, and gemma3:1b for the digest, where a quick friendly summary is all I need. About 50 seconds per notification sounds slow, but this runs while I am asleep. I am not in a hurry. That is the whole point.
As for cost: the model runs on my own machine, so there is no API bill at all. Sentry was on the free plan.
The night I unplugged the model on purpose
I wanted to see what happens when things break, so I killed Ollama in the middle of a run, right inside the first classify call.
Sentry caught it right away: SocketError: other side closed, then connect ECONNREFUSED 127.0.0.1:11434. The first attempt ended with an error status. Temporal waited and retried. I started Ollama again, and attempt 2 succeeded, cold model load included. The workflow went on and finished all six notifications. I did nothing except restart Ollama, which is exactly the amount of effort I like.
The bug Sentry found before it bit me
This test also exposed a real bug. Before the fix, the classifier caught connection errors and quietly returned can-wait. So if Ollama was down all night, I would wake up to a calm digest saying nothing needed me. That is the worst kind of bug: it looks like good news.
Now a connection error makes the activity throw, so Temporal retries it properly. In the trace, it shows up as an error you cannot miss.
One honest gap: there is no single parent span per workflow yet, so one trace can hold several workflow runs from the same worker. Linking traces to the Temporal workflow id is next on my list.
Why Does Open Innovation Matter?
My GitHub notifications include private repos, security reports and the occasional grumpy comment. I do not want to send all of that to a server I do not control just to find out it can wait.
With Snooze Desk, the model runs on my own machine through Ollama. The notification content goes from GitHub to my laptop and nowhere else. The only content that leaves is a reply I approve, and it goes back to GitHub. Sentry is optional, and the spans carry timings, token counts and labels, not the notification text.
Open weights also made the debugging story possible. Because I could run two Gemma sizes side by side, change the prompt, and read every token count and timing, I could prove that the small model was the problem and not my prompt. With a closed API, I would have been guessing behind a paywall.
It also costs nothing to run. A tool that works while you sleep should not send you a bill in the morning.
Prize Categories
- Best Use of Gemma: Gemma 4 E4B sorts the notifications and Gemma 3 1B writes the digest, all running locally in Ollama.
- Best Use of Temporal: the whole night is a durable workflow with activity retries that survived a real model outage, plus durable timers for snooze.
- Best Use of Sentry Agent Tracing: every model call is traced with tokens, latency, prompt version and retry attempt, and the traces found both a model quality problem and a silent failure bug.
Thanks for reading. I am going back to bed now. Snooze Desk has it covered.






Top comments (0)