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

The problem: gardening apps want you on your phone

Every gardening app I tried wanted me to scroll more: feeds, tips, notifications, "community". But the whole point of a garden is to be in it. The question I actually have on a Saturday morning is tiny:

What should I do outside this week?
The answer depends on one boring, very local fact: your frost dates. Tomatoes go out about a week after the last spring frost, and garlic goes in a few weeks before the first fall frost. Most people don't know their frost dates, and most apps hardcode a "zone" that may be off by weeks for your exact town.

So I built Touch Grass Garden Coach: type your town and get one short page you can glance at before heading outside.

What I built


Type a place (e.g. Boston) and you get:

  • Your frost dates, computed rather than looked up. I pull the last 10 full years of daily minimum temperatures for that exact spot, find the last spring frost and first fall frost of each year (min ≤ 0 °C), and take the median.

  • Plant this week. What to start indoors, sow, transplant or plant right now, with the date each window closes.

  • Care & harvest. What's ready to pick, what's coming up, and age-based care like "Thin carrots to 5 cm apart" or "Stake or cage tomatoes". Tender crops stop at first frost.

  • Frost & rain warnings from the 7-day forecast, plus the best day to get outside (the warmest dry day).

  • "This week outside": a checklist of at most 6 items written by a local open-weight model.

It also has a My garden tab (log what you actually planted, and get progress bars and exact harvest dates) and a Season tab (a 12-month timeline of every crop's windows, with today and your frost dates marked).

For Boston this week, it says: sow fall lettuce, spinach and radish, plant garlic and tulip bulbs, pick the last tomatoes, skip watering on Sunday, Monday and Friday, and go outside on Wednesday (dry, 25 °C).

Why the model runs locally

The checklist is written by Qwen 2.5 1.5B running through Ollama on localhost. There's no hosted AI API, no API key and no account. The weather comes from Open-Meteo, which is free and also needs no key.

I deliberately kept the model's job small. It never decides when to plant. All of that is plain, tested Python. The model only gets structured facts:

{ "place": "Boston, Massachusetts, US", "last_spring_frost": "2026-04-11", "first_fall_frost": "2026-11-07", "this_week_crops": ["Sow lettuce (fall crop)", "Plant garlic", "..."], "ready_to_harvest": ["tomato"], "care_tasks": ["Pinch tomato side shoots and tie in stems"], "forecast_tips": ["Rain on Mon Oct 12: skip watering"], "best_day_outside": "Wed Oct 14" } 

…and turns them into a friendly checklist. That design makes a 1.5B model genuinely useful: it can't invent a planting date, because it never has to work one out. Two small guardrails help too:

Lines mentioning a crop that isn't in the facts are dropped, since small models like to improvise.
Frost and harvest reminders are always kept, even if the model forgets them.
And if Ollama isn't running, the app doesn't break. It shows a rule-based checklist built from the same facts, with a small note: "Local model offline — showing rule-based plan."

Want a different model? OLLAMA_MODEL=gemma2:2b python server.py works with anything you've pulled.

How it works

The whole thing is Python 3.12 standard library only: http.server, urllib, json and statistics. There are no pip dependencies. The frontend is one HTML page and a plain ES module.

The core frost logic is ordinary, testable code:

for year, readings in sorted(by_year.items()): july1 = date(year, 7, 1) frosts = sorted(d for d, t in readings if t <= 0.0) spring = [d for d in frosts if d < july1] # last one = last spring frost fall = [d for d in frosts if d >= july1] # first one = first fall frost ... last_frost = statistics.median(spring_doys) 

A few details I'm happy with:

- Southern hemisphere: Melbourne's winter is in July, so the data is shifted half a year, run through the same logic, and shifted back.

- Frost-free places :(frost in fewer than half the years, like Miami or Mumbai) get approximate anchors that are clearly labelled as such.

- Crop calendar as data: each crop is a window in weeks relative to last or first frost, e.g. tomato transplant LF+1..LF+3, garlic FF-4..FF+2.

- Offline after the first lookup: frost history is cached on disk (it barely changes), so the calendar keeps working with no internet.

- 35 unit tests: fully offline, using synthetic temperature data for northern, southern and frost-free locations, plus the care and harvest logic.

Try it yourself

# optional, for the AI-written checklist ollama pull qwen2.5:1.5b python server.py # http://localhost:8000 python cli.py "Boston" # same plan in the terminal 

Why open matters here

A closed API could write the same six sentences. But a garden coach knows where you live and what you grow, and none of that needs to leave your laptop. With an open-weight model:

1.It runs locally, so your garden data stays on your machine.
2.There are no API keys and no cost, and nothing to sign up for.
3.You can swap any open model with one environment variable.
4.You can inspect everything: the prompt, the facts the model sees, and the rules that decide what's in season.

For a tool whose whole goal is getting you off the screen, that feels right: a small model quietly does its job on your laptop, then gets out of the way.

What I'd build next

1.Soil temperature from the forecast (great for bean and corn timing)
2.Succession reminders like "sow another row of lettuce"
3.Exporting the season as a calendar file to put on the fridge
4.Measuring whether people actually go outside more, rather than how long they spend in the app

For now, it has one job: tell you what to do in the garden this week, then send you outside.