<?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: Anirudh</title>
    <description>The latest articles on DEV Community by Anirudh (@anirudh_shivam).</description>
    <link>https://dev.to/anirudh_shivam</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%2F4048559%2Fd4e6bece-29ec-40bf-a68f-8af55e861388.png</url>
      <title>DEV Community: Anirudh</title>
      <link>https://dev.to/anirudh_shivam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anirudh_shivam"/>
    <language>en</language>
    <item>
      <title>I Built a Coding Agent That Runs on a 1.7B Model</title>
      <dc:creator>Anirudh</dc:creator>
      <pubDate>Fri, 02 Oct 2026 08:41:29 +0000</pubDate>
      <link>https://dev.to/anirudh_shivam/i-built-a-coding-agent-that-runs-on-a-17b-model-219p</link>
      <guid>https://dev.to/anirudh_shivam/i-built-a-coding-agent-that-runs-on-a-17b-model-219p</guid>
      <description>&lt;p&gt;I've been interested in local AI for a while, especially running AI models on hardware that isn't exactly a massive AI workstation.&lt;/p&gt;

&lt;p&gt;At some point, I started wondering:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How useful could a coding agent be if it had to run on a tiny local model?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I decided to build one.&lt;/p&gt;

&lt;p&gt;That's how &lt;strong&gt;MINICODE&lt;/strong&gt; started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ANIRudH-lab-life/MINICODE" rel="noopener noreferrer"&gt;GitHub — MINICODE&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is MINICODE?
&lt;/h2&gt;

&lt;p&gt;MINICODE is a terminal-based AI coding agent that I built around small local language models.&lt;/p&gt;

&lt;p&gt;The default setup uses &lt;strong&gt;Qwen3 1.7B through Ollama&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal isn't to compete with massive cloud models.&lt;/p&gt;

&lt;p&gt;Instead, I wanted to experiment with making a &lt;strong&gt;small model actually useful&lt;/strong&gt; by giving it tools and letting it interact with a coding environment.&lt;/p&gt;

&lt;p&gt;It can work with files, run commands, search the web, maintain conversation context, and interact with the project it's being used in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why 1.7B?
&lt;/h2&gt;

&lt;p&gt;I don't have some giant GPU server sitting under my desk.&lt;/p&gt;

&lt;p&gt;I wanted something that could run locally and be relatively lightweight.&lt;/p&gt;

&lt;p&gt;A 1.7B model is obviously limited compared with much larger models, but that's actually what makes the experiment interesting.&lt;/p&gt;

&lt;p&gt;Instead of solving everything by throwing a bigger model at the problem, I wanted to see how much I could improve the experience through the &lt;strong&gt;agent itself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The model doesn't have to do everything alone.&lt;/p&gt;

&lt;p&gt;MINICODE can give it tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the agent
&lt;/h2&gt;

&lt;p&gt;One of the first things I learned is that building an AI coding agent is very different from just making a chatbot.&lt;/p&gt;

&lt;p&gt;A chatbot can generate a response.&lt;/p&gt;

&lt;p&gt;An agent needs to interact with the world.&lt;/p&gt;

&lt;p&gt;For example, if I ask MINICODE to modify a project, the model needs to figure out what files it needs, inspect them, make changes, and potentially run commands to test those changes.&lt;/p&gt;

&lt;p&gt;That creates a loop something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User
 ↓
Model
 ↓
Tool call
 ↓
Tool executes
 ↓
Result goes back to model
 ↓
Model decides what to do next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Getting that loop working reliably was one of the most interesting parts of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  I didn't want the AI to have unlimited control
&lt;/h2&gt;

&lt;p&gt;Another thing I cared about was safety.&lt;/p&gt;

&lt;p&gt;Giving an AI access to a terminal means it could potentially execute commands that you didn't intend.&lt;/p&gt;

&lt;p&gt;So MINICODE asks for confirmation before performing potentially dangerous actions.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI → execute command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it's more like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI → "I want to execute this command"
             ↓
        You approve?
          ↙     ↘
        Yes      No
         ↓        ↓
     Execute    Tell AI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I reject an action, the model gets that information and can try another approach.&lt;/p&gt;

&lt;p&gt;It's a simple system, but I think keeping a human in the loop is important when experimenting with autonomous tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  I also built memory
&lt;/h2&gt;

&lt;p&gt;I wanted coding sessions to be persistent rather than disappearing when I closed the terminal.&lt;/p&gt;

&lt;p&gt;MINICODE can save conversations so I can come back to them later.&lt;/p&gt;

&lt;p&gt;That means I can work on something, save the session, and continue working on it another time.&lt;/p&gt;

&lt;p&gt;It's not some incredibly sophisticated long-term memory system, but it makes the agent much more practical to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making installation easy
&lt;/h2&gt;

&lt;p&gt;I also wanted someone to be able to try the project without spending an hour setting everything up.&lt;/p&gt;

&lt;p&gt;So I made an installer that handles the initial setup.&lt;/p&gt;

&lt;p&gt;The basic idea is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/ANIRudH-lab-life/MINICODE/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The default configuration uses Ollama and Qwen3 1.7B, so you can start experimenting with a local coding agent without needing a cloud API.&lt;/p&gt;

&lt;h2&gt;
  
  
  The funny part: small models are hard
&lt;/h2&gt;

&lt;p&gt;Working with a 1.7B model has actually made me learn more about agents.&lt;/p&gt;

&lt;p&gt;With a larger model, you can sometimes get away with a mediocre prompt or imperfect tool design.&lt;/p&gt;

&lt;p&gt;With a small model, those problems become obvious.&lt;/p&gt;

&lt;p&gt;If the tools aren't designed properly, it struggles.&lt;/p&gt;

&lt;p&gt;If the context gets messy, it struggles.&lt;/p&gt;

&lt;p&gt;If an error isn't explained clearly, it can get stuck.&lt;/p&gt;

&lt;p&gt;That means I have to think much more carefully about how the &lt;strong&gt;agent architecture&lt;/strong&gt; works.&lt;/p&gt;

&lt;p&gt;And that's probably been one of the most valuable parts of building MINICODE.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's still a work in progress
&lt;/h2&gt;

&lt;p&gt;MINICODE is nowhere near finished.&lt;/p&gt;

&lt;p&gt;There are still plenty of things I want to improve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better tool calling&lt;/li&gt;
&lt;li&gt;Better context management&lt;/li&gt;
&lt;li&gt;More reliable coding&lt;/li&gt;
&lt;li&gt;Better error handling&lt;/li&gt;
&lt;li&gt;More model support&lt;/li&gt;
&lt;li&gt;Improved terminal UI&lt;/li&gt;
&lt;li&gt;Better memory&lt;/li&gt;
&lt;li&gt;More autonomous workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I don't really see that as a problem.&lt;/p&gt;

&lt;p&gt;The whole point of the project is experimentation.&lt;/p&gt;

&lt;p&gt;I want to keep seeing how far I can push small local models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm building this
&lt;/h2&gt;

&lt;p&gt;For me, MINICODE is more than just another AI wrapper.&lt;/p&gt;

&lt;p&gt;I'm interested in what happens when you take a relatively small model and give it the right environment, tools, and architecture.&lt;/p&gt;

&lt;p&gt;Maybe the future of local AI isn't always about running the biggest model possible.&lt;/p&gt;

&lt;p&gt;Maybe sometimes it's about making &lt;strong&gt;smaller models work better&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's what I'm trying to find out.&lt;/p&gt;

&lt;p&gt;If you want to check it out, the entire project is open source:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ANIRudH-lab-life/MINICODE" rel="noopener noreferrer"&gt;https://github.com/ANIRudH-lab-life/MINICODE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to see what other people can do with it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>python</category>
      <category>llm</category>
    </item>
    <item>
      <title>Under the Hood of JobRadar: 8 Job Sources, a 1.7B Model, Zero Cloud</title>
      <dc:creator>Anirudh</dc:creator>
      <pubDate>Sun, 02 Aug 2026 05:28:42 +0000</pubDate>
      <link>https://dev.to/anirudh_shivam/under-the-hood-of-jobradar-8-job-sources-a-17b-model-zero-cloud-3gne</link>
      <guid>https://dev.to/anirudh_shivam/under-the-hood-of-jobradar-8-job-sources-a-17b-model-zero-cloud-3gne</guid>
      <description>&lt;p&gt;Job searching is tab hell. You open six boards, re-read the same listings, and pay $30/month for tools that are just feed aggregators wearing an "AI-powered" sticker.&lt;/p&gt;

&lt;p&gt;So I built JobRadar — a CLI tool that searches 8 job sources concurrently and scores every listing against your profile using a local LLM that runs on your own CPU. No API keys, no subscriptions, no resume leaving your machine.&lt;/p&gt;

&lt;p&gt;The launch post covered the what. This one covers the how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline
&lt;/h2&gt;

&lt;p&gt;The whole thing is one linear pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query + profile.yaml
      │
      ▼
8 source adapters (concurrent) ──► normalized Job objects
      │
      ▼
local LLM scores each job 0-100 (skills, experience, salary, remote fit)
      │
      ▼
seen-jobs cache (SQLite, 7-day)  ──► ranked table + results.csv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In code, the search phase looks like this:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;concurrent.futures&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;as_completed&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_pages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ThreadPoolExecutor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;futures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_pages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
                   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sources&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;future&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;as_completed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;futures&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;future&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;result&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;jobs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eight adapters, one interface, all running in parallel. A query that used to take me 20 minutes of tab-hopping finishes in under a minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  The sources: boards vs. direct ATS
&lt;/h2&gt;

&lt;p&gt;Five of the sources are classic job board APIs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Remotive&lt;/strong&gt; — remote jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arbeitnow&lt;/strong&gt; — worldwide, paginated&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RemoteOK&lt;/strong&gt; — remote, good volume&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobicy&lt;/strong&gt; — remote with salary data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Himalayas&lt;/strong&gt; — remote with seniority levels&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interesting two are &lt;strong&gt;Greenhouse&lt;/strong&gt; and &lt;strong&gt;Ashby&lt;/strong&gt;. These are applicant tracking systems that a huge chunk of tech companies use — and they have public career-page APIs. No auth, no scraping. You just hit their job board endpoint with a company slug:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreenhouseSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Source&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;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_pages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;jobs&lt;/span&gt; &lt;span class="o"&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;company&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;companies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="c1"&gt;# e.g. gitlab, figma, stripe
&lt;/span&gt;            &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://boards-api.greenhouse.io/v1/boards/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/jobs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;normalize_greenhouse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;jobs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means JobRadar pulls roles straight from company career pages — GitLab, Figma, Stripe, OpenAI, Anthropic, Linear — without an account or an API key on any of them. The company list is a YAML file you can edit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;greenhouse&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gitlab&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;figma&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;discord&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;shopify&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;stripe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LinkedIn scraping exists but is &lt;strong&gt;off by default&lt;/strong&gt; — it depends on undocumented HTML that breaks constantly, and it might violate their ToS. I'd rather ship without it and be honest about the tradeoff than bundle a ToS risk into the default path.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rating engine: a 1.7B model on your CPU
&lt;/h2&gt;

&lt;p&gt;This is the part people ask about the most. Every other tool I found uses cloud APIs (Claude, OpenAI) for scoring — your resume and search history go to someone else's server, and you pay per token. JobRadar runs &lt;strong&gt;qwen3-1.7b&lt;/strong&gt; (a 1.1 GB GGUF) on your machine via Ollama or llama.cpp.&lt;/p&gt;

&lt;p&gt;The rater auto-detects whatever local LLM server is running by scanning the standard ports:&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;_DEFAULT_PORTS&lt;/span&gt; &lt;span class="o"&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;http://localhost:11434&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;Ollama&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;    &lt;span class="c1"&gt;# Ollama default
&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8080&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;llama.cpp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;# llama.cpp default
&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:1234&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;LM Studio&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;# LM Studio default
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have a bigger model installed, it picks that up too — you can override with &lt;code&gt;--llm-model qwen3:8b&lt;/code&gt; and scoring gets smarter at the cost of speed.&lt;/p&gt;

&lt;p&gt;Each job gets scored 0-100 across four dimensions — skills match, experience fit, salary fit, remote fit — with the model's reasoning captured so you can see &lt;em&gt;why&lt;/em&gt; a job scored the way it did. Rating calls run concurrently (3 by default, &lt;code&gt;--max-concurrency&lt;/code&gt; to tune) with retry logic for the occasional malformed JSON response.&lt;/p&gt;

&lt;p&gt;Honest take: a 1.7B model is a good filter, not an oracle. It catches "this says Python but is actually a sales role" reliably. It does not have your gut feel about company culture, and it shouldn't — that's the point. The score is a starting point, not a verdict.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cache: don't re-review the same jobs
&lt;/h2&gt;

&lt;p&gt;Job boards republish the same listings constantly. JobRadar keeps a SQLite database of seen jobs (&lt;code&gt;~/.jobradar/seen_jobs.db&lt;/code&gt;) with a 7-day window, so every run only surfaces what's new. &lt;code&gt;--cache-days 30&lt;/code&gt; to stretch it, &lt;code&gt;--no-cache&lt;/code&gt; to see everything again.&lt;/p&gt;

&lt;h2&gt;
  
  
  The dashboard: FastAPI + vanilla JS
&lt;/h2&gt;

&lt;p&gt;The CLI is the core, but there's a companion web dashboard — a FastAPI backend, SQLite storage, and a dark-mode SPA with a Kanban pipeline. Jobs flow from Discovered to Reviewing to Applied to Interviewing, cards are color-coded by match score, and there's a live terminal-style activity log showing the LLM scoring progress as it happens. It reads like a terminal because the whole product is terminal-first.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd tell someone building this
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Normalize early.&lt;/strong&gt; Every source returns a different shape. Map everything to one &lt;code&gt;Job&lt;/code&gt; dataclass at the boundary and every downstream step gets simpler.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design for the offline case.&lt;/strong&gt; Local LLMs are fast enough for filtering, and "no cloud, no cost, no data leaving the machine" is a genuinely defensible product position, not a compromise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Be honest about limitations.&lt;/strong&gt; The README says it plainly: the AI is a guide, not a decision-maker. That honesty has been the most effective marketing I've done — people respond to tools that don't oversell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct ATS APIs are underrated.&lt;/strong&gt; Board aggregators are a race to the bottom; the companies themselves publish better, fresher data through their ATS.&lt;/li&gt;
&lt;/ol&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;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/ANIRudH-lab-life/job-radar/main/setup.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or browse the source: &lt;a href="https://github.com/ANIRudH-lab-life/job-radar" rel="noopener noreferrer"&gt;https://github.com/ANIRudH-lab-life/job-radar&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Landing page: &lt;a href="https://anirudh-lab-life.github.io/job-radar/" rel="noopener noreferrer"&gt;https://anirudh-lab-life.github.io/job-radar/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MIT licensed. Built with Python, Rich, FastAPI, SQLite, and a whole lot of tabs closed.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Also published: &lt;a href="https://dev.to/anirudh_shivam/i-built-a-job-search-agent-that-scores-200-jobs-with-local-ai-zero-cloud-zero-cost-21lk"&gt;the launch post&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>ai</category>
      <category>architecture</category>
    </item>
    <item>
      <title>I Built a Job Search Agent That Scores 200 Jobs With Local AI -- Zero Cloud, Zero Cost</title>
      <dc:creator>Anirudh</dc:creator>
      <pubDate>Mon, 27 Jul 2026 02:36:02 +0000</pubDate>
      <link>https://dev.to/anirudh_shivam/i-built-a-job-search-agent-that-scores-200-jobs-with-local-ai-zero-cloud-zero-cost-21lk</link>
      <guid>https://dev.to/anirudh_shivam/i-built-a-job-search-agent-that-scores-200-jobs-with-local-ai-zero-cloud-zero-cost-21lk</guid>
      <description>&lt;p&gt;Job searching is tab hell.&lt;/p&gt;

&lt;p&gt;You open LinkedIn, Indeed, RemoteOK, Glassdoor. You re-read the same listings. You copy-paste the same cover letter. You pay $30/month for tools that just aggregate feeds and call it "AI-powered."&lt;/p&gt;

&lt;p&gt;I wanted something better. So I built JobRadar.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Does
&lt;/h2&gt;

&lt;p&gt;JobRadar is a CLI tool that searches 8 job sources concurrently and scores every listing against your profile using a local LLM running on your machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; jobradar &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"python developer"&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; profile.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Eight boards searched in parallel. Every job scored 0-100. Results saved to CSV. Total time: under a minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Local AI Angle
&lt;/h2&gt;

&lt;p&gt;Every other job search tool I found uses cloud APIs for scoring -- OpenAI, Claude, whatever. Which means your resume, your search history, your career preferences all go to someone else's server. And you pay per token.&lt;/p&gt;

&lt;p&gt;JobRadar runs qwen3-1.7b (1.1 GB) on your CPU via Ollama. No API keys. No subscriptions. No data leaving your machine. The AI scores each job on four dimensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Skills match&lt;/strong&gt; -- do you have what they need?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experience fit&lt;/strong&gt; -- does your level match?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Salary fit&lt;/strong&gt; -- does it meet your range?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote fit&lt;/strong&gt; -- does it match your preference?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each job gets a score, a rating (Excellent/Good/Fair/Poor), and a reasoning paragraph explaining why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 8 Sources
&lt;/h2&gt;

&lt;p&gt;Most job search tools scrape 1-2 boards. JobRadar hits 8 simultaneously:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Remotive&lt;/strong&gt; -- remote jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RemoteOK&lt;/strong&gt; -- remote-first jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobicy&lt;/strong&gt; -- remote jobs with salary data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Himalayas&lt;/strong&gt; -- global remote jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arbeitnow&lt;/strong&gt; -- international jobs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Greenhouse ATS&lt;/strong&gt; -- 15 company career pages (GitLab, Stripe, Figma, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ashby ATS&lt;/strong&gt; -- 15 company career pages (OpenAI, Anthropic, Linear, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LinkedIn&lt;/strong&gt; -- opt-in (may violate ToS)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Greenhouse and Ashby sources pull directly from company career page APIs. No scraping, no auth, no fragility.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Scoring Works
&lt;/h2&gt;

&lt;p&gt;You define a profile YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Anirudh&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Backend Engineer&lt;/span&gt;
&lt;span class="na"&gt;skills&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Python&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FastAPI&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;PostgreSQL&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Docker&lt;/span&gt;
&lt;span class="na"&gt;experience_years&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="na"&gt;salary_min&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120000&lt;/span&gt;
&lt;span class="na"&gt;remote_ok&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JobRadar sends each job description plus your profile to the local LLM and gets back structured JSON with scores and reasoning. The model runs on your CPU -- no GPU required. On my machine (15GB RAM, no GPU), it processes about 9 seconds per job.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes This Different
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;JobRadar&lt;/th&gt;
&lt;th&gt;Cloud-based tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI scoring&lt;/td&gt;
&lt;td&gt;Local LLM (free)&lt;/td&gt;
&lt;td&gt;OpenAI API ($$)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data privacy&lt;/td&gt;
&lt;td&gt;Stays on your machine&lt;/td&gt;
&lt;td&gt;Sent to cloud&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Job sources&lt;/td&gt;
&lt;td&gt;8 concurrent&lt;/td&gt;
&lt;td&gt;1-3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web dashboard&lt;/td&gt;
&lt;td&gt;Yes (Kanban)&lt;/td&gt;
&lt;td&gt;Depends&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License&lt;/td&gt;
&lt;td&gt;MIT&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bash setup.sh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Account + API key&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;Beyond the CLI, there's a FastAPI dashboard with a Kanban-style pipeline to track your applications. Filters, search, config editor -- all running locally on port 3000.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt; with Rich for terminal UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; for local LLM inference (or llama.cpp)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; for the web dashboard&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; for caching&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;requests + BeautifulSoup&lt;/strong&gt; for scraping&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 github.com/ANIRudH-lab-life/job-radar
&lt;span class="nb"&gt;cd &lt;/span&gt;job-radar
bash setup.sh &lt;span class="c"&gt;# or setup.ps1 on Windows&lt;/span&gt;

&lt;span class="c"&gt;# Pick Ollama (recommended)&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; jobradar &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"python developer"&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; profile.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MIT licensed. No vendor lock-in. Your data stays yours.&lt;/p&gt;




&lt;p&gt;GitHub: github.com/ANIRudH-lab-life/job-radar&lt;/p&gt;

&lt;p&gt;If you find it useful, a star would mean a lot. If you have ideas for improvement, open an issue -- I read every one.&lt;/p&gt;




</description>
      <category>python</category>
      <category>opensource</category>
      <category>ai</category>
      <category>buildinpublic</category>
    </item>
  </channel>
</rss>
