<?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: Shubham Kondekar</title>
    <description>The latest articles on DEV Community by Shubham Kondekar (@shubham-kondekar).</description>
    <link>https://dev.to/shubham-kondekar</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%2F4154134%2Fa907ccf8-23c9-44f1-b00a-d63947443dc4.png</url>
      <title>DEV Community: Shubham Kondekar</title>
      <link>https://dev.to/shubham-kondekar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shubham-kondekar"/>
    <language>en</language>
    <item>
      <title>Sloth - a local file tidier that runs entirely on your laptop</title>
      <dc:creator>Shubham Kondekar</dc:creator>
      <pubDate>Mon, 26 Oct 2026 05:09:52 +0000</pubDate>
      <link>https://dev.to/shubham-kondekar/sloth-a-local-file-tidier-that-runs-entirely-on-your-laptop-cch</link>
      <guid>https://dev.to/shubham-kondekar/sloth-a-local-file-tidier-that-runs-entirely-on-your-laptop-cch</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;&lt;strong&gt;Sloth&lt;/strong&gt; is a local file tidier that runs entirely on your laptop.&lt;/p&gt;

&lt;p&gt;You point it at a folder — usually the downloads folder you have been avoiding for months — and it reads the files, groups them into piles, renames them into something you can actually search for, and shows you the whole plan before a single byte moves. When you approve it, everything goes into &lt;code&gt;Sloth Sorted/&lt;/code&gt;, and Sloth leaves a short morning note describing what happened.&lt;/p&gt;

&lt;p&gt;The person who gets to be lazier is anyone who has ever opened their Downloads folder, felt a small wave of dread, and closed it again. That is the entire audience. Sloth does the reading and the sorting; you keep the judgement call.&lt;/p&gt;

&lt;p&gt;The model is &lt;strong&gt;Qwen2.5-1.5B-Instruct&lt;/strong&gt; — open weights, Apache-2.0 — running locally through &lt;strong&gt;llama.cpp&lt;/strong&gt;. No account, no API key, no cloud, no telemetry. The app itself is Python standard library only. The only thing it asks of the network is one setup step to download the engine and the weights.&lt;/p&gt;

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

&lt;p&gt;There is no hosted demo, on purpose: the whole point is that your files never leave your machine. Here is what it looks like running locally.&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%2Fcivyl4vlqwbuc0bk06pv.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%2Fcivyl4vlqwbuc0bk06pv.png" alt="Sloth dashboard" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A scan of a 42-file messy folder (about 26 seconds on an M-series Mac):&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%2Foo2sejaewaophz8ftyr3.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%2Foo2sejaewaophz8ftyr3.png" alt="Sloth plan" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every row shows the new name, the original name, the model's reason, and a confidence score. The two files it is unsure about start unticked. Nothing moves until you press the button.&lt;/p&gt;

&lt;p&gt;After applying, a receipt and a morning note:&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%2Fktom0hjicrqpjxnz42kz.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%2Fktom0hjicrqpjxnz42kz.png" alt="Sloth receipt" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To reproduce locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/kondekarshubham123/sloth.git
&lt;span class="nb"&gt;cd &lt;/span&gt;sloth
./setup.sh          &lt;span class="c"&gt;# builds llama.cpp, fetches ~1 GB of weights, makes a demo folder&lt;/span&gt;
./sloth ui &lt;span class="nt"&gt;--open&lt;/span&gt;   &lt;span class="c"&gt;# http://127.0.0.1:8765&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or stay in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./sloth scan ~/Downloads
./sloth apply last &lt;span class="nt"&gt;--yes&lt;/span&gt;
./sloth undo
./sloth night &lt;span class="nt"&gt;--once&lt;/span&gt; &lt;span class="nt"&gt;--apply&lt;/span&gt;   &lt;span class="c"&gt;# tidy now, then leave a note&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;The repository is here: &lt;strong&gt;&lt;a href="https://github.com/kondekarshubham123/sloth" rel="noopener noreferrer"&gt;kondekarshubham123/sloth&lt;/a&gt;&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;git clone https://github.com/kondekarshubham123/sloth.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interesting parts are small and readable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/sloth/scanner.py&lt;/code&gt; — a careful folder walk that skips junk, symlinks, and its own output, and reads a bounded snippet from text-like files.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/sloth/planner.py&lt;/code&gt; — batching, rule hints, model reconciliation, and filename sanitising.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/sloth/llm.py&lt;/code&gt; — spawns and supervises a local &lt;code&gt;llama-server&lt;/code&gt;; talks to it over loopback.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/sloth/store.py&lt;/code&gt; — plans, apply, a JSONL journal, undo, and the morning note.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/sloth/netguard.py&lt;/code&gt; — a socket-level guard that refuses non-loopback connections.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;src/sloth/ui/&lt;/code&gt; — the dashboard in plain HTML, CSS, and JavaScript, with inline SVG illustrations and no external assets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Twelve unit tests cover the boring-but-important bits: name sanitising, extracting JSON from a chatty model, scan skip rules, path escapes, idempotent apply, undo, and the airgap.&lt;/p&gt;

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

&lt;p&gt;I wanted the model to be genuinely load-bearing, not a chat bubble bolted onto a file sorter. But I also knew a 1.5B model would occasionally be confidently wrong. So Sloth is a hybrid, and the split is deliberate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The model decides.&lt;/strong&gt; For each batch of six files, the planner sends a compact JSON view — name, extension, size, modification date, a short text snippet, and a rule hint — to a local &lt;code&gt;llama-server&lt;/code&gt;. It asks for strict JSON back: bucket, a kebab-case name, a reason under twelve words, and a confidence score.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The rules keep it honest.&lt;/strong&gt; A small deterministic engine supplies an objective hint for every file. If the model agrees with a hard signal, confidence gets a small bump. If it disagrees about something objective — an &lt;code&gt;.mp3&lt;/code&gt; is not a document, a file named &lt;code&gt;screenshot-2026-03-14&lt;/code&gt; is a screenshot, a boarding pass is travel — the rule wins, and the override is visible in the &lt;code&gt;why&lt;/code&gt; line. Semantic corrections are more conservative and only apply when the model itself is unsure.&lt;/p&gt;

&lt;p&gt;While testing, the model kept stamping today's date onto filenames that had no date in them. That is a very small, very believable hallucination, and exactly the kind of thing a person would not notice until next year. So &lt;code&gt;drop_bogus_date()&lt;/code&gt; strips a &lt;code&gt;YYYY-MM-DD&lt;/code&gt; prefix unless those digits appear in the original name or the file's actual modified date. Small guardrail, big difference in trust.&lt;/p&gt;

&lt;p&gt;The prompt treats filenames and snippets as untrusted data, never instructions, because a file called &lt;code&gt;ignore-previous-instructions.txt&lt;/code&gt; should be a file, not a command.&lt;/p&gt;

&lt;p&gt;Everything else is intentionally boring. The HTTP server is &lt;code&gt;http.server&lt;/code&gt;. The UI streams scan progress as newline-delimited JSON. The journal is JSONL. Undo reads the journal backwards and refuses any move that would escape the scan root. The morning note is Markdown written to &lt;code&gt;~/.sloth/briefings/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And the airgap is real rather than decorative: &lt;code&gt;netguard.install()&lt;/code&gt; replaces the socket connection path so non-loopback connections fail for the life of the process, the UI binds to &lt;code&gt;127.0.0.1&lt;/code&gt;, and &lt;code&gt;llama-server&lt;/code&gt; is launched with a loopback host. &lt;code&gt;./sloth doctor&lt;/code&gt; prints the model checksum, the engine backend, and the airgap state. The dashboard loads no CDN, no web fonts, and no analytics. The sloth drawing is inline SVG.&lt;/p&gt;

&lt;p&gt;The slow part is the point. Batches of six, a visible "reading files 13–18 of 42" line, and a plan you have to approve. It is a file tidier that behaves like a careful person rather than a progress bar.&lt;/p&gt;

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

&lt;p&gt;A closed API would have made this project easier and worse.&lt;/p&gt;

&lt;p&gt;The easy version sends your filenames, and possibly snippets of your contracts and medical notes, to someone else's server. That is a strange price to pay for tidying a Downloads folder. With open weights and open inference, the private version is also the capable version. Qwen2.5-1.5B is small enough to run on a laptop, good enough to name a file sensibly, and licensed so that I can ship it without asking permission.&lt;/p&gt;

&lt;p&gt;Open weights also made the &lt;em&gt;design&lt;/em&gt; possible. I could inspect how the model behaved, notice the invented-date pattern, and build a guardrail around it. I could swap in a larger model by changing one environment variable. I could build the entire thing offline, on a train, without a billing dashboard. And anyone reading the repo can verify the privacy claim in the code instead of trusting a landing page.&lt;/p&gt;

&lt;p&gt;The agent harness matters here too. llama.cpp is open, hackable, and runs on the hardware people already own. That is what turns "local AI" from a demo into something a normal person can actually use on a Tuesday night.&lt;/p&gt;

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

&lt;p&gt;I did not publish a DevRelay session for this build, so there is no embed to share. Being honest about that feels better than linking to something that does not exist.&lt;/p&gt;

&lt;p&gt;What I can share is the loop I actually worked in. I used an AI coding agent to scaffold the project, then spent most of the time on the unglamorous parts: making the model's JSON parse reliably, reducing the batch size until the 1.5B model stopped truncating output, catching the bogus date prefixes, fixing the apply button's disabled state, and re-running the same 42-file demo until apply and undo were both correct. The screenshots in this post are from the final build, not a mockup.&lt;/p&gt;

&lt;p&gt;The most useful agent contribution was not code generation. It was being able to run the app, read the model's output, and iterate on the prompt and the reconciliation rules in the same session.&lt;/p&gt;

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

&lt;p&gt;On the demo folder, Sloth read and classified &lt;strong&gt;42 files into 12 piles in about 26 seconds&lt;/strong&gt;. I approved 40 of them; the two low-confidence files stayed put. Apply moved all 40 into &lt;code&gt;Sloth Sorted/&lt;/code&gt; in under a second. Undo put all 40 back, from the journal, just as quickly.&lt;/p&gt;

&lt;p&gt;The honest number is not the 26 seconds. It is the twenty minutes I would have spent opening files called &lt;code&gt;scan0001.pdf&lt;/code&gt; and &lt;code&gt;q3 budget final FINAL v3.xlsx&lt;/code&gt; to work out what they were, plus the future minutes I will not spend searching for them. The folder is now something I can look at without flinching, and I did not have to make a single decision about a &lt;code&gt;.HEIC&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;That is the laziness Sloth is selling: not zero effort, just the effort moved to a place where it is cheap. The sloth reads slowly so you do not have to.&lt;/p&gt;

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

&lt;p&gt;Best Use of Gemma&lt;br&gt;
Use Gemma, Google's open-weight model, in building your project: run it locally, fine-tune it, or serve it through Google Cloud or another provider.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>ReceiptRack: a receipt sorter that never sends your receipts anywhere</title>
      <dc:creator>Shubham Kondekar</dc:creator>
      <pubDate>Sun, 18 Oct 2026 18:44:46 +0000</pubDate>
      <link>https://dev.to/shubham-kondekar/receiptrack-a-receipt-sorter-that-never-sends-your-receipts-anywhere-5g27</link>
      <guid>https://dev.to/shubham-kondekar/receiptrack-a-receipt-sorter-that-never-sends-your-receipts-anywhere-5g27</guid>
      <description>&lt;p&gt;Every freelancer I know has the same shoebox: a folder of receipt photos and invoice PDFs that gets sorted once a year, in a panic, before taxes. Cloud OCR APIs exist for this — and for exactly one reason (my clients' financial data never leaving my laptop, and paying $0 instead of per-page forever), I built &lt;strong&gt;ReceiptRack&lt;/strong&gt; on a local open-weight model instead.&lt;/p&gt;

&lt;p&gt;Drop receipts in → a vision model running &lt;strong&gt;on your machine&lt;/strong&gt; transcribes and structures them → suspicious extractions get flagged for a 10-second human review → keyword rules file them to the right client → export a CSV your accountant accepts.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    A[Receipt / invoice&amp;lt;br/&amp;gt;PNG · JPG · PDF] --&amp;gt; B[Preprocess&amp;lt;br/&amp;gt;Pillow]
    B --&amp;gt; C[Vision pass&amp;lt;br/&amp;gt;gemma3:4b via Ollama&amp;lt;br/&amp;gt;faithful transcription]
    C --&amp;gt; D[Structuring pass&amp;lt;br/&amp;gt;schema-constrained JSON&amp;lt;br/&amp;gt;temperature 0]
    D --&amp;gt; E{Validator&amp;lt;br/&amp;gt;flags · sum check}
    E --&amp;gt; F[(SQLite, local)]
    F --&amp;gt; G[Human review UI]
    G --&amp;gt; H[Client sorting&amp;lt;br/&amp;gt;rules + model]
    H --&amp;gt; I[CSV export]&lt;/code&gt;&lt;/pre&gt;



&lt;h2&gt;
  
  
  Why open is the business model, not a preference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Cloud OCR API&lt;/th&gt;
&lt;th&gt;ReceiptRack&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;Clients' spend leaves the machine&lt;/td&gt;
&lt;td&gt;Never leaves it — the pitch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Per-page, forever&lt;/td&gt;
&lt;td&gt;$0 marginal — scan 10 or 10,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lock-in&lt;/td&gt;
&lt;td&gt;Someone else's pricing&lt;/td&gt;
&lt;td&gt;Swap the model via one env var&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Niche fit&lt;/td&gt;
&lt;td&gt;Generic&lt;/td&gt;
&lt;td&gt;Fine-tune on &lt;em&gt;your&lt;/em&gt; clients' invoice formats&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The open pieces &lt;strong&gt;are&lt;/strong&gt; the product: &lt;code&gt;gemma3:4b&lt;/code&gt; (open-weight vision model), Ollama (local runtime), FastAPI + SQLite, MIT-licensed. A closed API structurally cannot promise "this runs on your laptop" — the privacy claim is only true because of what's open.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the community had already figured out (and what it hadn't)
&lt;/h2&gt;

&lt;p&gt;Two DEV posts shaped the design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bytefer's &lt;a href="https://dev.to/bytefer/ollama-ocr-for-high-precision-ocr-with-ollama-4o31"&gt;Ollama-OCR for High-Precision OCR with Ollama&lt;/a&gt; established the local vision-OCR pipeline — including a receipt demo. But the most interesting part is what the comments &lt;em&gt;didn't&lt;/em&gt; resolve: &lt;em&gt;"Does it hallucinate with large tables with lot of numbers?"&lt;/em&gt; went unanswered except by "go test the 90B demo yourself."&lt;/li&gt;
&lt;li&gt;Ajit Kumar's &lt;a href="https://dev.to/ajitkumar/the-complete-guide-to-ollama-run-large-language-models-locally-2mge"&gt;Complete Guide to Ollama&lt;/a&gt; makes the economics case plainly: &lt;em&gt;"Your data never leaves your machine… no API costs."&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And from an open-source invoice extractor's published eval: &lt;strong&gt;invoice # 20%, date 60%, total 60% field accuracy&lt;/strong&gt; with a small vision model. Read that before you ship anything that auto-files money documents. So ReceiptRack's core rule became: &lt;strong&gt;the model proposes, a human disposes.&lt;/strong&gt; Every extraction lands in a review queue with flags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;missing_total&lt;/code&gt;, &lt;code&gt;missing_vendor&lt;/code&gt;, &lt;code&gt;date_not_iso&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;line_items_mismatch&lt;/code&gt; — line items (+ tax) don't sum to the stated total&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last flag caught a real case in testing: an Uber receipt where the $4 tip isn't a line item. A human glances at it; the model never silently files a wrong number.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five things that broke, and the fixes that stuck
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Two passes beat one.&lt;/strong&gt; First version: image → JSON. Final: image → faithful transcription → JSON from the transcription. Same accuracy ceiling, but you get an auditable raw transcript in the UI, and re-parsing doesn't re-run the vision model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Optional schema fields = missing data.&lt;/strong&gt; The model happily returned &lt;code&gt;vendor: ""&lt;/code&gt; and skipped &lt;code&gt;category&lt;/code&gt; entirely when they had defaults. Making them &lt;code&gt;required&lt;/code&gt; in the JSON schema — with Ollama's schema-constrained decoding — turned "usually present" into &lt;em&gt;grammatically impossible to omit&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A prompt that returns &lt;code&gt;null&lt;/code&gt; for the total, deterministically.&lt;/strong&gt; The docs clearly said &lt;code&gt;TOTAL DUE 65.69&lt;/code&gt;; three runs in a row, &lt;code&gt;total: null&lt;/code&gt;. The fix was one unambiguous line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- total: the grand total the customer pays (TOTAL, TOTAL DUE, Amount Due).
  If the document says "TOTAL DUE 65.69", then total = 65.69.
  Never null when a total line exists.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temperature 0 doesn't save a confusing prompt — it just makes the confusion reproducible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. The model echoing the vendor as the client name.&lt;/strong&gt; Auto-sorting asked "which client should this go to?" and &lt;code&gt;gemma3:4b&lt;/code&gt; kept answering &lt;code&gt;"Figma Inc."&lt;/code&gt; (the vendor) no matter how sternly the prompt said "only names from the list." Instructions lost. So I stopped asking nicely and constrained the grammar:&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;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;client&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anyOf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enum&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;null&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;client&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wrong answers became &lt;strong&gt;unrepresentable&lt;/strong&gt;. This is the single best argument for open, schema-constrained local inference I have: a closed chat API gave me a JSON "format" hint; Ollama gave me a grammar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Malformed JSON still happens.&lt;/strong&gt; Even under schema constraints, one extraction in three crashed the parser. Retries (strict schema → loose JSON → validate) turned a hard failure into noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;~5–15 s per receipt on an M-series Mac, 100% GPU, 16 GB RAM&lt;/li&gt;
&lt;li&gt;3/3 correct vendor/date/total/tax/line items on the test set after fix #3&lt;/li&gt;
&lt;li&gt;Cost per receipt: $0.00 — forever&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Honest limitations
&lt;/h2&gt;

&lt;p&gt;Small open-weight models misread faded thermal prints — that's what the review queue is for. The LLM client-assignment fallback makes defensible-but-imperfect choices (a 4B model thinks every travel expense belongs to the design agency); deterministic keyword rules run first for that reason. Single-user, localhost-only by design.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull gemma3:4b
git clone https://github.com/kondekarshubham123/ReceiptRack.git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;receipt-rack
uv &lt;span class="nb"&gt;sync
&lt;/span&gt;uv run uvicorn app.main:app &lt;span class="nt"&gt;--port&lt;/span&gt; 8300   &lt;span class="c"&gt;# → http://127.0.0.1:8300&lt;/span&gt;
uv run python scripts/make_samples.py     &lt;span class="c"&gt;# demo receipts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;code&gt;https://github.com/kondekarshubham123/ReceiptRack&lt;/code&gt; · MIT · README has the full architecture and the env vars (&lt;code&gt;RECEIPT_RACK_MODEL&lt;/code&gt;, &lt;code&gt;OLLAMA_URL&lt;/code&gt;).&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🌐 Community Wisdom: [&lt;a href="https://dev.to/bytefer/ollama-ocr-for-high-precision-ocr-with-ollama-4o31"&gt;Ollama-OCR for High-Precision OCR with Ollama&lt;/a&gt;]
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: [&lt;a href="https://dev.to/bytefer"&gt;Bytefer&lt;/a&gt;]&lt;br&gt;
&lt;strong&gt;Tags&lt;/strong&gt;: &lt;code&gt;webdev&lt;/code&gt;, &lt;code&gt;programming&lt;/code&gt;, &lt;code&gt;javascript&lt;/code&gt;, &lt;code&gt;ai&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Establishes the local vision-model OCR pipeline as a proven pattern; the comments' unresolved question about hallucinated numbers in tables is why this project validates arithmetic instead of trusting the model.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://dev.to/bytefer/ollama-ocr-for-high-precision-ocr-with-ollama-4o31"&gt;Read Full Discussion&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🌐 Community Wisdom: [&lt;a href="https://dev.to/ajitkumar/the-complete-guide-to-ollama-run-large-language-models-locally-2mge"&gt;The Complete Guide to Ollama: Run Large Language Models Locally&lt;/a&gt;]
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Source&lt;/strong&gt;: [&lt;a href="https://dev.to/ajitkumar"&gt;Ajit Kumar&lt;/a&gt;]&lt;br&gt;
&lt;strong&gt;Tags&lt;/strong&gt;: &lt;code&gt;ollama&lt;/code&gt;, &lt;code&gt;llm&lt;/code&gt;, &lt;code&gt;rag&lt;/code&gt;, &lt;code&gt;ai&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The privacy/no-API-cost case this project's pitch rests on — with the honest tradeoff surfaced by readers: hardware is the real cost of going local.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://dev.to/ajitkumar/the-complete-guide-to-ollama-run-large-language-models-locally-2mge"&gt;Read Full Discussion&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
    </item>
    <item>
      <title>DeadZone Drill: offline flashcards that only work when you walk away from the internet</title>
      <dc:creator>Shubham Kondekar</dc:creator>
      <pubDate>Sun, 11 Oct 2026 04:35:27 +0000</pubDate>
      <link>https://dev.to/shubham-kondekar/deadzone-drill-offline-flashcards-that-only-work-when-you-walk-away-from-the-internet-2fjl</link>
      <guid>https://dev.to/shubham-kondekar/deadzone-drill-offline-flashcards-that-only-work-when-you-walk-away-from-the-internet-2fjl</guid>
      <description>&lt;h2&gt;
  
  
  The pitch in one sentence
&lt;/h2&gt;

&lt;p&gt;DeadZone Drill turns your study notes into a &lt;strong&gt;spoken flashcard drill you run on a walk&lt;/strong&gt;, with a local open-weight model writing and grading the cards — no account, no API key, no internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem I actually had
&lt;/h2&gt;

&lt;p&gt;I revise with flashcards, and flashcards are a screen activity: sit down, stare at a card, tap "again". Studies on recall &lt;em&gt;and&lt;/em&gt; the challenge's own framing kept pointing the same direction — I learn better when I'm moving, and I sit too much. The best moments of my last study session weren't at the desk at all. They were on a walk where I was muttering answers to myself.&lt;/p&gt;

&lt;p&gt;So I stopped trying to make the desk better and made the &lt;strong&gt;walk the study session&lt;/strong&gt;. DeadZone Drill is the tool I wanted: it talks, I answer out loud, and the screen stays in my pocket.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; drill build notes.md &lt;span class="nt"&gt;--deck&lt;/span&gt; foliage
&lt;span class="go"&gt;Added 12 card(s) to deck 'foliage' (source: gemma).

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; drill walk &lt;span class="nt"&gt;--deck&lt;/span&gt; foliage
&lt;span class="go"&gt;TTS engine: macOS say (default voice)
----------------------------------------------------
  12 card(s) due. Answer out loud, then grade yourself.
----------------------------------------------------
[1/12] deck=foliage box=1
Listening to the question...
&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What is the primary trigger for autumn colour?"&lt;/span&gt;
&lt;span class="go"&gt;Recall it, then press Enter to hear the answer...
A: Day length
Did you know it? [y/N, q to quit] y
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;----------------------------------------------------
  Reviewed 12 card(s). 9 correct (75%).
  Session over. Get outside.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Everything that matters runs on the machine. The only network call is to &lt;strong&gt;localhost&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    A["Your notes&amp;lt;br/&amp;gt;(.md / .txt)"] --&amp;gt; B["Gemma 3 via Ollama&amp;lt;br/&amp;gt;local, offline"]
    B --&amp;gt; C["Q/A cards&amp;lt;br/&amp;gt;SQLite + Leitner schedule"]
    C --&amp;gt; D{"Walk mode"}
    D --&amp;gt;|"speak question"| E["macOS say / Piper&amp;lt;br/&amp;gt;offline TTS"]
    E --&amp;gt; F["You answer&amp;lt;br/&amp;gt;out loud"]
    F --&amp;gt; G{"grade"}
    G --&amp;gt;|"typed / spoken"| H["Gemma grades&amp;lt;br/&amp;gt;local"]
    G --&amp;gt;|"self-grade"| I["one keypress"]
    H --&amp;gt; C
    I --&amp;gt; C&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Pipeline:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Generate&lt;/strong&gt; — &lt;code&gt;drill build notes.md&lt;/code&gt; sends your notes to a local &lt;strong&gt;Gemma 3&lt;/strong&gt; (via Ollama) with a strict prompt and asks for JSON flashcards. If no model is running, a dependency-free cloze generator still produces a usable deck.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recall&lt;/strong&gt; — &lt;code&gt;drill walk&lt;/code&gt; pulls the cards due today and &lt;strong&gt;speaks&lt;/strong&gt; each question with offline TTS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grade&lt;/strong&gt; — answer out loud and self-grade with one keypress, type it for model grading, or speak it if you have a local Whisper build.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schedule&lt;/strong&gt; — a small Leitner scheduler moves the card to the next box and sets the next review date in SQLite.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole thing is &lt;strong&gt;standard-library Python&lt;/strong&gt;. &lt;code&gt;pip install&lt;/code&gt; is not required; the Ollama client is 60 lines of &lt;code&gt;urllib&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open matters here (not as a slogan — as a requirement)
&lt;/h2&gt;

&lt;p&gt;The theme asks me to build something that gets people off the screen and into the world. The open pieces aren't decoration; they're the reason the product works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It works with no internet, because the model is local.&lt;/strong&gt; Card generation, text-to-speech, grading, and scheduling all run on-device. Airplane mode is a supported configuration, not a degraded one. A closed API would have made "study on a trail with no signal" impossible — which is exactly the scenario the app exists for. To prove it, &lt;code&gt;drill prerender&lt;/code&gt; writes all question audio to disk so a walk needs &lt;em&gt;zero&lt;/em&gt; synthesis work in the moment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;My notes stay mine.&lt;/strong&gt; Lecture notes, personal study material, and every review I've ever done live in a SQLite file in &lt;code&gt;~/.deadzone-drill&lt;/code&gt;. There is no upload step to remember to disable, and no server holding what I'm weakest at. This is the "keep someone's data off a server they don't control" clause of the prompt, made concrete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The brain is swappable.&lt;/strong&gt; Any Ollama model works. I developed against one model and changed one environment variable to run Gemma. No vendor migration, no rate limits, no deprecation notice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing to run.&lt;/strong&gt; There's no token meter between me and my own revision. I can drill 10 cards or 10,000 and the cost is identical: zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The open tools let the edges degrade and still work.&lt;/strong&gt; When Whisper isn't installed, the app doesn't break — it falls back to self-grading. When no model is running, it falls back to cloze cards and token-overlap grading. Open, composable pieces made graceful degradation cheap to build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm not claiming a local 4B model out-writes GPT-5 at flashcard creation. I &lt;em&gt;am&lt;/em&gt; claiming that the fraction of usefulness that requires the internet was zero, and that's the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built with
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 3 (via Ollama)&lt;/strong&gt; — the open-weight model that writes and grades cards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Python standard library&lt;/strong&gt; — no runtime dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;macOS &lt;code&gt;say&lt;/code&gt;&lt;/strong&gt;, with &lt;strong&gt;Piper&lt;/strong&gt; as a pluggable open-weight TTS engine&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;whisper.cpp&lt;/code&gt; / &lt;code&gt;faster-whisper&lt;/code&gt;&lt;/strong&gt; — optional offline speech-to-text&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — local card storage and review schedule&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What was hard
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Grading free-form recall without a cloud service.&lt;/strong&gt; Exact string matching punishes correct answers phrased differently. I solved it in two layers: a local model judges paraphrase and partial credit, and a token-overlap heuristic catches the case where no model is available. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Making "offline" real instead of aspirational.&lt;/strong&gt; Pre-rendering audio and testing with the network off forced every hidden assumption into the open.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&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/kondekarshubham123/deadline-drill deadzone-drill
&lt;span class="nb"&gt;cd &lt;/span&gt;deadzone-drill

&lt;span class="c"&gt;# optional: local model&lt;/span&gt;
ollama pull gemma3:4b

python3 &lt;span class="nt"&gt;-m&lt;/span&gt; drill sample               &lt;span class="c"&gt;# seed a demo deck (works offline)&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; drill walk &lt;span class="nt"&gt;--deck&lt;/span&gt; sample   &lt;span class="c"&gt;# drill it&lt;/span&gt;

&lt;span class="c"&gt;# or use your own notes&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; drill build notes.md &lt;span class="nt"&gt;--deck&lt;/span&gt; mine
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; drill walk &lt;span class="nt"&gt;--deck&lt;/span&gt; mine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/kondekarshubham123/deadline-drill" rel="noopener noreferrer"&gt;https://github.com/kondekarshubham123/deadline-drill&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License:&lt;/strong&gt; MIT&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live demo:&lt;/strong&gt; not applicable — it's a local-first tool, which is the point. The repo runs on any laptop in two commands.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Optional spoken &lt;em&gt;answers&lt;/em&gt; with a bundled Whisper build so the loop is fully hands-free&lt;/li&gt;
&lt;li&gt;Deck export/import for sharing a good set of cards&lt;/li&gt;
&lt;li&gt;A "grass streak" that tracks how many days you studied outside rather than how many cards you ground through&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built for the Hacktoberfest Open-Source AI Challenge, Week 1 (Touch Grass). If you try it, take it somewhere with no signal — that's where it's happiest.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Hive - A Local AI Life Assistant for My Family, Running on a Raspberry Pi</title>
      <dc:creator>Shubham Kondekar</dc:creator>
      <pubDate>Sun, 04 Oct 2026 20:00:49 +0000</pubDate>
      <link>https://dev.to/shubham-kondekar/hive-a-local-ai-life-assistant-for-my-family-running-on-a-raspberry-pi-289</link>
      <guid>https://dev.to/shubham-kondekar/hive-a-local-ai-life-assistant-for-my-family-running-on-a-raspberry-pi-289</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Hive&lt;/strong&gt; is a private, multi-user AI life assistant that runs entirely on a Raspberry Pi 4B — no cloud, no subscriptions, no data leaving your home network.&lt;/p&gt;

&lt;p&gt;I built it for my family. We needed a shared space to manage our week: upcoming events, daily expenses, and a clear picture of what actually matters each day. Every existing tool either costs money every month, sends your data somewhere, or needs a good internet connection. Hive does none of those things — it lives on a Pi on the shelf and is accessible from any phone on the home Wi-Fi.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it does:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💬 &lt;strong&gt;AI Chat&lt;/strong&gt; — talk naturally: "I spent ₹150 on paav bhaji" or "Schedule a gym session tomorrow at 7am" — Hive routes your message to the right agent and writes to the database&lt;/li&gt;
&lt;li&gt;📅 &lt;strong&gt;Event Planner&lt;/strong&gt; — add, view, and delete calendar events; the AI checks for conflicts automatically&lt;/li&gt;
&lt;li&gt;💸 &lt;strong&gt;Expense Tracker&lt;/strong&gt; — log spending by category with a monthly budget summary and INR formatting; export to JSON or CSV&lt;/li&gt;
&lt;li&gt;🎯 &lt;strong&gt;Priority Ranking&lt;/strong&gt; — AI scores your upcoming events and expenses by urgency so you always know what to focus on&lt;/li&gt;
&lt;li&gt;🎙️ &lt;strong&gt;Voice Input&lt;/strong&gt; — speak instead of type, transcribed locally by OpenAI Whisper (no audio leaves the Pi)&lt;/li&gt;
&lt;li&gt;🌅 &lt;strong&gt;Morning Briefings&lt;/strong&gt; — the Pi pushes a daily summary to all connected users via WebSocket at a scheduled time&lt;/li&gt;
&lt;li&gt;📱 &lt;strong&gt;Multi-user, multi-device&lt;/strong&gt; — family members register by name + PIN, each has their own data, accessible from any phone on the same Wi-Fi&lt;/li&gt;
&lt;/ul&gt;




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

&lt;blockquote&gt;
&lt;p&gt;The app runs on a Raspberry Pi 4B (8 GB) on the local network. Any device on the same Wi-Fi opens &lt;code&gt;http://&amp;lt;pi-ip&amp;gt;:8000&lt;/code&gt; to get the full PWA.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🎥 &lt;strong&gt;Watch the demo:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://youtu.be/ykFI4QWlZVs" rel="noopener noreferrer"&gt;https://youtu.be/ykFI4QWlZVs&lt;/a&gt;&lt;/p&gt;


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

&lt;p&gt;🐙 &lt;strong&gt;GitHub Repository:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://github.com/kondekarshubham123/Hive" rel="noopener noreferrer"&gt;https://github.com/kondekarshubham123/Hive&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Key file structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hive/
├── server/
│   ├── main.py              # FastAPI app, WebSocket, SPA routing
│   ├── agents/
│   │   ├── orchestrator.py  # LangGraph StateGraph — keyword classify → route → tool-call loop
│   │   ├── tools.py         # LangChain tools: create_event, log_expense, get_open_tasks, ...
│   │   └── state.py         # HiveState TypedDict
│   ├── routers/
│   │   ├── auth_router.py   # Register / login by name+PIN, JWT issue
│   │   ├── chat.py          # POST /chat — SSE streaming, history fetch, message persist
│   │   ├── events.py        # CRUD /events
│   │   ├── expenses.py      # CRUD /expenses + budget summary
│   │   ├── priorities.py    # GET + POST /refresh — LLM priority scoring
│   │   └── voice.py         # POST /voice — Whisper transcription
│   └── database.py          # aiosqlite, 6-table schema, single DB_PATH
├── client/                  # React 19 + Vite + Tailwind CSS PWA
└── setup/
    ├── install_pi.sh        # One-shot Pi setup: apt, Ollama, venv, Node, systemd
    └── Modelfile            # hive-fast: gemma2:2b + tuned context/temperature/stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;h3&gt;
  
  
  Open-source AI stack
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LLM runtime&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; — runs &lt;code&gt;hive-fast&lt;/code&gt;, a custom build of &lt;a href="https://ai.google.dev/gemma" rel="noopener noreferrer"&gt;Gemma 2 2B&lt;/a&gt; (Google's open-weight model)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent framework&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://github.com/langchain-ai/langgraph" rel="noopener noreferrer"&gt;LangGraph 0.2&lt;/a&gt; — &lt;code&gt;StateGraph&lt;/code&gt; with conditional routing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLM library&lt;/td&gt;
&lt;td&gt;&lt;a href="https://github.com/langchain-ai/langchain" rel="noopener noreferrer"&gt;LangChain / langchain-ollama&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Voice transcription&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://github.com/openai/whisper" rel="noopener noreferrer"&gt;OpenAI Whisper&lt;/a&gt; &lt;code&gt;base.en&lt;/code&gt; — runs locally, no API key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;
&lt;a href="https://fastapi.tiangolo.com/" rel="noopener noreferrer"&gt;FastAPI&lt;/a&gt; with SSE streaming and WebSocket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;SQLite via &lt;a href="https://github.com/omnilib/aiosqlite" rel="noopener noreferrer"&gt;aiosqlite&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;React 19, Vite, Tailwind CSS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Agent architecture
&lt;/h3&gt;

&lt;p&gt;The core insight is a &lt;strong&gt;keyword intent classifier&lt;/strong&gt; in front of the LangGraph router. Instead of running a second LLM inference to classify intent (which added 4–7 s per request), a simple keyword scan routes messages effectively instantly:&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;_INTENT_KEYWORDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expense&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pay&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;₹&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rs &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;schedule&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;schedule&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;meeting&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;remind&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tomorrow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priority&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priority&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;focus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;what should i&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;share&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;share&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;send to&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notify&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_keyword_classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keywords&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_INTENT_KEYWORDS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kw&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;kw&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;general&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once classified, LangGraph routes to the matching node (&lt;code&gt;planner_node&lt;/code&gt;, &lt;code&gt;expense_node&lt;/code&gt;, etc.), which binds the appropriate tools and runs a tool-call loop (up to 5 rounds). The LLM's system prompt always includes the caller's &lt;code&gt;user_id&lt;/code&gt; so every tool call writes to the right user's data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance on Pi
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;hive-fast&lt;/code&gt; Modelfile tunes Gemma 2 2B with &lt;code&gt;num_ctx 2048&lt;/code&gt;, &lt;code&gt;num_thread 4&lt;/code&gt;, &lt;code&gt;temperature 0.2&lt;/code&gt; — responses arrive in &lt;strong&gt;2–4 s&lt;/strong&gt; on the Pi's ARM Cortex-A72 CPU.&lt;/p&gt;

&lt;p&gt;A keyword intent classifier avoids an additional LLM call before the model is invoked, cutting out the extra 4–7 s that a second "classify intent" LLM call would cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Voice pipeline
&lt;/h3&gt;

&lt;p&gt;Whisper's &lt;code&gt;base.en&lt;/code&gt; model runs as a subprocess via &lt;code&gt;openai-whisper&lt;/code&gt; (not &lt;code&gt;faster-whisper&lt;/code&gt;, which has a C extension that fails to build on Python 3.13 + aarch64 + FFmpeg 6.x). Audio is uploaded as WebM, converted by ffmpeg, and transcribed in ~2 s.&lt;/p&gt;




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

&lt;p&gt;A closed API version of this — GPT-4o + a hosted database — would cost money every month and would mean every family member's schedule, spending habits, and daily priorities live on someone else's server.&lt;/p&gt;

&lt;p&gt;Open weights made it possible to run a capable model on a ₹7,000 single-board computer that sits on a shelf and consumes 5–8 W. The entire stack — model weights, inference runtime, agent framework, voice transcription — is open source. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt;: no application data needs to leave the home network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: the ongoing infrastructure cost is essentially electricity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Longevity&lt;/strong&gt;: no API key to rotate, no service to deprecate, no pricing change to break the family's workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizability&lt;/strong&gt;: the &lt;code&gt;Modelfile&lt;/code&gt; lets us tune the model's personality, context size, and stop tokens without touching the inference server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open innovation didn't just make this cheaper — it made it possible to build a private AI assistant that can live in the home.&lt;/p&gt;




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

&lt;p&gt;&lt;em&gt;Built with &lt;a href="https://claude.com/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt; — iterative development over multiple sessions: architecture → scaffolding → Pi deployment → bug fixes → performance tuning.&lt;/em&gt;&lt;/p&gt;




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

&lt;h3&gt;
  
  
  Gemma — Best Use of Gemma 🏆
&lt;/h3&gt;

&lt;p&gt;Hive runs &lt;strong&gt;Gemma 2 2B&lt;/strong&gt; as its core reasoning model — fully locally on a Raspberry Pi 4B, with no cloud LLM calls or API key required.&lt;/p&gt;

&lt;p&gt;The model is loaded via &lt;a href="https://ollama.com/" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; and wrapped in a custom &lt;code&gt;Modelfile&lt;/code&gt; (&lt;code&gt;hive-fast&lt;/code&gt;) that tunes it for the Pi's constraints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="n"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;gemma2&lt;/span&gt;:&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;PARAMETER&lt;/span&gt; &lt;span class="n"&gt;num_ctx&lt;/span&gt; &lt;span class="m"&gt;2048&lt;/span&gt;     &lt;span class="c"&gt;# fits chat history + tool responses
&lt;/span&gt;&lt;span class="n"&gt;PARAMETER&lt;/span&gt; &lt;span class="n"&gt;num_thread&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;     &lt;span class="c"&gt;# all 4 Pi CPU cores
&lt;/span&gt;&lt;span class="n"&gt;PARAMETER&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;.&lt;span class="m"&gt;2&lt;/span&gt;  &lt;span class="c"&gt;# decisive, low-variance answers
&lt;/span&gt;&lt;span class="n"&gt;PARAMETER&lt;/span&gt; &lt;span class="n"&gt;repeat_penalty&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;.&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;PARAMETER&lt;/span&gt; &lt;span class="n"&gt;stop&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;end_of_turn&amp;gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gemma 2 2B handles all three AI tasks in Hive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agentic tool calls&lt;/strong&gt; — understands the user's natural-language request and generates the arguments needed for tools such as &lt;code&gt;log_expense&lt;/code&gt;, &lt;code&gt;create_event&lt;/code&gt;, and &lt;code&gt;get_open_tasks&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Priority scoring&lt;/strong&gt; — reads a JSON list of upcoming events and expenses, scores each 0–1 by urgency and deadline proximity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;General conversation&lt;/strong&gt; — answers follow-up questions and summarises the day&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The keyword classifier routes intent without another LLM call, so Gemma only needs to run for the actual reasoning/tool-use step.&lt;/p&gt;

&lt;p&gt;On Pi 4B (ARM Cortex-A72, 4 cores, 8 GB), first-token latency is typically &lt;strong&gt;2–4 s&lt;/strong&gt; — fast enough for a family assistant that people can use throughout the day.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture at a Glance
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         ┌──────────────────┐
                         │   Family Device  │
                         │ Phone / Laptop   │
                         └────────┬─────────┘
                                  │
                                  ▼
                         ┌──────────────────┐
                         │     FastAPI      │
                         │   Hive Backend   │
                         └────────┬─────────┘
                                  │
                         ┌────────▼─────────┐
                         │ Keyword Intent   │
                         │    Classifier    │
                         └────────┬─────────┘
                                  │
                                  ▼
                         ┌──────────────────┐
                         │    LangGraph     │
                         │ Agent Orchestrator│
                         └────────┬─────────┘
                                  │
                         ┌────────▼─────────┐
                         │    Gemma 2 2B    │
                         │      Ollama      │
                         └────────┬─────────┘
                                  │
                         ┌────────▼─────────┐
                         │   Hive Tools     │
                         │ Events / Expense │
                         │ Priorities / etc │
                         └────────┬─────────┘
                                  │
                         ┌────────▼─────────┐
                         │      SQLite      │
                         │   Local Storage  │
                         └──────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;Hive started with a simple idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Build something useful for the people around me, not just another AI demo.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It became an experiment in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local AI&lt;/li&gt;
&lt;li&gt;Small Language Models&lt;/li&gt;
&lt;li&gt;Agentic workflows&lt;/li&gt;
&lt;li&gt;Raspberry Pi inference&lt;/li&gt;
&lt;li&gt;Voice AI&lt;/li&gt;
&lt;li&gt;Privacy-first software&lt;/li&gt;
&lt;li&gt;Multi-user AI systems&lt;/li&gt;
&lt;li&gt;Open-source infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And most importantly, it became something my family can actually use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI doesn't always need a data center. Sometimes it can live on a Raspberry Pi sitting on a shelf at home. 🐝&lt;/strong&gt;&lt;/p&gt;




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

&lt;p&gt;🐙 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/kondekarshubham123/Hive" rel="noopener noreferrer"&gt;https://github.com/kondekarshubham123/Hive&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🎥 &lt;strong&gt;YouTube Demo:&lt;/strong&gt; &lt;a href="https://youtu.be/ykFI4QWlZVs" rel="noopener noreferrer"&gt;https://youtu.be/ykFI4QWlZVs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🏆 &lt;strong&gt;Hacktoberfest Challenge:&lt;/strong&gt; &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;https://dev.to/challenges/hacktoberfest-weekend-2026-10-01&lt;/a&gt;&lt;/p&gt;

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