<?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: Twisted-Code'r</title>
    <description>The latest articles on DEV Community by Twisted-Code'r (@jeffrin-dev).</description>
    <link>https://dev.to/jeffrin-dev</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3817901%2F6517f8eb-a101-4823-9acb-d0ce98eaa1ff.jpg</url>
      <title>DEV Community: Twisted-Code'r</title>
      <link>https://dev.to/jeffrin-dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jeffrin-dev"/>
    <language>en</language>
    <item>
      <title>AUTO WRITES PR FOR YOU - PRDRAFT</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Sat, 18 Apr 2026 07:17:35 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/auto-writes-pr-for-you-prdraft-9cd</link>
      <guid>https://dev.to/jeffrin-dev/auto-writes-pr-for-you-prdraft-9cd</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/jeffrin-dev/i-got-tired-of-prs-that-just-said-fix-so-i-built-a-github-app-that-writes-the-description-for-obd" class="crayons-story__hidden-navigation-link"&gt;I got tired of PRs that just said "fix" — so I built a GitHub App that writes the description for you&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/jeffrin-dev" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3817901%2F6517f8eb-a101-4823-9acb-d0ce98eaa1ff.jpg" alt="jeffrin-dev profile" class="crayons-avatar__image" width="800" height="450"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/jeffrin-dev" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Twisted-Code'r
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Twisted-Code'r
                
              
              &lt;div id="story-author-preview-content-3486556" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/jeffrin-dev" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3817901%2F6517f8eb-a101-4823-9acb-d0ce98eaa1ff.jpg" class="crayons-avatar__image" alt="" width="800" height="450"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Twisted-Code'r&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/jeffrin-dev/i-got-tired-of-prs-that-just-said-fix-so-i-built-a-github-app-that-writes-the-description-for-obd" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 11&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/jeffrin-dev/i-got-tired-of-prs-that-just-said-fix-so-i-built-a-github-app-that-writes-the-description-for-obd" id="article-link-3486556"&gt;
          I got tired of PRs that just said "fix" — so I built a GitHub App that writes the description for you
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/automation"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;automation&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/github"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;github&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/jeffrin-dev/i-got-tired-of-prs-that-just-said-fix-so-i-built-a-github-app-that-writes-the-description-for-obd" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;2&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/jeffrin-dev/i-got-tired-of-prs-that-just-said-fix-so-i-built-a-github-app-that-writes-the-description-for-obd#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>I got tired of PRs that just said "fix" — so I built a GitHub App that writes the description for you</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Sat, 11 Apr 2026 10:54:30 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/i-got-tired-of-prs-that-just-said-fix-so-i-built-a-github-app-that-writes-the-description-for-obd</link>
      <guid>https://dev.to/jeffrin-dev/i-got-tired-of-prs-that-just-said-fix-so-i-built-a-github-app-that-writes-the-description-for-obd</guid>
      <description>&lt;p&gt;We've all seen it.&lt;/p&gt;

&lt;p&gt;You open a pull request from a teammate — or your past self — and the description says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"fix bug"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's it. No context. No what changed. No why. You're now a code archaeologist trying to reverse-engineer intent from a diff.&lt;/p&gt;

&lt;p&gt;I've been that person. I've also been on the reviewing end, nudging people repeatedly for context that should've been in the description from the start. It's death by a thousand tiny frustrations.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real problem isn't laziness
&lt;/h2&gt;

&lt;p&gt;Developers don't skip PR descriptions because they don't care. They skip them because by the time the code is done, switching context to write documentation feels like starting a second job. You've been deep in the problem for hours. Writing "what changed and why" in plain English requires a different gear entirely.&lt;/p&gt;

&lt;p&gt;So most people don't. Or they write something just good enough to pass review, which ends up useless to anyone reading it six months later.&lt;/p&gt;




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

&lt;p&gt;I'm a solo developer in Kerala, India, building &lt;strong&gt;PRDraft&lt;/strong&gt; — a GitHub App that reads your PR diff and auto-writes a structured description. Two-click install, zero config.&lt;/p&gt;

&lt;p&gt;When you open a PR, it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetches the diff&lt;/li&gt;
&lt;li&gt;Sends it to an LLM (Groq / llama-3.3-70b)&lt;/li&gt;
&lt;li&gt;Posts a structured description directly to your PR body&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The output looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## What changed
Refactored the auth middleware to use JWT validation instead of session cookies.
Removed the legacy session store dependency.

## Why
Session-based auth was causing intermittent failures in the load-balanced setup.
JWT tokens eliminate the shared state problem entirely.

## How to test
- Log in with an existing account — confirm token is returned in response header
- Test expired token path — confirm 401 is returned correctly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not perfect every time. But dramatically better than "fix auth" — and it takes zero effort from the developer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack (all free)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Next.js on Vercel&lt;/li&gt;
&lt;li&gt;Supabase (PostgreSQL)&lt;/li&gt;
&lt;li&gt;Groq API (free tier — 14,400 req/day)&lt;/li&gt;
&lt;li&gt;Paddle for payments&lt;/li&gt;
&lt;li&gt;GitHub App webhooks via Octokit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Total infra cost: &lt;strong&gt;$0/month&lt;/strong&gt;. Built this in evenings over 4 weeks while learning most of it as I went.&lt;/p&gt;




&lt;h2&gt;
  
  
  The thing nobody tells you about building GitHub Apps
&lt;/h2&gt;

&lt;p&gt;The hardest part wasn't the AI integration. It was webhook deduplication.&lt;/p&gt;

&lt;p&gt;GitHub retries webhooks aggressively if your endpoint doesn't respond in time. I once had a single PR trigger 38 webhook calls. My PR count was wildly inflated, users were hitting the free tier cap immediately, and I had no idea why.&lt;/p&gt;

&lt;p&gt;Fix: unique constraint on &lt;code&gt;(installation_id, pr_number)&lt;/code&gt; in Supabase, plus a dedup guard before processing. The webhook still fires 38 times — but only the first one does anything.&lt;/p&gt;

&lt;p&gt;If you're building on GitHub webhooks, add this early. Don't find out the hard way like I did.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where it is now
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Live at &lt;a href="https://github.com/apps/prdraft" rel="noopener noreferrer"&gt;github.com/apps/prdraft&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Free for first 5 PRs, then $9/month&lt;/li&gt;
&lt;li&gt;2 installs so far (one of which is me)&lt;/li&gt;
&lt;li&gt;GitHub Marketplace listing submitted, waiting on review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No paid users yet. That's the next problem to solve.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you're tired of writing PR descriptions — or tired of reviewing PRs with no context — install it and let me know what the output looks like on your actual diffs.&lt;/p&gt;

&lt;p&gt;Feedback at this stage means everything. I read every reply.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/apps/prdraft" rel="noopener noreferrer"&gt;Install PRDraft — free for 5 PRs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Review
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4754jivm89k1s7j5jpy.png" 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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4754jivm89k1s7j5jpy.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Building in public. Day 10 of however long this takes.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>github</category>
      <category>productivity</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I built a GitHub App that auto-writes PR descriptions — here's what happened in 8 days</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Mon, 06 Apr 2026 17:30:22 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/i-built-a-github-app-that-auto-writes-pr-descriptions-heres-what-happened-in-8-days-5b79</link>
      <guid>https://dev.to/jeffrin-dev/i-built-a-github-app-that-auto-writes-pr-descriptions-heres-what-happened-in-8-days-5b79</guid>
      <description>&lt;p&gt;I hate writing PR descriptions.&lt;/p&gt;

&lt;p&gt;Not because I'm lazy — I know what I changed. Articulating it clearly, in a format that helps reviewers, takes 10 extra minutes of context switching. Every. Single. Time.&lt;/p&gt;

&lt;p&gt;So I built PRDraft — a GitHub App that reads your diff when you open a PR and posts a structured description automatically. 2-click install, zero config, no CLI.&lt;/p&gt;

&lt;p&gt;Here's what 8 days of building looks like from scratch, solo, from Kerala, India.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 1–2: Does anyone actually care?
&lt;/h2&gt;

&lt;p&gt;Before writing a single line of code I posted in GitHub Discussions and dropped a question on Dev.to:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Who actually writes good PR descriptions consistently?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Got real responses. Two that stuck:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"Yes, real pain point especially on fast-moving teams"&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;"I'd trust it if it accurately reflects the diff and I can edit before submitting"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That was enough. Building justified.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 3–5: Building the thing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tech stack I landed on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next.js (App Router) + Tailwind&lt;/li&gt;
&lt;li&gt;Supabase (PostgreSQL) for installs and PR event tracking&lt;/li&gt;
&lt;li&gt;Groq API (llama-3.3-70b-versatile) for AI generation — genuinely free, 14,400 requests/day, works in India&lt;/li&gt;
&lt;li&gt;Octokit for GitHub App integration&lt;/li&gt;
&lt;li&gt;Vercel for hosting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Groq instead of Claude or Gemini:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anthropic API costs money, no free tier&lt;/li&gt;
&lt;li&gt;Google Gemini free tier has limit:0 quota for India region — confirmed bug&lt;/li&gt;
&lt;li&gt;Groq is genuinely free and fast&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total infra cost: $0/month&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User opens PR → GitHub sends webhook → verify signature → 
fetch diff → send to Groq → post structured description back to PR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated description looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## What changed&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Added webhook signature verification using Octokit
&lt;span class="p"&gt;-&lt;/span&gt; Introduced free tier cap logic (5 PRs/month) checked before incrementing

&lt;span class="gu"&gt;## Why&lt;/span&gt;
Prevents unauthorized webhook calls and limits free usage before billing is set up.

&lt;span class="gu"&gt;## How to test&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Open a PR on a repo where PRDraft is installed
&lt;span class="p"&gt;-&lt;/span&gt; Check that the description is auto-populated within seconds

&lt;span class="gu"&gt;## Notes&lt;/span&gt;
Free tier cap is checked BEFORE incrementing pr_count to avoid off-by-one errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Day 5: First external user
&lt;/h2&gt;

&lt;p&gt;roshhellwett installed it, opened a PR, got a description within seconds.&lt;/p&gt;

&lt;p&gt;Their feedback: &lt;em&gt;"Works as expected — the structure is solid and actually saves time. Groq is noticeably fast. For complex PRs with scattered changes it can feel a bit generic — but as a starting point to edit from? Definitely useful."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That was the moment this stopped being a side project and started being a product.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 6–7: Bug fixes and distribution
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bugs I fixed:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free tier cap was incrementing BEFORE the check — off-by-one error meant users got 6 PRs, not 5&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;account_login&lt;/code&gt; was being overwritten as 'unknown' on every PR event — upsert was hitting the wrong fields&lt;/li&gt;
&lt;li&gt;GitHub retries webhooks every 15s on timeout — PR #15 fired 38 times. Fixed with a unique constraint on &lt;code&gt;(installation_id, pr_number)&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Distribution channels I tried:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dev.to — fully open, post live ✅&lt;/li&gt;
&lt;li&gt;Indie Hackers — post live, daily updates ✅&lt;/li&gt;
&lt;li&gt;GitHub Marketplace — submitted for review ✅&lt;/li&gt;
&lt;li&gt;Reddit — karma 3, blocked until Day 9&lt;/li&gt;
&lt;li&gt;Hacker News — karma -8, commenting daily to recover&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Painful lesson:&lt;/strong&gt; Every platform blocks new accounts. Don't assume channels are open.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 7: Dashboard
&lt;/h2&gt;

&lt;p&gt;Built a full dashboard at &lt;code&gt;/dashboard&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plan badge (Free / Pro)&lt;/li&gt;
&lt;li&gt;PRs used vs cap with a colour-coded progress bar&lt;/li&gt;
&lt;li&gt;Recent PR activity — repo, PR number, timestamp&lt;/li&gt;
&lt;li&gt;Upgrade CTA&lt;/li&gt;
&lt;li&gt;Installation info&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub automatically redirects users to the dashboard after install via the Setup URL — no OAuth needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Day 8: More dashboard improvements
&lt;/h2&gt;

&lt;p&gt;Shipped today:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recent activity now shows &lt;strong&gt;PR titles&lt;/strong&gt; alongside repo and PR number&lt;/li&gt;
&lt;li&gt;Every generated PR description now has a &lt;strong&gt;dashboard link in the footer&lt;/strong&gt; — so anyone on the team can check usage without hunting for the URL&lt;/li&gt;
&lt;li&gt;Free tier cap now &lt;strong&gt;posts a comment directly on the PR&lt;/strong&gt; when the limit is hit, instead of silently doing nothing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The payment provider saga
&lt;/h2&gt;

&lt;p&gt;This is the part nobody talks about.&lt;/p&gt;

&lt;p&gt;Building the product took days. Setting up payments is taking longer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stripe&lt;/strong&gt; — invite-only in India since 2024&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lemon Squeezy&lt;/strong&gt; — international payments blocked for individuals in India&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gumroad&lt;/strong&gt; — payout setup issues for Indian bank accounts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Paddle&lt;/strong&gt; — working on it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The product is ready to charge. The money pipe is the blocker.&lt;/p&gt;

&lt;p&gt;Update Apr 18: Automated outreach system now running daily. 57+ emails sent to team leads.&lt;/p&gt;




&lt;h2&gt;
  
  
  Current numbers (Day 8)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Installs&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paid users&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MRR&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PRs described&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infra cost&lt;/td&gt;
&lt;td&gt;$0/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Get payment provider working (Paddle)&lt;/li&gt;
&lt;li&gt;Invite more beta users&lt;/li&gt;
&lt;li&gt;Reddit posts unlock ~Day 9&lt;/li&gt;
&lt;li&gt;HN karma grind back to positive&lt;/li&gt;
&lt;li&gt;Month 2: first paid conversion push&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;2-click install, no config, free for 5 PRs/month:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/apps/prdraft" rel="noopener noreferrer"&gt;github.com/apps/prdraft&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Landing page: &lt;a href="https://prdraft.carrd.co" rel="noopener noreferrer"&gt;prdraft.carrd.co&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Related: I stopped writing PR descriptions — here's what I did instead&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Building in public from Kerala, India. Following along on Indie Hackers → search PRDraft.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I stopped writing PR descriptions. Here's what I did instead.</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Thu, 02 Apr 2026 15:58:14 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/i-stopped-writing-pr-descriptions-heres-what-i-did-instead-1eon</link>
      <guid>https://dev.to/jeffrin-dev/i-stopped-writing-pr-descriptions-heres-what-i-did-instead-1eon</guid>
      <description>&lt;p&gt;I opened 6 PRs last week.&lt;br&gt;
I wrote a good description for exactly one of them.&lt;/p&gt;

&lt;p&gt;The rest looked like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"fix bug"&lt;/li&gt;
&lt;li&gt;"update styles"
&lt;/li&gt;
&lt;li&gt;"wip"&lt;/li&gt;
&lt;li&gt;"changes" (my personal low point)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And I'm not even ashamed — I've seen senior engineers with &lt;br&gt;
10 years of experience do the same thing.&lt;/p&gt;

&lt;p&gt;Here's why it happens:&lt;/p&gt;

&lt;p&gt;You just finished 3 hours of deep work. You know exactly what &lt;br&gt;
you changed and why. Writing it down feels like explaining a &lt;br&gt;
joke — the effort of articulating it kills the momentum. So &lt;br&gt;
you type something vague and hit submit.&lt;/p&gt;

&lt;p&gt;The reviewer then has to reverse-engineer your intent from &lt;br&gt;
the diff. They leave a comment asking what you changed. &lt;br&gt;
You explain it in the comment. Everyone wastes 20 minutes &lt;br&gt;
doing what the PR description should have done in the first place.&lt;/p&gt;

&lt;p&gt;So I started building a GitHub App to fix this for myself.&lt;/p&gt;

&lt;p&gt;It hooks into GitHub, reads the diff when you open a PR, &lt;br&gt;
and writes the description for you. Structured — what changed, &lt;br&gt;
why, how to test it, what to watch for. Takes about 4 seconds.&lt;/p&gt;

&lt;p&gt;I'm still building it. Calling it PRDraft.&lt;/p&gt;

&lt;p&gt;Honest question for this community: is this a real pain &lt;br&gt;
for you, or have you just accepted it as part of the job?&lt;/p&gt;

&lt;p&gt;If you want it : &lt;a href="https://prdraft.carrd.co" rel="noopener noreferrer"&gt;https://prdraft.carrd.co&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>productivity</category>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>I built an open-source tool that stops personal data from leaking into AI chatbots</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Sun, 29 Mar 2026 05:40:46 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/i-built-an-open-source-tool-that-stops-personal-data-from-leaking-into-ai-chatbots-1fno</link>
      <guid>https://dev.to/jeffrin-dev/i-built-an-open-source-tool-that-stops-personal-data-from-leaking-into-ai-chatbots-1fno</guid>
      <description>&lt;p&gt;Ever copy-pasted something into ChatGPT and immediately &lt;br&gt;
thought "wait, should I have done that?"&lt;/p&gt;

&lt;p&gt;If you're building an AI app that handles user data, you need to know what's leaking into your LLM API before a regulator does.&lt;/p&gt;

&lt;p&gt;That's the problem ShadowAudit solves.&lt;/p&gt;

&lt;p&gt;It sits between your app and any LLM API and scans every &lt;br&gt;
prompt before it leaves your system — catching emails, &lt;br&gt;
phone numbers, API keys, and Indian national IDs like &lt;br&gt;
Aadhaar and PAN numbers.&lt;/p&gt;

&lt;p&gt;Two lines to integrate:&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="n"&gt;sa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ShadowAudit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shadowaudit.yaml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Everything else stays the same.&lt;/p&gt;

&lt;p&gt;It also generates GDPR Article 30 compliance reports &lt;br&gt;
automatically from your audit log — one command, done.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpf9v4b2n5wlpqwxiloi.png" 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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftpf9v4b2n5wlpqwxiloi.png" alt="Demo of ShadowAudit scanning API and masking it." width="730" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built this over summer as part of my open-source portfolio.&lt;br&gt;
Would love feedback from the community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub: &lt;a href="//github.com/Jeffrin-dev/ShadowAudit"&gt;github.com/Jeffrin-dev/ShadowAudit&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>CloudDev v0.3.0 — I built a free LocalStack alternative in Go with 17 AWS services published: true</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Tue, 24 Mar 2026 09:47:56 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/clouddev-v030-i-built-a-free-localstack-alternative-in-go-with-17-aws-servicespublished-true-5ci4</link>
      <guid>https://dev.to/jeffrin-dev/clouddev-v030-i-built-a-free-localstack-alternative-in-go-with-17-aws-servicespublished-true-5ci4</guid>
      <description>&lt;p&gt;If you've ever used LocalStack and balked at the $35/month price tag for the pro version, CloudDev might be exactly what you're looking for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CloudDev&lt;/strong&gt; is a free, open-source local AWS emulator built in Go — a single binary, zero runtime dependencies, works with your existing AWS CLI and SDKs out of the box.&lt;/p&gt;

&lt;p&gt;Today I'm releasing &lt;strong&gt;v0.3.0&lt;/strong&gt;, which adds 8 new AWS services and brings the total to &lt;strong&gt;17 emulated services&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/Jeffrin-dev/CloudDev" rel="noopener noreferrer"&gt;github.com/Jeffrin-dev/CloudDev&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;The "vendor kills free tier, community builds alternative" pattern keeps playing out everywhere. LocalStack's free tier is increasingly limited, and most developers just need basic local emulation for dev and CI — not a $35/month SaaS subscription.&lt;/p&gt;

&lt;p&gt;The goal was simple: a tool that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works with zero config changes to your existing AWS CLI setup&lt;/li&gt;
&lt;li&gt;Ships as a single Go binary with no runtime dependencies&lt;/li&gt;
&lt;li&gt;Covers the AWS services that 90% of applications actually use&lt;/li&gt;
&lt;li&gt;Is completely free and open source&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's in v0.3.0
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🔐 Auth &amp;amp; Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IAM&lt;/strong&gt; (port 4593) — users, roles, policies, AssumeRole&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;STS&lt;/strong&gt; (port 4592) — GetCallerIdentity, AssumeRole, GetSessionToken&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KMS&lt;/strong&gt; (port 4599) — CreateKey, Encrypt, Decrypt, GenerateDataKey&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🏗️ Orchestration
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CloudFormation&lt;/strong&gt; (port 4581) — CreateStack, UpdateStack, parses YAML/JSON templates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step Functions&lt;/strong&gt; (port 4585) — state machines, executions, RUNNING → SUCCEEDED transitions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🌉 Events &amp;amp; Cache
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EventBridge&lt;/strong&gt; (port 4587) — event buses, rules, PutEvents with Lambda/SQS routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ElastiCache&lt;/strong&gt; (ports 4597/4598) — Redis-compatible TCP server + HTTP management API&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cognito&lt;/strong&gt; (port 4596) — user pools, users, InitiateAuth with mock tokens&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Jeffrin-dev/CloudDev.git
&lt;span class="nb"&gt;cd &lt;/span&gt;CloudDev
go build &lt;span class="nt"&gt;-o&lt;/span&gt; clouddev &lt;span class="nb"&gt;.&lt;/span&gt;

./clouddev init my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
../clouddev up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. All 17 services start immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Works With Your Existing AWS CLI
&lt;/h2&gt;

&lt;p&gt;No special tooling needed. Just point &lt;code&gt;--endpoint-url&lt;/code&gt; at CloudDev:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# KMS — create a key and encrypt/decrypt&lt;/span&gt;
aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4599 kms create-key &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--description&lt;/span&gt; &lt;span class="s2"&gt;"my-key"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4599 kms encrypt &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--key-id&lt;/span&gt; key-1 &lt;span class="nt"&gt;--plaintext&lt;/span&gt; &lt;span class="s2"&gt;"hello-world"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# Cognito — create a user pool and authenticate&lt;/span&gt;
aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4596 cognito-idp create-user-pool &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--pool-name&lt;/span&gt; my-pool &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4596 cognito-idp initiate-auth &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--auth-flow&lt;/span&gt; USER_PASSWORD_AUTH &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--auth-parameters&lt;/span&gt; &lt;span class="nv"&gt;USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;user,PASSWORD&lt;span class="o"&gt;=&lt;/span&gt;pass &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--client-id&lt;/span&gt; client-1 &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# Step Functions — create and run a state machine&lt;/span&gt;
aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4585 stepfunctions create-state-machine &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; my-machine &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--definition&lt;/span&gt; &lt;span class="s1"&gt;'{"StartAt":"Hello","States":{"Hello":{"Type":"Pass","End":true}}}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role-arn&lt;/span&gt; arn:aws:iam::000000000000:role/role &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Web Dashboard
&lt;/h2&gt;

&lt;p&gt;Every service gets a real-time status indicator in the dashboard at &lt;code&gt;localhost:4580&lt;/code&gt;. It auto-refreshes every 5 seconds so you can see at a glance what's running.&lt;/p&gt;

&lt;p&gt;All 17 services show up with their port and a green/red status dot.&lt;/p&gt;




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

&lt;p&gt;This project was built with an unusual workflow: &lt;strong&gt;Claude as the instructor and Codex as the developer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Claude designed the architecture, wrote the detailed implementation prompts for each module, debugged issues from test output, and caught protocol mismatches (like the AWS CLI sending &lt;code&gt;AWSStepFunctions.*&lt;/code&gt; instead of &lt;code&gt;AmazonStates.*&lt;/code&gt; as the X-Amz-Target prefix — something you only discover by sniffing the actual HTTP request).&lt;/p&gt;

&lt;p&gt;Codex implemented each module from those prompts, one PR at a time.&lt;/p&gt;

&lt;p&gt;It's been a genuinely interesting experiment in human-AI-AI collaboration. The hardest bugs were always the subtle protocol differences between what the AWS documentation says and what the AWS CLI actually sends.&lt;/p&gt;




&lt;h2&gt;
  
  
  Complete Service &amp;amp; Port Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;S3&lt;/td&gt;
&lt;td&gt;4566&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DynamoDB&lt;/td&gt;
&lt;td&gt;4569&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda&lt;/td&gt;
&lt;td&gt;4574&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQS&lt;/td&gt;
&lt;td&gt;4576&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Gateway&lt;/td&gt;
&lt;td&gt;4572&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SNS&lt;/td&gt;
&lt;td&gt;4575&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secrets Manager&lt;/td&gt;
&lt;td&gt;4584&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudWatch Logs&lt;/td&gt;
&lt;td&gt;4586&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IAM&lt;/td&gt;
&lt;td&gt;4593&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STS&lt;/td&gt;
&lt;td&gt;4592&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KMS&lt;/td&gt;
&lt;td&gt;4599&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudFormation&lt;/td&gt;
&lt;td&gt;4581&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Step Functions&lt;/td&gt;
&lt;td&gt;4585&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EventBridge&lt;/td&gt;
&lt;td&gt;4587&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ElastiCache (Redis)&lt;/td&gt;
&lt;td&gt;4598&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ElastiCache (HTTP)&lt;/td&gt;
&lt;td&gt;4597&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cognito&lt;/td&gt;
&lt;td&gt;4596&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;v0.4.0 will focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CloudWatch Metrics&lt;/li&gt;
&lt;li&gt;SQS FIFO queues&lt;/li&gt;
&lt;li&gt;Lambda layers&lt;/li&gt;
&lt;li&gt;X-Ray tracing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get Involved
&lt;/h2&gt;

&lt;p&gt;The project is Apache 2.0 licensed and contributions are very welcome. Check out &lt;a href="https://github.com/Jeffrin-dev/CloudDev/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt; to get started.&lt;/p&gt;

&lt;p&gt;If CloudDev saves you time or money, a ⭐ on GitHub goes a long way — it helps other developers find the project.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/Jeffrin-dev/CloudDev" rel="noopener noreferrer"&gt;github.com/Jeffrin-dev/CloudDev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>devops</category>
      <category>aws</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I Built a Free Voice-Enabled AI Agent That Uses Notion as Its Brain — Notion MCP Challenge</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Sat, 21 Mar 2026 12:42:40 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/i-built-a-free-voice-enabled-ai-agent-that-uses-notion-as-its-brain-notion-mcp-challenge-1m38</link>
      <guid>https://dev.to/jeffrin-dev/i-built-a-free-voice-enabled-ai-agent-that-uses-notion-as-its-brain-notion-mcp-challenge-1m38</guid>
      <description>&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;NotionMind is a free, voice-enabled AI agent that uses your Notion workspace as its long-term memory. You can save notes by speaking, ask questions about your past work, search by meaning not keywords, trace connections across a knowledge graph, and view a stunning terminal analytics dashboard — all at &lt;strong&gt;zero cost&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The tagline: &lt;strong&gt;Your Notion workspace, but it thinks back.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhs6vqrmf5kmqh8hftgj9.png" alt=" " width="800" height="420"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  The Problem I Was Solving
&lt;/h2&gt;

&lt;p&gt;I had hundreds of Notion notes but couldn't actually use them. Searching by keyword misses context. I'd forget I already researched something. I couldn't see patterns in what I was learning. Notes just sat there — static, passive, dumb.&lt;/p&gt;

&lt;p&gt;I wanted a brain that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remembers everything I tell it&lt;/li&gt;
&lt;li&gt;Answers questions from my own notes&lt;/li&gt;
&lt;li&gt;Finds connections I missed&lt;/li&gt;
&lt;li&gt;Works offline, costs nothing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Free Stack (Genuinely $0/Month)
&lt;/h2&gt;

&lt;p&gt;This was a hard constraint I set myself — no paid APIs, no credits, nothing that expires.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI Brain&lt;/td&gt;
&lt;td&gt;Groq — Llama 3.3 70B + Llama 3.1 8B (free tier)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workspace&lt;/td&gt;
&lt;td&gt;Notion API (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Semantic Search&lt;/td&gt;
&lt;td&gt;fastembed BAAI/bge-small-en-v1.5 (runs locally)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web Search&lt;/td&gt;
&lt;td&gt;DuckDuckGo ddgs (no key needed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Voice Input&lt;/td&gt;
&lt;td&gt;Google Speech Recognition (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Voice Output&lt;/td&gt;
&lt;td&gt;Microsoft Edge TTS — Jenny Neural (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Telegram Bot&lt;/td&gt;
&lt;td&gt;python-telegram-bot (free)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Total: &lt;strong&gt;$0/month&lt;/strong&gt;. Not "free tier with limits you'll hit." Actually free.&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works — The MCP Architecture
&lt;/h2&gt;

&lt;p&gt;NotionMind uses the Notion MCP to give Groq structured access to your workspace. The agent has three tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mcp_search_notes&lt;/code&gt; — keyword search across the database&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp_create_note&lt;/code&gt; — create new notes with AI-generated title + tags&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mcp_list_all_notes&lt;/code&gt; — retrieve recent notes sorted by date&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you ask a question, the MCP agent calls these tools in a loop until it has enough context to answer.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kdt9ffqqn7zgip12fn9.png" alt=" " width="800" height="203"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Feature Walkthrough
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Smart Save
&lt;/h3&gt;

&lt;p&gt;Type or speak anything. Groq auto-generates the title, tags, and date:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: i fixed the JWT expiry bug in the auth module today
→ routed to: save
✓ Saved!
Title: Fixed JWT Expiry Bug
Tags:  auth, bug-fix, JWT
Date:  2026-03-24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  2. Natural Language Routing
&lt;/h3&gt;

&lt;p&gt;This was one of my favorite features to build. Instead of making users type exact commands, Groq reads the input and routes it automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: who is Virat Kohli
→ routed to: ask

&amp;gt;: show me my recent notes
→ routed to: list

&amp;gt;: remind me to study at 6pm
→ routed to: remind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exact command names bypass Groq entirely — zero latency for power users.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7md4i6xusl845b759bf.png" alt=" " width="800" height="381"&gt; 
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3. Semantic Search
&lt;/h3&gt;

&lt;p&gt;This is where it gets interesting. Regular search matches keywords. Semantic search matches meaning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: graph → 7. Search
What are you looking for: cricketer from Kerala
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It finds the note about Sanju Samson even though the search phrase "cricketer from Kerala" doesn't appear verbatim anywhere. The fastembed model converts both the query and all note content into vectors, then measures cosine similarity.&lt;/p&gt;

&lt;p&gt;The model runs entirely on CPU — no API call, no internet needed after the first download.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41ejswgoep9jgo3yduqj.png" alt=" " width="800" height="109"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4. Think — Multi-hop Reasoning
&lt;/h3&gt;

&lt;p&gt;Ask a complex question. NotionMind finds relevant notes, expands one hop through the knowledge graph, then asks Groq to reason across all of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: graph → 8. Think
Your question: what have I been researching lately?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It extracts keywords from your question, searches each separately, merges results, pulls in graph-connected notes, and gives you a synthesized answer with exact note citations.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Recall — Knowledge Evolution
&lt;/h3&gt;

&lt;p&gt;Pick any topic and see how your understanding evolved over time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: graph → 9. Recall
Topic to recall: notionmind
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Groq narrates the arc: initial curiosity → experiments → insights → where it seems headed. It references your actual notes and dates.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4ufle2uwgvqowm3gq46.png" alt=" " width="800" height="280"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6. The Dashboard
&lt;/h3&gt;

&lt;p&gt;This is the most visually striking part of the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub-style 30-day activity heatmap using ASCII heat characters (· ▪ ▫ ▬ █)&lt;/li&gt;
&lt;li&gt;14-day knowledge growth bar chart&lt;/li&gt;
&lt;li&gt;Topic velocity — tags this week vs last week with ↑ ↓ → trend arrows&lt;/li&gt;
&lt;li&gt;Quick stats panel — streak, total notes, top tag, avg per day&lt;/li&gt;
&lt;li&gt;Upcoming reminders panel&lt;/li&gt;
&lt;li&gt;Pending todos with priority icons&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7z2l4vw0qeu90fjjjd6b.png" 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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7z2l4vw0qeu90fjjjd6b.png" alt=" " width="800" height="378"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  7. AI Insights
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: insights
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four beautifully styled panels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔥 &lt;strong&gt;Peak Productivity&lt;/strong&gt; — when you're most active, specific dates cited&lt;/li&gt;
&lt;li&gt;🕳 &lt;strong&gt;Knowledge Gaps&lt;/strong&gt; — what you're underexploring given your current work&lt;/li&gt;
&lt;li&gt;📉 &lt;strong&gt;Fading Topics&lt;/strong&gt; — what you explored but drifted from&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;This Week's Action&lt;/strong&gt; — one sharp, specific recommendation&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs0c8sookzbdnskslcfy.png" alt=" " width="800" height="312"&gt; 
&lt;/h2&gt;

&lt;h3&gt;
  
  
  8. Knowledge Graph
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: graph → 1. Build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Groq analyses all your notes in pairs and finds genuine content connections — not just temporal ones. The graph is stored locally and built incrementally, so it only checks new pairs on each rebuild.&lt;/p&gt;

&lt;p&gt;From there you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View an ASCII tree of connections&lt;/li&gt;
&lt;li&gt;Find the shortest path between two notes&lt;/li&gt;
&lt;li&gt;See all neighbours of a note&lt;/li&gt;
&lt;li&gt;Manually relate two notes&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  9. Suggest — Auto Related Notes
&lt;/h3&gt;

&lt;p&gt;Every time you save a note, NotionMind automatically suggests related ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Saved! Title: Watched India vs Australia

Related notes in your brain:
  → research about Virat Kohli (2026-03-22)
  → research about god of cricket (2026-03-23)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The suggestion engine extracts the single main keyword from your note (ignoring noise like "today", "watched", "done"), then matches it against existing note summaries. Fast and surprisingly accurate.&lt;/p&gt;




&lt;h3&gt;
  
  
  10. Full Telegram Bot
&lt;/h3&gt;

&lt;p&gt;Every feature is available on your phone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/save   /ask    /today   /list    /search
/semantic       /read    /delete  /stats
/todos  /addtodo        /donetodo
/remind /reminders
/think  /recall  /dashboard      /insights
/weekly /inbox   /results
/menu   /export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4r5shoamy9c6aga1gfux.jpg" alt=" " width="800" height="1600"&gt; 
&lt;/h2&gt;

&lt;h3&gt;
  
  
  11. Todo List
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: todo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Todos stored directly in your Notion database, tagged &lt;code&gt;todo&lt;/code&gt;. Add with priority (🔴 high / 🟡 medium / 🟢 low), due date, and notes. Overdue items highlighted in red. Completed items archived cleanly.&lt;/p&gt;




&lt;h3&gt;
  
  
  12. Voice Mode
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;: voice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Speak your note. Google STT transcribes it, you confirm, NotionMind saves it. Responses are read back using Edge TTS (Jenny neural voice online, espeak offline). Six languages supported: English, Hindi, Spanish, French, Tamil, Malayalam.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hardest Parts to Build
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Semantic search that doesn't hallucinate
&lt;/h3&gt;

&lt;p&gt;My first attempt used Groq to rank notes by relevance. It hallucinated constantly — returning completely unrelated notes with score 1.0. The fix was switching to fastembed for actual vector similarity, which never hallucinates because it's pure math. The tricky part was getting "cricketer from Kerala" to correctly find the Sanju Samson note — the solution was fetching full page block content instead of just the summary field.&lt;/p&gt;

&lt;h3&gt;
  
  
  The suggest feature
&lt;/h3&gt;

&lt;p&gt;The naive approach (semantic search the full note text) was too slow and too noisy. "I watched cricket match today" would match notes about "daily summaries" because the word "today" was everywhere. The fix was asking Groq to extract a single main keyword first — so "cricket match" becomes just &lt;code&gt;cricket&lt;/code&gt;, which then matches only cricket notes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Command routing strictness
&lt;/h3&gt;

&lt;p&gt;Early versions of the Groq router would confidently route "who is Sachin Tendulkar" to &lt;code&gt;list&lt;/code&gt; instead of &lt;code&gt;ask&lt;/code&gt;. The fix was a strict JSON schema, an explicit confidence threshold, and specific rules for question words (who/what/when/where/why/how → always &lt;code&gt;ask&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Add Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Browser extension to save highlighted web content directly to NotionMind&lt;/li&gt;
&lt;li&gt;Daily digest email — Groq summarises yesterday's notes and emails it to you&lt;/li&gt;
&lt;li&gt;Obsidian sync — two-way sync with Obsidian vault&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/Jeffrin-dev/NotionMind" rel="noopener noreferrer"&gt;github.com/Jeffrin-dev/NotionMind&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License&lt;/strong&gt;: MIT — free to use, fork, and build on&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Jeffrin-dev/NotionMind.git
&lt;span class="nb"&gt;cd &lt;/span&gt;NotionMind
python3 &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;notion-client&lt;span class="o"&gt;==&lt;/span&gt;2.2.1 groq python-dotenv rich &lt;span class="se"&gt;\&lt;/span&gt;
            httpx ddgs SpeechRecognition edge-tts pygame &lt;span class="se"&gt;\&lt;/span&gt;
            schedule python-telegram-bot fastembed numpy
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;span class="c"&gt;# fill in your Notion + Groq API keys&lt;/span&gt;
python3 notionmind.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need a free Notion account and a free Groq account. That's it. No credit card anywhere.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built for the Notion MCP Challenge · March 2026 · by Jeffrin&lt;/em&gt;&lt;/p&gt;

</description>
      <category>notionchallenge</category>
      <category>ai</category>
      <category>python</category>
      <category>mcp</category>
    </item>
    <item>
      <title>I Ditched GitHub Copilot and Now I Code With AI for Free — Locally</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Sat, 21 Mar 2026 04:25:04 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/i-ditched-github-copilot-and-now-i-code-with-ai-for-free-locally-n94</link>
      <guid>https://dev.to/jeffrin-dev/i-ditched-github-copilot-and-now-i-code-with-ai-for-free-locally-n94</guid>
      <description>&lt;p&gt;I was paying $10/month for GitHub Copilot. It's fine. It works. But it means every keystroke I type goes to Microsoft's servers, my code context gets shipped off somewhere, and I'm locked into whatever pricing they decide next year.&lt;/p&gt;

&lt;p&gt;Then I found out I could run a better-than-Copilot setup on my own machine, completely free, with no data leaving my computer.&lt;/p&gt;

&lt;p&gt;Here's exactly how I did it, and how you can too.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Actually Need
&lt;/h2&gt;

&lt;p&gt;Before anything else — honest expectations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A machine with &lt;strong&gt;at least 8GB RAM&lt;/strong&gt; (16GB is better)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;~5GB free disk space&lt;/strong&gt; per model&lt;/li&gt;
&lt;li&gt;A decent CPU, or an NVIDIA/Apple Silicon GPU for speed&lt;/li&gt;
&lt;li&gt;About &lt;strong&gt;20 minutes&lt;/strong&gt; of setup time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No API keys. No credit cards. No subscriptions.&lt;/p&gt;




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

&lt;p&gt;&lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; is the piece that makes all of this possible. It's basically a runtime that lets you pull and run open-source LLMs the same way Docker lets you run containers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;macOS / Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://ollama.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt;&lt;br&gt;
Download the installer from &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;ollama.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Verify it's running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Pull a Coding Model
&lt;/h2&gt;

&lt;p&gt;This is the part where you choose your AI. For coding specifically, these are the ones worth using:&lt;/p&gt;

&lt;h3&gt;
  
  
  For most people (8GB RAM):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull qwen2.5-coder:7b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Qwen 2.5 Coder from Alibaba is genuinely impressive. Beats older Copilot versions on HumanEval benchmarks. Specialised entirely for code.&lt;/p&gt;

&lt;h3&gt;
  
  
  If you have 16GB+ RAM:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull qwen2.5-coder:14b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Noticeably better at multi-file context and explaining complex logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  If you're on Apple Silicon (M1/M2/M3):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull deepseek-coder-v2:16b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Runs fast on Metal. Great at refactoring and docstring generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Absolute minimum (4GB RAM):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull qwen2.5-coder:3b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Smaller but still surprisingly capable for autocomplete and simple functions.&lt;/p&gt;

&lt;p&gt;Test it immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama run qwen2.5-coder:7b &lt;span class="s2"&gt;"write a Python function to flatten a nested list"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you get a clean response, you're good.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Pick Your Editor Integration
&lt;/h2&gt;

&lt;p&gt;Now the fun part — making it feel like Copilot inside your actual editor.&lt;/p&gt;

&lt;h3&gt;
  
  
  VS Code → Continue
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://continue.dev" rel="noopener noreferrer"&gt;Continue&lt;/a&gt; is the open-source Copilot alternative. It's a VS Code (and JetBrains) extension that hooks directly into your local Ollama instance.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the Continue extension from the VS Code marketplace&lt;/li&gt;
&lt;li&gt;Open Continue's config file (&lt;code&gt;~/.continue/config.json&lt;/code&gt;) and add:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Qwen Coder 7B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ollama"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"qwen2.5-coder:7b"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"tabAutocompleteModel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Qwen Coder 7B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ollama"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"qwen2.5-coder:7b"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Tab&lt;/code&gt; to accept inline completions, &lt;code&gt;Cmd+I&lt;/code&gt; (Mac) or &lt;code&gt;Ctrl+I&lt;/code&gt; (Windows) to open the chat panel.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. You now have inline autocomplete, a chat panel, and codebase-aware Q&amp;amp;A — all local.&lt;/p&gt;

&lt;h3&gt;
  
  
  Neovim → gen.nvim or avante.nvim
&lt;/h3&gt;

&lt;p&gt;If you're a Neovim user, add this to your config with &lt;a href="https://github.com/David-Kunz/gen.nvim" rel="noopener noreferrer"&gt;gen.nvim&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'gen'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"qwen2.5-coder:7b"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"11434"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;code&gt;:Gen&lt;/code&gt; opens a prompt. Select code visually and run &lt;code&gt;:Gen Enhance_Code&lt;/code&gt; or &lt;code&gt;:Gen Add_Tests&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  JetBrains → Continue (same plugin, different install)
&lt;/h3&gt;

&lt;p&gt;Install Continue from the JetBrains marketplace. Same config file works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4: Supercharge It With Open WebUI (Optional but Worth It)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/open-webui/open-webui" rel="noopener noreferrer"&gt;Open WebUI&lt;/a&gt; gives you a ChatGPT-like interface for your local models. Useful when you want to have a longer conversation about architecture, paste in a whole file, or explain a bug.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--add-host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host.docker.internal:host-gateway &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; open-webui:/app/backend/data &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; open-webui &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/open-webui/open-webui:main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:3000&lt;/code&gt;, connect to your Ollama instance, and you have a full ChatGPT-style interface running entirely offline.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Performance
&lt;/h2&gt;

&lt;p&gt;After a month of daily use on a MacBook Pro M2 with 16GB RAM, here's what I found:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Qwen 2.5 Coder 7B&lt;/th&gt;
&lt;th&gt;GitHub Copilot&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple function completion&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refactoring a 100-line file&lt;/td&gt;
&lt;td&gt;✅ Good&lt;/td&gt;
&lt;td&gt;✅ Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explaining unfamiliar code&lt;/td&gt;
&lt;td&gt;✅ Very good&lt;/td&gt;
&lt;td&gt;✅ Very good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-file context&lt;/td&gt;
&lt;td&gt;⚠️ Limited&lt;/td&gt;
&lt;td&gt;✅ Better&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speed (M2 Mac)&lt;/td&gt;
&lt;td&gt;~2–3 tok/sec&lt;/td&gt;
&lt;td&gt;Near instant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy&lt;/td&gt;
&lt;td&gt;✅ 100% local&lt;/td&gt;
&lt;td&gt;❌ Sent to servers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;✅ Free&lt;/td&gt;
&lt;td&gt;❌ $10/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Speed is the real tradeoff. On CPU-only machines, responses are slower than a cloud API. On Apple Silicon or an NVIDIA GPU, the gap closes a lot.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Part Nobody Tells You
&lt;/h2&gt;

&lt;p&gt;Prompting matters more locally than with cloud models.&lt;/p&gt;

&lt;p&gt;Cloud models like GPT-4 or Claude have been fine-tuned to be forgiving — they infer what you meant even if you're vague. Smaller local models are more literal. A vague prompt gets a vague answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instead of:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fix this function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Try:&lt;/strong&gt;&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="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;Python&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;supposed&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;JWT&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; 
&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;It&lt;/span&gt; &lt;span class="n"&gt;currently&lt;/span&gt; &lt;span class="n"&gt;throws&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;KeyError&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; 
&lt;span class="n"&gt;expired&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Fix&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;expiry&lt;/span&gt; &lt;span class="n"&gt;handling&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; 
&lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="nb"&gt;any&lt;/span&gt; &lt;span class="n"&gt;decode&lt;/span&gt; &lt;span class="n"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More context = dramatically better output. Once I adjusted my prompting habit, the quality difference between local and cloud shrank a lot.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bonus: Free Cloud Options When Local Isn't Enough
&lt;/h2&gt;

&lt;p&gt;Sometimes you need a bigger model for a hard problem. These are genuinely free with no credit card:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://console.groq.com" rel="noopener noreferrer"&gt;Groq&lt;/a&gt;&lt;/strong&gt; — Llama 3.1 70B running at insane speed. Free tier is generous.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://aistudio.google.com" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt;&lt;/strong&gt; — Gemini 1.5 Flash, 1M token context window, free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://cloud.cerebras.ai" rel="noopener noreferrer"&gt;Cerebras&lt;/a&gt;&lt;/strong&gt; — 1M tokens/day free, fastest inference available right now.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can configure all of these in Continue the same way as Ollama — just swap the provider and add an API key.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Install Ollama&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://ollama.com/install.sh | sh

&lt;span class="c"&gt;# 2. Pull a coding model&lt;/span&gt;
ollama pull qwen2.5-coder:7b

&lt;span class="c"&gt;# 3. Install Continue extension in VS Code&lt;/span&gt;

&lt;span class="c"&gt;# 4. Start coding for free&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your code stays on your machine. You pay nothing. It's genuinely good enough for daily use.&lt;/p&gt;

&lt;p&gt;The setup takes 20 minutes and you'll never think about it again.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this helped, I'm posting more practical AI dev workflow stuff — follow along. And if your local setup is different from mine, drop it in the comments — curious what models people are running.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>CloudDev v0.2.0 — SNS, Secrets Manager, CloudWatch Logs and more!</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Fri, 20 Mar 2026 04:34:43 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/clouddev-v020-sns-secrets-manager-cloudwatch-logs-and-more-1j0k</link>
      <guid>https://dev.to/jeffrin-dev/clouddev-v020-sns-secrets-manager-cloudwatch-logs-and-more-1j0k</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.tourl"&gt;&lt;/a&gt;# CloudDev v0.2.0 is here! 🎉&lt;/p&gt;

&lt;p&gt;Following the success of v0.1.0, I've released CloudDev v0.2.0 &lt;br&gt;
with 8 new modules!&lt;/p&gt;

&lt;h2&gt;
  
  
  What's new?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3 New AWS Services
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;📣 &lt;strong&gt;SNS&lt;/strong&gt; — pub/sub with SQS delivery&lt;/li&gt;
&lt;li&gt;🔐 &lt;strong&gt;Secrets Manager&lt;/strong&gt; — local secret storage
&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;CloudWatch Logs&lt;/strong&gt; — log groups and streams&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5 New Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;⚡ &lt;strong&gt;Lambda Hot Reload&lt;/strong&gt; — drop a zip, auto-loads in 2 seconds&lt;/li&gt;
&lt;li&gt;📋 &lt;strong&gt;Status Command&lt;/strong&gt; — &lt;code&gt;clouddev status&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;💾 &lt;strong&gt;Data Persistence&lt;/strong&gt; — survives restarts&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;Cost Estimator&lt;/strong&gt; — &lt;code&gt;clouddev estimate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;☸️ &lt;strong&gt;Kubernetes Support&lt;/strong&gt; — detect services from k8s manifests&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clouddev init my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
clouddev up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 GitHub: &lt;a href="https://github.com/Jeffrin-dev/CloudDev" rel="noopener noreferrer"&gt;https://github.com/Jeffrin-dev/CloudDev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful please ⭐ the repo!&lt;/p&gt;

</description>
      <category>go</category>
      <category>aws</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
    <item>
      <title>I built a free, open-source alternative to LocalStack — CloudDev</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Wed, 18 Mar 2026 05:39:19 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/i-built-a-free-open-source-alternative-to-localstack-clouddev-59k</link>
      <guid>https://dev.to/jeffrin-dev/i-built-a-free-open-source-alternative-to-localstack-clouddev-59k</guid>
      <description>&lt;h1&gt;
  
  
  I built a free, open-source alternative to LocalStack — CloudDev
&lt;/h1&gt;

&lt;p&gt;If you've been following the news, LocalStack recently ended its &lt;br&gt;
free Community Edition. Developers now need an account and are &lt;br&gt;
being pushed toward paid plans.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;CloudDev&lt;/strong&gt; — a lightweight, 100% free, open-source &lt;br&gt;
local AWS development environment. No account. No paywalls. Forever.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is CloudDev?
&lt;/h2&gt;

&lt;p&gt;CloudDev lets you run core AWS services locally on your machine &lt;br&gt;
with a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clouddev up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It starts local emulators for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🪣 &lt;strong&gt;Amazon S3&lt;/strong&gt; — object storage&lt;/li&gt;
&lt;li&gt;🗄️ &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt; — NoSQL database&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;AWS Lambda&lt;/strong&gt; — serverless functions&lt;/li&gt;
&lt;li&gt;📨 &lt;strong&gt;Amazon SQS&lt;/strong&gt; — message queues&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Amazon API Gateway&lt;/strong&gt; — HTTP routing to Lambda&lt;/li&gt;
&lt;li&gt;🖥️ &lt;strong&gt;Web Dashboard&lt;/strong&gt; — live service status&lt;/li&gt;
&lt;li&gt;🔍 &lt;strong&gt;IaC Detection&lt;/strong&gt; — auto-configure from Terraform/CloudFormation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I built it
&lt;/h2&gt;

&lt;p&gt;Developing on AWS is painful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have to deploy to the cloud just to test&lt;/li&gt;
&lt;li&gt;Provisioning Lambda or API Gateway takes minutes&lt;/li&gt;
&lt;li&gt;Accidental usage generates unexpected charges&lt;/li&gt;
&lt;li&gt;Hard to test locally without internet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CloudDev solves all of this.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Initialize a project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clouddev init my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;my-app/&lt;/span&gt;
  &lt;span class="s"&gt;clouddev.yml&lt;/span&gt;
  &lt;span class="s"&gt;functions/&lt;/span&gt;
  &lt;span class="s"&gt;infrastructure/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Configure services (clouddev.yml)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;s3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;dynamodb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;lambda&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;sqs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;api_gateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Start your local cloud
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clouddev up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;S3 server starting on port 4566
DynamoDB server starting on port 4569
Lambda server starting on port 4574
API Gateway starting on port 4572
Dashboard running at http://localhost:4580
CloudDev is running. Press Ctrl+C to stop...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Use with the real AWS CLI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# S3 — create bucket and upload file&lt;/span&gt;
aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 s3 mb s3://my-bucket
aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4566 s3 &lt;span class="nb"&gt;cp &lt;/span&gt;file.txt s3://my-bucket/

&lt;span class="c"&gt;# DynamoDB — create table and put item&lt;/span&gt;
aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4569 dynamodb create-table &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--table-name&lt;/span&gt; Users &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--attribute-definitions&lt;/span&gt; &lt;span class="nv"&gt;AttributeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;,AttributeType&lt;span class="o"&gt;=&lt;/span&gt;S &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--key-schema&lt;/span&gt; &lt;span class="nv"&gt;AttributeName&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;,KeyType&lt;span class="o"&gt;=&lt;/span&gt;HASH &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--billing-mode&lt;/span&gt; PAY_PER_REQUEST

&lt;span class="c"&gt;# Lambda — create and invoke function&lt;/span&gt;
aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4574 lambda create-function &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; hello &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--runtime&lt;/span&gt; python3.9 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--handler&lt;/span&gt; hello.handler &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt; arn:aws:iam::000000000000:role/test &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--zip-file&lt;/span&gt; fileb://hello.zip

aws &lt;span class="nt"&gt;--endpoint-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:4574 lambda invoke &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; hello &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--payload&lt;/span&gt; &lt;span class="s1"&gt;'{"key": "value"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  output.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Auto-detect from Terraform
&lt;/h3&gt;

&lt;p&gt;Have an existing Terraform project? Just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;clouddev detect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;CloudDev scans your &lt;code&gt;.tf&lt;/code&gt; files and automatically enables &lt;br&gt;
the right services in &lt;code&gt;clouddev.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Web Dashboard
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;http://localhost:4580&lt;/code&gt; to see live service status:&lt;/p&gt;

&lt;p&gt;![CloudDev Dashboard showing all services running in green]&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4n9vclmdegjq1l25103u.png" 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/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4n9vclmdegjq1l25103u.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How it compares to LocalStack
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;CloudDev&lt;/th&gt;
&lt;th&gt;LocalStack Free&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Requires account&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes (now required)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open source&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;⚠️ Partial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S3, DynamoDB, Lambda&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web dashboard&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IaC auto-detection&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;🆓 Free forever&lt;/td&gt;
&lt;td&gt;💰 Paid plans&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;

&lt;p&gt;CloudDev is built in &lt;strong&gt;Go&lt;/strong&gt; — which means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single binary, no runtime dependencies&lt;/li&gt;
&lt;li&gt;Fast startup&lt;/li&gt;
&lt;li&gt;Low memory usage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes integration&lt;/li&gt;
&lt;li&gt;Cost estimation before deployment&lt;/li&gt;
&lt;li&gt;Plugin system for additional AWS services&lt;/li&gt;
&lt;li&gt;More AWS service emulators&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;👉 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/Jeffrin-dev/CloudDev" rel="noopener noreferrer"&gt;github.com/Jeffrin-dev/CloudDev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, please ⭐ the repo and share it with &lt;br&gt;
other AWS developers who are affected by the LocalStack change!&lt;/p&gt;

&lt;p&gt;Contributions are very welcome — check out &lt;br&gt;
&lt;a href="https://github.com/Jeffrin-dev/CloudDev/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;CONTRIBUTING.md&lt;/a&gt; &lt;br&gt;
to get started.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with Go, Let's Get Started !&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>aws</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
    <item>
      <title>Claude AI Gets Weirdly Slow After 9 PM (I Noticed It While Reviewing Code)</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Fri, 13 Mar 2026 15:01:15 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/claude-ai-gets-weirdly-slow-after-9-pm-i-noticed-it-while-reviewing-code-4gia</link>
      <guid>https://dev.to/jeffrin-dev/claude-ai-gets-weirdly-slow-after-9-pm-i-noticed-it-while-reviewing-code-4gia</guid>
      <description>&lt;p&gt;I ran into something interesting recently while using Claude AI to review some of my code.&lt;/p&gt;

&lt;p&gt;During the day the responses were &lt;strong&gt;fast&lt;/strong&gt;. I could paste a file, ask for suggestions, iterate quickly, and the workflow felt smooth.&lt;/p&gt;

&lt;p&gt;But when I tried doing the same thing later in the evening — around &lt;strong&gt;9 PM and after&lt;/strong&gt; — the experience changed a lot.&lt;/p&gt;

&lt;p&gt;Responses suddenly took &lt;strong&gt;much longer&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Sometimes it would sit there &lt;em&gt;“thinking” for quite a while&lt;/em&gt; before returning the review.&lt;/p&gt;

&lt;p&gt;At first I assumed it was something on my side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;maybe my internet
&lt;/li&gt;
&lt;li&gt;maybe the browser tab
&lt;/li&gt;
&lt;li&gt;maybe I pasted too much code
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But after trying a few times on different days, I noticed the same pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  It’s Probably Peak Usage
&lt;/h3&gt;

&lt;p&gt;My guess is pretty simple.&lt;/p&gt;

&lt;p&gt;Evenings are when a lot of developers start working on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;side projects
&lt;/li&gt;
&lt;li&gt;open source
&lt;/li&gt;
&lt;li&gt;debugging issues from the day
&lt;/li&gt;
&lt;li&gt;experimenting with AI tools&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So tools like &lt;strong&gt;Claude&lt;/strong&gt;, &lt;strong&gt;ChatGPT&lt;/strong&gt;, and &lt;strong&gt;Gemini&lt;/strong&gt; probably get a &lt;strong&gt;huge spike in requests&lt;/strong&gt; around that time.&lt;/p&gt;

&lt;p&gt;And when millions of prompts hit the system at once, response times naturally slow down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Developers Notice It More
&lt;/h3&gt;

&lt;p&gt;The funny part is that developers probably notice this more than anyone else.&lt;/p&gt;

&lt;p&gt;When you're using AI for &lt;strong&gt;code review or debugging&lt;/strong&gt;, you're usually sending multiple prompts in a row:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ask for review
&lt;/li&gt;
&lt;li&gt;ask for improvements
&lt;/li&gt;
&lt;li&gt;clarify something
&lt;/li&gt;
&lt;li&gt;test another idea&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That workflow depends on &lt;strong&gt;fast feedback&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Even a small delay starts to feel frustrating when you're in that loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not Really a Complaint
&lt;/h3&gt;

&lt;p&gt;To be fair, these systems are doing a massive amount of work behind the scenes. Running models at this scale is insanely expensive.&lt;/p&gt;

&lt;p&gt;But it was interesting to notice how &lt;strong&gt;time of day actually affects the experience&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now I’m curious if other developers have noticed the same thing when using AI tools for code reviews at night.&lt;/p&gt;

&lt;p&gt;Is it just me, or does AI also have a &lt;strong&gt;“rush hour”&lt;/strong&gt;? &lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>llm</category>
      <category>performance</category>
    </item>
    <item>
      <title>I had a problem that I suspect many developers have — duplicate files scattered across external drives, backup archives, and media collections with no reliable way to clean them up without risking data loss. Found a way, moreover made a way..</title>
      <dc:creator>Twisted-Code'r</dc:creator>
      <pubDate>Fri, 13 Mar 2026 14:39:48 +0000</pubDate>
      <link>https://dev.to/jeffrin-dev/i-had-a-problem-that-i-suspect-many-developers-have-duplicate-files-scattered-across-external-39eb</link>
      <guid>https://dev.to/jeffrin-dev/i-had-a-problem-that-i-suspect-many-developers-have-duplicate-files-scattered-across-external-39eb</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/jeffrin-dev" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3817901%2F6517f8eb-a101-4823-9acb-d0ce98eaa1ff.jpg" alt="jeffrin-dev"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/jeffrin-dev/how-i-built-a-duplicate-file-finder-that-handles-1-million-files-without-crashing-24bh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How I Built a Duplicate File Finder That Handles 1 Million Files Without Crashing&lt;/h2&gt;
      &lt;h3&gt;Twisted-Code'r ・ Mar 11&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#python&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#cli&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>python</category>
      <category>opensource</category>
      <category>cli</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
