<?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: Om Lahore</title>
    <description>The latest articles on DEV Community by Om Lahore (@omlahore47).</description>
    <link>https://dev.to/omlahore47</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%2F4155877%2F90a97d93-c4dd-4d89-93e0-5e20b2343661.png</url>
      <title>DEV Community: Om Lahore</title>
      <link>https://dev.to/omlahore47</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/omlahore47"/>
    <language>en</language>
    <item>
      <title>39 screenshots and not one useful name, so a local Gemma names them for me</title>
      <dc:creator>Om Lahore</dc:creator>
      <pubDate>Wed, 21 Oct 2026 20:02:15 +0000</pubDate>
      <link>https://dev.to/omlahore47/39-screenshots-and-not-one-useful-name-so-a-local-gemma-names-them-for-me-11bn</link>
      <guid>https://dev.to/omlahore47/39-screenshots-and-not-one-useful-name-so-a-local-gemma-names-them-for-me-11bn</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;slothshot renames screenshots after what's in them. &lt;code&gt;Screenshot 2026-10-03 at 08.15.44.png&lt;/code&gt; becomes &lt;code&gt;2026-10-03 railbook-e-ticket-pnr-4421907736.png&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My screenshots folder had 39 files in three naming schemes, because they came over from a Linux laptop: &lt;code&gt;Screenshot from 2026-02-17 19-14-51.png&lt;/code&gt;, &lt;code&gt;2026-04-09_01-26-24.png&lt;/code&gt; and the macOS &lt;code&gt;Screenshot 2026-10-17 at 13.34.06.png&lt;/code&gt;. None of them said what was in the picture. When I needed one, I opened thumbnails until I found it.&lt;/p&gt;

&lt;p&gt;Renaming them by hand would fix that, and I was never going to do it. So now a vision model on my laptop looks at each screenshot and picks a name: the app or site, and the specific thing on screen. The date stays at the front so the folder still sorts by time. It's for me, and for anyone whose Desktop looks like my Screenshots folder.&lt;/p&gt;

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

&lt;p&gt;Eight made-up screenshots (a failing Go test, a flat group chat about the electricity bill, a UPI payment, a code review, a train ticket, a Grafana-style alert, a poha recipe and a macOS dialog):&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8wyqits3v1cih61odp34.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8wyqits3v1cih61odp34.png" alt="slothshot naming eight sample screenshots" width="799" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The default is a dry run. &lt;code&gt;-apply&lt;/code&gt; renames, &lt;code&gt;-undo&lt;/code&gt; puts every old name back from a log file in the folder, and &lt;code&gt;-watch 1m&lt;/code&gt; keeps it running so each new screenshot gets a name within a minute of me taking it.&lt;/p&gt;

&lt;p&gt;It isn't perfect. It spelled SanDisk "sandsik". On the Go test it wrote "test-monthly-rollup-fail" and left out the actual panic, which is what I'd search for. On my own folder it named a black screenshot &lt;code&gt;the-image-provided-is-completely-black&lt;/code&gt;, which is accurate. A name that's mostly right is still easier to search than &lt;code&gt;Screenshot 2026-10-16 at 16.30.00.png&lt;/code&gt;.&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/omlahore" rel="noopener noreferrer"&gt;
        omlahore
      &lt;/a&gt; / &lt;a href="https://github.com/omlahore/slothshot" rel="noopener noreferrer"&gt;
        slothshot
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Renames your screenshots after what's in them, using a local vision model (Gemma 4 on llama.cpp)
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;slothshot&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Renames your screenshots after what's in them. &lt;code&gt;Screenshot 2026-10-03 at 08.15.44.png&lt;/code&gt; becomes &lt;code&gt;2026-10-03 railbook-e-ticket-pnr-4421907736.png&lt;/code&gt;, so Finder and Spotlight can find it when you type "pnr" three weeks later.&lt;/p&gt;
&lt;p&gt;A local open-weight vision model (Gemma 4 E4B through llama.cpp) looks at each picture. Nothing leaves your machine, which matters because screenshot folders are full of chats, bank pages and login screens.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/omlahore/slothshot/docs/run.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fomlahore%2Fslothshot%2FHEAD%2Fdocs%2Frun.png" alt="slothshot on the eight sample screenshots"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Run it&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;You need &lt;a href="https://github.com/ggml-org/llama.cpp" rel="noopener noreferrer"&gt;llama.cpp&lt;/a&gt; and Go.&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;brew install llama.cpp
llama-server -hf ggml-org/gemma-4-E4B-it-GGUF:Q4_0 --port 8092 -c 8192
go install github.com/omlahore/slothshot@latest

slothshot ~/Pictures/Screenshots            # dry run, prints the new names
slothshot -apply ~/Pictures/Screenshots     # renames them
slothshot -undo ~/Pictures/Screenshots      # puts the old names back
slothshot -watch 1m ~/Pictures/Screenshots  # leave it running, new screenshots get named as they land
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It only touches files with a default screenshot name: macOS (&lt;code&gt;Screenshot ... at ...&lt;/code&gt;), GNOME (&lt;code&gt;Screenshot from ...&lt;/code&gt;), Flameshot (&lt;code&gt;2026-04-09_01-26-24.png&lt;/code&gt;), Android and CleanShot…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/omlahore/slothshot" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;The model is Gemma 4 E4B, Google's open-weight model that takes images, quantized to 4 bits (the Q4_0 GGUF from ggml-org) and served by llama.cpp's llama-server on localhost. The CLI is about 230 lines of Go with one dependency, golang.org/x/image, for resizing.&lt;/p&gt;

&lt;p&gt;For each file:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A regex decides whether the name is a default screenshot name (macOS, GNOME, Flameshot, Android, CleanShot). Files it has already renamed have words after the date, so they never match. Running it twice does nothing the second time.&lt;/li&gt;
&lt;li&gt;The image is scaled so its long side is 1536 px and sent to llama-server's OpenAI-compatible endpoint with a short prompt: 3 to 6 words, name the app only if its name is on screen, include the specific thing (the error, the merchant and amount, the page title).&lt;/li&gt;
&lt;li&gt;Go turns the answer into a slug: lowercase, hyphens, at most six words. If the name is taken, it adds &lt;code&gt;-2&lt;/code&gt;. Every rename is appended to &lt;code&gt;.slothshot.tsv&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two things went wrong first.&lt;/p&gt;

&lt;p&gt;Every answer came back empty. Gemma 4 thinks before it answers by default, and with &lt;code&gt;max_tokens&lt;/code&gt; at 40 it spent all of them on "Thinking Process: 1. Analyze the Request". Passing &lt;code&gt;chat_template_kwargs: {"enable_thinking": false}&lt;/code&gt; turned that off, and answers came back in about a second.&lt;/p&gt;

&lt;p&gt;At 1024 px the model read the PNR 4421907736 as 44197736, two digits gone. A wrong PNR in a filename is worse than none, because you search for the right one and it isn't there. At 1536 px it read all ten digits. Each image now takes roughly 2.5 seconds instead of 1.3. A file gets renamed once, so I took the slower, correct version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;I didn't think of my screenshots folder as private until I read the names slothshot proposed for it. There were chats with friends, video calls with other people's faces in them, and a few login pages. Naming those with a hosted API means uploading every one of them, and with &lt;code&gt;-watch&lt;/code&gt; on, every new one as well.&lt;/p&gt;

&lt;p&gt;With Gemma on llama.cpp none of it leaves the laptop. It works with Wi-Fi off, and there's no per-image bill, so leaving it on to watch the folder costs nothing. The model is a 5 GB file on my disk. When a better open model comes out I change one flag, and if a provider retires this one next year, my copy keeps working.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;I ran it on my real folder in dry-run mode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It proposed names for 39 screenshots in 1 minute 47 seconds, between 0.6 and 3.8 seconds each, on a 16 GB MacBook Air. I didn't have to watch it.&lt;/li&gt;
&lt;li&gt;Doing it by hand means opening each one, working out what it is and typing a name. Call it 30 seconds each, so about 20 minutes. I'd been putting that off since the oldest file, which is from December 2025.&lt;/li&gt;
&lt;li&gt;I took 13 screenshots between October 6 and October 17, about one a day. With &lt;code&gt;-watch&lt;/code&gt; running from a LaunchAgent (the plist is in the README), each one has a name by the time I go looking for it, and I don't lift a finger.&lt;/li&gt;
&lt;li&gt;Finding one meant scrolling thumbnails. After &lt;code&gt;-apply&lt;/code&gt;, it's typing "mailbox" or "pnr" into Finder.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nine of the 39 were screens from the same dashboard, and four of those came out with exactly the same name. &lt;code&gt;-apply&lt;/code&gt; numbers them &lt;code&gt;-2&lt;/code&gt;, &lt;code&gt;-3&lt;/code&gt; and &lt;code&gt;-4&lt;/code&gt; instead of overwriting anything.&lt;/p&gt;

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

&lt;p&gt;Best Use of Gemma: slothshot runs Gemma 4 E4B (open weights, GGUF on llama.cpp) for every name it gives.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>go</category>
      <category>ai</category>
    </item>
    <item>
      <title>I built a GST invoice checker that runs on a laptop, and it caught its own AI's mistake</title>
      <dc:creator>Om Lahore</dc:creator>
      <pubDate>Sun, 18 Oct 2026 11:42:43 +0000</pubDate>
      <link>https://dev.to/omlahore47/i-built-a-gst-invoice-checker-that-runs-on-a-laptop-and-it-caught-its-own-ais-mistake-2pkl</link>
      <guid>https://dev.to/omlahore47/i-built-a-gst-invoice-checker-that-runs-on-a-laptop-and-it-caught-its-own-ais-mistake-2pkl</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;gstsort reads a folder of GST invoices, PDFs or phone photos, and tells you which ones you can claim input tax credit on and which ones you can't yet.&lt;/p&gt;

&lt;p&gt;Every Indian business registered for GST claims back the tax it paid on purchases, and the claim only holds if the invoice is right: the supplier's GSTIN is valid, it's billed to your GSTIN, the tax type matches the states involved, and the numbers add up. Freelancers and small agencies collect a pile of these every month and check them by hand, or pay their CA to, and a CA office does the same for dozens of clients. Those are the people who'd pay for this: the freelancer gets a clean sheet in a few minutes instead of an evening, and the CA office gets a first pass over every client's folder before anyone opens a PDF.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2h2fm27mb5seb10stix.jpg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc2h2fm27mb5seb10stix.jpg" alt="sample invoice, photographed at an angle" width="800" height="1001"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I ran it on ten sample invoices with made-up suppliers. Six of them have a problem planted in them, and it found all six:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqtqiw9lvx77wahaihfwq.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqtqiw9lvx77wahaihfwq.png" alt="gstsort output on the ten sample invoices" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All ten took about two minutes on a laptop with 16 GB of RAM, 12 to 16 seconds an invoice, with nothing going over the network.&lt;/p&gt;

&lt;p&gt;One catch wasn't planted. On the Inkwell invoice the model read the GSTIN 27ABZPI9054E1Z4 as 27ABZP19054E1Z4, an I turned into a 1. A wrong GSTIN in your purchase register won't reconcile with GSTR-2B, and that's credit you don't get. A GSTIN has a check digit, and the PAN inside it has letters and digits in fixed slots, so gstsort put an I back in the slot that has to be a letter, recomputed the check digit, saw it match, and fixed it. When a fix doesn't make the check digit agree, like the Lensbox invoice where the GSTIN printed on the invoice itself is wrong, it leaves it alone and flags it for a human.&lt;/p&gt;

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


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/omlahore" rel="noopener noreferrer"&gt;
        omlahore
      &lt;/a&gt; / &lt;a href="https://github.com/omlahore/gstsort" rel="noopener noreferrer"&gt;
        gstsort
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Check GST invoices for input tax credit problems with a local vision model
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;gstsort&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Point it at a folder of GST invoices (PDFs or phone photos) and it gives you a CSV of everything on them, plus a list of the ones you shouldn't claim input tax credit on yet. A local open-weight vision model reads the invoices, so they never leave your machine.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/omlahore/gstsort/docs/run.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fomlahore%2Fgstsort%2FHEAD%2Fdocs%2Frun.png" alt="gstsort output on the ten sample invoices"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ gstsort -gstin 27AKXPS4821M1Z7 samples/
...
06-typo-gstin.pdf (Lensbox Camera Rentals LB-26-0391)
  - supplier GSTIN "27AAKFL4410C1ZQ" fails the checksum, recheck it on the invoice

07-total-mismatch.pdf (INKWELL STATIONERS IW-2207)
  - taxable 1580.00 + tax 284.40 + cess 0.00 doesn't add up to total 1964.40 (off by -100.00)
  ~ read supplier GSTIN as 27ABZP19054E1Z4, fixed to 27ABZPI9054E1Z4 (checksum confirms)
...
10 invoices, 4 clean. Input tax credit ready to claim: ₹3437.82. Held back for review: ₹2406.56
Wrote invoices.csv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What it checks&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;The model only reads. Everything after that is plain code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GSTIN format and the mod-36 check digit. A misread look-alike (an…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/omlahore/gstsort" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;The model is Qwen2.5-VL-7B-Instruct, an open-weight vision model, quantized to 4 bits (Q4_K_M GGUF) and served by llama.cpp's llama-server on localhost. The CLI is about 400 lines of Go.&lt;/p&gt;

&lt;p&gt;For each invoice:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;PDFs get rendered to PNG with pdftoppm, and phone photos get scaled down so the long side is 1400 px. A 4000 px photo blows past the context window of a 7B vision model.&lt;/li&gt;
&lt;li&gt;The image goes to llama-server's OpenAI-compatible endpoint with a JSON schema in &lt;code&gt;response_format&lt;/code&gt;. llama.cpp turns that schema into a grammar, so the model can only produce valid JSON with the fields I asked for: GSTINs, invoice number, date, taxable value, CGST, SGST, IGST, cess, total and the HSN/SAC codes.&lt;/li&gt;
&lt;li&gt;Everything after that is plain Go. The model reads the invoice and never decides whether a credit is claimable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GSTIN format and the mod-36 check digit, with the look-alike repair above&lt;/li&gt;
&lt;li&gt;billed to your GSTIN, and no buyer GSTIN means it's a B2C bill with no credit&lt;/li&gt;
&lt;li&gt;same state means CGST + SGST, different states means IGST&lt;/li&gt;
&lt;li&gt;CGST equals SGST, the effective rate is a real GST slab, and taxable + tax + cess equals the total&lt;/li&gt;
&lt;li&gt;restaurant services (SAC 99633x), which are usually blocked credit under section 17(5)&lt;/li&gt;
&lt;li&gt;the same supplier and invoice number showing up twice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The output is a CSV with every field, the credit you can claim on each invoice, and the reason for anything held back. Place-of-supply edge cases like a hotel stay in another state still need a human, and the README says so.&lt;/p&gt;

&lt;p&gt;I tried letting the model pick an expense category too. It labeled almost everything "travel", including a broadband bill. So that field went, and the food check reads the SAC code instead, which is printed on the invoice and doesn't need guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Invoices are other people's financial data. A CA office holds them for dozens of clients and has every reason not to upload them to someone else's API. With an open-weight model on llama.cpp nothing leaves the machine, it works with the internet off, and there's no per-page API bill, so running a whole year of invoices through it is fine.&lt;/p&gt;

&lt;p&gt;Running the inference server myself also means I control the decoding. The JSON schema is enforced as a grammar while the model generates, so I never parse free text and hope. When a better open vision model comes out, I point llama-server at it and nothing else changes.&lt;/p&gt;

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