<?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: Rohith Pavithran</title>
    <description>The latest articles on DEV Community by Rohith Pavithran (@rohithtp).</description>
    <link>https://dev.to/rohithtp</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%2F509052%2F1a0f8134-7793-4e1e-9821-f06880c29390.png</url>
      <title>DEV Community: Rohith Pavithran</title>
      <link>https://dev.to/rohithtp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rohithtp"/>
    <language>en</language>
    <item>
      <title>Free Voice Music Curator: Ditch Premium Music Fees with ElevenLabs &amp; Google AI</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sun, 12 Jul 2026 15:18:44 +0000</pubDate>
      <link>https://dev.to/rohithtp/free-voice-music-curator-ditch-premium-music-fees-with-elevenlabs-google-ai-454c</link>
      <guid>https://dev.to/rohithtp/free-voice-music-curator-ditch-premium-music-fees-with-elevenlabs-google-ai-454c</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-07-09"&gt;Weekend Challenge: Passion Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built the &lt;strong&gt;Free Voice Music Curator&lt;/strong&gt;, an intelligent full-stack audio player powered entirely by public APIs, legal Creative Commons music, and zero paid subscription walls.&lt;/p&gt;

&lt;p&gt;Inspired by the challenge prompt of &lt;strong&gt;passion&lt;/strong&gt;, I wanted to capture the absolute devotion fans and hobbyists pour into their musical worlds. However, classic web-streaming apps are trapped behind heavy OAuth logic or aggressive paid premium tiers. The &lt;em&gt;Free Voice Music Curator&lt;/em&gt; solves this by allowing users to command a local audio player using natural voice strings (via ElevenLabs), which are dynamically parsed by Google AI to pull over 500,000 legal, free-streaming tracks from Jamendo.&lt;/p&gt;

&lt;h3&gt;
  
  
  🟢 The Free-Tier Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ElevenLabs Agent ] ➔ Webhook ➔ [ Backend Server ] ➔ Jamendo REST API
                                        │
                                        ▼
                        [ HTML5 Audio Player Engine ] ➔ (Plays raw .mp3 stream)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;The application is fully configured and ready!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Development Webhook:&lt;/strong&gt; &lt;code&gt;https://ais-dev-vtsuihfhfsyunprfhoszsh-559194232025.asia-east1.run.app/api/webhook/elevenlabs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production Webhook Simulator:&lt;/strong&gt; Included directly inside the UI console so you can fire direct preset configurations (e.g., &lt;code&gt;💤 Lofi Study&lt;/code&gt;, &lt;code&gt;🏎️ Synthwave&lt;/code&gt;, &lt;code&gt;🎸 Acoustic&lt;/code&gt;) to watch the system respond in real time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The interface features a gorgeous deep interstellar slate and emerald canvas (&lt;code&gt;bg-slate-900&lt;/code&gt; / &lt;code&gt;text-emerald-400&lt;/code&gt;) alongside modern typography pairings (&lt;code&gt;Space Grotesk&lt;/code&gt; and &lt;code&gt;Inter&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Here is the clean &lt;strong&gt;Python Core Engine&lt;/strong&gt; snippet used to process the incoming webhook metadata securely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;vlc&lt;/span&gt;  &lt;span class="c1"&gt;# Install via: pip install python-vlc
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FreeVoiceMusicCurator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client_id&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://api.jamendo.com/v3.0/tracks/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_curated_stream_urls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_genre&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_artist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Querying free cloud library for: Genre=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_genre&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Artist=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_artist&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;client_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audioformat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mp32&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;popularity_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target_genre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_genre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;target_artist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;artist_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;target_artist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="n"&gt;tracks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

            &lt;span class="n"&gt;stream_targets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tracks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;stream_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;audio&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stream_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;stream_targets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;artist&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;artist_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stream_url&lt;/span&gt;
                    &lt;span class="p"&gt;})&lt;/span&gt;

            &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stream_targets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;stream_targets&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;API Fetch Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The execution pipeline flows fluidly across three modern technical frameworks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Intelligent Conversational Agent (ElevenLabs):&lt;/strong&gt; I built a blank agent powered by a custom webhook tool named &lt;code&gt;play_free_genre_music&lt;/code&gt;. It listens for spoken triggers like &lt;em&gt;"Play some high-energy synthwave beats"&lt;/em&gt; and extracts clean textual params (&lt;code&gt;prompt&lt;/code&gt;, &lt;code&gt;genre&lt;/code&gt;, &lt;code&gt;artist&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contextual AI Translation Engine (Google AI Studio):&lt;/strong&gt; The backend leverages the &lt;code&gt;gemini-3.5-flash&lt;/code&gt; model to analyze the full natural-language transcripts, scrubbing out specific moods, obscure tags, or strict artist names, complete with a local rule-based keyword fallback parser to guarantee zero downtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive Web Player Platform:&lt;/strong&gt; Built an HTML5 audio context interface complete with a live API resource monitor (tracking Jamendo's 35,000 free monthly request tier cap) and real-time scrolling telemetry log panels recording every single serverless event transcript.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;This application is being submitted to the following prize categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of ElevenLabs:&lt;/strong&gt; For mapping custom voice conversational tools to a local audio state architecture seamlessly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Google AI:&lt;/strong&gt; Using Gemini to turn messy, natural speech commands into highly structured metadata payloads.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>googleai</category>
      <category>elevenlabs</category>
    </item>
    <item>
      <title>Terminal Web 2.0: AI Preflight, Healing, and Safety</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sun, 07 Jun 2026 11:45:57 +0000</pubDate>
      <link>https://dev.to/rohithtp/terminal-web-20-ai-preflight-healing-and-safety-dbj</link>
      <guid>https://dev.to/rohithtp/terminal-web-20-ai-preflight-healing-and-safety-dbj</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Terminal Web (&lt;code&gt;py_terminal&lt;/code&gt;)&lt;/strong&gt; is a powerful terminal-based UI web project utilizing Python and the &lt;a href="https://github.com/Textualize/rich" rel="noopener noreferrer"&gt;Rich&lt;/a&gt; library for beautiful terminal output combined with advanced command execution capabilities.&lt;/p&gt;

&lt;p&gt;As part of the Finish-Up-A-Thon, I transformed this tool by integrating an &lt;strong&gt;AI Safety Net&lt;/strong&gt;—a proactive layer designed to protect users from executing destructive shell commands (e.g., &lt;code&gt;rm -rf&lt;/code&gt;, &lt;code&gt;git push --force&lt;/code&gt;) while maintaining a fluid and rapid developer experience. The safety net employs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tier-1 Heuristics:&lt;/strong&gt; Instant, offline protection against common dangerous commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier-2 AI Preflight:&lt;/strong&gt; LLM-powered risk analysis that summarizes potential consequences and affected resources for &lt;code&gt;MUTATING+&lt;/code&gt; risk levels.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intelligent Self-Healing:&lt;/strong&gt; A workflow that diagnoses failed commands (e.g., permission errors, missing paths) and suggests safe alternatives to get you back on track.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Project Repository:&lt;/strong&gt; &lt;a href="https://github.com/rohithtp/py_terminal" rel="noopener noreferrer"&gt;https://github.com/rohithtp/py_terminal&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;Previously, &lt;code&gt;py_terminal&lt;/code&gt; was an effective CLI wrapper with dual execution modes (interactive and capture) and beautifully formatted outputs. However, it had one critical flaw: it blindly executed whatever bash command was provided, offering no protection against accidental system damage. In a modern development environment where LLMs are sometimes used to generate complex, unverified commands, ensuring those commands are safe to run locally became a high priority.&lt;/p&gt;

&lt;p&gt;To "finish it up" for this hackathon, I drastically leveled up the tool's intelligence and safety by adding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An AI Preflight Loop:&lt;/strong&gt; Intercepts risky commands, uses LLMs to generate reversibility notes, and blocks execution until explicit user confirmation is given.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Self-Healing Workflow:&lt;/strong&gt; Catches non-zero exit codes, diagnoses the error (e.g., "No such file or directory"), and proposes an LLM-generated fix that gets re-routed through the safety preflight loop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite Caching:&lt;/strong&gt; Caches preflight AI evaluations to avoid duplicate API calls and guarantees zero latency for repeated commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline Graceful Degradation:&lt;/strong&gt; The UI falls back beautifully to local heuristic warnings when the LLM API is unavailable, ensuring the tool is always usable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Status Capture Utility:&lt;/strong&gt; A built-in telemetry tool to rapidly verify repository and dependency health.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;GitHub Copilot acted as an exceptionally fast pair programmer throughout this challenge. It was instrumental in scaffolding the &lt;code&gt;pexpect&lt;/code&gt;-based automated test suite for validating the AI Safety Net, mocking out LLM network responses, and quickly laying out the boilerplate for the Rich UI panels. &lt;/p&gt;

&lt;p&gt;When constructing the SQLite caching mechanism, Copilot seamlessly anticipated the database schema I needed and handled boilerplate queries, allowing me to focus entirely on the core business logic of the safety heuristics and healing loop. It transformed complex refactoring and UI layout tasks into smooth, effortless completions.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Team Members:&lt;/strong&gt; &lt;a class="mentioned-user" href="https://dev.to/rohithtp"&gt;@rohithtp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
    </item>
    <item>
      <title>mnemo — A local-first learning agent that remembers, without leaking</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sun, 31 May 2026 09:20:10 +0000</pubDate>
      <link>https://dev.to/rohithtp/mnemo-a-local-first-learning-agent-that-remembers-without-leaking-d49</link>
      <guid>https://dev.to/rohithtp/mnemo-a-local-first-learning-agent-that-remembers-without-leaking-d49</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hermes-agent-2026-05-15"&gt;Hermes Agent Challenge&lt;/a&gt;: Build With Hermes Agent&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;mnemo&lt;/strong&gt; is a learning-management agent for kids and self-directed learners. It tracks topics, sequences them by prerequisites, schedules spaced-repetition reviews (SM-2), generates quizzes, and adapts the plan over time through a Hermes-driven feedback loop.&lt;/p&gt;

&lt;p&gt;The problem: hosted AI tutors send a child's mistakes, struggles, and reading level to someone else's servers. Browser-only chat loops forget everything the moment the tab closes — no cross-session adaptation, no long-term plan. And LLMs happily hallucinate URLs and quiz answers, so nothing stops an unreviewed link from reaching a 6th-grader.&lt;/p&gt;

&lt;p&gt;mnemo's answer is a three-part stance baked into the schema, not bolted on:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Local-first by default.&lt;/strong&gt; SQLite (WAL) on-device, 7 tables, 3 migrations. Hermes-3 runs locally via Ollama. A HuggingFace API path exists for constrained hardware but requires explicit opt-in and is clearly labelled in the UI — every hosted call is logged to the &lt;code&gt;events&lt;/code&gt; table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two gates before any content reaches the learner.&lt;/strong&gt; Every external &lt;code&gt;resource&lt;/code&gt; starts &lt;code&gt;approved = 0&lt;/code&gt; in the schema. A second gate joins a &lt;code&gt;source_allowlist&lt;/code&gt; table at the SQL layer — even an approved resource is suppressed if its origin isn't a trusted source (&lt;code&gt;khan-academy&lt;/code&gt;, &lt;code&gt;ck12&lt;/code&gt;, internal-curriculum). Both gates have dedicated scenario tests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The agent proposes; a human approves.&lt;/strong&gt; Pace changes, resource-type shifts, and any preference write goes through a confirmation gate. The agent literally cannot mutate learner preferences without a human checkbox — enforced via an MCP deny-list, not just UI.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Pitch deck (single-file Reveal.js, no build step):&lt;br&gt;
&lt;strong&gt;&lt;a href="https://plain-frost-2119.rohithtp.workers.dev/" rel="noopener noreferrer"&gt;pitch.html&lt;/a&gt;&lt;/strong&gt; — 6 slides covering the problem, the Hermes differentiator, architecture, the two-gate safety model, and a realistic dashboard mockup of the shipped UI.&lt;/p&gt;

&lt;p&gt;Quick local run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &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
sqlite3 learning.db &amp;lt; migrations/001_init.sql
sqlite3 learning.db &amp;lt; migrations/002_quiz_bank.sql
sqlite3 learning.db &amp;lt; migrations/003_source_allowlist.sql
python &lt;span class="nt"&gt;-m&lt;/span&gt; uvicorn webapp.app:app &lt;span class="nt"&gt;--reload&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:8000&lt;/code&gt; for the dashboard, or run a Hermes session end-to-end:&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 hermes3
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/api/agent/session &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"learner_id": 1, "backend": "ollama"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dashboard streams each tool call the agent makes, then refreshes progress and the review queue automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Repository: &lt;strong&gt;&lt;a href="https://gitea.com/rohithtp/mnemo" rel="noopener noreferrer"&gt;gitea.com/rohithtp/mnemo&lt;/a&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Key directories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;webapp/&lt;/code&gt; — FastAPI REST + SSE + static dashboard (25+ endpoints)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp_server/&lt;/code&gt; — stdio MCP server exposing 7 tools to Hermes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/agent/&lt;/code&gt; — Hermes session orchestrator, allowlist, memory, insights&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/learning/&lt;/code&gt; — SM-2 algorithm, sequencing logic, safety/privacy gates&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;migrations/&lt;/code&gt; — 3 SQL files, schema-version tracked&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tests/&lt;/code&gt; — 69 passing tests (SM-2 unit + integration + API + scenario)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docs/&lt;/code&gt; — full build plan, decisions log, 25-risk register, two-profile docs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  My Tech Stack
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Choice&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; (WAL mode) on-device · libSQL/Turso documented as forward path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; + uvicorn + SSE streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent runtime&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Hermes-3&lt;/strong&gt; via &lt;strong&gt;Ollama&lt;/strong&gt; (local) · HuggingFace Inference API fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool surface&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;stdio MCP&lt;/strong&gt; (Hermes) + &lt;strong&gt;WebMCP&lt;/strong&gt; progressive enhancement (Chrome 146+)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Vanilla JS + plain CSS — no framework, no build step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spaced repetition&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;SM-2&lt;/strong&gt; algorithm, implemented as pure functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;pytest&lt;/strong&gt; — 15 SM-2 unit + 18 integration + 31 API + 5 scenario = &lt;strong&gt;69 passing&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Dockerfile&lt;/strong&gt; + systemd unit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;Python 3.11+ (3.14 tested)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All Python deps are pinned in &lt;code&gt;requirements.txt&lt;/code&gt;. The Hermes-3 model digest is pinned by SHA256 and asserted at startup so a silent upstream change can't drift the agent's behaviour mid-session (R02 mitigation).&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Used Hermes Agent
&lt;/h2&gt;

&lt;p&gt;Hermes-3 is the orchestration brain for the whole adaptive loop. The reason it had to be Hermes specifically, not a stateless prompt loop, comes down to four capabilities:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tool-calling over a real schema.&lt;/strong&gt; &lt;code&gt;src/agent/session.py&lt;/code&gt; runs a tool-calling loop where Hermes drives a study session by calling the 7 MCP tools (&lt;code&gt;get_progress_summary&lt;/code&gt;, &lt;code&gt;get_ready_topics&lt;/code&gt;, &lt;code&gt;start_topic&lt;/code&gt;, &lt;code&gt;get_next_review_items&lt;/code&gt;, &lt;code&gt;record_review_result&lt;/code&gt;, &lt;code&gt;recommend_resources&lt;/code&gt;, &lt;code&gt;generate_quiz&lt;/code&gt;). Each call is logged to the &lt;code&gt;events&lt;/code&gt; table with arguments and result. The agent isn't generating advice in prose — it's writing to SQLite through audited tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Cross-session memory.&lt;/strong&gt; Every session writes a &lt;code&gt;memory_note&lt;/code&gt; event summarising patterns the agent noticed. The next session's system prompt is injected with the most recent notes for that learner, so Hermes "remembers" that this kid struggles with unlike denominators across sessions, not just within one tab. Memory notes are per-learner and stay on-device.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Pattern analysis + human-approvable proposals.&lt;/strong&gt; Phase 6 added &lt;code&gt;POST /api/agent/insights/{learner_id}&lt;/code&gt;. Hermes reads the event trail across a configurable window, computes &lt;code&gt;avg_quality&lt;/code&gt;, &lt;code&gt;days_active&lt;/code&gt;, resource-type variety, and emits structured proposals like &lt;code&gt;{"type": "pace", "direction": "increase", "reason": "avg quality above 4.0"}&lt;/code&gt;. Each proposal is stored with &lt;code&gt;resolved_at = NULL&lt;/code&gt; and surfaces in the dashboard with Approve / Dismiss buttons. The agent never silently applies pace changes — a human resolves each proposal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Allowlist-enforced tool boundary.&lt;/strong&gt; &lt;code&gt;src/agent/allowlist.py&lt;/code&gt; defines &lt;code&gt;AGENT_ALLOWLIST&lt;/code&gt; and &lt;code&gt;AGENT_DENY_LIST&lt;/code&gt; as constants. &lt;code&gt;set_learner_preferences&lt;/code&gt; is on the deny-list, so even if the model is jailbroken into trying to mutate preferences directly, the session orchestrator raises &lt;code&gt;PermissionError&lt;/code&gt; before the tool runs. This is the difference between "the UI hides it" and "the agent cannot do it."&lt;/p&gt;

&lt;p&gt;The combination — local model + persistent memory + audited tool calls + human-in-the-loop on every state-mutating proposal — is what makes mnemo trustable as a coach for a child, not just for an adult tinkerer. That posture is what the Hermes agent makes practical; a hosted stateless chatbot can't enforce any of it.&lt;/p&gt;

</description>
      <category>hermesagentchallenge</category>
      <category>devchallenge</category>
      <category>agents</category>
      <category>hermesagent</category>
    </item>
    <item>
      <title>StudyTrak // Astra Core – Gemma 4 Challenge Submission</title>
      <dc:creator>Rohith Pavithran</dc:creator>
      <pubDate>Sat, 23 May 2026 17:42:27 +0000</pubDate>
      <link>https://dev.to/rohithtp/studytrak-astra-core-gemma-4-challenge-submission-cc6</link>
      <guid>https://dev.to/rohithtp/studytrak-astra-core-gemma-4-challenge-submission-cc6</guid>
      <description>&lt;h1&gt;
  
  
  StudyTrak // Astra Core – Gemma 4 Challenge Submission
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Build with Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;StudyTrak (Astra Core)&lt;/strong&gt; is an immersive, high-fidelity student spaced repetition planner and neural coaching console. Designed to work completely local-first or proxy securely via remote endpoints, StudyTrak solves the "academic attention fragmentation" problem. It merges class schedules, homework tracker boards, spaced-repetition card decks (SM-2 scheduler), and deep neural academic helpers into a single HUD-inspired dashboard. &lt;/p&gt;

&lt;h3&gt;
  
  
  Core Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🗓️ &lt;strong&gt;Astra Chrono Scheduler&lt;/strong&gt;: Interactive class blocks and room assignments synced with responsive real-time layout structures.&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Spaced Repetition Flashcards&lt;/strong&gt;: Localized FSRS/SM-2 simulator (with grades: &lt;em&gt;Forgot&lt;/em&gt;, &lt;em&gt;Hard Link&lt;/em&gt;, &lt;em&gt;Good Match&lt;/em&gt;, &lt;em&gt;Perfect Spot&lt;/em&gt;) scheduling item intervals adaptively.&lt;/li&gt;
&lt;li&gt;🎙️ &lt;strong&gt;Multi-Modal Capture Panel&lt;/strong&gt;: Scan worksheets (Camera/Photo uploads) or type natural language inputs to automatically parse schedule drafts and pending homework proposals.&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;Subject Advisory Chat Tutor&lt;/strong&gt;: Academic conversational helper grounded directly in defined high-school/college subjects.&lt;/li&gt;
&lt;li&gt;🧘‍♀️ &lt;strong&gt;Empathetic Reflection Journal&lt;/strong&gt;: Conversational weekly debriefs tracking achievements, struggles, and proposed behavioral corrections.&lt;/li&gt;
&lt;li&gt;🔊 &lt;strong&gt;Voice Speech Synthesis&lt;/strong&gt;: Listen to high-fidelity audio versions of daily briefings with an interactive audio player.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  App In Google AI
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AiStudio&lt;/strong&gt;: &lt;a href="https://ai.studio/apps/97a83485-4fc2-43ae-8eb7-b82d63cdb1e9" rel="noopener noreferrer"&gt;https://ai.studio/apps/97a83485-4fc2-43ae-8eb7-b82d63cdb1e9&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The complete, pristine full-stack source code is published on Gitea at &lt;a href="https://gitea.com/rohithtp/studytrak" rel="noopener noreferrer"&gt;https://gitea.com/rohithtp/studytrak&lt;/a&gt;. You can clone, audit, or deploy the application directly from this repository.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Used Gemma 4
&lt;/h2&gt;

&lt;p&gt;StudyTrak leverages the lightweight yet highly competent capabilities of the &lt;strong&gt;Gemma 4&lt;/strong&gt; model lineup to deliver a privacy-preserving co-pilot:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Model Choices and Fit&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 Tiny (E2B - 1.5GB)&lt;/strong&gt;: Configured as the optimal on-device WebLLM/MediaPipe companion. We chose the E2B formulation because it easily fits within the standard modern browser sandbox, enabling sub-150ms real-time token generation for micro-scans and speech transcription parsing without any outbound network latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 Standard (E4B - 3GB)&lt;/strong&gt;: Selected for core desktop semantic analysis, empathetic reflection summaries, and structuring homework proposals from handwritten worksheet snapshots. It balances rapid execution speeds with reasoning traits needed to provide high-quality structural mentorship.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Context Grounding&lt;/strong&gt;:&lt;br&gt;
Every prompt generated goes through a deep localized context packaging layer, supplying active subject indices, schedule constraints, and historic reflection streaks to completely ground prompt results with zero external leak risk.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
    </item>
  </channel>
</rss>
