<?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: Kavyansh Kumar Baghel</title>
    <description>The latest articles on DEV Community by Kavyansh Kumar Baghel (@krish007code).</description>
    <link>https://dev.to/krish007code</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%2F4162389%2Fd0549695-0492-418c-9011-2fa30efde866.jpg</url>
      <title>DEV Community: Kavyansh Kumar Baghel</title>
      <link>https://dev.to/krish007code</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/krish007code"/>
    <language>en</language>
    <item>
      <title>Invoice Sorter: a private expense tracker for freelancers that runs on a laptop</title>
      <dc:creator>Kavyansh Kumar Baghel</dc:creator>
      <pubDate>Thu, 15 Oct 2026 10:45:06 +0000</pubDate>
      <link>https://dev.to/krish007code/invoice-sorter-a-private-expense-tracker-for-freelancers-that-runs-on-a-laptop-2eoj</link>
      <guid>https://dev.to/krish007code/invoice-sorter-a-private-expense-tracker-for-freelancers-that-runs-on-a-laptop-2eoj</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;&lt;strong&gt;Invoice Sorter&lt;/strong&gt; is a small command-line tool for freelancers. You point it at a folder of PDF invoices and receipts, and it writes one clean &lt;code&gt;expenses.csv&lt;/code&gt; with vendor, date, total, currency and category.&lt;/p&gt;

&lt;p&gt;The people who would pay for it are freelancers, consultants and small studios who lose a weekend at tax time retyping receipts into a spreadsheet. Their invoices contain client names and amounts, so many of them don't want to upload those to a cloud service. Invoice Sorter does the whole job on their own laptop, so the data never leaves it.&lt;/p&gt;

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

&lt;p&gt;Terminal recording (8 sample invoices in, &lt;code&gt;expenses.csv&lt;/code&gt; out, about 45 seconds, all local): &lt;a href="https://asciinema.org/a/CWEnTFK4dQxtn78a" rel="noopener noreferrer"&gt;https://asciinema.org/a/CWEnTFK4dQxtn78a&lt;/a&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/krish007code" rel="noopener noreferrer"&gt;
        krish007code
      &lt;/a&gt; / &lt;a href="https://github.com/krish007code/invoice-sorter" rel="noopener noreferrer"&gt;
        invoice-sorter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Local invoice/receipt sorter for freelancers: PDFs in, expenses.csv out, powered by Ollama
    &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;Local Invoice Sorter&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Freelancers and solo consultants who would pay for a lightweight bookkeeping helper can use this local invoice sorter to turn text-based PDF invoices and receipts into a tidy expense CSV, without hand-copying vendors, dates, totals, currencies, and categories. It saves time on repetitive expense entry while keeping client and financial documents on their own laptop.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why local and open&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Documents are read locally and sent only to your local Ollama instance, so client data never leaves your laptop. After downloading a model, processing works offline and has zero per-document API cost. The model is swappable through an environment variable, so you can use the open-weight model that works best for your machine without vendor lock-in. Extraction uses an LLM for extraction, rules as a safety net for common category keywords.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Requirements&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.astral.sh/uv/" rel="nofollow noopener noreferrer"&gt;uv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ollama.com/" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt; running locally&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup and usage&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;uv sync
ollama pull qwen2.5:3b
uv run make_samples.py
uv&lt;/pre&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/krish007code/invoice-sorter" 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;qwen2.5:3b&lt;/code&gt;, an open-weight model, served locally by &lt;strong&gt;Ollama&lt;/strong&gt;. It runs on my 16 GB laptop with no GPU.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline:&lt;/strong&gt; &lt;code&gt;pdfplumber&lt;/code&gt; pulls the text out of each PDF. The model returns structured JSON (vendor, date, total, currency, category) in JSON mode at temperature 0. Polars writes the CSV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM for extraction, rules as a safety net:&lt;/strong&gt; The small model handled vendors, dates, totals and currencies well, including summing an invoice with two line items. Categories were its weak spot. On the first run it labelled almost everything "services", and after I rewrote the prompt with definitions and examples it still invented a category called "hosting" for a DigitalOcean invoice. I added a short keyword-rules fallback (under 25 lines) that corrects invalid or implausible categories. All 8 sample invoices now come out right.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed:&lt;/strong&gt; on a CPU-only laptop it processes about one invoice every 5-6 seconds (8 invoices in about 45 seconds, measured from the demo recording). That's plenty for a freelancer's monthly batch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configurable:&lt;/strong&gt; the model comes from an &lt;code&gt;OLLAMA_MODEL&lt;/code&gt; environment variable and the output file from a &lt;code&gt;--out&lt;/code&gt; flag, so trying Llama or Phi is a one-line change.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy:&lt;/strong&gt; client invoices never leave the laptop. There is no upload and no third-party API to trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; there is no per-document fee. Running 500 receipts at tax time costs nothing beyond electricity, which makes a low price viable for a side hustle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Offline:&lt;/strong&gt; the pipeline makes no cloud calls, so once the model is pulled it works without internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lock-in:&lt;/strong&gt; I can swap Qwen, Llama or Phi without rewriting anything, and no vendor can change the pricing under me.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tinkering:&lt;/strong&gt; because I run the model myself, I could see exactly where it failed (categories) and fix it with prompts plus rules. With a closed API I'd be stuck with whatever it returned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honest limits:&lt;/strong&gt; it only reads text-based PDFs (scans need OCR), and a 3B model can still mislabel edge cases. Next up: OCR with Tesseract, Excel export, GST-ready columns and a watch-folder mode.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>My Friend Has Five ChatGPT Accounts and Zero Shared Memory, So I Built LocalClip</title>
      <dc:creator>Kavyansh Kumar Baghel</dc:creator>
      <pubDate>Mon, 05 Oct 2026 15:06:22 +0000</pubDate>
      <link>https://dev.to/krish007code/y-friend-has-five-chatgpt-accounts-and-zero-shared-memory-so-i-built-localclip-1jhn</link>
      <guid>https://dev.to/krish007code/y-friend-has-five-chatgpt-accounts-and-zero-shared-memory-so-i-built-localclip-1jhn</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;LocalClip&lt;/strong&gt; is a local-first memory for ChatGPT. I built it for my friend mushe, who uses several free ChatGPT accounts. Each account is a silo, so when he hits a limit and switches, he has to re-explain everything from scratch.&lt;/p&gt;

&lt;p&gt;LocalClip captures his chats automatically and turns them into a linked Obsidian vault on his own machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Tampermonkey userscript captures each ChatGPT turn and tags it with an account label.&lt;/li&gt;
&lt;li&gt;A local Python server queues the turns, and a local model extracts a title, topic and bullets for each one.&lt;/li&gt;
&lt;li&gt;The vault gets one note per turn, with Prev/Next links and a hub note per topic that merges turns from every account.&lt;/li&gt;
&lt;li&gt;A handoff command (&lt;code&gt;python -m server.handoff --topic "..."&lt;/code&gt;) builds a brief he can paste into a fresh chat to continue where he left off.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;His problem was never "move to another AI provider". It was "my context is scattered across accounts, and I don't want it on someone else's server."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What already exists:&lt;/strong&gt; I compared this with the native memory-import tools from Anthropic and Google, browser extensions like MemoryPlugin and Promptive Sentry, hosted memory services, and the open-source OmniContext. Most of them handle switching between providers, often through a cloud service. LocalClip targets several accounts on one provider, with automatic capture and fully local storage. I'm not claiming it's the first tool in this space.&lt;/p&gt;

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

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

&lt;p&gt;&lt;em&gt;LocalClip running on my machine: captured ChatGPT turns turned into linked notes in the Obsidian vault.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The workflow in short: chat as usual, LocalClip captures each closed turn, the vault updates with notes and topic hubs, and &lt;code&gt;python -m server.handoff --topic "Quantum Computing"&lt;/code&gt; writes a brief he can paste into a fresh chat.&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/krish007code" rel="noopener noreferrer"&gt;
        krish007code
      &lt;/a&gt; / &lt;a href="https://github.com/krish007code/localclip" rel="noopener noreferrer"&gt;
        localclip
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      this is a ease tool that let you utilize multiple chatgpt free acounts and save that context in form of obsidian knowledge graph make it easy to interpret for human and ai agents
    &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;LocalClip&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Capture ChatGPT conversations turn by turn into a local Obsidian vault — with
&lt;code&gt;[[wiki links]]&lt;/code&gt;, Prev/Next navigation, and topic hubs. Processed by a local
LLM (Ollama). Nothing leaves your machine.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Quick start&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;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; 1. Clone and enter the repo&lt;/span&gt;
git clone &lt;span class="pl-k"&gt;&amp;lt;&lt;/span&gt;repo-url&lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt; localclip
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; localclip
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; 2. Create your personal config&lt;/span&gt;
cp config.example.json config.json

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; 3. Generate a token — paste it in BOTH places shown below&lt;/span&gt;
openssl rand -hex 16

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;   → open config.json and set:  "token": "&amp;lt;your-token&amp;gt;"&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;   → open userscript/localclip.user.js and set:  const TOKEN = "&amp;lt;your-token&amp;gt;";&lt;/span&gt;

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; 4. Install Ollama and pull a model (first time only)&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;   https://ollama.com/download&lt;/span&gt;
ollama pull llama3.2

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; 5. Start the LocalClip server&lt;/span&gt;
uv run python -m server.server

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; 6. Install the userscript in Tampermonkey&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;   a. Open Tampermonkey → Dashboard → click the + tab&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;   b. Delete the placeholder code&lt;/span&gt;
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;   c. Paste the entire contents&lt;/span&gt;&lt;/pre&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/krish007code/localclip" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The userscript's token is a placeholder in the repo. Each user generates their own with &lt;code&gt;openssl rand -hex 16&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Built with Kiro as the coding agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open-source AI:&lt;/strong&gt; the model is &lt;code&gt;llama3.2&lt;/code&gt;, run locally through Ollama. It reads each closed turn and returns JSON with a title, topic and bullet points.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Capture:&lt;/strong&gt; a Tampermonkey userscript reads the ChatGPT page, converts messages to markdown with Turndown, and posts them to &lt;code&gt;127.0.0.1&lt;/code&gt; with a token.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server:&lt;/strong&gt; a local Python server dedupes and queues each turn. A turn counts as complete once the next question exists, so no streaming detection is needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage:&lt;/strong&gt; an append-only &lt;code&gt;nodes.jsonl&lt;/code&gt;. The &lt;code&gt;next&lt;/code&gt; link is derived, never stored.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rendering:&lt;/strong&gt; the LLM returns JSON only, and my code writes every file. That keeps a small local model's output predictable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accounts:&lt;/strong&gt; the label is part of the dedupe key, so the same conversation from two accounts stays distinct. Topic hubs merge all accounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handoff:&lt;/strong&gt; the brief is built deterministically from stored nodes, ordered by time across accounts. No extra model call is needed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bugs I hit and fixed:&lt;/strong&gt; a wrong Turndown &lt;code&gt;@require&lt;/code&gt; path, an import error from running the server directly, slow Ollama calls causing timeouts, resends and duplicate nodes (fixed with a queue and idempotency), and over-aggressive LLM skipping (now gated in code). The project has 199 passing tests (162 Python, 37 Node).&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Tested live with one account so far. The multi-account path is covered by unit tests but not yet by two live accounts.&lt;/li&gt;
&lt;li&gt;ChatGPT only. The Claude and Gemini selectors are stubs.&lt;/li&gt;
&lt;li&gt;It depends on ChatGPT's page structure, which can change.&lt;/li&gt;
&lt;li&gt;The account label is set per browser profile, so he needs one profile per account.&lt;/li&gt;
&lt;li&gt;It needs Ollama and a running local server, which is more setup than an extension.&lt;/li&gt;
&lt;li&gt;A small local model produces plainer summaries than a hosted one.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;My friend's chats are personal: study notes, half-formed ideas, questions he'd rather not hand to another company. Because the model runs locally, LocalClip never sends his chats anywhere beyond the ChatGPT page he already uses.&lt;/p&gt;

&lt;p&gt;A closed API would have meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;his conversations leaving his machine again just to be summarized,&lt;/li&gt;
&lt;li&gt;a per-call cost or rate limit, for someone who is already working around free-tier limits,&lt;/li&gt;
&lt;li&gt;no way for him to inspect or change what happens to his data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With an open model, he can swap &lt;code&gt;llama3.2&lt;/code&gt; for any model Ollama runs, read every line of the code, and keep working offline.&lt;/p&gt;

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