<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Renuka Kamani</title>
    <description>The latest articles on DEV Community by Renuka Kamani (@renuka_kamani_f063f91b63c).</description>
    <link>https://dev.to/renuka_kamani_f063f91b63c</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4175232%2F5eb18990-27f2-42cd-90cc-fcbb394309b1.png</url>
      <title>DEV Community: Renuka Kamani</title>
      <link>https://dev.to/renuka_kamani_f063f91b63c</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/renuka_kamani_f063f91b63c"/>
    <language>en</language>
    <item>
      <title>TouchGrass AI: Building a Local AI Companion That Gets You Outside 🌿</title>
      <dc:creator>Renuka Kamani</dc:creator>
      <pubDate>Sun, 11 Oct 2026 04:02:57 +0000</pubDate>
      <link>https://dev.to/renuka_kamani_f063f91b63c/touchgrass-ai-building-a-local-ai-companion-that-gets-you-outside-26g9</link>
      <guid>https://dev.to/renuka_kamani_f063f91b63c/touchgrass-ai-building-a-local-ai-companion-that-gets-you-outside-26g9</guid>
      <description>&lt;h1&gt;
  
  
  TouchGrass AI: Building a Local AI Companion That Gets You Outside 🌿
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;An AI companion designed to help you spend less time on screens and more time in the real world.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Problem: We're Spending Too Much Time on Screens
&lt;/h2&gt;

&lt;p&gt;As developers, we spend hours staring at terminals, code editors, documentation, and pull requests. Even when our eyes feel tired and our minds need a break, stepping away from the computer isn't always easy.&lt;/p&gt;

&lt;p&gt;And when we finally go outside, we often take our screens with us. We check notifications, scroll through social media, or open another app.&lt;/p&gt;

&lt;p&gt;We're physically outdoors, but mentally, we're still online.&lt;/p&gt;

&lt;p&gt;For Hacktoberfest 2026 Week 1, themed &lt;strong&gt;“Touch Grass,”&lt;/strong&gt; I wanted to build something different: an AI application that doesn't encourage people to stay on the screen longer.&lt;/p&gt;

&lt;p&gt;Instead, I built &lt;strong&gt;TouchGrass AI — a local AI companion that helps you put your device away and explore the world around you.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What Is TouchGrass AI?
&lt;/h2&gt;

&lt;p&gt;TouchGrass AI turns your available free time, mood, surroundings, and preferred activities into a personalized outdoor micro-adventure.&lt;/p&gt;

&lt;p&gt;Instead of generating another long conversation, it gives you a practical mission you can remember and complete away from your screen.&lt;/p&gt;

&lt;p&gt;Users can choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Available time:&lt;/strong&gt; 10, 20, 30, 60, or 120 minutes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mood:&lt;/strong&gt; Stressed, Bored, Energetic, Curious, or Peaceful.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Activity:&lt;/strong&gt; Walking, Gardening, Observation, Birdwatching, or Surprise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environment:&lt;/strong&gt; Neighborhood, Park, Garden, Campus, or Balcony.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility preferences:&lt;/strong&gt; Adapt the mission to the user's mobility and comfort needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each generated adventure contains:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A creative title and a short narrative hook.&lt;/li&gt;
&lt;li&gt;Three to five clear, sequential steps.&lt;/li&gt;
&lt;li&gt;A sensory observation challenge, such as noticing different leaf shapes or listening for bird calls.&lt;/li&gt;
&lt;li&gt;A screen-free instruction encouraging users to silence and pocket their phones.&lt;/li&gt;
&lt;li&gt;A reflection question to consider after returning.&lt;/li&gt;
&lt;li&gt;A distraction-free active mode that displays only the information needed before heading outside.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is simple: &lt;strong&gt;use AI to make the screen the shortest part of the experience.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Why Local AI Instead of a Cloud API?
&lt;/h2&gt;

&lt;p&gt;I chose Google Gemma through Ollama because the project's purpose is to encourage people to disconnect, and its personal inputs should remain private.&lt;/p&gt;

&lt;h3&gt;
  
  
  Privacy by design
&lt;/h3&gt;

&lt;p&gt;A user's mood, preferences, and reflections can be personal. By running inference locally through Ollama, TouchGrass AI can generate missions without sending those inputs to a cloud AI provider, provided the application uses only local endpoints and does not transmit the data elsewhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  Offline capability
&lt;/h3&gt;

&lt;p&gt;Once the application dependencies and model weights have been downloaded, the core mission-generation workflow can operate without an internet connection while the local Ollama service is available.&lt;/p&gt;

&lt;p&gt;This is useful when someone wants to prepare an activity before leaving home or visiting a location with poor connectivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Freedom to experiment
&lt;/h3&gt;

&lt;p&gt;Using an open-weight model makes it possible to experiment with different models, adjust prompts, inspect the application logic, and build without requiring a paid cloud AI API key.&lt;/p&gt;

&lt;p&gt;Gemma is an open-weight model distributed under Google's Gemma Terms of Use. Its terms still apply, so open-weight should not be confused with unrestricted licensing.&lt;/p&gt;

&lt;p&gt;For this project, local inference is not just a technical choice. It supports the central idea: technology should help people reconnect with the world around them.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. How I Built It
&lt;/h2&gt;

&lt;p&gt;TouchGrass AI uses a modular Python architecture with a Streamlit interface, Ollama for local inference, Pydantic for data validation, and SQLite for progress tracking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python:&lt;/strong&gt; Core application logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit:&lt;/strong&gt; User interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama:&lt;/strong&gt; Local model serving.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Google Gemma:&lt;/strong&gt; Open-weight language model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pydantic:&lt;/strong&gt; Input and output validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite:&lt;/strong&gt; Adventure history and observation progress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pytest:&lt;/strong&gt; Automated testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Architecture
&lt;/h3&gt;

&lt;p&gt;The application follows this flow:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;![ ](https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/articles/q11fnt53ny17kvpy7vt1.png)&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  Key modules
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;app.py&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Provides the Streamlit interface, collects user preferences, and displays generated missions in a nature-inspired visual design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;services/ollama_service.py&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Communicates with Ollama's local HTTP API, including model discovery and generation. It handles connection failures, missing models, and timeouts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;services/mission_generator.py&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Builds prompts, requests structured JSON output, extracts the JSON payload, and validates the result against a Pydantic model called &lt;code&gt;OutdoorMission&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;services/progress_service.py&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stores adventure history and observation completions in SQLite. It calculates consecutive-day streaks from recorded dates rather than inventing progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The Hardest Challenge: Getting Reliable JSON from a Small Local Model
&lt;/h2&gt;

&lt;p&gt;One of the most interesting challenges was making small local models return structured, usable mission data.&lt;/p&gt;

&lt;p&gt;A model may produce conversational text before its answer, wrap JSON in Markdown code fences, omit required fields, or return malformed output.&lt;/p&gt;

&lt;p&gt;That becomes a problem when the application expects a specific structure.&lt;/p&gt;

&lt;p&gt;I addressed this with three layers of protection.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Ollama JSON mode
&lt;/h3&gt;

&lt;p&gt;The generation request uses &lt;code&gt;"format": "json"&lt;/code&gt; to encourage valid JSON output.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. JSON extraction
&lt;/h3&gt;

&lt;p&gt;An &lt;code&gt;extract_json&lt;/code&gt; helper isolates the JSON object from surrounding text or Markdown formatting.&lt;/p&gt;

&lt;p&gt;This makes the parser more tolerant of unexpected presentation, although malformed or incomplete JSON can still fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Pydantic validation and offline fallback
&lt;/h3&gt;

&lt;p&gt;The extracted object is validated against the &lt;code&gt;OutdoorMission&lt;/code&gt; schema. If generation fails or the output cannot be validated, the application can use its curated offline mission library.&lt;/p&gt;

&lt;p&gt;The fallback is explicitly labeled &lt;strong&gt;“🍂 Curated Offline Library”&lt;/strong&gt;, so users can distinguish a locally generated AI mission from a predefined mission.&lt;/p&gt;

&lt;p&gt;This approach matters because a local model should not be allowed to break the entire user experience just because one response is malformed.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Testing and Verification
&lt;/h2&gt;

&lt;p&gt;I treated reliability as an important part of the project rather than relying only on a successful demonstration.&lt;/p&gt;

&lt;p&gt;The automated test suite uses Pytest and mocked Ollama endpoints to test behavior without requiring live inference for every test.&lt;/p&gt;

&lt;p&gt;The test cases cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User preference validation.&lt;/li&gt;
&lt;li&gt;Outdoor mission schema validation.&lt;/li&gt;
&lt;li&gt;JSON extraction from plain text and Markdown.&lt;/li&gt;
&lt;li&gt;Fallback behavior when Ollama cannot connect.&lt;/li&gt;
&lt;li&gt;Fallback behavior after a timeout.&lt;/li&gt;
&lt;li&gt;Consecutive-day streak calculation.&lt;/li&gt;
&lt;li&gt;Historical streak retention and multiple sessions on the same day.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reported test results
&lt;/h3&gt;

&lt;p&gt;The test run recorded for this project was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;14 out of 14 tests passed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Execution time: 0.18 seconds&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These results should correspond to the actual test run in the published repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local inference example
&lt;/h3&gt;

&lt;p&gt;A recorded inference run with &lt;code&gt;gemma:2b&lt;/code&gt; generated the following mission:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Title:&lt;/strong&gt; Floral Fable Hunt&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Duration:&lt;/strong&gt; 10 minutes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Steps:&lt;/strong&gt; 4&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observation challenge:&lt;/strong&gt; Identify at least five different types of plant leaves and notice their textures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Screen-free rule:&lt;/strong&gt; Keep your phone in silent mode and focus on the natural world around you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generation source:&lt;/strong&gt; Local Gemma model&lt;/p&gt;

&lt;p&gt;The recorded run completed without using the curated fallback library.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. How to Run TouchGrass AI
&lt;/h2&gt;

&lt;p&gt;You can run the project on your own computer with Python and Ollama.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install Ollama
&lt;/h3&gt;

&lt;p&gt;Download and install Ollama from &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;https://ollama.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pull the model used by the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull gemma:2b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ollama normally runs in the background after installation. If its server is already running, you do not need to start another instance with &lt;code&gt;ollama serve&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Clone the repository
&lt;/h3&gt;

&lt;p&gt;Replace the URL below with the actual public repository URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone YOUR_GITHUB_REPOSITORY_URL
&lt;span class="nb"&gt;cd &lt;/span&gt;touchgrass-ai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Create a virtual environment
&lt;/h3&gt;

&lt;p&gt;On Windows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;venv&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\venv\Scripts\Activate.ps1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;pip&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;requirements.txt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On macOS or Linux:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Run the tests
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pytest tests &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Launch the application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;streamlit run app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;a href="http://localhost:8501" rel="noopener noreferrer"&gt;http://localhost:8501&lt;/a&gt; in your browser.&lt;/p&gt;

&lt;p&gt;Choose your preferences, generate an adventure, memorize the steps, and head outside.&lt;/p&gt;

&lt;p&gt;For offline use, make sure the required dependencies and model weights have already been installed and downloaded.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. What's Next?
&lt;/h2&gt;

&lt;p&gt;There are several directions in which TouchGrass AI could grow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Offline nature soundscapes:&lt;/strong&gt; Optional ambient audio for rain, wind, and flowing water.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Printable field notes:&lt;/strong&gt; Exportable PDF or Markdown checklists for screen-free nature journaling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Season-aware missions:&lt;/strong&gt; Adapt activities to seasonal changes and locally relevant environmental conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;More model choices:&lt;/strong&gt; Allow users to configure different compatible local models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility improvements:&lt;/strong&gt; Offer more ways to adapt activities to individual needs and surroundings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These improvements would expand the experience without losing its main purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Building TouchGrass AI reinforced an idea I find important: AI does not always have to maximize engagement with technology.&lt;/p&gt;

&lt;p&gt;Sometimes, the most useful application is the one that helps us close the laptop, leave the notifications behind, and pay attention to what's around us.&lt;/p&gt;

&lt;p&gt;Open-weight models and local inference make this experience more private, customizable, and accessible to people who want to experiment without depending on a paid cloud AI service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The best AI interaction might be the one that inspires you to stop interacting and start exploring.&lt;/strong&gt; 🌱&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub repository:&lt;/strong&gt; [&lt;a href="https://github.com/Renuka-Kamani/touchgrass_ai" rel="noopener noreferrer"&gt;https://github.com/Renuka-Kamani/touchgrass_ai&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Application screenshots:&lt;/strong&gt; [&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/..." class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/..." alt="Uploading image" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Built for the Hacktoberfest 2026 Open-Source AI Challenge — Week 1: Touch Grass.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
