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

My phone says I slept 4 hours 24 minutes a night this week.

I'm job hunting in Ireland, so every email might be the one. I did everything people recommend: notifications off for every social app, every WhatsApp chat archived. Email is the only door I left open, because that's where an interview invite or an offer will arrive.

It's also the door everything else walks through. One notification at 7am and I'm in: the email, then LinkedIn "just in case", then Instagram, then the chats I archived. Forty minutes later the morning is gone, and with it the book, the gym, packing food and catching the bus. At night it's the opposite problem. I can never be sure nothing important came in, so I don't sleep well either.

Here it is in my own voice:

Every shot of the board is real. The night and morning scenes are faceless AI stand-ins, because I couldn't film my own mornings before the deadline.

So I built Morning Sloth: an Arduino UNO Q on my desk that reads my Gmail overnight, lets open-weight Gemma 4 decide on the board whether anything actually needs me, and shows the answer as one face on its LED matrix. In the morning it also counts down to my bus, using the live feed.

Why an UNO Q, and why a sloth. The UNO Q came in the event pack for the Hacktoberfest fest I'm hosting in Galway this Thursday, 29 October. I was too curious to leave it in the box. Then Week 3 dropped with a sloth theme, and it fit: a small board running a model on its own CPU is slow, and that's fine. I had no extra modules, so my first ideas, which needed temperature sensors and the like, were out. I asked a different question instead: what's actually wrong with my week, and how could this board help? The answer was email, my phone, and sleep.

TL;DR. Look at the sloth, not your phone. Asleep: nothing needs you. One eye open: someone you've written to replied, and it can wait. Wide awake: something needs you today. Gemma 4 E2B runs in llama.cpp on the UNO Q's own CPU, so my job search and my bills never leave the room. On email it had never seen, it made the right wake-or-sleep call 98% of the time, with zero false wakes.

What I Built

The real UNO Q matrix: asleep, one eye open, wide awake

A sloth with three moods, and nothing to scroll:

  • Asleep, breathing slowly: nothing needs you. The phone stays face down.
  • One eye open: someone you've written to replied, or a deadline is close. It can wait until the bus.
  • Wide awake, blinking: something needs you today: a failed payment, a parcel arriving, a leaked API key, a recruiter asking for something.
  • A bus and a number: from 9am to 1pm, the minutes until the next 404 actually reaches Castlegar GAA, delays and cancellations included. A dot in the corner means the time is live.

Live bus countdown: 11 minutes, with the live dot in the top-right corner

It never touches your mailbox. Read the email on your phone and the sloth goes back to sleep on its own. From 02:00 to 06:00 the matrix goes dark, so it isn't one more light keeping you up.

Who gets to be lazier? Me first: someone who has to keep email on, but loses mornings to it. Then anyone who keeps their phone out of the bedroom and still worries about what's waiting. The sloth makes the one decision that used to need my phone, and most mornings that decision is "no".

Why not Gmail's Important label? I checked it against my own inbox. Gmail marked a Trustpilot review request and a vendor's "[urgent]" incident notice as Important, and missed both of my failed electricity top-ups. And a label still means unlocking the phone to look at it.

Demo

The raw demo, uncut: 4 minutes 52 seconds, filmed on my Meta Ray-Ban glasses at half past midnight, nothing sped up. I send myself two emails and you watch Gemma read them on the board. The cards beside the footage explain what's happening while it thinks.

  • 0:35 I send "Quick question for tomorrow" from an address the sloth counts as someone I've written to.
  • 1:43 One eye opens. Gemma said fyi, and the people-you've-written-to rule raised it to soon.
  • 2:08 I send "Webinar starting in 10 minutes".
  • 3:24 Wide awake. The starting-soon rule makes it needs_today, whatever Gemma says.
  • 4:27 I read it on my phone, and the sloth goes back to sleep on its own.

Code

GitHub logo MuhammadMurtuzaHussain / morning-sloth

Look at the sloth, not your phone: Gemma 4 on an Arduino UNO Q sorts your Gmail overnight and shows one face on the LED matrix.

Morning Sloth: Gemma 4 on an Arduino UNO Q. Look at the sloth, not your phone.

Look at the sloth, not your phone. An Arduino UNO Q reads your Gmail overnight, open-weight Gemma 4 decides on the board whether anything needs you, and one face on an LED matrix tells you

See it live Ā· Demo guide Ā· Setup Ā· Results Ā· Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 3: Slow and Steady

Tests Gemma 4 E2B on the board Arduino UNO Q Your mail never leaves the room MIT

Morning Sloth 🦄

In plain words: you sleep late, you hate waking up to twenty notifications, and only one in four overnight emails actually matters. The sloth reads your inbox for you and shows one of three faces. You only pick up your phone when it's awake.

See it live

Real footage of the board, no editing tricks. The face is the whole interface.






















Asleep One eye open Wide awake Bus
The sloth asleep, breathing slowly The sloth with one eye open The sloth wide awake, blinking The bus countdown with a live dot
Nothing needs you. Leave the phone. Someone you know wrote, or a deadline is close. It can wait until
…





MIT licensed. The README has the full setup: one docker run for Gemma, one adb push for the app, and a one-line command that saves your Gmail app password on the board without it ever showing on screen.

How I Built It

Gmail (read-only IMAP) ──► python on the UNO Q's Linux side ──► Gemma 4 E2B in llama.cpp, on the board
                                       │                                   │
Sent mail (who you've written to) ā”€ā”€ā”€ā”€ā”€ā”˜            needs_today / soon / fyi / noise
                                                                           │
TFI live bus feed ──► bus.py countdown                           floors.py code rules
                              │                                            │
                              └────────► sketch on the STM32 ā—„ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
                                                 │
                                         13 Ɨ 8 LED matrix
Enter fullscreen mode Exit fullscreen mode

The UNO Q has two brains: a Qualcomm Linux computer and an STM32 microcontroller, joined by Arduino's Bridge. The Linux side does the slow work. It reads Gmail over IMAP with EXAMINE and BODY.PEEK, so it can never mark anything read or move it. It sends each new email, one at a time, to Gemma 4 E2B running in llama.cpp in a Docker container on the same board, and turns the highest level among unread emails into a face. The STM32 asks for that face over the Bridge and draws it: breathing when asleep, blinking when awake.

Choosing the model on the board, not on a laptop

I labelled 91 of my real emails by hand and ran three open models on the UNO Q itself:

Model Exact Wake vs. quiet Speed on the board
Gemma 3 270M 7% 13% (called all 91 urgent) 7.6 s/email
Gemma 3 1B 12% 21% 39 s/email
Gemma 4 E2B 69% 86% 34 s/email

The first surprise: Gemma 4 E2B "thinks" by default, and it spent its whole answer budget on reasoning, so every first answer came back empty. With thinking off (--reasoning-budget 0 and enable_thinking: false) it answers with one short JSON object.

Gemma judges, code guarantees

Gemma reads the sender, subject and preview, and picks a level. Then plain code applies rules Gemma can't override:

Rule Why I added it
A bill sender reporting a failure is always needs_today Gemma called both of my failed PrepayPower top-ups "fyi"
A carrier delivering today is needs_today Gemma called An Post's "delivering today" "fyi"
An event "starting in N minutes" is needs_today Gemma called a webinar going live "noise"
Someone you've written to is at least soon Gemma put a recruiter and a request for slides in "noise"
Google's alerts about connecting the sloth are capped at fyi Setting up an app password sends three security alerts

Rules can raise a level but never lower it, apart from that one setup cap. I wrote the rules after seeing the first 91 emails, so I also kept 46 held-out emails from three other days, labelled before running anything:

Wake vs. quiet False wakes Needed me that day
Design set (85 scored) 88% 7 5 of 6 caught
Held-out set (42 scored) 98% 0 3 of 3 wake it

One held-out miss changed the prompt: GitHub's "Possible valid secrets detected" alert, which Gemma first called noise. One extra line about security problems with your own accounts fixed it, without turning ordinary sign-in notices into false alarms. Every number, misses included, is in eval/RESULTS.md.

The bus that's actually coming

The timetable said my bus was 24 minutes away. The live feed said the 20:24 was running 48 minutes late, so the next bus was really 12 minutes away. With a free Transport for Ireland key, the board downloads the national GTFS-Realtime feed every two minutes during bus hours. As protobuf it's about 500 KB, against 2.9 MB as JSON, so I decode it with about 70 lines of standard-library code instead of adding a protobuf library to the board. It applies delays, drops cancelled buses and adds extra ones. If the feed is down or more than 10 minutes old, the countdown falls back to the timetable and the live dot goes out.

The repo has 40 tests, run on every push. They cover the rules, the setup cap, the 9am to 1pm bus window, Irish summer time (including Sunday's clock change), the October bank holiday timetable, the protobuf decoder, and late, cancelled and extra buses.

Why Does Open Innovation Matter?

Because this is my job search, my bills and my home address. Triaging it with a cloud model would mean sending all of that to someone else's server every night. Gemma 4 E2B runs on the board's own CPU, so the mail never leaves the room. The only traffic leaving the board is the read-only connection to Gmail and, during bus hours, a download of the public bus feed.

Because a closed API can't live on a small board on my desk. Open weights and llama.cpp let me choose a model by measuring it on the actual hardware: the 270M was fast and useless, the 1B was slow and useless, and E2B was the one that worked. I could turn its thinking off, change its prompt and wrap it in rules, all on the device.

Because it costs nothing to run, ever. No tokens, no subscription, no account. The sloth will work the same in five years even if every AI company changes its pricing tomorrow.

Where a closed model would win: speed. A frontier API would rate an email in a second instead of 34. But the sloth reads while I sleep, and ten emails overnight take about six minutes. Slow and steady is fine when nobody's waiting.

My Agent Session

Four Claude Code sessions, curated into one, from "I have an UNO Q and no sensors" to the live bus feed and the films. It keeps the ideas that died along with the one that lived. Damp Sloth died when the board turned out to have no sensors, and I wouldn't fake readings. Drying Window failed the "do we even need the board?" test. Then the LED grid became a job a phone can't do.

Building Morning Sloth with Claude Code: a bare Arduino UNO Q, four hours of sleep, and a sloth that reads my email
You

I want to go with Arduino for this week. Tell me what can be done in that.

Agent

Read the Week 3 brief first: build something with open models that rewards laziness; writing counts most, and Best Use of Arduino only counts the UNO Q. Then searched DEV: inbox triage, file tidying and auto-reply sloths were already posted. A generic sloth assistant would get lost; what worked in Return Route and Deis was one specific person, a real place and a number you can measure. First ideas: a laundry sloth, a heating nudger and a desk sloth.

You

I have an Arduino UNO Q in hand, but I am thinking what can be done here. Let's brainstorm more ideas.

Agent

Checked which UNO Q projects already exist on DEV (birdsong, the night sky, a phone lockbox, private documents, a smell sensor, a vibration stethoscope), so the laundry idea looked less new. Ten more ideas; the pick was Damp Sloth for a shared house in Galway: six people, a broken dryer, clothes on the rack for three days, windows nobody opens.

You

Yes, let's build Damp Sloth. Start with the board check: what sensors I have, how fast Gemma runs on the UNO Q, and get baseline humidity logging going tonight.

Agent

Asked before installing adb. The board: 4 GB RAM, 4 cores, Debian 13, offline, clock stuck in 2025. The Modulino sockets are wired to the microcontroller, not Linux, so I wrote a small app whose sketch scans every I2C address on both buses.

You

It says can't find SSID. Can you give me a command to list the networks it can see?

Agent

Scanned from the board and gave a connect command with nmcli --ask, so the Wi-Fi password is typed into the board and never into the chat. Once online the clock synced, and I pulled llama.cpp's arm64 server image plus three Gemma GGUFs: 270M, 1B and Gemma 4 E2B.

You

I don't have anything else with me. I just have this board. If there's no sensor on the board, we can't continue.

Agent

Agreed. The only sensors are the chips' own thermometers, and there's no microphone. Damp Sloth can't be built honestly, and I won't fake readings. Offered Rack Sloth instead (QR codes on the washer and rack, plus the forecast), with its weakness stated: it estimates damp, it doesn't measure it.

You

They still have to scan the QR code to see the queue. Maybe we can differ from this idea and think of something else that fits the theme, with the capabilities of the Arduino. Are there any submissions for Arduino for Week 3 so far?

Agent

No Week 3 UNO Q entries yet. What the bare board can do: scan Bluetooth and Wi-Fi, fetch anything online, run Gemma, and draw on its LED grid. Your QR worry is fair, so drop human input altogether: Drying Window, which reads the forecast and shows one icon.

You

Do we actually need an Arduino board for that? I like the idea, I'm just thinking of validation: how well does it fit the theme?

Agent

Honestly, no: a phone widget could do it, and an Arduino judge would spot that. Scored it against the judging criteria (strong story, weak use of the board and of Gemma) and proposed a three-question test for any idea: does it fall apart without the board? Without Gemma? Can you prove the lazy payoff by Saturday?

You

Let's think of a different idea. As we have the beautiful LED, how can we make an excellent use of it?

Agent

The grid's best job is not being a screen. A phone shows everything; 13 Ɨ 8 LEDs have room for one thing, and choosing that one thing is real work for Gemma. Top idea: a sloth that watches your notifications. Asleep means leave the phone; wide awake means look now. A phone app telling you not to look at your phone defeats itself.

You

I like both idea 1 and 2. I have been having trouble sleeping for the past few weeks, so I wake up late, and when I wake up late the last thing I want to do is use my phone. I would rather glance at the Arduino to know how much time I have until the bus leaves, because once I pick up my phone there are many notifications. I keep all my chats archived, so I miss the updates on them.

Agent

Ideas 1 and 2 are one device with two jobs. The bus countdown is arithmetic, so code owns it. Deciding which messages matter is judgment, so that's Gemma's job. And because you're sleeping badly, the grid stays fully dark overnight: dark until it's useful is a design choice, not a setting.

You

Many times I wake up to email notifications that are important, and some are just eh. WhatsApp we can drop; my family is considerate and can call me if needed. Let's focus on emails. See my Gmail to analyse and get evidence.

Agent

Read 19 to 22 October from sender, subject and preview only: about 29 emails a day, and about 1 in 4 overnight emails needed you that morning. Gmail's Important label flagged a Trustpilot review request and a vendor's '[urgent]' notice, and missed both failed electricity top-ups. Keyword rules fail too. So: Gemma judges meaning, and code sets floors only from signals that are reliable.

You

Yes: build a small labelled set from these emails (sender, subject, snippet only), copy it to the board, and compare Gemma 270M, 1B and 4 E2B against your labels for accuracy and speed.

Agent

Gemma 4 E2B 'thinks' by default and returned empty answers until thinking was switched off. Gemma 3 270M called all 91 emails urgent; 1B called 67 of them 'soon' and never said noise. Only E2B can sort email, but it missed 5 of 6 emails that needed you, including both failed top-ups. That's where 'code guarantees' has to work: three narrow rules (failed bills, deliveries today, events starting now) took it from 1 of 6 to 5 of 6. A broader 'a real person wrote' rule woke you for 14 emails it shouldn't have, so I dropped it. Fine-tuning on Tinker would mean uploading your real emails, which undercuts 'the mail never leaves the room', so I advised against it.

You

Keep Gemma 4 E2B plus the code rules. Next, add a 'people I've replied to' rule from my Sent mail and test on fresh emails.

Agent

Labelled 46 emails from three other days before running anything, so the test stayed blind. The new rule rescued a direct request for slides with zero false wakes. The biggest miss was GitHub's 'Possible valid secrets detected', which Gemma called noise. The fix belongs in the prompt, not a code rule, because most sign-in alerts are ones you caused yourself.

You

Yes, start building the device: Gmail read-only fetch on the board, Gemma + rules, and the sloth on the LED matrix. Add the security line to the prompt while you're at it.

Agent

Gemma runs in its own container that restarts with the board. gmail.py opens mail with EXAMINE and BODY.PEEK and reads only the first 30 KB, so it can never mark anything read. triage.py holds the prompt and is shared with the benchmark, so scores test exactly what the device runs. The faces are ASCII art in tools/faces.py, generated into the STM32 sketch: asleep (breathing), one eye open, wide awake (blinking), dark in quiet hours, and a 'lost' dot if Gmail or Gemma is unreachable.

You

I've entered the app password and pressed Enter. But my password is 16 letters long... sorry, 11.

Agent

An 11-character password meant your normal Google password, not an app password. I wiped it from the board straight away. The next attempt read 20 characters because Google's page puts invisible non-breaking spaces between the groups, so the setup command now keeps letters only and refuses to save anything that isn't exactly 16.

You

Ran the fixed command; it showed length 16 and restarted the app.

Agent

Gmail accepted it and the board found 204 people you've written to. On the first real pass, five minutes later the same 20 emails were still unread, which proves the board changed nothing. Two Google security alerts from tonight's setup woke the sloth: the next false alarm worth fixing.

You

Yes, re-score both email sets on the board with the current prompt, using the device's Gemma server, and handle self-caused Google security alerts.

Agent

A setup cap: Google alerts naming 'Morning Sloth', or arriving within an hour of that one, can't go above fyi. Re-scored on the board: 98% wake-vs-quiet on the held-out set with zero false wakes, and every email that needed you that day wakes it. Also fixed times in the sender's timezone (the container has no tzdata, and the clocks went back that Sunday), made it wake as soon as one email matters, and added a bus countdown from the public TFI timetable. At 09:00:55 the board logged 'leave in 1 min' for the 09:02 bus. Live tracking needed a TFI account, and I don't create accounts for people.

You

Use DevRelay and fetch me this week's Arduino category entries. Tell me which of these are Week 3 challenge entries for sloth.

Agent

None of the Arduino-tagged posts is a Week 3 sloth entry. The #hf26challenge feed has about 40 sloth-themed posts, mostly inbox or chat triage on a laptop. So the difference has to be the object: no screen to scroll, the model on the board, and the bus.

You

Let's pick up where we left the Arduino project. I connected the Arduino now, idk what it is connected on. Also we will be making a demo video, let me know the script. Need to submit in like 9 hours.

Agent

Found it as an UNO Q on a USB modem port. Gemma and the app were running, but the board had no internet because the phone hotspot wasn't visible. The startup traceback was harmless (each poll is wrapped and retried). Flagged that the challenge API's end time disagreed with the page's stated deadline, and wrote a 90-second script with two emails that always change the face, because code rules decide them, not Gemma.

You

We need to improve the app a bit more. I was going to get API keys; can you tell me from where and which ones?

Agent

Only one key was worth it: Transport for Ireland's GTFS-Realtime feed, which fixes the README's own 'timetable, not live' limit. I advised against cloud AI keys (they'd undercut the privacy story) and against partner keys added just for prize categories.

You

I have the key, let me know where to share it.

Agent

Not in the chat. A one-line command reads it hidden on the board and saves it to secrets.env and its backup, so it's never printed or committed.

You

I think it is saved now. Did the terminal thing.

Agent

The national feed is 2.9 MB as JSON but 500 KB as protobuf, so I wrote about 70 lines of standard-library wire-format decoding instead of adding a library to the board. It matches trips by ID (the timetable was re-cut to keep them), applies delays carried forward from earlier stops as the spec says, drops cancelled or skipped buses, adds extra ones, and falls back to the timetable if the data is over 10 minutes old. A corner dot shows the time is live. Checked the decoder against the JSON version: same 1,755 trips. That night the timetable said 24 minutes, but the 20:24 was 48 minutes late, so the real answer was 12.

You

I can't get the open one eye. Can you maybe run the command, so I can see all three faces one by one?

Agent

Two causes. The iPhone hotspot had gone to sleep and the board had stopped retrying, so I set it to retry forever. And your own address is deliberately left out of 'people you've written to', so emails to yourself could never open one eye. I added an EXTRA_CONTACTS setting, a real feature for a partner or a boss, then ran the sequence live: asleep, one eye (Gemma said fyi, the contact rule raised it to soon), wide awake (Gemma said noise, the starting-soon rule raised it to needs_today).

You

I need this to be more genuine, as I am only solving my problem. Here's my sleep data: 4 hours 24 minutes. I'm looking for a job in Ireland and can't sleep properly. I keep notifications off for all my socials and all my chats archived, so the only notifications are emails. When I see an email notification I naturally open my socials and get pulled into doomscrolling. My morning is precious: books, exercise, packing food, the bus. The current video feels like AI slop. Look at these Higgsfield launch references; I think Case 5 can be used. And I want to use my own voice.

Agent

Watched all seven cases by scrubbing each video into a frame grid. Case 5's power comes from an invented CG product in a fantasy sky, and rendering your board that way would make the one real thing look fake. Recommended Case 1's real routine plus Case 7's character comedy instead: a calm sloth that's better at mornings than you are, in your own story. Your cloned voice was already in your ElevenLabs workspace, so no API key was needed.

You

I won't be able to film. Can you just generate footage using ElevenLabs Creative? I like your recommendation, let's use that.

Agent

Priced it first: Kling 2.5 Turbo at about 2,100 credits per 5-second shot, against 14,000 for the first model. Seven faceless stand-in shots (a hooded figure at the desk, a hand reaching for the phone, a thumb scrolling, a book in morning light, packing lunch, walking to the bus, the phone left in the hallway). No AI face pretending to be you. Picked the voice take that clearly said 'Ireland', not 'an island'. Every shot of the board stayed real footage, and the end card says which parts are AI.

You

Can we make a second draft according to the Case 5 reference? I really liked the magic and product building.

Agent

Modelled the UNO Q in three.js: one LED glowing in the dark, 103 more gathering into the grid, the board and its parts landing one by one while the sky turns from night to dawn, envelopes diving into the chip, chrome speech-bubble signs, a glass dome that a cloud bounces off. The LED faces use the sketch's own pixel maps. Frame checks caught two problems: unlit LEDs glowing white, so no face could be read, and signs covering the board.

You

Let's keep the raw demo uncut, because a demo should be raw. Just add infographics in the dead spaces to tell more about the project.

Agent

Kept all 4:52 of the Ray-Ban footage, converted from HDR. The portrait footage fills the middle third of a 16:9 frame, so 25 cards sit in the side panels during the waits: what the faces mean, why it takes ~35 seconds, the model shoot-out, the rules, why it lives on the board, the held-out results. Captions fix Whisper's 'slot' to 'sloth'. Checked the laptop screen at full resolution (the Gmail compose window and search suggestions can't be read) and cropped the Wi-Fi module's MAC address out of every photo.

You

I only want the bus timings displayed from 9 in the morning to 1 in the afternoon; outside that window, just the sloth face. Can you make the quiet hours 2 am to 6 am?

Agent

The bus window is now 09:00 to 13:00 and quiet hours are 02:00 to 06:00, in the code, the README and on the board. The board's Docker log had a corrupted byte, so the app now writes its own event file, and tools/demo.py watch shows each email arriving, a live 'Gemma is thinking' timer, Gemma's label, the rule that overrode it and the face, drawn in the terminal.

The Lazy Payoff

I've used it since Thursday night, on my real inbox. Here's what it saves, measured honestly:

  • The first glance of the day. Over three nights, about 1 in 4 of my overnight emails needed me that morning. The sloth tells me whether one of those is waiting, so on a quiet night I don't unlock the phone at all.
  • The forty minutes. The email check was never the real problem; it was the door to LinkedIn, Instagram and the chats. No unlock, no door.
  • The bus run. One glance at the matrix tells me when to leave, delays included. No transport app, which would be another unlock.
  • What it caught. On its first night it woke up for exactly two things: a failed electricity top-up and a parcel out for delivery. Both were real and needed me that morning. Everything else let it sleep.

What I didn't expect: it's a companion. I've been working too much: hosting a fest, job hunting, posting reels at midnight. A sloth asleep on the desk is a small daily reminder that nothing needs me right now, and that going slow is allowed. It keeps me in check. Fewer unlocks mean less anxiety in the morning, more focus for the book or the gym, and a calmer head. That's the payoff I care about most, and the one I can't put a number on yet.

What it hasn't fixed yet: my sleep. A few nights is too soon to show up in the graph, and I won't pretend otherwise. So tonight the phone sleeps in the hallway and the sloth stays on the desk. I'll post next week's graph either way.

Prize Categories

  • Best Use of Arduino: an open-weight model running on the UNO Q, with each half doing what it's best at: Gemma, IMAP and the live bus feed on the Qualcomm Linux side, the faces and breathing on the STM32, joined by the Bridge.
  • Best Use of Gemma: Gemma 4 E2B, chosen by measuring three Gemma models on the board, with thinking turned off, a prompt fixed by a held-out miss, and code rules around it. 98% wake-vs-quiet on held-out email.
  • Best Use of ElevenLabs: the story film is narrated in my own cloned voice, and ElevenLabs also made the music, the sound effects and the AI stand-in shots for the nights and mornings I couldn't film.

On AI in this post: I drafted it with Claude Code and checked every number against the repo. The raw demo is real footage, uncut. In the story film, the board footage and my sleep data are real, the night and morning scenes are faceless AI stand-ins (ElevenLabs), and the voice is mine, cloned with ElevenLabs. The 3D opener is the board modelled in code (three.js), with the faces drawn from the sketch's own pixel maps.