<?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: Hamid Naeem Khan</title>
    <description>The latest articles on DEV Community by Hamid Naeem Khan (@hamidkhan1001).</description>
    <link>https://dev.to/hamidkhan1001</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%2F4177526%2Fd3681f3b-90bf-49b5-9ae0-b6cf06810fc9.jpg</url>
      <title>DEV Community: Hamid Naeem Khan</title>
      <link>https://dev.to/hamidkhan1001</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hamidkhan1001"/>
    <language>en</language>
    <item>
      <title>Shoebox: a receipt sorter for freelancers that never uploads a receipt</title>
      <dc:creator>Hamid Naeem Khan</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:02:33 +0000</pubDate>
      <link>https://dev.to/hamidkhan1001/shoebox-a-receipt-sorter-for-freelancers-that-never-uploads-a-receipt-4idk</link>
      <guid>https://dev.to/hamidkhan1001/shoebox-a-receipt-sorter-for-freelancers-that-never-uploads-a-receipt-4idk</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;Every freelancer I know has the same tax-season ritual: a Downloads folder full of &lt;code&gt;Invoice_final(2).pdf&lt;/code&gt;, forwarded receipts, and invoices they sent to clients, and a weekend lost to sorting it. &lt;strong&gt;Shoebox&lt;/strong&gt; does the sorting.&lt;/p&gt;

&lt;p&gt;Point it at a messy folder. It reads each document with a model running on your own machine, then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;files a copy into &lt;code&gt;YYYY/YYYY-MM/category/&lt;/code&gt; with a readable name (&lt;code&gt;2026-04-02_GitHub_4.00.pdf&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;flags duplicates (the same receipt emailed twice)&lt;/li&gt;
&lt;li&gt;sets aside anything it can't read or doesn't trust, in &lt;code&gt;_needs-review/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;writes a &lt;code&gt;ledger.csv&lt;/code&gt; an accountant can open, and prints spend by category, with invoices you sent counted as income&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is a dry run by default, and it copies, never moves, because the originals are your client records.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who would pay:&lt;/strong&gt; a freelancer or one-person agency once a year at tax time, or a bookkeeper who wants a first pass over a client's shoebox of documents. I have not tested willingness to pay (see "My First User").&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull llama3.2:3b
shoebox samples/inbox &lt;span class="nt"&gt;--out&lt;/span&gt; out            &lt;span class="c"&gt;# dry run: writes out/ledger.csv only&lt;/span&gt;
shoebox samples/inbox &lt;span class="nt"&gt;--out&lt;/span&gt; out &lt;span class="nt"&gt;--apply&lt;/span&gt;    &lt;span class="c"&gt;# copies files into out/YYYY/YYYY-MM/category/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;samples/make_samples.py&lt;/code&gt; generates fictional receipts and invoices (PDF and text) so you can try it without touching real records.&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/HamidKhan1001" rel="noopener noreferrer"&gt;
        HamidKhan1001
      &lt;/a&gt; / &lt;a href="https://github.com/HamidKhan1001/shoebox" rel="noopener noreferrer"&gt;
        shoebox
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &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;Shoebox&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Local-only receipt and invoice sorter for freelancers. Point it at a messy folder; it reads each document with an open-weight model running on your own machine (Ollama, default &lt;code&gt;llama3.2:3b&lt;/code&gt;), files copies into &lt;code&gt;YYYY/YYYY-MM/category/&lt;/code&gt;, flags duplicates, and writes a &lt;code&gt;ledger.csv&lt;/code&gt; for your accountant. Nothing leaves your laptop: the client refuses any non-loopback host.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Use&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;python3.11 -m venv .venv &lt;span class="pl-k"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="pl-c1"&gt;source&lt;/span&gt; .venv/bin/activate &lt;span class="pl-k"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip install -e &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;.[dev]&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
ollama pull llama3.2:3b
shoebox &lt;span class="pl-k"&gt;~&lt;/span&gt;/Downloads/receipts --out &lt;span class="pl-k"&gt;~&lt;/span&gt;/books         &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; dry run, writes ledger only&lt;/span&gt;
shoebox &lt;span class="pl-k"&gt;~&lt;/span&gt;/Downloads/receipts --out &lt;span class="pl-k"&gt;~&lt;/span&gt;/books --apply &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; copies files (originals untouched)&lt;/span&gt;
pytest&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Supports text-based PDFs and txt/md/csv/eml/html. Scanned images need OCR, which is not included.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Trust checks&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Small models make mistakes, so every result is validated: the extracted total must appear in the document text, dates must be plausible, and anything failing goes to &lt;code&gt;_needs-review/&lt;/code&gt; instead of being filed silently.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Sample data and eval&lt;/h2&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HamidKhan1001/shoebox" 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;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; &lt;code&gt;llama3.2:3b&lt;/code&gt;, an open-weight model, served locally by Ollama. Ollama's JSON-schema &lt;code&gt;format&lt;/code&gt; option constrains the output to my fields, so I always get parseable JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extraction:&lt;/strong&gt; &lt;code&gt;pypdf&lt;/code&gt; for text-based PDFs, plain reads for txt/eml/html. No OCR, so scanned images are listed as unreadable rather than guessed at.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation (the part that matters):&lt;/strong&gt; a small model will sometimes invent numbers, so every result is checked against the source text. The extracted total must literally appear in the document, the date must be plausible, and a failure sends the file to &lt;code&gt;_needs-review/&lt;/code&gt; instead of filing it. "Invoice you sent" is forced to category &lt;code&gt;income&lt;/code&gt; in code, not left to the model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy by construction:&lt;/strong&gt; the client refuses any host that isn't loopback, so a misconfigured URL fails instead of leaking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How well does it work?&lt;/strong&gt; I generated 15 fictional documents with known answers and scored &lt;code&gt;llama3.2:3b&lt;/code&gt; (CPU only, an Intel Mac, about 25-28 s per document):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;field&lt;/th&gt;
&lt;th&gt;first prompt&lt;/th&gt;
&lt;th&gt;fixed prompt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;date&lt;/td&gt;
&lt;td&gt;15/15&lt;/td&gt;
&lt;td&gt;15/15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;total&lt;/td&gt;
&lt;td&gt;15/15&lt;/td&gt;
&lt;td&gt;15/15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vendor&lt;/td&gt;
&lt;td&gt;13/15&lt;/td&gt;
&lt;td&gt;12/15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;doc type&lt;/td&gt;
&lt;td&gt;12/15&lt;/td&gt;
&lt;td&gt;12/15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;category&lt;/td&gt;
&lt;td&gt;3/15&lt;/td&gt;
&lt;td&gt;12/15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first run was bad: category was 3/15 because my own prompt mentioned "income" and the 3B model labelled nearly everything income. Removing it from the model's choices took category to 12/15.&lt;/p&gt;

&lt;p&gt;What is still wrong: three supplier invoices were read as invoices &lt;em&gt;I&lt;/em&gt; sent, two client invoices got my own name as the vendor, and one vendor came back empty. Of the 6 documents with an error, only 1 was flagged for review; the other 5 would be filed silently. My validator catches hallucinated amounts and bad dates, but not a wrong category or the wrong party. So the honest status is: reliable on amounts and dates, shaky on judgment, and you should skim the ledger before trusting it for taxes. This is 15 synthetic documents and a single run, so treat it as indicative, not a benchmark.&lt;/p&gt;

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

&lt;p&gt;Receipts and client invoices are exactly what you don't want to paste into someone else's API: client names, rates, addresses. Running an open-weight model locally means the documents never leave the laptop, there is no per-page fee eating a small business's margin, and it works on a train with no signal. I can also swap the model with &lt;code&gt;--model&lt;/code&gt; as better small models appear, and a niche like "invoices from my country's utilities" is something I could fine-tune for, which a closed API wouldn't let me do. The tradeoff is real, though: a 3B model on a CPU is slower and less accurate than a frontier API, and I'd say so to any customer.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;I built this with Claude Code. &amp;lt;!-- Add a DevRelay link here if you saved one, otherwise delete this section. --&amp;gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My First User
&lt;/h2&gt;

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

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>TrailBird: an offline bird-call identifier for your next hike</title>
      <dc:creator>Hamid Naeem Khan</dc:creator>
      <pubDate>Sun, 11 Oct 2026 18:58:40 +0000</pubDate>
      <link>https://dev.to/hamidkhan1001/trailbird-an-offline-bird-call-identifier-for-your-next-hike-530</link>
      <guid>https://dev.to/hamidkhan1001/trailbird-an-offline-bird-call-identifier-for-your-next-hike-530</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;TrailBird is a local bird-call identifier for hikers. You give it a short recording, and it returns the top 3 likely species with confidence scores. It flags low-confidence results as uncertain and shows a short listening note. The screen is meant for a quick glance, so the walk stays the main event. Audio never leaves your laptop. It's for hikers and casual birders who want to put the phone down and look up.&lt;/p&gt;

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

&lt;p&gt;A live demo isn't deployed yet. The repo is public, and I'm finishing the model wiring and UI now. I'll add a demo video and link to this post when it's ready.&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/HamidKhan1001" rel="noopener noreferrer"&gt;
        HamidKhan1001
      &lt;/a&gt; / &lt;a href="https://github.com/HamidKhan1001/trailbird" rel="noopener noreferrer"&gt;
        trailbird
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Offline bird-call identifier (BirdNET, Gradio) for the Hacktoberfest Touch Grass challenge
    &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;TrailBird: offline bird-call identifier&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Identify a bird from a short recording on the trail, with no internet and no audio leaving your laptop.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Status: work in progress (Hacktoberfest 2026, "Touch Grass" challenge).&lt;/strong&gt;
Done so far: audio loading/resampling/chunking (&lt;code&gt;trailbird/audio.py&lt;/code&gt;) and top-3 / uncertainty / disclaimer formatting (&lt;code&gt;trailbird/results.py&lt;/code&gt;).
Still to do: BirdNET inference wiring, Gradio UI, tests, demo audio.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Planned model&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/birdnet-team/BirdNET-Analyzer" rel="noopener noreferrer"&gt;BirdNET&lt;/a&gt; via the &lt;code&gt;birdnet&lt;/code&gt; Python package (~6,000 species), run locally with ONNX.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code: MIT. &lt;strong&gt;Model weights: CC BY-NC-SA 4.0&lt;/strong&gt; (non-commercial, share-alike, attribution required). Fine for this non-commercial project; not OSI-open weights.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Disclaimer&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Results are an assistive prediction, not a definitive identification.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;License&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Project code: MIT. BirdNET model weights: CC BY-NC-SA 4.0.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/HamidKhan1001/trailbird" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Current state: audio loading, resampling and chunking, plus top-3 ranking, uncertainty flagging and the disclaimer, are in the repo. BirdNET inference, the Gradio UI and tests are still in progress.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; &lt;a href="https://github.com/birdnet-team/BirdNET-Analyzer" rel="noopener noreferrer"&gt;BirdNET&lt;/a&gt;, an open-weight model covering about 6,000 species, run locally through the &lt;code&gt;birdnet&lt;/code&gt; Python package with ONNX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audio pipeline (Python):&lt;/strong&gt; mono conversion, resampling to 48 kHz, and 3-second chunking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result handling:&lt;/strong&gt; the top-3 results are marked uncertain when the best score is under 50% or within 10 points of second place. Every result carries an "assistive prediction, not a definitive identification" disclaimer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI:&lt;/strong&gt; Gradio, planned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Licenses:&lt;/strong&gt; the code is MIT. The BirdNET weights are CC BY-NC-SA 4.0, so non-commercial use with attribution and share-alike. BirdNET is by the Cornell Lab of Ornithology and Chemnitz University of Technology.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Open weights let identification run on a laptop with no signal, no API key and no upload of where you were or what you recorded. A closed API needs connectivity, which trails often lack, and sends your recordings to someone else's server. Open code and weights also mean anyone can audit, fix or extend it, for example with regional species notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;Built with Claude Code. [Add your DevRelay session embed here, or delete this section.]&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>HI</title>
      <dc:creator>Hamid Naeem Khan</dc:creator>
      <pubDate>Sun, 11 Oct 2026 17:37:40 +0000</pubDate>
      <link>https://dev.to/hamidkhan1001/hi-1bcb</link>
      <guid>https://dev.to/hamidkhan1001/hi-1bcb</guid>
      <description></description>
    </item>
  </channel>
</rss>
