DEV Community

Cover image for touchgrass — an offline, open-weight agent whose only job is to make you stop using it.
Ravi Teja Bhagavatula
Ravi Teja Bhagavatula

Posted on

touchgrass — an offline, open-weight agent whose only job is to make you stop using it.

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

touchgrass — an offline, open-weight agent whose only job is to make you stop using it.

It runs Gemma locally (via Ollama, on 127.0.0.1), takes your minutes and coordinates, and prints a Field Card: one short loop, three noticing prompts anchored to your actual latitude and day length, one dare, and instructions for what to do with the phone. Then the screen part is over. There is no feed, no streak, no second screen. The artifact is paper — print it, tape it to your phone case, go.

╭──────────────────────────────────────────────────────────────╮
│ touchgrass                                          No. 0284 │
│ F I E L D   C A R D                                          │
│ Sun 11 Oct 2026 · evening                                  │
╰──────────────────────────────────────────────────────────────╯

  FIELD CARD — this evening's card

  new moon · any ground · ☀ 06:26–18:06

  THE LOOP
     Walk toward the setting sun. Head south until the buildings
     thin. Continue until you reach a patch of bare earth.

  NOTICE — three things
     01  Feel the wind on your face. Note its direction.
     02  Pick up a stone. Examine its weight and texture.
     03  Observe the shadows lengthening. How do they shift?

  THE DARE
     Kick a pebble. Listen to the echo.

  POCKET THE PHONE
     Photograph the color of the sky just after the sun dips
     below the horizon.

  generated by gemma3:4b on 127.0.0.1 (local) · loopback only · no network
Enter fullscreen mode Exit fullscreen mode

Who is it for? Anyone whose screen time needs an off-ramp. Runners, parents, students, and — honestly — hackers on submission day.

Demo

There is no deployed link, and that's the point: this tool works with the radio off. The demo is three commands on your own laptop:

ollama pull gemma3:4b
pip install -e . --break-system-packages
touchgrass doctor --proof   # hero moment: the internet gets refused live
touchgrass demo             # proof + card + journal in ~30 seconds
touchgrass serve            # → http://127.0.0.1:8765, loopback-only web UI
Enter fullscreen mode Exit fullscreen mode

The demo web UI (touchgrass serve, loopback only)

touchgrass demo web UI in a browser: time, effort and setting controls on the left and a paper-styled Field Card preview on the right

Terminal Field Card

Terminal showing a generated touchgrass Field Card with a sunset loop, three noticing prompts, a dare, and a pocket-the-phone instruction

touchgrass doctor --proof

touchgrass doctor proof output showing three public IP addresses blocked at the network boundary while loopback to the local Ollama model stays allowed

Taking it outside (bonus points, honestly earned):
I printed the card, taped it to my phone case, and walked the local park for 30 minutes at sunset. The route — head south until the buildings thin, find bare earth — worked exactly as written; no map needed. The shadow prompt was the one that landed: I stood and watched the light move instead of walking through it, and the stone prompt stopped me a second time. The dare (kick a pebble, listen for the echo) got a laugh out of me, which is more than most software has managed outdoors. One honest finding: the sky-photo instruction arrived a few minutes before the sky did anything interesting — the next iteration should time the pocket-the-phone moment to sunset itself, which the tool already computes.

Code

Repo: https://github.com/RaviTeja799/touchgrass

MIT licensed. Python 3.9+, zero third-party dependencies — stdlib only, so pip install works on a plane. Layout:

touchgrass/
  cli.py        plan / demo / serve / log / recall / doctor / locate
  serve.py      loopback-only demo web UI (one self-contained page)
  brain.py      Ollama chat + model auto-resolve + fallback planner
  card.py       FieldCard → colour terminal / receipt text / HTML / JSON
  phenology.py  solar declination, day length, sun times, moon phase
  journal.py    SQLite + FTS5 outing log, on your disk
  offline.py    socket-layer network guard + live proof
  geo.py        locate-once-cached-forever (flags > env > cache > default)
Enter fullscreen mode Exit fullscreen mode

The part I'm proudest of is the smallest one — "we don't send your data anywhere" as a demonstration instead of a sentence:

# offline.py — refuses every non-loopback socket in the process
def _check(address, where):
    if not _enabled:
        return
    host = _host_of(address)
    if _is_loopback(host):
        return
    raise NetworkBlocked(
        f"touchgrass blocked an outbound call to {address!r} (via {where})."
    )
Enter fullscreen mode Exit fullscreen mode
$ touchgrass doctor --proof
  leaving the machine:
    ok  1.1.1.1          blocked at the boundary
    ok  8.8.8.8          blocked at the boundary
    ok  93.184.216.34    blocked at the boundary
  staying on the machine:
    ok  127.0.0.1:11434  loopback allowed -- model reachable
Enter fullscreen mode Exit fullscreen mode

How I Built It

Open-source AI: Gemma 3 (gemma3:4b, falling back to any gemma* on disk) running locally through Ollama. No API keys, no per-token billing, no rate limits. The project is built around the model in three layers:

  1. Season math first, model voice second. Before Gemma is even called, phenology.py computes solar declination, day length, longitude-corrected sunrise/sunset, and lunar phase from the calendar and your coordinates — farmer's-almanac arithmetic, no network. On 11 October at +17.7°, +83.3° that's an 11h 40m day, sun about 06:26–18:06. Delete the model entirely and the tool still knows what kind of afternoon it is. Gemma supplies the voice (route, dare, exit line), never the facts. The prompt libraries are latitude-aware too: inside the tropics the tool swaps temperate leaf-fall prompts for heat-and-rain ones, so the card reads true where you actually stand.
  2. A guard, not a promise. offline.py patches the socket layer so anything imported into the process that tries to phone home is refused at the boundary — and doctor --proof shows you the refusal live.
  3. Graceful degradation as a design principle. No model on disk? A hand-written fallback planner (10 archetypes) still gets you outside. Tiny model echoing the schema or parroting the example? Echo/parrot detection repairs those fields from the seed-varied planner, so the card is always fresh and printable. A field guide that stops working without wifi is not a field guide.

The rest is stdlib Python: argparse CLI, http.server demo UI, sqlite3 with FTS5 for the journal (touchgrass recall "what was turning in autumn" searches your own outings on your own disk). Location resolves as flags → env → cached fix → default; touchgrass locate is the single online step, cached for every --offline run after. The HTML card is fully self-contained (no webfonts, no CDN) and sized for 80mm thermal paper.

Why Does Open Innovation Matter?

Three things this project can only do because the model is open and local:

  1. It works with the radio off. A trail tool that needs a data plan is not a trail tool. Closed APIs can't make this claim at all — and "we don't send your data anywhere" in a README is worthless next to a live refusal at the socket boundary.
  2. It costs nothing, forever. No key, no bill, no 6am-Sunday rate limit when you actually want to go outside. Open weights + local inference + zero-dependency Python = a tool a student can run on a 2019 laptop.
  3. I can change its mind. The system prompt bans chirpy chatbot words outright; --model accepts anything Ollama serves. A hosted endpoint kept drifting my prompt toward "embark on a journey of discovery" — with a local model I just rewrote the instructions and regenerated. No lock-in, no roadmap permission slip.

Open innovation is what turns AI from a chat window you rent into a field guide you own.

Prize Categories

  • Best Use of Gemma 🏔️ — Gemma 3 (gemma3:4b) via Ollama generates every Field Card's voice; the model auto-resolves to whatever Gemma is on disk, and the whole offline-local argument only works because the weights are open.

Repo: https://github.com/RaviTeja799/touchgrass · MIT · Built tonight, used tonight.

Now go outside. The screen part is over.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.