DEV Community

Musaddiq Ahmed Khan
Musaddiq Ahmed Khan

Posted on

Sprout: a creature that starves indoors

Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass Submission 🌿

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass

What I Built

Sprout is a creature that lives on your phone and starves indoors.

It's a Tamagotchi with one rule: it only eats things that exist outside. Hold your phone up to real sunlight and it drinks. Point the camera at actual grass and it eats. Carry it on a walk and it perks up. Shake it awake and it tells you — groggily — about the dream it just lost. Every word it speaks is generated on-device by Gemma 4, an open-weight model running inside the app. There is no server. In a forest with zero bars of signal, the creature still talks back.

It also refuses to let you cheat the theme:

  • Indoor lamps and bright windowsills don't count as sun — the ambient light sensor only banks "drinks" above outdoor-class lux.
  • A photo of a green wall gets rejected by a pixel classifier before the AI ever sees it.
  • Leave the phone in a sunny window and walk away? Nothing happens. Sunlight only counts toward growth while you're actually engaged with the creature — it can't evolve alone.

Who is it for? Anyone whose screen time is beating their outside time. The shortest path to keeping Sprout alive is to put on shoes.

Demo

▶ Video demo: https://drive.google.com/file/d/1c7aG0o_WBRdop3rcMKDgyWcqQPEbmjhC

Code

GitHub repo:

Sprout

A creature that needs you to go outside. On-device AI, sunlight detection, grass verification.

Built for Hacktoberfest 2026 — Week 1: Touch Grass.

What it is

Sprout is a small creature that lives on your phone. It hatches from an egg, then survives on two things:

  • Sunlight — detected by the Android ambient light sensor (TYPE_LIGHT), no camera needed
  • Grass — confirmed by a green-pixel HSV classifier, with Gemma vision as a borderline arbiter

Every line the creature speaks — its greeting, its gratitude, its confusion when you show it something that isn't grass — is generated on-device by Gemma 4 E2B running locally through LiteRT-LM. No network call, no API key, no data leaves the device.

Why open-source AI

  • Private by design: photos of your environment, your outdoor habits, your streak — nothing leaves the device
  • Offline: the creature works in a forest…

MIT licensed. Requires Android API 30+ (arm64).

How I Built It

Sprout is a Flutter app, but the interesting parts are three systems that never touch the network.

The body: physical detection

Everything the creature senses comes straight from the phone's hardware — I wrote my own Kotlin EventChannels instead of pulling sensor plugins:

  • Sunlight — Android TYPE_LIGHT ambient sensor. The feed threshold is 5,000 lux, deliberately above indoor bulbs (~200–800) and bright windows (~1–3k); only genuinely outdoor light counts. Charge builds in 3-second "drinks" at a 10 Hz tick, and a passing shadow drains the bar at 40% speed instead of wiping it — sustained darkness still does.
  • Shake — accelerometer magnitude over 2.5 g, with a 900 ms cooldown so one physical shake doesn't fire fifty events. A rough wake: the creature stirs, but the dream it was having is gone.
  • Tilt — a low-pass filter over the same accelerometer broadcast pulls gravity out of the noise and emits lateral lean (-1..1). Tilt it sideways and the creature complains.
  • Walking — TYPE_STEP_DETECTOR emits one event per step; carrying it outside counts as care.
  • Grass — camera photos are downscaled to 64×64 and scored by a pure-statistics HSV classifier: hue 60–160°, saturation > 0.25, value > 0.20. ≥40% green pixels passes, <20% fails, and the grey zone in between goes to the model. An md5 of the photo blocks re-feeding the same patch twice.

The mind: a local, open-weight model

Every line of dialogue — the hatch moment, the morning greeting keyed to its energy/hunger/stage/streak/mood, gratitude after a drink of sun, confusion at a rejected photo, dreams, dizziness, songs — comes from Gemma 4 E2B running locally through LiteRT-LM (flutter_edge_ai). No API key, no network call, ~40–80 tokens per line under a character system prompt, a fresh session per call so prompts never accumulate.

Two places go beyond text:

  • Function calling. Periodically the creature is asked what it wants — Gemma picks a native tool call: demand_sunlight, request_grass, request_walk, sing, nap, ask, or invent_quest, which lets it author a small real-world quest ("find something round and alive") that it later verifies itself.
  • Vision. The borderline grass verdict and judgePhoto — a yes/no check of a photo against a verification prompt the creature invented — run the model's vision modality with an 8-token cap.

The model is downloadable, not hardcoded

A first-run Model Manager screen pulls the ~2.4 GB gemma-4-E2B-it.litertlm from the ungated Hugging Face litert-community mirror — resumable progress, cancel, and a foreground service so Android's background limit can't kill the download. You can also sideload any .litertlm file through a file picker, which means a fine-tuned creature personality is a file swap away. Until the model lands, a deterministic FakeGemmaClient keeps the whole game playable — and keeps the test suite model-free.

State, care logs, quest progress, and stage history persist in sqflite. Evolution runs on trials: a couple of feeds plus a completed real-world quest, or roughly nine seconds of honest sunlight.

Layer Tech
App Flutter 3.44.5 / Dart 3.12.2
AI Gemma 4 E2B .litertlm via flutter_edge_ai (LiteRT-LM)
Lux sensor Custom Kotlin EventChannel → TYPE_LIGHT
Grass gate Custom HSV classifier, ~0 ms, no ML
Storage sqflite
Camera camera + image_picker + image

Why Does Open Innovation Matter?

A creature whose whole job is sending you outside cannot depend on a network — that's the premise. Open weights make the premise real:

  • Offline where it matters. The app works in a forest, on a mountain, in a dead zone — exactly the places it sends you. A closed API would brick its voice the moment you left coverage.
  • Private by design. Photos of your yard, your walking habits, your streak — none of it leaves the device, because there is nowhere to send it.
  • Inspectable and swappable. The brain is a .litertlm file you can audit, swap, or fine-tune into a different personality — the file-picker import exists precisely so someone can ship their own.
  • Zero marginal cost. It can nag you to go outside forever, for free. No API bill scaling with how needy the creature gets.

Prize Categories

  • Best Use of Gemma — Gemma 4 E2B is the creature's entire voice, decision-maker, and vision arbiter, running fully on-device via LiteRT-LM.

Built with ❤️ by Musaddiq625

Top comments (2)

Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more