<?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: David Anton Alvarez</title>
    <description>The latest articles on DEV Community by David Anton Alvarez (@virien84).</description>
    <link>https://dev.to/virien84</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%2F212069%2Fe2299311-49cb-4b1e-93b9-d7b76ee247b5.png</url>
      <title>DEV Community: David Anton Alvarez</title>
      <link>https://dev.to/virien84</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/virien84"/>
    <language>en</language>
    <item>
      <title>Read the Fine Print: a contract red-flag reviewer for freelancers that never uploads your contract</title>
      <dc:creator>David Anton Alvarez</dc:creator>
      <pubDate>Sun, 18 Oct 2026 15:24:45 +0000</pubDate>
      <link>https://dev.to/virien84/read-the-fine-print-a-contract-red-flag-reviewer-for-freelancers-that-never-uploads-your-contract-2llc</link>
      <guid>https://dev.to/virien84/read-the-fine-print-a-contract-red-flag-reviewer-for-freelancers-that-never-uploads-your-contract-2llc</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;Freelancers sign contracts written by the client's side. The traps are always the same: payment at Net 90, "unlimited revisions", IP transferred before you've been paid, no kill fee, a non-compete, unlimited liability, an auto-renewal you forget about. Most of us skim, sign, and find out later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read the Fine Print&lt;/strong&gt; is a web app for that moment before you sign. Paste the contract or drop the PDF, and every clause gets a traffic light:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔴 &lt;strong&gt;To change&lt;/strong&gt;: don't sign it as it is.&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;To negotiate&lt;/strong&gt;: common, but worth pushing back on.&lt;/li&gt;
&lt;li&gt;🟢 &lt;strong&gt;Fine&lt;/strong&gt;: nothing to do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each flagged clause comes with a plain-English explanation and a ready-to-send message asking for a fairer version. &lt;strong&gt;Copy email to client&lt;/strong&gt; puts them all into one polite email.&lt;/p&gt;

&lt;p&gt;The important part: &lt;strong&gt;the AI runs entirely in your browser.&lt;/strong&gt; Client contracts are confidential and often under NDA, so the app never sends them anywhere. No server, no account, no API key.&lt;/p&gt;

&lt;p&gt;Who would pay for it? Freelancers who sign a handful of contracts a year and can't justify a lawyer for each one. A lawyer's review costs more than many small gigs pay; a one-off purchase or a few dollars a month for a tool that catches the obvious traps is an easy sell.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://virien84.github.io/read-the-fine-print/" rel="noopener noreferrer"&gt;virien84.github.io/read-the-fine-print&lt;/a&gt; (needs WebGPU: recent Chrome or Edge on a laptop/desktop). Click &lt;strong&gt;Try a sample contract&lt;/strong&gt; to see it work without using a real one.&lt;/p&gt;

&lt;p&gt;The first visit downloads the model (~3 GB) once; after that the browser caches it and it loads in about 11 seconds. Each clause takes 7–13 seconds on my NVIDIA Turing GPU, and the bundled 13-clause sample contract is reviewed in about 2.5 minutes, with live progress as each clause comes in.&lt;/p&gt;

&lt;p&gt;On that sample, which I seeded with the classic traps, the app flags the payment terms, unlimited revisions, IP-before-payment, non-compete, liability and auto-renewal clauses. It's honest to say it isn't perfect: the termination clause only gets a yellow, and it leans strict (a fair IP clause sometimes comes back yellow instead of green). For a "read this before signing" tool, erring on the side of caution is the right failure mode.&lt;/p&gt;

&lt;p&gt;I haven't put it in front of a paying freelancer yet, so no first-user story this week.&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/Virien84" rel="noopener noreferrer"&gt;
        Virien84
      &lt;/a&gt; / &lt;a href="https://github.com/Virien84/read-the-fine-print" rel="noopener noreferrer"&gt;
        read-the-fine-print
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Read the Fine Print&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Spot the clauses that cost freelancers money, before you sign.&lt;/p&gt;
&lt;p&gt;Paste or drop a client contract and every clause gets a traffic light:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🔴 &lt;strong&gt;To change&lt;/strong&gt;: don't sign it as it is.&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;To negotiate&lt;/strong&gt;: common, but worth pushing back on.&lt;/li&gt;
&lt;li&gt;🟢 &lt;strong&gt;Fine&lt;/strong&gt;: nothing to do.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each flagged clause comes with a plain-English explanation and a ready-to-send message asking for a fairer version, and &lt;strong&gt;Copy email to client&lt;/strong&gt; puts them all in one email.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The AI runs entirely in your browser.&lt;/strong&gt; Client contracts are confidential and often under NDA, so Read the Fine Print never sends them anywhere: no server, no account, no API key.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it works&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://huggingface.co/mlc-ai/gemma-4-E2B-it-q4f16_1-MLC" rel="nofollow noopener noreferrer"&gt;Gemma 4 E2B&lt;/a&gt; via &lt;a href="https://github.com/mlc-ai/web-llm" rel="noopener noreferrer"&gt;WebLLM&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Runs on your GPU through WebGPU, in a Web Worker. Downloaded once (~3 GB) and cached by the browser. Gemma 3 1B is the fallback for&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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/Virien84/read-the-fine-print" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Vite + React, no backend.&lt;/p&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PDF / pasted text ─► pdf.js (local) ─► split into clauses
                                            │
                                            ▼
                     Gemma 4 E2B (WebLLM, WebGPU, Web Worker)
                     JSON-schema output, one clause at a time
                                            │
                                            ▼
                       🔴🟡🟢 + explanation + pushback ─► email to client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Model:&lt;/strong&gt; &lt;a href="https://huggingface.co/mlc-ai/gemma-4-E2B-it-q4f16_1-MLC" rel="noopener noreferrer"&gt;Gemma 4 E2B&lt;/a&gt; through &lt;a href="https://github.com/mlc-ai/web-llm" rel="noopener noreferrer"&gt;WebLLM&lt;/a&gt;, in a Web Worker so the page stays responsive. Gemma 3 1B is the fallback for GPUs without &lt;code&gt;shader-f16&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Constrained output:&lt;/strong&gt; every answer follows a JSON schema, so parsing never fails. The trick that mattered most: putting &lt;code&gt;explanation&lt;/code&gt; &lt;strong&gt;before&lt;/strong&gt; &lt;code&gt;level&lt;/code&gt; in the schema. When the model has to explain the clause first and only then pick a colour, its verdicts got noticeably more accurate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A checklist of known traps:&lt;/strong&gt; the prompt lists the classic freelance traps, so a small model compares against a list instead of relying on its own judgement. I also had to add a rule that the pushback must actually be better than the original (an early version "negotiated" a 60-day notice period up to 90).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clause splitting:&lt;/strong&gt; numbered clauses first, paragraph fallback, signature blocks skipped. PDFs are read locally with &lt;a href="https://mozilla.github.io/pdf.js/" rel="noopener noreferrer"&gt;pdf.js&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surviving a lost GPU:&lt;/strong&gt; on long runs Chrome sometimes loses the WebGPU device and refuses it until reload. The app parks the review in &lt;code&gt;sessionStorage&lt;/code&gt;, reloads, and resumes where it left off.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One lesson: more is not always better. I tried "red lines" (user-defined deal-breakers), an enum of trap types and a second yes/no verification pass. On the full sample, accuracy got &lt;em&gt;worse&lt;/em&gt; (the preamble got flagged, revisions got missed) and it cost twice the GPU time. I went back to the single, simple prompt.&lt;/p&gt;

&lt;p&gt;I built it with Claude Code as my coding agent.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy is the product.&lt;/strong&gt; Many contracts forbid sharing them with third parties. A cloud API is a third party. An open-weight model running on your own GPU is not, so you can review an NDA-covered contract without breaking it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The economics work.&lt;/strong&gt; No per-token bill means I can sell it cheaply (or give it away) without losing money on every review.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No lock-in.&lt;/strong&gt; If a better small open model ships next month, it's a one-line change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prior art and inspiration from the DEV community:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/agentedeia/the-5-contract-clauses-that-quietly-wreck-freelancers-and-the-exact-words-to-push-back-4omp"&gt;The 5 contract clauses that quietly wreck freelancers&lt;/a&gt; by agentedeia: the clause → pushback format.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/aldobarbosa/3-simple-contract-rules-i-use-so-clients-stop-asking-for-free-reworks-3n88"&gt;The biggest mistake I made with client contracts&lt;/a&gt; by aldobarbosa: unlimited revisions in real life.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/methezain/ocr-llm-pipeline-for-contract-review-what-actually-works-in-production-52gk"&gt;OCR + LLM Pipeline for Contract Review&lt;/a&gt; by methezain.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/zaydmulani09/i-built-a-local-llm-that-runs-entirely-in-your-browser-no-install-no-gpu-no-server-3c3c"&gt;I built a local LLM that runs entirely in your browser&lt;/a&gt; by zaydmulani09.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/__13_77/building-a-context-aware-legal-contract-analyzer-with-gemma-and-gemini-ko"&gt;Building a Context-Aware Legal Contract Analyzer with Gemma and Gemini&lt;/a&gt; by __13_77. My angle: fully local, and focused on freelancers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not legal advice.&lt;/strong&gt; For anything high-stakes, ask a lawyer.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma 4 E2B runs fully in the browser through WebGPU and does the whole review, with JSON-schema constrained output per clause.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemma</category>
      <category>webgpu</category>
    </item>
    <item>
      <title>NaturDex: a Pokédex for real nature that runs offline on a recycled phone</title>
      <dc:creator>David Anton Alvarez</dc:creator>
      <pubDate>Sun, 11 Oct 2026 01:05:05 +0000</pubDate>
      <link>https://dev.to/virien84/naturdex-a-pokedex-for-real-nature-that-runs-offline-on-a-recycled-phone-2amo</link>
      <guid>https://dev.to/virien84/naturdex-a-pokedex-for-real-nature-that-runs-offline-on-a-recycled-phone-2amo</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;We live surrounded by plants and animals we never look at. The robin on the fence, the heather on the hillside, the butterfly crossing the path. Kids walk past all of them with their eyes on a screen.&lt;/p&gt;

&lt;p&gt;So I flipped it around and used the screen to send them outside. &lt;strong&gt;NaturDex&lt;/strong&gt; is a Pokédex for real nature. You photograph a plant or an animal, and an AI model running &lt;strong&gt;on the phone&lt;/strong&gt; tells you what it is. If it's new, it goes into your NaturDex with its number, its photo and the date you found it. The goal is to fill it, and the only way to do that is to go out and look.&lt;/p&gt;

&lt;p&gt;The scenario I designed it for is a &lt;strong&gt;school field trip to the forest&lt;/strong&gt;. Schools could hand out &lt;strong&gt;recycled phones&lt;/strong&gt; (old phones everyone has in a drawer) with NaturDex installed, and the activity is to fill the NaturDex. That scenario set three hard rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No signal.&lt;/strong&gt; Forests don't have coverage, so everything has to work &lt;strong&gt;offline&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kids' privacy.&lt;/strong&gt; No accounts, no uploads. Photos and GPS positions of children never leave the phone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Old hardware, zero cost.&lt;/strong&gt; It has to run on a phone that's a few years old, with no app store and no API bill.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And, since it's for children outdoors, a fourth one: &lt;strong&gt;safety first.&lt;/strong&gt; NaturDex warns before it entertains.&lt;/p&gt;

&lt;p&gt;How a trip works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Before leaving, on wifi:&lt;/strong&gt; tap &lt;em&gt;Prepare trip&lt;/em&gt;. It downloads the model (87 MB) and the list of 1,944 species that live in the region (Asturias, in northern Spain).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;In the forest:&lt;/strong&gt; tap the big camera button. In a few seconds NaturDex answers in one of three ways: &lt;em&gt;"It's a European Robin!"&lt;/em&gt;, &lt;em&gt;"Which one is it?"&lt;/em&gt; (and the kid compares the photo with three options), or &lt;em&gt;"Hmm, I'm not sure…"&lt;/em&gt; with a tip to take a better photo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every species found&lt;/strong&gt; gets its NaturDex number (No. 0046 for the robin) and a coloured badge for its kind: bird, plant, butterfly, fungus…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why only Asturias?&lt;/strong&gt; Because it's where I live, and where I could actually use it. The AI model knows living things from all over the world, but the species list and, above all, the safety rules have to be right for the place where the kids are. Which vipers live here, which plants are poisonous, which species are protected by law: I can only vouch for that in a region I know. So I chose to do one region well instead of the whole world badly. The last section explains how other regions could join.&lt;/p&gt;

&lt;p&gt;If you don't live in Asturias, you can still try it: on a computer, the camera button opens a file picker, so you can give it any photo of a common European species, like a robin, a fly agaric or a peacock butterfly.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://virien84.github.io/naturdex/" rel="noopener noreferrer"&gt;virien84.github.io/naturdex&lt;/a&gt;. Open it on a phone, tap &lt;em&gt;Prepare trip&lt;/em&gt; on wifi, then go outside. You can also install it from the browser menu (&lt;em&gt;Install app&lt;/em&gt; / &lt;em&gt;Add to Home screen&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The design is a handheld field device: a red shell, a big blue lens that glows while the AI is thinking, a leaf-green LCD screen and chunky buttons that press down.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ready to go&lt;/th&gt;
&lt;th&gt;A confident answer&lt;/th&gt;
&lt;th&gt;Added to the NaturDex&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&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%2Fwo6rzri2mgkvqt1m1erc.jpg" alt="Camera screen" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&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%2Fkc7o7i9llga542jkh4hy.jpg" alt="It's a European Robin" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&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%2Fwnepbdujum6gkl960abc.jpg" alt="New species" width="780" height="1688"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That robin is a small bird far away, between branches, and NaturDex is still 100% sure. The shield means it's a protected species: look, but don't disturb it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safety comes first.&lt;/strong&gt; Dangerous species get a black-and-yellow hazard warning above everything else. On the right, the model isn't sure which snake it is, but one of the candidates is a snake, and that's enough to warn.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Deadly mushroom&lt;/th&gt;
&lt;th&gt;"Could it be…?"&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&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%2F2bishyd4ihm2r5z2qb6c.jpg" alt="Fly agaric warning" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&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%2Fscolawqtqitw6rlpcaeo.jpg" alt="Snake warning" width="780" height="1688"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;When the model hesitates, the kid decides.&lt;/strong&gt; It's a learning moment: compare your photo with the options. And when NaturDex really doesn't know, it says so instead of guessing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Which one is it?&lt;/th&gt;
&lt;th&gt;Not sure&lt;/th&gt;
&lt;th&gt;My NaturDex&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&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%2F2hr8sdtg2sr0kut3p0fy.jpg" alt="Which one is it" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&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%2Ff64n0f5bodfs5b7r1qzd.jpg" alt="Not sure" width="780" height="1688"&gt;&lt;/td&gt;
&lt;td&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%2Fw4jmenbq0bjjh42eyyfw.jpg" alt="Album" width="780" height="1688"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;At night the screen switches to a backlit LCD:&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%2Fl24115wn5q0zuuth5h1c.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl24115wn5q0zuuth5h1c.jpg" alt="Dark mode" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The photos in these screenshots are openly licensed iNaturalist observations from Spain (CC BY / CC0). Credits are in &lt;a href="https://github.com/Virien84/naturdex/blob/main/screenshots/CREDITS.md" rel="noopener noreferrer"&gt;screenshots/CREDITS.md&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  I took it outside
&lt;/h3&gt;

&lt;p&gt;I installed it on my phone, a mid-range Android (vivo V50 Lite), and went out to photograph trees and plants. All three answers showed up: direct identifications, "Which one is it?" with the right species among the options, and "not sure". It worked with no errors.&lt;/p&gt;

&lt;p&gt;The "not sure" one taught me something. I had photographed &lt;strong&gt;a whole tree standing among other trees&lt;/strong&gt;. The model looks at a square crop of 224×224 pixels, and in that square there were several crowns and a lot of sky, so it couldn't tell which tree I meant. It was right not to guess. So now the camera says &lt;em&gt;"For trees, photograph one leaf, flower or the bark"&lt;/em&gt;, and the "not sure" screen repeats it.&lt;/p&gt;

&lt;p&gt;The second lesson was about patience. After taking a photo, &lt;strong&gt;the app looked frozen&lt;/strong&gt;. The message "Looking closely…" existed, but the screen never got the chance to show it (more on that below). Kids would tap again, or give up. Now the lens glows and a spinner turns from the very first instant.&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/Virien84" rel="noopener noreferrer"&gt;
        Virien84
      &lt;/a&gt; / &lt;a href="https://github.com/Virien84/naturdex" rel="noopener noreferrer"&gt;
        naturdex
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;NaturDex&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;A nature "Pokémon Snap" for school field trips: photograph plants and animals and fill your NaturDex, &lt;strong&gt;fully offline&lt;/strong&gt; on recycled phones.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://virien84.github.io/naturdex/" rel="nofollow noopener noreferrer"&gt;https://virien84.github.io/naturdex/&lt;/a&gt; (open it on a phone, tap &lt;em&gt;Prepare trip&lt;/em&gt; on wifi, then go outside).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app/&lt;/code&gt; — the PWA (React + Vite + vite-plugin-pwa + onnxruntime-web).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;embeddings/&lt;/code&gt; — Python scripts (uv) that prepare the model and the species list on a laptop.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Virien84/naturdex/SAFETY.md" rel="noopener noreferrer"&gt;&lt;code&gt;SAFETY.md&lt;/code&gt;&lt;/a&gt; — how NaturDex keeps kids and protected species safe.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it is hosted&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What&lt;/th&gt;
&lt;th&gt;Where&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The app&lt;/td&gt;
&lt;td&gt;GitHub Pages, rebuilt on every push to &lt;code&gt;main&lt;/code&gt; by &lt;a href="https://github.com/Virien84/naturdex/.github/workflows/deploy.yml" rel="noopener noreferrer"&gt;&lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt;&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The BioCLIP model (87 MB, too big for GitHub)&lt;/td&gt;
&lt;td&gt;Hugging Face: &lt;a href="https://huggingface.co/Virien/naturdex-bioclip-onnx" rel="nofollow noopener noreferrer"&gt;Virien/naturdex-bioclip-onnx&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Species list + embeddings (~5 MB)&lt;/td&gt;
&lt;td&gt;In this repo, &lt;code&gt;app/public/species/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Everything runs on the phone: photos and locations never leave it.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Credits&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://huggingface.co/imageomics/bioclip" rel="nofollow noopener noreferrer"&gt;BioCLIP&lt;/a&gt; by the Imageomics Institute (MIT).&lt;/li&gt;
&lt;li&gt;Species occurrences from &lt;a href="https://www.gbif.org/" rel="nofollow noopener noreferrer"&gt;GBIF&lt;/a&gt;; test photos from &lt;a href="https://www.inaturalist.org/" rel="nofollow noopener noreferrer"&gt;iNaturalist&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



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


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;app/&lt;/code&gt;: the PWA (React + Vite + vite-plugin-pwa + onnxruntime-web).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;embeddings/&lt;/code&gt;: Python scripts that prepare the model and the species list on a laptop.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SAFETY.md&lt;/code&gt;: every safety rule and where the data behind it comes from.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT licensed. The model is on Hugging Face: &lt;a href="https://huggingface.co/Virien/naturdex-bioclip-onnx" rel="noopener noreferrer"&gt;Virien/naturdex-bioclip-onnx&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The trick that makes it fit on a phone is splitting the AI work in two: the heavy, one-off part runs &lt;strong&gt;once, on a laptop&lt;/strong&gt;, and the phone only does what it has to do for each photo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LAPTOP, once                                 PHONE, every photo (offline)

GBIF ─► 1,944 species of Asturias            Photo ─► BioCLIP image encoder
          │                                          (ONNX int8, 87 MB, WASM)
          ▼                                              │
BioCLIP text encoder ─► 1 "fingerprint"                 ▼
per species (512 numbers)  ──────────────────►  compare with the 1,944
                                                fingerprints ─► top 5 + %
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;1. The model: BioCLIP.&lt;/strong&gt; &lt;a href="https://huggingface.co/imageomics/bioclip" rel="noopener noreferrer"&gt;BioCLIP&lt;/a&gt; is an open CLIP model (MIT) trained by the Imageomics Institute on the Tree of Life: millions of images of organisms with their full taxonomy. Like any CLIP model, it puts images and texts in the same space, so it can do &lt;strong&gt;zero-shot&lt;/strong&gt; classification: no training on my side, just compare the photo with a text description of each species.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The species list, on the laptop.&lt;/strong&gt; A script downloads from &lt;a href="https://www.gbif.org/" rel="noopener noreferrer"&gt;GBIF&lt;/a&gt; every species with at least 20 human observations in Asturias since 2000 (1,933), and a safety script adds 11 dangerous species that are too rare to make the cut, because the app can only warn about species it knows. Then BioCLIP's text encoder turns each species into a "fingerprint": its full taxonomy and common name, averaged over 15 photo prompts ("a photo of a…", "a blurry photo of a…"). That's a 4 MB file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The model, on the phone.&lt;/strong&gt; I exported only BioCLIP's &lt;strong&gt;image&lt;/strong&gt; encoder to ONNX and quantized its weights to int8: from 345 MB to &lt;strong&gt;87 MB&lt;/strong&gt;. It's too big for GitHub Pages, so it lives on Hugging Face, which serves it with CORS. The phone runs it with &lt;code&gt;onnxruntime-web&lt;/code&gt; (WebAssembly), compares the photo's embedding with the 1,944 fingerprints, and picks a verdict:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;probability&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;CONFIDENT&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;confident&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;UNSURE&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;maybe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unsure&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;precautionWarnings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;candidates&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;Those thresholds (70% and 40%) aren't guesses. I evaluated the int8 model, running exactly as the phone does, on &lt;strong&gt;244 research-grade iNaturalist photos from Spain&lt;/strong&gt; (82 species, including every dangerous one):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;top-1&lt;/th&gt;
&lt;th&gt;top-3&lt;/th&gt;
&lt;th&gt;top-5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;66%&lt;/td&gt;
&lt;td&gt;81%&lt;/td&gt;
&lt;td&gt;86%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the evaluation (an earlier run, with 232 of those photos), above 70% the top answer was right 84% of the time, so NaturDex says "It's a…!". Between 40% and 70% it was right only ~45%, but the right species was usually in the top 3, so NaturDex shows three and lets the kid choose. Below 40% it was right 7% of the time, so it says "not sure".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Safety rules (&lt;a href="https://github.com/Virien84/naturdex/blob/main/SAFETY.md" rel="noopener noreferrer"&gt;SAFETY.md&lt;/a&gt;).&lt;/strong&gt; This is the part that matters most, because a wrong answer here isn't a bug, it's a child touching something.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Look, don't touch.&lt;/strong&gt; Every species can carry a warning: &lt;em&gt;danger&lt;/em&gt; (vipers, the Asian hornet, foxglove, death cap…) or &lt;em&gt;caution&lt;/em&gt; (wasps, nettles…). They come from a hand-curated list with a source for each, plus group rules: never eat wild mushrooms, don't touch amphibians' skin.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precaution rule:&lt;/strong&gt; if &lt;em&gt;any&lt;/em&gt; of the top 5 candidates with at least 5% probability is dangerous, the warning shows, even when it's not the top answer. That's the "Could it be a Viperine Snake?" screenshot. On the 124 test photos of hazardous species, 118 got a warning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every snake is "danger".&lt;/strong&gt; In the test, the model identified a venomous Baskian viper as a harmless viperine snake &lt;strong&gt;with 96% confidence&lt;/strong&gt;. Kids can't tell them apart either, so NaturDex never relies on that difference.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NaturDex never says that anything is edible.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hide where threatened species live.&lt;/strong&gt; The 283 species protected in Spain or Asturias show a "look, but don't disturb it" note, and for threatened ones the saved GPS position is rounded to about 10 km, like iNaturalist does, so a shared album can't lead anyone to a nest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Offline for real.&lt;/strong&gt; It's a PWA: a service worker caches the app shell, the fonts and onnxruntime's WebAssembly; the model and species list go to Cache Storage when you tap &lt;em&gt;Prepare trip&lt;/em&gt;; the album lives in IndexedDB. Once prepared, it works with no connection: I tested it by preparing the trip, cutting the network, reloading the page and identifying a butterfly. If you're building something similar, &lt;a href="https://dev.to/ohugonnot/offline-pwa-the-pitfalls-of-an-app-that-never-asks-for-the-network-fc7"&gt;this post on offline PWA pitfalls&lt;/a&gt; by ohugonnot covers the Vite PWA and Workbox traps well.&lt;/p&gt;
&lt;h3&gt;
  
  
  Three bugs worth sharing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The app looked frozen, because the browser never got to paint.&lt;/strong&gt; Decoding a full-size phone photo, checking whether it's blurry and running the model all happen on the page's single thread. React had already switched to the "thinking" screen, but the browser had no free moment to draw it. The fix is to wait for a paint before the heavy work:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Waits until the browser has drawn the screen. Decoding the photo and running&lt;/span&gt;
&lt;span class="c1"&gt;// the model block the page, so without this the "thinking" screen never shows.&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;nextPaint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&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;The spinner and the glowing lens are CSS &lt;code&gt;transform&lt;/code&gt;/&lt;code&gt;opacity&lt;/code&gt; animations, which the GPU keeps running even while the model has the page busy. Measured inside the page with the CPU throttled 4×: the spinner is painted 0.05 s after the photo arrives, and the result comes ~13 s later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Firefox got stuck at 99%.&lt;/strong&gt; After downloading, the app asks the browser not to delete its data (&lt;code&gt;navigator.storage.persist()&lt;/code&gt;). Chrome, Brave and Safari answer at once. Firefox &lt;strong&gt;asks the user first&lt;/strong&gt;, and the app waited for that answer. If the kid didn't notice the prompt, the download looked stuck forever. Now it waits at most 3 seconds and moves on. I found it by running the full flow (download + identify) in Chromium, Brave, Firefox and WebKit with Playwright, and all four pass now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"It's an European Robin!"&lt;/strong&gt; In English it's &lt;em&gt;a&lt;/em&gt; European. Small, but the app talks to kids.&lt;/p&gt;

&lt;p&gt;I built it with Claude Code as my coding agent: it did the heavy lifting on the ONNX export, the evaluation script, the PWA plumbing and the design, while I made the decisions and tested it outside.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;For this project, open isn't a nice-to-have. A closed API would have broken every one of the rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It works in the forest.&lt;/strong&gt; A cloud model needs coverage. BioCLIP runs on the phone, in the browser, in airplane mode. That's only possible because the weights are open: I could export them to ONNX, quantize them to int8 and host the result myself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Children's photos and locations stay on the phone.&lt;/strong&gt; With a cloud API, every photo a child takes (and where they took it) would go to a server the school doesn't control. Here there are no accounts, no uploads and no analytics. Nothing to consent to, nothing to leak.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing per photo.&lt;/strong&gt; A class of 25 kids taking photos all morning would be thousands of API calls. With an open model running locally, the cost is zero, forever, and the school doesn't need a credit card or an API key.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It runs on old phones.&lt;/strong&gt; It's just a web page: no app store, no installation process, no minimum Android version beyond a modern browser. Recycled phones are enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A specialist beats a generalist here.&lt;/strong&gt; BioCLIP was trained by researchers specifically on the Tree of Life, with taxonomy. It knows thousands of European species, from beetles to orchids. And being open, I could measure exactly how good it is on photos from my region, and set the thresholds from that data instead of trusting a black box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's adaptable.&lt;/strong&gt; The model doesn't change from one place to another; only the species list and the safety rules do. Another region is a matter of re-running the Python scripts with another GBIF area. No one has to ask for permission.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The data is open too: species from GBIF, test photos from iNaturalist, protected species from public Spanish catalogues. Open models plus open data made a tool that a school can own.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's next: regions made by the people who live there
&lt;/h2&gt;

&lt;p&gt;Asturias is a starting point, not the limit. The final idea, and the reason it had to be open source, is that &lt;strong&gt;anyone could add their own region&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;region pack&lt;/strong&gt; is small: the species list and its fingerprints (about 5 MB, generated with the scripts in the repo from GBIF data), plus the region's safety files. The model stays the same for everyone.&lt;/li&gt;
&lt;li&gt;The safety files are the valuable part, and the part I can't write for other places: which species are dangerous there, which ones are protected, and where to hide locations. Today &lt;code&gt;safety.py&lt;/code&gt; is built around Spanish and Asturian catalogues. The plan is to turn it into one folder per region (&lt;code&gt;dangerous.csv&lt;/code&gt;, &lt;code&gt;sensitive.csv&lt;/code&gt;, the local protected-species list), so &lt;strong&gt;the people who know each place are the ones who feed it&lt;/strong&gt;: a biology teacher, a park ranger, a local naturalists' group.&lt;/li&gt;
&lt;li&gt;New regions would arrive as &lt;strong&gt;pull requests&lt;/strong&gt; to a shared repository, where others can review the sources before a pack goes live, and NaturDex would list them in &lt;em&gt;Prepare trip&lt;/em&gt; so a school picks its own before the trip.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the kind of collaboration a closed app can't have: the AI is open, the data is open, and the knowledge that keeps kids safe comes from the community itself.&lt;/p&gt;
&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;This is the session from the last day: testing it outside on my phone, fixing the "frozen" screen, the Pokédex-style redesign, the install icons, the cross-browser test that caught the Firefox bug, and preparing this post (including swapping out a photo of a run-over fox for a living one). It's in Spanish, my native language.&lt;/p&gt;


&lt;div class="ltag-agent-session"&gt;
  &lt;div class="agent-session-header"&gt;
    
    &lt;span class="agent-session-tool-icon-badge" title="Claude Code"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;NaturDex: field-testing, a Pokédex-style redesign and cross-browser fixes&lt;/span&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-scroll"&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;He hecho una pequeña prueba solo con arboles y plantas. He tenido los tres supuestos: no detección, detección con opción de que el usuario elija y la detección directa.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Read project memory and find classification thresholds&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Read project memory and find classification thresholds&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Read the classifier decision logic&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Read the classifier decision logic&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;¡Buena señal! Los tres resultados que has visto &lt;strong&gt;son justo los que diseñamos&lt;/strong&gt;. Salen de &lt;code&gt;classifier.js&lt;/code&gt;, que mira lo seguro que está el modelo de su primera opción:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lo que viste&lt;/th&gt;
&lt;th&gt;Confianza de la 1ª opción&lt;/th&gt;
&lt;th&gt;Qué tal acertó en las pruebas del PC (244 fotos)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Detección directa&lt;/strong&gt; ("It's a …!")&lt;/td&gt;
&lt;td&gt;≥ 70 %&lt;/td&gt;
&lt;td&gt;Acierta ~84 % de las veces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Elegir entre opciones&lt;/strong&gt; ("Which one is it?")&lt;/td&gt;
&lt;td&gt;entre 40 % y 70 %&lt;/td&gt;
&lt;td&gt;La 1ª acierta ~45 %, pero la buena suele estar entre las 3 primeras&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;No detección&lt;/strong&gt; ("Not sure, take another photo")&lt;/td&gt;
&lt;td&gt;&amp;lt; 40 %&lt;/td&gt;
&lt;td&gt;Solo acertaría ~7 %, así que es mejor no …&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;1-Si. 2-No estoy seguro pero creo que si. 3-Igusl que la 2. 4-un árbol entero cerca de otros. 5-no&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Find camera screen messages and hints&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Find camera screen messages and hints&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Find where the not-sure message is rendered&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Find where the not-sure message is rendered&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/components/SpeciesCard.jsx&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;SpeciesCard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/screens/CameraScreen.jsx&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;screens&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;CameraScreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Build the app and run the linter&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Build the app and run the linter&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;¡Perfecto! Con esto la prueba en el vivo sale bien: funciona en un móvil real, sin errores, y aparecen los tres casos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sobre el caso que no detectó (un árbol entero junto a otros):&lt;/strong&gt; era lo esperable. En el recorte de 224×224 se mezclan las copas de varios árboles con el cielo, y el modelo no sabe en cuál fijarse. La app se comportó bien: prefirió decir "no estoy seguro" antes que inventarse una especie.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;He hecho un cambio pequeño para guiar a los niños&lt;/strong&gt; (todo en inglés, como el resto de la app):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cámara&lt;/strong&gt; (&lt;code&gt;app/src/screens/CameraScreen.jsx&lt;/code&gt;): el consejo que sale debajo del botón ah …&lt;/li&gt;
&lt;/ul&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Antes de subir y desplegar hay algo que no me gusta: después de sacar la foto, no da muestras de hacer nada y pienso que se ha colgado. Reparalo poniendo un indicador de espera&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ya veo la causa. Te lo explico y lo arreglo.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Check existing styles and onnxruntime settings&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Check existing styles and onnxruntime settings&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ahora hago los cambios:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/screens/CameraScreen.jsx&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;screens&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;CameraScreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/index.css&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;index&lt;/span&gt;&lt;span class="nc"&gt;.css&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Check preview size, build and lint&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Check preview size, build and lint&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Compila bien. Ahora lo pruebo en un navegador automático: le paso una foto y compruebo que la ruedecita aparece antes de que salga el resultado.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Start the dev server for the test&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Start the dev server for the test&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Run the headless spinner test&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Run the headless spinner test&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Me he equivocado: he dejado en el comando una llamada suelta a &lt;code&gt;python3&lt;/code&gt;, que se queda esperando para siempre (la memoria ya avisaba de esto). La detengo y lo repito bien.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Run the in-page timing test&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Run the in-page timing test&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;photo            +0.00s
spinner painted  +0.05s
result           +12.89s&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Ya está arreglado: la ruedecita de espera aparece en cuanto haces la foto. En una prueba con el procesador ralentizado 4 veces para imitar un móvil modesto, se pintó a los &lt;strong&gt;0,05 s&lt;/strong&gt; de llegar la foto, y el resultado salió a los ~13 s.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Por qué parecía colgada.&lt;/strong&gt; JavaScript en una página web hace todo con un solo "trabajador". Después de la foto le tocaban tres tareas pesadas seguidas:&lt;br&gt;
1. Abrir la foto.&lt;br&gt;
2. Comprobar si está borrosa u oscura.&lt;br&gt;
3. Pasar el modelo de IA.&lt;/p&gt;

&lt;p&gt;Para redibujar la pantalla, ese mismo trabajador tiene que estar libre. Como no paraba ni un momento, el mensaje "Looking clo …&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Haz el commit y el push&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Commit the changes and push to GitHub&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Commit the changes and push to GitHub&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Wait for the GitHub Pages deploy to finish&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Wait for the GitHub Pages deploy to finish&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ya está subido y publicado. La web &lt;a href="https://virien84.github.io/naturdex/" rel="noopener noreferrer"&gt;https://virien84.github.io/naturdex/&lt;/a&gt; ya tiene la ruedecita de espera y los consejos para fotografiar árboles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Commit:&lt;/strong&gt; &lt;code&gt;d8c635b&lt;/code&gt;, "Show a spinner while identifying, and tips for photographing trees".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Despliegue:&lt;/strong&gt; GitHub Actions lo terminó sin errores y he comprobado que la web carga bien. …&lt;/li&gt;
&lt;/ul&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Mientras tengo una pregunta de Claude code: la gente recomienda instalar los plugins omni-route, frontend-design, headroom, mem-palace y playwright. Quiero instalarlos, que se puedan usar en todos mis proyectos y que me digas como se usan&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Antes de instalar nada miro qué es cada uno y de dónde sale. Algunos son oficiales de Anthropic y otros son de terceros, y un plugin puede ejecutar código en tu PC.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;List plugin subcommands and search the official marketplace&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ List plugin subcommands and search the official marketplace&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-websearch"&gt;WebSearch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;OmniRoute Claude Code plugin github&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;OmniRoute Claude Code plugin github&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-websearch"&gt;WebSearch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;headroom Claude Code plugin context compression github&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;headroom Claude Code plugin context compression github&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-websearch"&gt;WebSearch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;MemPalace Claude Code plugin install github&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;MemPalace Claude Code plugin install github&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-webfetch"&gt;WebFetch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;https://github.com/MemPalace/mempalace&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;https://github.com/MemPalace/mempalace&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-webfetch"&gt;WebFetch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;https://github.com/chopratejas/headroom&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;https://github.com/chopratejas/headroom&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-webfetch"&gt;WebFetch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;https://github.com/diegosouzapw/OmniRoute&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;https://github.com/diegosouzapw/OmniRoute&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Inspect the plugins' files before installing&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Inspect the plugins' files before installing&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Install the two official plugins for all projects&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Install the two official plugins for all projects&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ya tienes instalados para todos tus proyectos los dos plugins oficiales, &lt;strong&gt;frontend-design&lt;/strong&gt; y &lt;strong&gt;playwright&lt;/strong&gt;. Los otros tres no los he instalado todavía: al investigarlos he visto cosas que conviene que sepas antes de decidir. …&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Vamos a trabajar en el frontend, ya que es de noche y no voy a salir a sacar fotos, pero se puede trabajar en eso. Usa frontend-design para que la aplicación tenga un diseño similar a una pokedex, centrada en el público juvenil&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Esta sesión empezó antes de instalar el plugin, así que leo directamente las instrucciones de la skill &lt;code&gt;frontend-design&lt;/code&gt; y las aplico. Luego reviso cómo está hecha la app ahora.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Read the frontend-design skill instructions&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Read the frontend-design skill instructions&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;List species kinds, keys and dependencies&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ List species kinds, keys and dependencies&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Install the two font packages&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Install the two font packages&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ahora el código. Primero, una función para numerar las especies como en una Pokédex:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/ml/classifier.js&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ml&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/components/KindChip.jsx&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;KindChip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ahora la carcasa del aparato (&lt;code&gt;App.jsx&lt;/code&gt;), la ficha de resultado, que pasa a parecer una entrada de la Pokédex, y la pantalla del álbum (My NaturDex).&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/screens/DexScreen.jsx&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;screens&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;DexScreen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jsx&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ahora la hoja de estilos completa: colores, carcasa, lente, pantalla LCD, botones físicos y etiquetas de tipo.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Update theme colors, cache fonts, new icon, build and lint&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Update theme colors, cache fonts, new icon, build and lint&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Compila bien. Ahora hago capturas en tamaño móvil para revisar el diseño con mis propios ojos, como pide la skill:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Take light-mode screenshots of every screen&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Take light-mode screenshots of every screen&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Shrink the photo preview and remove the meter&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Shrink the photo preview and remove the meter&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Take dark-mode screenshots&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Take dark-mode screenshots&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;En modo oscuro, el fondo de la foto sale verde claro y deslumbra. Lo cambio a oscuro fijo, cierro el servidor que se había quedado abierto y compilo:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Fix preview background, stop old server, build and lint&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Fix preview background, stop old server, build and lint&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;NaturDex ya tiene un diseño tipo Pokédex: la app parece un aparato de explorador. …&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Qué ha cambiado&lt;/strong&gt;&lt;br&gt;
- &lt;strong&gt;Carcasa roja&lt;/strong&gt; con la gran &lt;strong&gt;lente azul&lt;/strong&gt; y tres LEDs. Mientras la IA piensa, la lente brilla y …&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Si, haz commit y push&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Commit the redesign and push to GitHub&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Commit the redesign and push to GitHub&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Wait for the deploy and check the live site&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Wait for the deploy and check the live site&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;El nuevo diseño ya está en la web: &lt;a href="https://virien84.github.io/naturdex/" rel="noopener noreferrer"&gt;https://virien84.github.io/naturdex/&lt;/a&gt;. …&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recuerda el plazo:&lt;/strong&gt; la entrega es &lt;strong&gt;mañana lunes 12 a las 08:59&lt;/strong&gt;. Lo que queda, por orden de importancia:&lt;br&gt;
1. &lt;strong&gt;Post de DEV.&lt;/strong&gt;&lt;br&gt;
2. &lt;strong&gt;Iconos para instalar la app.&lt;/strong&gt;&lt;br&gt;
3. &lt;strong&gt;Logros (gamificación).&lt;/strong&gt;&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Vamos con los iconos&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Creo los iconos a partir de la lente del favicon. Hacen falta tres tamaños:&lt;br&gt;
- &lt;strong&gt;192 y 512 px:&lt;/strong&gt; los que Android exige para poder instalar la app.&lt;br&gt;
- &lt;strong&gt;Versión "maskable" de 512 px:&lt;/strong&gt; Android recorta el icono en círculo, gota u otra forma según el móvil. Esta versión va a sangre, con el fondo rojo hasta los bordes, para que el recorte nunca deje esquinas raras.&lt;br&gt;
- &lt;strong&gt;180 px:&lt;/strong&gt; para iPhone.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Render the PNG icons into the app&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Render the PNG icons into the app&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/vite.config.js&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;vite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Build and check icons in HTML, manifest and offline cache&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Build and check icons in HTML, manifest and offline cache&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Ask Chrome whether the app is installable&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Ask Chrome whether the app is installable&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;installability errors: []
manifest errors: []&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Los iconos están hechos y Chrome ya considera NaturDex &lt;strong&gt;instalable&lt;/strong&gt;: su comprobación interna no devuelve ningún error. …&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Antes del commit y push: yo uso Brave, y habrá gente que use otros navegadores que no sean Chrome. ¿Funcionará igual?&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Buena pregunta. En vez de responder de memoria, lo pruebo: Playwright puede usar los motores de &lt;strong&gt;Firefox&lt;/strong&gt; y de &lt;strong&gt;Safari&lt;/strong&gt; (WebKit), además de Chrome, y miro si tienes Brave instalado en el PC para probarlo también.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Download the Firefox and WebKit test engines&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Download the Firefox and WebKit test engines&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Run the full flow in Chrome, Brave, Firefox and WebKit&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Run the full flow in Chrome, Brave, Firefox and WebKit&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Brave, Chrome y WebKit (Safari) funcionan. Firefox se queda atascado en la descarga, así que miro qué pasa:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Debug the download in Firefox&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Debug the download in Firefox&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Downloading Species fingerprints…  99%&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/data/tripData.js&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;tripData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;De paso, en las pruebas salió &lt;strong&gt;"It's an European Robin!"&lt;/strong&gt;. En inglés es &lt;em&gt;"a European"&lt;/em&gt;, porque "European" suena con /j/. Lo arreglo también:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;app/src/ml/classifier.js&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ml&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Rebuild and rerun all four browsers&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Rebuild and rerun all four browsers&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Funciona igual en Brave, Firefox y Safari, después de arreglar un fallo que dejaba la app colgada en Firefox.&lt;/p&gt;

&lt;p&gt;Lo he probado de verdad, no de memoria. En cada navegador hice el recorrido completo con la versión de producción: descargar el modelo desde Hugging Face, hacer una foto de un petirrojo e identificarla. …&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Si, haz commit y push&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Commit icons and fixes, then push&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Commit icons and fixes, then push&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Los iconos y los dos arreglos ya están publicados en &lt;a href="https://virien84.github.io/naturdex/" rel="noopener noreferrer"&gt;https://virien84.github.io/naturdex/&lt;/a&gt;. …&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Empecemos&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Primero cargo las instrucciones para publicar en DEV y consulto las bases del reto: plantilla obligatoria, etiquetas y criterios de valoración.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-webfetch"&gt;WebFetch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;https://dev.to/challenges/hacktoberfest-week1-2026-10-05&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;https://dev.to/challenges/hacktoberfest-week1-2026-10-05&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Read the project README and safety rules&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Read the project README and safety rules&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Perfecto. Hago las capturas desde la web publicada, en tamaño móvil y en JPEG para que pesen poco:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Take post screenshots from the live site&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Take post screenshots from the live site&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;El script tenía un fallo: después de guardar una especie, pulsaba el botón de cámara de abajo, pero si ya estás en la cámara ese botón no hace nada. Eso &lt;strong&gt;también le pasaría a un niño&lt;/strong&gt;. Arreglo la app para que pulsar un botón siempre lleve al principio de esa pantalla.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Make pad buttons restart their screen, then build&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Make pad buttons restart their screen, then build&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Retry the post screenshots&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Retry the post screenshots&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Antes de seguir, dos problemas con las fotos:&lt;br&gt;
1. La del zorro es un zorro &lt;strong&gt;atropellado&lt;/strong&gt;: no es lo que queremos enseñar a niños ni a los jueces.&lt;br&gt;
2. Las fotos de prueba vienen de &lt;strong&gt;iNaturalist&lt;/strong&gt;, y cada una tiene su propia licencia y su autor. Si salen en el post y en el repo hay que citarlos.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Look up photo licenses on iNaturalist&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Look up photo licenses on iNaturalist&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Download openly licensed photos with credits&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Download openly licensed photos with credits&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Fotos con licencia libre descargadas: 32, cada una con su autor. Ahora paso todas por la app para elegir las que dan cada caso (seguro, aviso de peligro, "Which one is it?"):&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Classify every open photo in the app&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Classify every open photo in the app&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Por favor, que no aparezca el zorro atropellado&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Entendido: el zorro atropellado no saldrá. Era una foto del primer lote y ya la he descartado. Antes de elegir sustituto, miro las fotos de zorro nuevas para asegurarme de que son de un zorro vivo:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Retake post screenshots with open photos&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Retake post screenshots with open photos&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;En la culebra parece verse la tripa hacia arriba, lo que podría indicar que está muerta. Con la petición que me has hecho, prefiero no arriesgar: miro las otras fotos de culebra.&lt;/p&gt;

                &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Las dos están vivas. Uso la del pedregal, de Martiño Cabana Otero (CC BY), que también da &lt;em&gt;"Could it be a Viperine Snake?"&lt;/em&gt;:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Retake screenshots with the live snake photo&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Retake screenshots with the live snake photo&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Las capturas están bien. Hasta el petirrojo, que sale pequeño y entre ramas, lo reconoce al 100 %. Ahora creo el archivo de créditos de las fotos para el repositorio:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Commit the fix and screenshots, then push&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ Commit the fix and screenshots, then push&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ahora guardo esta sesión en DEV para incrustarla en el post, como hiciste en el anterior.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-footer"&gt;
    &lt;span class="agent-session-meta"&gt;
        24 of 24 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;



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

&lt;p&gt;None. NaturDex doesn't use any partner technology, so I'm entering only the overall prize.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>pwa</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Should I Buy: a traffic light for my friend who never makes it to the end of the month</title>
      <dc:creator>David Anton Alvarez</dc:creator>
      <pubDate>Sun, 04 Oct 2026 21:26:36 +0000</pubDate>
      <link>https://dev.to/virien84/should-i-buy-a-traffic-light-for-my-friend-who-never-makes-it-to-the-end-of-the-month-3h6e</link>
      <guid>https://dev.to/virien84/should-i-buy-a-traffic-light-for-my-friend-who-never-makes-it-to-the-end-of-the-month-3h6e</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;I have a friend who never makes it to the end of the month. He isn't reckless. He just doesn't know, at the moment he's looking at something in an online shop, whether he can actually afford it &lt;em&gt;today&lt;/em&gt;. The salary arrived on the 1st, rent and bills are gone, and somewhere around the 20th the money runs out.&lt;/p&gt;

&lt;p&gt;Banking apps tell you what you've &lt;strong&gt;already&lt;/strong&gt; spent. He needed something that answers the question &lt;strong&gt;before&lt;/strong&gt; he clicks "Add to cart".&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;Should I Buy&lt;/strong&gt;, a browser extension for Chrome and Edge. When you open a product page in any online shop, a small card appears in the corner with a traffic light:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;You can afford it.&lt;/strong&gt; It fits your spending pace for the month, and it shows how much you'd have left per day until payday.&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;You can, but it's tight.&lt;/strong&gt; You have the money, but you're ahead of your pace. It tells you how many days to wait until it fits.&lt;/li&gt;
&lt;li&gt;🔴 &lt;strong&gt;Not now.&lt;/strong&gt; It tells you how many months it would take to buy it &lt;strong&gt;without touching your savings&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of the numbers, a local model writes one short, honest sentence the way a friend would say it.&lt;/p&gt;

&lt;p&gt;You configure it once with four numbers: monthly net income, fixed expenses, how much you want to save, and your payday. Everything else happens on its own while you browse.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Settings.&lt;/strong&gt; Four numbers, and you immediately see how much free money you really have each month.&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%2F7l6ll8l2kzgkxx16hj8p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7l6ll8l2kzgkxx16hj8p.jpg" alt="Settings page" width="800" height="888"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thinking…&lt;/strong&gt; As soon as a page looks like a shop, the card appears while Gemma reads the page.&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%2Fia7ikpy6bnxtoe4a6mwz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fia7ikpy6bnxtoe4a6mwz.jpg" alt="Thinking badge on an Amazon product page" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🟢 Green.&lt;/strong&gt; A pack of spoons for €3.99: easy yes. Note that Gemma ignored the €13.03 shipping line and the €0.04/unit price and picked the actual price.&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%2F14bumgbsxfgnhjzazt2j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F14bumgbsxfgnhjzazt2j.jpg" alt="Green verdict" width="800" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🟡 Yellow.&lt;/strong&gt; Headphones for €179.99 early in the month. Affordable, but at €7.86/day for the next 28 days it's tight, and waiting 10 days makes it fit the pace. (This is my demo shop, which deliberately has a crossed-out price, a shipping cost, an instalment price and related products to try to confuse the model.)&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%2Fhc9mxayyygj36uybp8dh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhc9mxayyygj36uybp8dh.jpg" alt="Yellow verdict" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔴 Red.&lt;/strong&gt; A €1,207.72 laptop with €400 of free money a month: 3 months putting aside all your free money, or 5 putting aside half. No lecture, just the math and a nudge.&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%2Fdpyakr0ib6zocqu3au7a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdpyakr0ib6zocqu3au7a.jpg" alt="Red verdict" width="799" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;I bought it&lt;/strong&gt; button logs the purchase, so the next verdicts take it into account.&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%2Fqd8e3414gnc19crduxz8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqd8e3414gnc19crduxz8.jpg" alt="After clicking I bought it" width="798" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What my friend said
&lt;/h3&gt;

&lt;p&gt;I handed it over and he used it while browsing. Two things stood out to him:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It doesn't feel slow.&lt;/strong&gt; While he's reading the product's features, the model is already thinking, so by the time he's ready to decide, the verdict is there. The wait happens while he's busy reading anyway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;He really appreciated the realistic comment and the estimate.&lt;/strong&gt; A plain "no" would be useless; "3 months without touching your savings" is a plan.&lt;/li&gt;
&lt;/ol&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/Virien84" rel="noopener noreferrer"&gt;
        Virien84
      &lt;/a&gt; / &lt;a href="https://github.com/Virien84/Should-I-Buy" rel="noopener noreferrer"&gt;
        Should-I-Buy
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Should I Buy 💸&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/Virien84/Should-I-Buy#english" rel="noopener noreferrer"&gt;English&lt;/a&gt; · &lt;a href="https://github.com/Virien84/Should-I-Buy#espa%C3%B1ol" rel="noopener noreferrer"&gt;Español&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;English&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Can I afford it?&lt;/strong&gt; A browser extension that shows you a traffic light whenever you're looking at a product in any online shop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;You can afford it&lt;/strong&gt;: it fits your spending pace for the month.&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;You can, but it's tight&lt;/strong&gt;: it tells you how much you'd have left per day until payday, and how many days to wait for it to fit your pace.&lt;/li&gt;
&lt;li&gt;🔴 &lt;strong&gt;Not now&lt;/strong&gt;: it tells you how many months it would take to buy it without touching your savings.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I built it for a friend who never makes it to the end of the month.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Screenshots&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;🟢 You can afford it&lt;/th&gt;
&lt;th&gt;🟡 You can, but it's tight&lt;/th&gt;
&lt;th&gt;🔴 Not now&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Virien84/Should-I-Buy/screenshots/green-verdict.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FVirien84%2FShould-I-Buy%2FHEAD%2Fscreenshots%2Fgreen-verdict.jpg" alt="Green verdict on Amazon"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Virien84/Should-I-Buy/screenshots/yellow-verdict.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FVirien84%2FShould-I-Buy%2FHEAD%2Fscreenshots%2Fyellow-verdict.jpg" alt="Yellow verdict on the demo shop"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Virien84/Should-I-Buy/screenshots/red-verdict.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FVirien84%2FShould-I-Buy%2FHEAD%2Fscreenshots%2Fred-verdict.jpg" alt="Red verdict on Amazon"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Thinking…&lt;/th&gt;
&lt;th&gt;Settings&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Virien84/Should-I-Buy/screenshots/red-thinking.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FVirien84%2FShould-I-Buy%2FHEAD%2Fscreenshots%2Fred-thinking.jpg" alt="Thinking badge while Gemma reads the page"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Virien84/Should-I-Buy/screenshots/settings.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FVirien84%2FShould-I-Buy%2FHEAD%2Fscreenshots%2Fsettings.jpg" alt="Settings page"&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Why open, local AI&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Should I Buy sees &lt;strong&gt;every shop you visit&lt;/strong&gt; and knows &lt;strong&gt;your income, your expenses and your savings&lt;/strong&gt;…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Virien84/Should-I-Buy" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Plain JavaScript, Manifest V3, no build step. MIT licensed.&lt;/p&gt;

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

&lt;p&gt;The whole thing is three pieces: a content script that decides whether a page is worth looking at, a background worker that talks to the model, and a small budget module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Shop page ──► content.js ──► background.js ──► Gemma 3 (Ollama, localhost)
                                   │
                                   └──► budget.js (exact math) ──► 🟢🟡🔴
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;1. Gemma reads the shop, so I don't have to write a scraper per site.&lt;/strong&gt;&lt;br&gt;
Every shop marks up prices differently: crossed-out prices, unit prices, shipping, instalments, "customers also bought"… Instead of writing selectors for each site, the extension sends the visible text of the page to &lt;strong&gt;Gemma 3 4B&lt;/strong&gt; running locally with &lt;strong&gt;Ollama&lt;/strong&gt;, and asks for structured JSON using Ollama's &lt;code&gt;format&lt;/code&gt; parameter:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EXTRACT_SCHEMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;is_product_page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;boolean&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;is_product_page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product_name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currency&lt;/span&gt;&lt;span class="dl"&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;The prompt asks it to decide whether this is &lt;em&gt;one&lt;/em&gt; product page (not a listing, search results or cart) and to return the price the buyer would actually pay. In my tests it correctly rejected a search results page, picked €179.99 over the crossed-out €249.99, and picked $749 over a "List Price" of $899.99 on an English page. It works the same on Spanish and English Amazon pages. If a shop publishes clean &lt;code&gt;schema.org/Product&lt;/code&gt; data, the extension uses it directly and skips the model call.&lt;/p&gt;

&lt;p&gt;To avoid sending every page to the model, the content script only wakes it up when the page looks like a shop: product structured data, a product &lt;code&gt;og:type&lt;/code&gt;, or a price next to an "add to cart"-style button (in several languages).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The math is NOT done by the AI.&lt;/strong&gt;&lt;br&gt;
This was a deliberate choice. A language model is great at reading a messy page and bad at being trusted with your money, so the verdict is plain, tested JavaScript:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free money = income − fixed expenses − savings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spending pace:&lt;/strong&gt; free money is "earned" day by day from payday. On day 3 you haven't earned what you have on day 28, so a big purchase early in the month turns yellow even if the money is technically in the account.&lt;/li&gt;
&lt;li&gt;Red verdicts compute how many months of free money you'd need, so the answer is always "without touching your savings".
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onPace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;free&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;cycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;elapsed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;cycle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;spent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;onPace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;free&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;spent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yellow&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nx"&gt;verdict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;3. Gemma writes the friendly sentence, with guardrails.&lt;/strong&gt;&lt;br&gt;
A second, non-blocking call gives Gemma the verdict and the computed facts, and asks for one casual sentence of 25 words max, with the instruction to use only the numbers it's given. The traffic light appears first and the sentence fills in a few seconds later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Making it fast enough on a normal laptop.&lt;/strong&gt; On my laptop (16 GB RAM, CPU inference), a verdict takes about 9 seconds and the sentence about 6. The very first call after starting the browser took around 90 seconds, because the model has to load into memory. So the extension pre-loads the model when the browser starts, and keeps it loaded for 30 minutes (&lt;code&gt;keep_alive&lt;/code&gt;). That's why my friend found it quick: by the time he's done reading the product, it's ready.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One gotcha worth sharing:&lt;/strong&gt; Ollama rejects requests from browser extensions by default (HTTP 403). You have to allow them with &lt;code&gt;OLLAMA_ORIGINS="chrome-extension://*"&lt;/code&gt; and restart Ollama. That's in the README for Windows, macOS and Linux.&lt;/p&gt;

&lt;p&gt;I built it in an evening, pairing with Claude Code as my coding agent.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Think about what this extension sees: &lt;strong&gt;every shop you visit&lt;/strong&gt;, plus &lt;strong&gt;your income, your fixed expenses and your savings&lt;/strong&gt;. That is about as personal as data gets. I would not ask my friend to send that to a cloud API, and he wouldn't agree to it anyway.&lt;/p&gt;

&lt;p&gt;With an open-weight model running locally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nothing leaves his computer.&lt;/strong&gt; No page text, no prices, no salary. The only network call goes to &lt;code&gt;localhost:11434&lt;/code&gt;. His settings live in the extension's local storage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing to run.&lt;/strong&gt; Someone who struggles to make it to the end of the month shouldn't need a paid API key to be told whether he can afford a pair of headphones. And because it calls the model on every product page, a per-request API bill would add up fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No account, no key, no sign-up.&lt;/strong&gt; Install Ollama, pull the model, load the extension.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The model is swappable.&lt;/strong&gt; If his laptop struggles, he can switch to &lt;code&gt;gemma3:1b&lt;/code&gt; in the settings. If a better open model comes out, it's a one-line change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A closed API would have made this either a privacy problem or a subscription. With an open model it's just a tool he owns.&lt;/p&gt;

&lt;p&gt;Running locally isn't automatically private, though (&lt;a href="https://dev.to/jfisher4002/your-local-llm-is-not-as-private-as-you-think-3ek7"&gt;this post&lt;/a&gt; is a good reminder). Ollama only listens on localhost, and the extension only has host permission for that address. It's in the same spirit as &lt;a href="https://dev.to/chintanonweb/pocketcfo-a-private-personal-finance-brain-that-runs-entirely-in-your-browser-2aoc"&gt;PocketCFO&lt;/a&gt;, which also keeps personal finance data on-device with Gemma.&lt;/p&gt;
&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;Here is the full session with my coding agent, from "what hackathons are open this month?" to the finished extension. It's mostly in Spanish, my native language. You can see the idea taking shape, the disk filling up halfway through the model download (and moving Ollama's models to another drive), the 403 from Ollama when an extension calls it, testing Gemma against tricky price layouts, and the switch to English for the judges.&lt;/p&gt;


&lt;div class="ltag-agent-session"&gt;
  &lt;div class="agent-session-header"&gt;
    
    &lt;span class="agent-session-tool-icon-badge" title="Claude Code"&gt;
&lt;/span&gt;
    &lt;span class="agent-session-title"&gt;Building Should I Buy: a local-AI budget traffic light for a friend&lt;/span&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-scroll"&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;¿Qué hackathons hay abiertos este mes? Usa DevRelay&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-skill"&gt;Skill&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"skill": "devrelay-challenges", "args": "Hackathons abiertos en octubre 2026"}&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"skill"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"devrelay-challenges"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hackathons abiertos en octubre 2026"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Launching skill: devrelay-challenges&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-toolsearch"&gt;ToolSearch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;select:mcp__devrelay-gateway__get_challenges,mcp__devrelay-gateway__search_ml...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;select:mcp__devrelay-gateway__get_challenges,mcp__devrelay-gateway__search_mlh_events,mcp__devrelay-gateway__get_events&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaygetchallenges"&gt;mcp__devrelay-gateway__get_challenges&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{}&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"Ok":[{"id":82,"title":"Hacktoberfest Open-Source AI Challenge: Week 4","slug":"hacktoberfest-week4-2026-10-26","description":"Register now to be notified as details drop.","details":null,"full_details":"","type_of":"challenge","starts_at":"2026-10-26T16:00:00.000Z","ends_at":"2026-10-31T06:59:00.000Z","published":true,"cover_image":"https://dev-to-uploads.s3.us-east-2.amazonaws.com/uploads/event
… [15668 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaysearchmlhevents"&gt;mcp__devrelay-gateway__search_mlh_events&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"event_format": "hackathon", "starts_before": "2026-10-31", "limit": 50}&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event_format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hackathon"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"starts_before"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-31"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"Ok":{"events":[{"id":"01a062af-7088-c530-82c5-b593e5825360","name":"FinHack$","slug":"finhack-33","status":"canceled","event_format":"hackathon","starts_at":1790903471,"ends_at":1791158399,"starts_at_utc":"2026-10-02T01:11:11Z","ends_at_utc":"2026-10-04T23:59:59Z","time_zone":null,"private":false,"website_url":null,"submission_url":null,"self_check_in_mode":"disabled","check_in":{"state":"event_
… [22540 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Esto es lo que hay en DevRelay para octubre de 2026 (hoy es 4 de octubre). Todas las horas están en UTC.&lt;/p&gt;
&lt;h2 id="agent-session-513-1-dev-challenges-online"&gt;DEV Challenges (online)&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Abiertos ahora&lt;/strong&gt;&lt;br&gt;
| Reto | Cierre | Queda |&lt;br&gt;
|---|---|---|&lt;br&gt;
| &lt;a href="https://dev.to/events/78"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt; | 5 oct, 06:59 | &lt;strong&gt;~1 día&lt;/strong&gt; |&lt;br&gt;
| &lt;a href="https://dev.to/events/70"&gt;Kaggle Benchmark Writing Challenge&lt;/a&gt; | 12 oct, 06:59 | ~8 días |&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Build for a Friend:&lt;/strong&gt; hay que construir algo con IA open-source como pieza central (un modelo open-weight, un framework open-source o inferencia local) que resuelva un problema real de una persona concreta. Tiene que ser un proyecto nuevo. Se entrega publicando un post en DEV con el tag &lt;code&gt;#hf26challenge&lt;/code&gt;. Hay $2,450 en premios para 17 ganadores. Al jurado lo que más le pesa es la calidad del post. Hay categorías de patrocinador, entre ellas Gemma, DigitalOcean, Render, MongoDB Atlas y ElevenLabs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kaggle:&lt;/strong&gt; el organizador todavía no ha publicado las reglas detalladas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Próximos:&lt;/strong&gt; la serie Hacktoberfest Open-Source AI Challenge sigue con el mismo prompt y un tema nuevo cada lunes. Cada semana es una entrega aparte:&lt;br&gt;
- Semana 1: del 5 oct, 16:00, al 12 oct, 06:59&lt;br&gt;
- Semana 2: del 12 al 18 oct&lt;br&gt;
- Semana 3: del 19 al 25 oct&lt;br&gt;
- Semana 4: del 26 al 31 oct&lt;/p&gt;

&lt;p&gt;&lt;em&gt;El Sanity Challenge ya cerró (4 oct, 06:59).&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="agent-session-513-1-hackathons-mlh-presenciales-la-inscripción-sigue-abierta"&gt;Hackathons MLH (presenciales; la inscripción sigue abierta)&lt;/h2&gt;

&lt;p&gt;Dejé fuera los cancelados y los de este fin de semana, que terminan hoy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;9–11 oct:&lt;/strong&gt; HackNC, HackBIOS, Hack Knight, Hackathon TecNM Campus Saltillo (México), Hacklanta, Knight Hacks IX, HackRU, Palmetto Hacks, hackPHS, CodeRED Orion, Innohacks 4.0&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;16–18 oct:&lt;/strong&gt; SwampHacks XII, Hack the Valley, HackGB, Girls Hoo Hack, DubHacks, IKU Womxn in STEM (Reino Unido), Technica, LA Hacks AI Hackathon&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;23–25 oct:&lt;/strong&gt; Cal Hacks 13.0, SBUHacks, OxHack '26 (Oxford), HackTX 26, Hack at Penn State&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;31 oct – 1 nov:&lt;/strong&gt; hackCBS 9.0 (India)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tu carpeta se llama &lt;code&gt;Hacktoberfest/2026/DEV Challenges/1&lt;/code&gt;, así que puede que ya estés con el Weekend Challenge. Si es así, cierra en menos de un día. Puedo revisar tu proyecto contra las reglas y dejarte el post de entrega como borrador. También puedo inscribirte en alguno de los hackathons MLH.&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Efectivamente, quiero participar en Build for a Friend, pero no se ni por donde empezar, no se como hacer lo que hay que hacer&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; ls -la &amp;amp;&amp;amp; date -u; wh...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; ls -la &amp;amp;&amp;amp; date -u; which ollama node python git 2&amp;gt;/dev/null; ollama list 2&amp;gt;/dev/null&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Exit code 127
total 0
drwxr-xr-x 1 david 197609 0 Oct  4 10:30 .
drwxr-xr-x 1 david 197609 0 Oct  4 10:30 ..
Sun Oct  4 15:43:36 UTC 2026
~/AppData/Local/Microsoft/WindowsApps/python
/mingw64/bin/git&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Tranquilo, es más sencillo de lo que parece. Te cuento lo que hay que hacer y el tiempo que queda.&lt;/p&gt;
&lt;h2 id="agent-session-513-3-tiempo"&gt;Tiempo&lt;/h2&gt;

&lt;p&gt;Son las 15:43 UTC y la entrega cierra el &lt;strong&gt;5 oct a las 06:59 UTC&lt;/strong&gt;, así que quedan &lt;strong&gt;unas 15 horas&lt;/strong&gt;. Da para algo pequeño, y el reto lo pide así: &lt;em&gt;"No tiene que ser grande. Tiene que importarle a esa persona."&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="agent-session-513-3-lo-que-hay-que-entregar"&gt;Lo que hay que entregar&lt;/h2&gt;

&lt;p&gt;Al final todo es &lt;strong&gt;un post en DEV&lt;/strong&gt; con el tag &lt;code&gt;#hf26challenge&lt;/code&gt; que incluya:&lt;br&gt;
1. &lt;strong&gt;Qué construiste y para quién&lt;/strong&gt;: una persona real (tu madre, un amigo, tu abuelo...).&lt;br&gt;
2. &lt;strong&gt;Una demo&lt;/strong&gt;: capturas, un GIF o un vídeo corto.&lt;br&gt;
3. &lt;strong&gt;El código&lt;/strong&gt;: un repo público en GitHub.&lt;br&gt;
4. &lt;strong&gt;Por qué es importante que sea open-source&lt;/strong&gt;: por ejemplo, que funciona sin internet, que los datos no salen de su ordenador o que no cuesta nada usarlo.&lt;/p&gt;

&lt;p&gt;El jurado puntúa &lt;strong&gt;sobre todo la calidad del post&lt;/strong&gt;. Una herramienta sencilla con una buena historia gana a un proyecto complejo mal contado.&lt;/p&gt;
&lt;h2 id="agent-session-513-3-el-plan-yo-me-encargo-de-la-parte-técnica"&gt;El plan (yo me encargo de la parte técnica)&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tú eliges&lt;/strong&gt; la persona y el problema. Es lo único que no puedo decidir yo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yo construyo&lt;/strong&gt; con tu ayuda una app pequeña con un modelo abierto (por ejemplo &lt;strong&gt;Gemma&lt;/strong&gt; con &lt;strong&gt;Ollama&lt;/strong&gt;, que corre en tu PC). Usar Gemma además te hace optar a la categoría "Best Use of Gemma", de $200.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tú la pruebas&lt;/strong&gt; y, si puedes, se la enseñas a esa persona y apuntas qué te dice. Eso da puntos extra.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Yo te redacto el post&lt;/strong&gt; como borrador en DEV y tú lo revisas y lo publicas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tu carpeta está vacía y no tienes Ollama instalado. Lo instalamos en el paso 2: tarda unos 10 minutos.&lt;/p&gt;
&lt;h2 id="agent-session-513-3-lo-que-necesito-de-ti-ahora"&gt;Lo que necesito de ti ahora&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;¿Para quién lo vas a construir y qué le cuesta en su día a día?&lt;/strong&gt; Basta con una frase. Por ejemplo:&lt;br&gt;
- &lt;em&gt;"Mi madre recibe cartas del banco o de Hacienda y no las entiende"&lt;/em&gt;: una app que se las explica en lenguaje sencillo, sin subir sus documentos a ningún sitio.&lt;br&gt;
- &lt;em&gt;"Mi abuelo se olvida de qué pastillas toma"&lt;/em&gt;: un asistente que lee la caja del medicamento y le recuerda la pauta.&lt;br&gt;
- &lt;em&gt;"Un amigo está aprendiendo inglés"&lt;/em&gt;: un compañero de conversación con paciencia infinita que funciona sin conexión.&lt;br&gt;
- &lt;em&gt;"Mi compañero de piso tiene alergias"&lt;/em&gt;: un planificador de comidas que las tiene en cuenta.&lt;/p&gt;

&lt;p&gt;Dime la tuya, aunque sea solo una idea a medias, y empezamos.&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Para ese amigo que nunca llega a fin de més, una extensión de navegador o una aplicación que detecte que está en una web de tienda, y que indique de manera visual si el producto que está viendo se lo puede permitir o no. La aplicación pediría como configuración el income mensual, los gastos fijos mensuales y, si ahorra dinero cada més, para, en función del día del mes en el que estás, decirte si te lo deberías permitir o no. También decirte en cuantos meses podrías permitirtelo sin descapitalizarte. No se si se puede hacer una aplicación así con IA en local.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Sí, se puede hacer, y que la IA corra en local es justamente lo mejor de la idea para el post: ni lo que navega tu amigo ni sus datos de dinero salen nunca de su ordenador. Empiezo instalando Ollama, que es el programa que ejecuta el modelo de IA en local.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-powershell"&gt;PowerShell&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;winget install --id Ollama.Ollama -e --accept-source-agreements --accept-pack...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;winget install --id Ollama.Ollama -e --accept-source-agreements --accept-package-agreements --silent&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Command running in background with ID: bn91zozdg. Output is being written to: &amp;lt;scratchpad&amp;gt; You will be notified when it completes. To check interim output, use Read on that file path.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-toolsearch"&gt;ToolSearch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;select:mcp__devrelay-gateway__search_dev_to_semantic,WebFetch&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;select:mcp__devrelay-gateway__search_dev_to_semantic,WebFetch&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-webfetch"&gt;WebFetch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"url": "https://ollama.com/library", "prompt": "List the Gemma model familie...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://ollama.com/library"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"List the Gemma model families available (gemma, gemma2, gemma3, gemma4, etc.) with their tags/sizes, especially small ones (1b-4b) suitable for a laptop."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;# Gemma Model Families Available

Based on the Ollama library, here are the Gemma model families suitable for laptops:

**Gemma** (Original)
- Sizes: 2B, 7B
- "Gemma is a family of lightweight, state-of-the-art open models built by Google DeepMind"

**Gemma2**
- Sizes: 2B, 9B, 27B
- "Google Gemma 2 is a high-performing and efficient model available in three sizes"

**Gemma3**
- Sizes: 270M, 1B, 4B
… [544 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaysearchdevtosemantic"&gt;mcp__devrelay-gateway__search_dev_to_semantic&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Chrome extension calling local Ollama API CORS OLLAMA_ORIGINS&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Chrome extension calling local Ollama API CORS OLLAMA_ORIGINS&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"Ok":[{"id":4573937,"title":"Ollama API: A Practical Guide with Examples","description":"A practical Ollama API guide: generate and chat endpoints, streaming, options, structured JSON, tool calling, Python, and the OpenAI-compatible route.","tags":["ollama","api","llm","python"],"path":"/amareswer/ollama-api-a-practical-guide-with-examples-4di9","url":"https://dev.to/amareswer/ollama-api-a-practi
… [1832 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Gemma 3 está disponible en Ollama. Para un portátil la mejor opción es &lt;code&gt;gemma3:4b&lt;/code&gt;, que además te hace optar al premio "Best Use of Gemma". Mientras se instala Ollama, escribo la extensión.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git init -q &amp;amp;&amp;amp; mkdir ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git init -q &amp;amp;&amp;amp; mkdir -p extension/icons &amp;amp;&amp;amp; powershell -NoProfile -Command "Get-CimInstance Win32_ComputerSystem | Select TotalPhysicalMemory; Get-CimInstance Win32_VideoController | Select Name,AdapterRAM"&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;TotalPhysicalMemory
-------------------
        17095188480&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\manifest.json

{
  ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\manifest.json

{
  "manifest_version": 3,
  "name": "FinDeMes",
  "version": "0.1.0",
  "description": "¿Me lo puedo permitir? Un semáforo para cada producto que miras, con IA que corre en tu ordenador.",
  "permissions": ["storage"],
  "host_permissions": ["http://localhost:11434/*", "http://127.0.0.1:11434/*"],
  "background": {
    "serv
… [433 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\manifest.json (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\budget.js

// Lógic...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\budget.js

// Lógica del presupuesto. Sin IA: las cuentas tienen que ser exactas y explicables.

export const DEFAULT_SETTINGS = {
  name: "",
  income: 0,        // ingresos netos al mes
  fixed: 0,         // gastos fijos al mes (alquiler, facturas, suscripciones...)
  savings: 0,       // lo que aparta cada mes para ahorrar
  payday: 1, 
… [2835 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\budget.js (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js

impo...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js

import { DEFAULT_SETTINGS, evaluate, money } from "./budget.js";

const EXTRACT_SCHEMA = {
  type: "object",
  properties: {
    is_product_page: { type: "boolean" },
    product_name: { type: "string" },
    price: { type: "number" },
    currency: { type: "string" },
  },
  required: ["is_product_page", "product_name", "pri
… [6143 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\content.js

// Se e...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\content.js

// Se ejecuta en cada página. Solo despierta a la IA si la página "huele" a tienda.
(() =&amp;gt; {
  const BUY_WORDS = /añadir al carrito|añadir a la cesta|comprar ahora|add to (cart|basket|bag)|buy now|in den warenkorb|ajouter au panier|aggiungi al carrello|adicionar ao carrinho/i;
  const PRICE_RE = /(\d{1,3}([.,\s]\d{3})*([.,]\d{2}
… [7061 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\content.js (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.html

&amp;lt;!doc...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.html

&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang="es"&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;title&amp;gt;FinDeMes · Configuración&amp;lt;/title&amp;gt;
  &amp;lt;style&amp;gt;
    body { font: 15px/1.5 system-ui, sans-serif; max-width: 520px; margin: 40px auto; padding: 0 16px; color: #1a202c; }
    h1 { margin-bottom: 4px; }
    .sub { color: #4a5568; margin-top: 0; }
    label { dis
… [2081 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.html (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.js

import ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.js

import { DEFAULT_SETTINGS, money } from "./budget.js";

const FIELDS = ["name", "income", "fixed", "savings", "payday", "currency", "model", "ollamaUrl"];
const NUMERIC = new Set(["income", "fixed", "savings", "payday"]);
const $ = (id) =&amp;gt; document.getElementById(id);

function read() {
  const s = {};
  for (const f of FIELDS) 
… [1471 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.js (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\popup.html

&amp;lt;!docty...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\popup.html

&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang="es"&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;style&amp;gt;
    body { font: 14px/1.4 system-ui, sans-serif; width: 300px; margin: 0; padding: 14px; color: #1a202c; }
    h2 { margin: 0 0 10px; font-size: 16px; }
    .meter { height: 10px; background: #e2e8f0; border-radius: 5px; overflow: hidden; margin: 8px 0; }
… [535 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\popup.html (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\popup.js

import { ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\popup.js

import { DEFAULT_SETTINGS, monthSummary, money } from "./budget.js";

const $ = (id) =&amp;gt; document.getElementById(id);
$("options").onclick = () =&amp;gt; chrome.runtime.openOptionsPage();

async function render() {
  const stored = await chrome.storage.local.get(["settings", "purchases"]);
  const settings = { ...DEFAULT_SETTINGS, ...stor
… [1569 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\popup.js (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cat "&amp;lt;scratchpad&amp;gt;" | tail -5; ls "%LOCALAPPDATA%/Programs/Ollama" 2&amp;gt;/dev/null&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cat "&amp;lt;scratchpad&amp;gt;" | tail -5; ls "%LOCALAPPDATA%/Programs/Ollama" 2&amp;gt;/dev/null&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;El hash del instalador se verificó correctamente
Iniciando instalación de paquete...
Instalado correctamente

[exited with code 0]
app.ico
lib
ollama app.exe
ollama.exe
unins000.dat
unins000.exe
unins000.msg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ollama ya está instalado. Ahora descargo el modelo Gemma, que pesa unos 3 GB.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;O="%LOCALAPPDATA%/Programs/Ollama/ollama.exe"; (curl -s localhost:11434/api/v...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ O="%LOCALAPPDATA%/Programs/Ollama/ollama.exe"; (curl -s localhost:11434/api/version || (nohup "$O" serve &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 &amp;amp; sleep 4; curl -s localhost:11434/api/version)); echo; "$O" pull gemma3:4b 2&amp;gt;&amp;amp;1 | tail -2&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Command running in background with ID: bml7x7e0e. Output is being written to: &amp;lt;scratchpad&amp;gt; You will be notified when it completes. To check interim output, use Read on that file path.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-powershell"&gt;PowerShell&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Add-Type -AssemblyName System.Drawing
$dir = "~\Documents\Hacktoberfest\2026\...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Add-Type -AssemblyName System.Drawing
$dir = "~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\icons"
foreach ($s in 16,48,128) {
  $bmp = New-Object System.Drawing.Bitmap $s,$s
  $g = [System.Drawing.Graphics]::FromImage($bmp)
  $g.SmoothingMode = 'AntiAlias'
  $g.Clear([System.Drawing.Color]::Transparent)
  $w = $s/3
  $cols = '#e53e3e','#d69e2e','#1f9d55'
  for ($i=0; $i -lt 3; $i++) {
… [659 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Name        Length
----        ------
icon128.png   1676
icon16.png     332
icon48.png     672
C:\Program Files\Google\Chrome\Application\chrome.exe
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;S="&amp;lt;scratchpad&amp;gt;"; mkdir -p "$S"; cp "~/Documents/Hacktoberfest/2026/DEV Chall...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ S="&amp;lt;scratchpad&amp;gt;"; mkdir -p "$S"; cp "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension/budget.js" "$S/"; cat &amp;gt; "$S/t.html" &amp;lt;&amp;lt;'EOF'
&amp;lt;pre id=o&amp;gt;&amp;lt;/pre&amp;gt;&amp;lt;script type=module&amp;gt;
import {evaluate,payCycle} from "./budget.js";
const st={income:1500,fixed:900,savings:100,payday:1,currency:"EUR"}; // libre 500
const out=[];const T=(l,p,pur,d)=&amp;gt;{const r=evaluate(p,st,pur,new Date(d));out.push(l+" "+JSON.
… [957 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;dia3 30€ {"v":"green","el":3,"days":31,"left":29,"onPace":48.39,"rem":500}
dia3 200€ {"v":"yellow","el":3,"days":31,"left":29,"onPace":48.39,"rem":500,"wait":10}
dia28 200€ {"v":"green","el":28,"days":31,"left":4,"onPace":451.61,"rem":500}
dia15 900€ {"v":"red","el":15,"days":31,"left":17,"onPace":241.94,"rem":500,"mA":1,"mH":2}
dia15 gastado450 100€ {"v":"red","el":15,"days":31,"left":17,"onPace"
… [1154 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Las cuentas del presupuesto dan lo esperado en todos los casos que he probado. Veamos cómo va la descarga del modelo.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cat "&amp;lt;scratchpad&amp;gt;" | tr '\r' '\n' | tail -3&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cat "&amp;lt;scratchpad&amp;gt;" | tr '\r' '\n' | tail -3&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.35.1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;curl -s -o /dev/null -w "%{http_code}\n" -H "Origin: chrome-extension://abcde...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ curl -s -o /dev/null -w "%{http_code}\n" -H "Origin: chrome-extension://abcdefghijklmnop" localhost:11434/api/tags; "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;403
NAME    ID    SIZE    MODIFIED&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ollama rechaza las peticiones que vienen de extensiones del navegador. Para que la extensión pueda hablar con él hay que darle permiso con una variable de entorno:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-powershell"&gt;PowerShell&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;[Environment]::SetEnvironmentVariable("OLLAMA_ORIGINS", "chrome-extension://*...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;[Environment]::SetEnvironmentVariable("OLLAMA_ORIGINS", "chrome-extension://*", "User"); [Environment]::GetEnvironmentVariable("OLLAMA_ORIGINS","User")&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;chrome-extension://*&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Mientras termina la descarga, escribo el README y la licencia, que el reto pide que el código sea abierto:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md

# FinDeMes 💸

**¿M...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md

# FinDeMes 💸

**¿Me lo puedo permitir?** Una extensión de navegador que, cuando estás mirando un producto en cualquier tienda online, te enseña un semáforo:

- 🟢 **Te lo puedes permitir**: entra en tu ritmo de gasto del mes.
- 🟡 **Puedes, pero te aprieta**: te dice cuánto te quedaría al día hasta que cobres y cuántos días esperar para que 
… [2510 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; cat &amp;gt; LICENSE &amp;lt;&amp;lt;'EOF'...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; cat &amp;gt; LICENSE &amp;lt;&amp;lt;'EOF'
MIT License

Copyright (c) 2026 David Antón

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distrib
… [793 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;David Anton Alvarez
&amp;lt;email&amp;gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; sed -i 's/Copyright (...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; sed -i 's/Copyright (c) 2026 David Antón/Copyright (c) 2026 David Anton Alvarez/' LICENSE; "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list; cat "&amp;lt;scratchpad&amp;gt;" | tr '\r' '\n' | tail -2&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;NAME    ID    SIZE    MODIFIED 
{"version":"0.35.1"}&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-monitor"&gt;Monitor&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;until "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list | grep -q gemma3; do s...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;until "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list | grep -q gemma3; do sleep 15; done; echo listo&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;&amp;lt;tool_use_error&amp;gt;InputValidationError: Monitor failed due to the following issue:
The required parameter `description` is missing

This tool's schema was not sent to the API — it was not in the discovered-tool set derived from message history. Without the schema in your prompt, typed parameters (arrays, numbers, booleans) get emitted as strings and the client-side parser rejects them. Load the tool
… [1178 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-toolsearch"&gt;ToolSearch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;select:Monitor&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;select:Monitor&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;python --version 2&amp;gt;&amp;amp;1; py --version 2&amp;gt;&amp;amp;1&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ python --version 2&amp;gt;&amp;amp;1; py --version 2&amp;gt;&amp;amp;1&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Python 3.14.0b2
Python 3.14.0b2&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\demo\index.html

&amp;lt;!doctype ht...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\demo\index.html

&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang="es"&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;title&amp;gt;Auriculares SonoMax Pro – TiendaDemo&amp;lt;/title&amp;gt;
  &amp;lt;style&amp;gt;
    body { font: 16px/1.5 system-ui, sans-serif; margin: 0; color: #222; }
    header { background: #222; color: #fff; padding: 12px 24px; }
    main { display: flex; gap: 32px; max-width: 960px; margin: 32
… [1135 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: ~\Documents\Hacktoberfest\2026\DEV Challenges\1\demo\index.html (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;until "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list | grep -q gemma3; do s...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ until "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list | grep -q gemma3; do sleep 10; done; "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Command did not complete within its 600s timeout and was moved to the background (ID: blahiryga). Output is being written to: &amp;lt;scratchpad&amp;gt; You will be notified when it completes. To check interim output, use Read on that file path.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cat "&amp;lt;scratchpad&amp;gt;" | tr '\r' '\n' | grep -v '^$' | tail -3; "%LOCALAPPDATA%/P...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cat "&amp;lt;scratchpad&amp;gt;" | tr '\r' '\n' | grep -v '^$' | tail -3; "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;pulling aeda25e63ebd:   6% ▕█                 ▏ 210 MB/3.3 GB                  [K[?25h[?2026l
Error: max retries exceeded: write ~\.ollama\models\blobs\sha256-aeda25e63ebd698fab8638ffb778e68bed908b960d39d0becc650fa981609d25-partial: There is not enough space on the disk.
[exited with code 0]
NAME    ID    SIZE    MODIFIED&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;La descarga ha fallado porque &lt;strong&gt;no queda espacio en el disco&lt;/strong&gt;. Miro cuánto espacio libre hay:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-powershell"&gt;PowerShell&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Get-PSDrive -PSProvider FileSystem | Select-Object Name, @{n='LibreGB';e={[ma...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Get-PSDrive -PSProvider FileSystem | Select-Object Name, @{n='LibreGB';e={[math]::Round($_.Free/1GB,2)}}, @{n='UsadoGB';e={[math]::Round($_.Used/1GB,1)}}; $p = "$env:USERPROFILE\.ollama\models\blobs"; if (Test-Path $p) { Get-ChildItem $p | Select Name, @{n='MB';e={[math]::Round($_.Length/1MB)}} }&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Name                                                                               LibreGB UsadoGB
----                                                                               ------- -------
C                                                                                     0,05   475,3
D                                                                                    39,33   696,9

… [1781 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-taskstop"&gt;TaskStop&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"task_id": "blahiryga"}&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"task_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blahiryga"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"message":"Successfully stopped task: blahiryga (until \"%LOCALAPPDATA%/Programs/Ollama/ollama.exe\" list | grep -q gemma3; do sleep 10; done; \"%LOCALAPPDATA%/Programs/Ollama/ollama.exe\" list)","task_id":"blahiryga","task_type":"local_bash","command":"until \"%LOCALAPPDATA%/Programs/Ollama/ollama.exe\" list | grep -q gemma3; do sleep 10; done; \"%LOCALAPPDATA%/Programs/Ollama/ollama.exe\" list"
… [1 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-powershell"&gt;PowerShell&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Get-Process ollama*, "ollama app" -ErrorAction SilentlyContinue | Stop-Proces...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Get-Process ollama*, "ollama app" -ErrorAction SilentlyContinue | Stop-Process -Force -Confirm:$false
Remove-Item "$env:USERPROFILE\.ollama\models\blobs\*-partial*" -Force -Confirm:$false
New-Item -ItemType Directory -Force "D:\ollama\models" | Out-Null
[Environment]::SetEnvironmentVariable("OLLAMA_MODELS", "D:\ollama\models", "User")
$env:OLLAMA_MODELS = "D:\ollama\models"; $env:OLLAMA_ORIGINS = 
… [333 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;origin check: 200
C_LibreGB
---------
     1,96&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ollama ya acepta peticiones de la extensión y C: ha recuperado 2 GB. Descargo de nuevo el modelo, esta vez en D:.&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;"%LOCALAPPDATA%/Programs/Ollama/ollama.exe" pull gemma3:4b 2&amp;gt;&amp;amp;1 | tr '\r' '\n...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" pull gemma3:4b 2&amp;gt;&amp;amp;1 | tr '\r' '\n' | grep -E "success|Error" ; "%LOCALAPPDATA%/Programs/Ollama/ollama.exe" list&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Command running in background with ID: bjuggsm9z. Output is being written to: &amp;lt;scratchpad&amp;gt; You will be notified when it completes. To check interim output, use Read on that file path.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;&amp;lt;scratchpad&amp;gt;

# Reproduce la llamada de extracción de background.js contra va...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;&amp;lt;scratchpad&amp;gt;

# Reproduce la llamada de extracción de background.js contra varias páginas de texto.
import json, re, time, urllib.request

bg = open(r"~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js", encoding="utf-8").read()
prompt = re.search(r"const EXTRACT_PROMPT = `(.*?)`;", bg, re.S).group(1)
schema = {"type": "object", "properties": {"is_product_page": {"type": "bool
… [1619 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;File created successfully at: &amp;lt;scratchpad&amp;gt; (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;until grep -qE "success|Error" "&amp;lt;scratchpad&amp;gt;"; do sleep 10; done; cat "&amp;lt;scrat...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ until grep -qE "success|Error" "&amp;lt;scratchpad&amp;gt;"; do sleep 10; done; cat "&amp;lt;scratchpad&amp;gt;"&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;success [K[?25h[?2026l
NAME         ID              SIZE      MODIFIED               
gemma3:4b    a2af6cc3eb7f    3.3 GB    Less than a second ago    

[exited with code 0]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Gemma ya está descargado. Pruebo si sabe leer bien las páginas:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;PYTHONIOENCODING=utf-8 python "&amp;lt;scratchpad&amp;gt;"&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ PYTHONIOENCODING=utf-8 python "&amp;lt;scratchpad&amp;gt;"&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;demo      92.9s {"is_product_page":true, "product_name":"SonoMax Pro", "price":179.99, "currency":"EUR"}
listado    8.1s {"is_product_page":false,"product_name":"zapatillas","price":129.95,"currency":"EUR"}
en         9.4s {"is_product_page": true, "product_name": "Acer Swift Go 14 Laptop", "price": 749.00, "currency": "USD"}&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js
--- o...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js
--- old
chrome.runtime.onInstalled.addListener(({ reason }) =&amp;gt; {
  if (reason === "install") chrome.runtime.openOptionsPage();
});
+++ new
// Cargar el modelo en memoria al abrir el navegador: la primera respuesta en frío puede tardar más de un minuto.
async function warmUp() {
  const settings = await getSettings();
  fetch(`
… [336 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;The file ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js has been updated successfully. (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; sed -i 's/keep_alive:...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; sed -i 's/keep_alive: "15m"/keep_alive: "30m"/' extension/background.js &amp;amp;&amp;amp; cat &amp;gt; "$TEMP/note.json" &amp;lt;&amp;lt;'EOF'
{"model":"gemma3:4b","stream":false,"options":{"temperature":0.7},"messages":[{"role":"system","content":"Eres un amigo cercano, sincero y con humor que ayuda a llegar a fin de mes. Hablas con Pablo. Escribe UNA sola frase en español (má
… [436 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Oye, con 11 euros al día y un SonoMax Pro que te aprieta, ¡es el momento de priorizar tu paz mental, ¿no?


real    0m6.356s
user    0m0.015s
sys 0m0.046s&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;La frase del amigo sale en unos 6 s. Guardo el trabajo en git:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git add -A &amp;amp;&amp;amp; git com...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git add -A &amp;amp;&amp;amp; git commit -q -m "FinDeMes: extensión que dice si te puedes permitir un producto, con Gemma en local

Co-Authored-By: Claude Opus 5.5 &amp;lt;noreply@anthropic.com&amp;gt;" &amp;amp;&amp;amp; git log --oneline &amp;amp;&amp;amp; git status --short&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;warning: in the working copy of 'LICENSE', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'demo/index.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'extension/background.js', LF will be replaced by CRLF the
… [909 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Y arranco la tienda de prueba para que puedas verla funcionar ya mismo:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/demo" &amp;amp;&amp;amp; python -m http.s...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/demo" &amp;amp;&amp;amp; python -m http.server 8000&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Command running in background with ID: bochs308p. Output is being written to: &amp;lt;scratchpad&amp;gt; You will be notified when it completes. To check interim output, use Read on that file path.
Session cwd remains ~\Documents\Hacktoberfest\2026\DEV Challenges\1; directory changes made by the backgrounded command do not apply to subsequent commands.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Sí se podía hacer con IA en local, y &lt;strong&gt;FinDeMes&lt;/strong&gt; ya está construido. Es una extensión para Chrome o Edge que, al abrir la ficha de un producto en cualquier tienda, enseña un semáforo en la esquina:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🟢 &lt;strong&gt;Te lo puedes permitir:&lt;/strong&gt; dice cuánto le quedaría al día hasta cobrar.&lt;/li&gt;
&lt;li&gt;🟡 &lt;strong&gt;Puedes, pero te aprieta:&lt;/strong&gt; además dice cuántos días esperar para que entre en su ritmo de gasto.&lt;/li&gt;
&lt;li&gt;🔴 &lt;strong&gt;Ahora no:&lt;/strong&gt; dice en cuántos meses podría comprarlo sin tocar sus ahorros.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lleva también una frase corta escrita por Gemma, como lo diría un amigo, y un botón &lt;strong&gt;"Lo he comprado"&lt;/strong&gt; que resta el gasto del mes. Le he añadido el día de cobro, porque el mes de tu amigo empieza cuando cobra, no el día 1.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;El reparto de trabajo, que es lo que contarás en el post:&lt;/strong&gt; Gemma lee la página, decide si es un producto y saca el precio real, sin programar un lector para cada tienda. Las cuentas del presupuesto son código normal, porque tienen que ser exactas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lo que he comprobado:&lt;/strong&gt;&lt;br&gt;
- Las cuentas del presupuesto dan lo esperado en todos los casos que probé.&lt;br&gt;
- Gemma acierta en tres páginas de prueba: elige el precio bueno y no el tachado, el del envío ni el de plazos; distingue un listado de búsqueda de una ficha de producto; y funciona en inglés.&lt;br&gt;
- La frase del amigo tarda unos 6 s y el semáforo unos 9 s. La primera vez que se carga el modelo tarda más de un minuto; por eso la extensión lo precarga al abrir el navegador.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lo que no he probado:&lt;/strong&gt; la extensión cargada en el navegador de principio a fin, porque Chrome no me deja instalarla por ti. Si algo falla al probarla, pégame el error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dos cosas que he cambiado en tu PC:&lt;/strong&gt;&lt;br&gt;
- Tu &lt;strong&gt;disco C: estaba lleno&lt;/strong&gt; (le quedaban 50 MB) y la primera descarga del modelo falló. He movido los modelos de Ollama a &lt;code&gt;D:\ollama\models&lt;/code&gt; y C: tiene ahora unos 2 GB libres. Te conviene liberar más espacio pronto, porque Windows va mal con el disco tan lleno.&lt;br&gt;
- He añadido una variable de entorno para que Ollama acepte peticiones de extensiones del navegador.&lt;/p&gt;
&lt;h2 id="agent-session-513-5-pruébala-ahora-5-minutos"&gt;Pruébala ahora (5 minutos)&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;En Chrome abre &lt;code&gt;chrome://extensions&lt;/code&gt;, activa &lt;strong&gt;Modo desarrollador&lt;/strong&gt;, pulsa &lt;strong&gt;Cargar descomprimida&lt;/strong&gt; y elige la carpeta &lt;code&gt;extension&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Se abre la configuración. Mete los números de tu amigo (o unos inventados) y pulsa &lt;strong&gt;Probar conexión&lt;/strong&gt; en "IA local", que debería decir "Todo listo ✔".&lt;/li&gt;
&lt;li&gt;Abre la tienda de prueba que tengo arrancada en &lt;strong&gt;&lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt;&lt;/strong&gt; y después prueba en una tienda real.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="agent-session-513-5-lo-que-queda-cierra-en-13-h-el-5-oct-a-las-0659-utc-en-españa-a-las-0859"&gt;Lo que queda (cierra en ~13 h, el 5 oct a las 06:59 UTC; en España, a las 08:59)&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Que la pruebe tu amigo&lt;/strong&gt; y apuntar qué dice. Da puntos extra y es lo mejor del post.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capturas o un GIF&lt;/strong&gt; del semáforo en los tres colores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subir el código a GitHub.&lt;/strong&gt; Ya está guardado en git en local. Si quieres, creo el repo público y lo subo, pero confírmamelo antes porque lo publica.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;El post en DEV.&lt;/strong&gt; Te lo redacto como borrador con el tag &lt;code&gt;#hf26challenge&lt;/code&gt;, centrado en tu amigo y en por qué es importante que todo sea local: sus webs y su dinero no salen de su ordenador. Tú lo revisas y lo publicas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;¿Lo pruebas y me cuentas qué tal?&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Antes de hacer nada, quiero dos cosas:&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Vale, no toco nada. Tu mensaje se ha cortado después de "dos cosas:" y no me ha llegado cuáles son. ¿Me las escribes?&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Antes de hacer nada, quiero dos cosas:&lt;/p&gt;

                &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;[Request interrupted by user]&lt;/p&gt;

                &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Antes de hacer nada quiero dos cosas: la primera, es que el readme lo quiero en inglés primero (el organizador del hacktoberfest es angloparlante) y después en Español. Por esta misma razón, hay que cambiar el nombre de la app, que quiero que sea Should I Buy, y que los textos de meter los datos estén también en inglés&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-grep"&gt;Grep&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"pattern": "FinDeMes|findemes", "path": "~\\Documents\\Hacktoberfest\\2026\\...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FinDeMes|findemes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Documents&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Hacktoberfest&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;2026&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;DEV Challenges&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"output_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"-i"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;extension\content.js:105:      title.textContent = "FinDeMes no puede pensar";
extension\options.html:5:  &amp;lt;title&amp;gt;FinDeMes · Configuración&amp;lt;/title&amp;gt;
extension\options.html:21:  &amp;lt;h1&amp;gt;FinDeMes 💸&amp;lt;/h1&amp;gt;
extension\popup.html:18:  &amp;lt;h2&amp;gt;FinDeMes 💸&amp;lt;/h2&amp;gt;
README.md:1:# FinDeMes 💸
README.md:13:FinDeMes ve **todas las tiendas que visitas** y conoce **tu sueldo, tus gastos y tus ahorros**. Esos datos no deberían sal
… [126 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension" &amp;amp;&amp;amp; sed -i 's/"...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension" &amp;amp;&amp;amp; sed -i 's/"name": "FinDeMes"/"name": "Should I Buy"/; s/"default_title": "FinDeMes"/"default_title": "Should I Buy"/; s/"description": ".*"/"description": "Can I afford it? A traffic light for every product you look at, powered by AI that runs on your own computer."/' manifest.json &amp;amp;&amp;amp; sed -i 's/FinDeMes no puede pensar/Should I Buy 
… [134 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;3:  "name": "Should I Buy",
5:  "description": "Can I afford it? A traffic light for every product you look at, powered by AI that runs on your own computer.",
21:    "default_title": "Should I Buy"&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ahora la página de configuración en inglés:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.html

&amp;lt;!doc...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.html

&amp;lt;!doctype html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;title&amp;gt;Should I Buy · Settings&amp;lt;/title&amp;gt;
  &amp;lt;style&amp;gt;
    body { font: 15px/1.5 system-ui, sans-serif; max-width: 520px; margin: 40px auto; padding: 0 16px; color: #1a202c; }
    h1 { margin-bottom: 4px; }
    .sub { color: #4a5568; margin-top: 0; }
    label { disp
… [2074 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;The file ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\options.html has been updated successfully. (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension" &amp;amp;&amp;amp; sed -i \
 -...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension" &amp;amp;&amp;amp; sed -i \
 -e 's/`Te quedan ${money(free, s.currency)} libres al mes para el día a día y los caprichos.`/`You have ${money(free, s.currency)} free each month for day-to-day spending and treats.`/' \
 -e 's/"Con estos números no te queda dinero libre al mes."/"With these numbers you have no free money left each month."/' \
 -e 's/"Gua
… [361 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;17:  $("free").textContent =
32:  $("status").textContent = "Saved ✔";
33:  setTimeout(() =&amp;gt; ($("status").textContent = ""), 2000);
38:  $("ollama").textContent = "Testing…";
41:    $("ollama").textContent = `Cannot connect: ${res.error}`;
43:    $("ollama").textContent = `Connected, but the model is missing. Run: ollama pull ${read().model}`;
45:    $("ollama").textContent = "All set ✔";&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ahora el README, primero en inglés y después en español:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md

# Should I Buy 💸

...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md

# Should I Buy 💸

[English](#english) · [Español](#español)

## English

**Can I afford it?** A browser extension that shows you a traffic light whenever you're looking at a product in any online shop:

- 🟢 **You can afford it**: it fits your spending pace for the month.
- 🟡 **You can, but it's tight**: it tells you how much you'd have lef
… [5060 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;The file ~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md has been updated successfully. (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; grep -rni findemes . ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; grep -rni findemes . --exclude-dir=.git; python -c "import json;json.load(open('extension/manifest.json',encoding='utf-8'))" &amp;amp;&amp;amp; git add -A &amp;amp;&amp;amp; git commit -q -m "Rename to Should I Buy; English settings page and bilingual README

Co-Authored-By: Claude Opus 5.5 &amp;lt;noreply@anthropic.com&amp;gt;" &amp;amp;&amp;amp; git log --oneline | head -1&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'extension/content.js', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'extension/manifest.json', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'extension/options.html', LF will be 
… [346 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;He hecho los dos cambios y los he guardado en git:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;README bilingüe:&lt;/strong&gt; ahora va primero en inglés y después en español, con enlaces arriba para saltar a cada idioma.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La app se llama Should I Buy:&lt;/strong&gt; he cambiado el nombre en el manifest, en la descripción de la extensión (ahora en inglés), en el popup y en el aviso de error. &lt;strong&gt;Toda la página de configuración está en inglés&lt;/strong&gt;: los campos, las ayudas y los mensajes de guardar y de probar la conexión.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Si ya habías cargado la extensión en Chrome, pulsa el botón de recargar en &lt;code&gt;chrome://extensions&lt;/code&gt; para ver los cambios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lo que sigue en español:&lt;/strong&gt;&lt;br&gt;
- El semáforo que aparece en las tiendas: "Te lo puedes permitir", el botón "Lo he comprado", etc.&lt;br&gt;
- El popup con el resumen del mes.&lt;br&gt;
- La frase que escribe Gemma.&lt;br&gt;
- Las cantidades se escriben al estilo español ("179,99 €").&lt;/p&gt;

&lt;p&gt;Si tu amigo habla español puede tener sentido dejarlo así, pero los jueces verán las capturas con textos en español. ¿Lo paso todo a inglés o lo dejo como está?&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Pásalo todo al inglés, pero deja los presupuestos en Euros&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;1    import { DEFAULT_SETTINGS, evaluate, money } from "./budget.js";
2   
3   const EXTRACT_SCHEMA = {
4     type: "object",
5     properties: {
6       is_product_page: { type: "boolean" },
7       product_name: { type: "string" },
8       price: { type: "number" },
9       currency: { type: "string" },
10    },
11    required: ["is_product_page", "product_name", "price", "currency"],
12  };
13  
14  const EXTRACT_PROM
… [7053 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-write"&gt;Write&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js

impo...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js

import { DEFAULT_SETTINGS, evaluate, money } from "./budget.js";

const EXTRACT_SCHEMA = {
  type: "object",
  properties: {
    is_product_page: { type: "boolean" },
    product_name: { type: "string" },
    price: { type: "number" },
    currency: { type: "string" },
  },
  required: ["is_product_page", "product_name", "pri
… [6470 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;The file ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension\background.js has been updated successfully. (file state is current in your context — no need to Read it back)&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension" &amp;amp;&amp;amp; sed -i \
 -...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension" &amp;amp;&amp;amp; sed -i \
 -e 's|// Lógica del presupuesto. Sin IA: las cuentas tienen que ser exactas y explicables.|// Budget logic. No AI here: the maths has to be exact and explainable.|' \
 -e 's|// ingresos netos al mes|// monthly net income|' \
 -e 's|// gastos fijos al mes (alquiler, facturas, suscripciones...)|// monthly fixed expenses (ren
… [1169 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;1:// Budget logic. No AI here: the maths has to be exact and explainable.
5:  income: 0,        // monthly net income
6:  fixed: 0,         // monthly fixed expenses (rent, bills, subscriptions...)
7:  savings: 0,       // what gets put aside every month
8:  payday: 1,        // day of the month the salary arrives (1-28)
11:  ollamaUrl: "http://localhost:11434",
20:// Current pay cycle: from the l
… [547 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ahora el semáforo de las tiendas y el popup:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension" &amp;amp;&amp;amp; sed -i \
 -...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/extension" &amp;amp;&amp;amp; sed -i \
 -e 's|// Se ejecuta en cada página. Solo despierta a la IA si la página "huele" a tienda.|// Runs on every page. Only wakes the AI up if the page "smells" like a shop.|' \
 -e 's|// ---------- Interfaz ----------|// ---------- UI ----------|' \
 -e 's|green: "Te lo puedes permitir", yellow: "Puedes, pero te aprieta", red: 
… [1926 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Exit code 2
grep: -P supports only unibyte and UTF-8 locales&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-grep"&gt;Grep&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"pattern": "[áéíóúñ¿¡]|Pensando|Ahora no|carrito", "path": "~\\Documents\\Ha...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[áéíóúñ¿¡]|Pensando|Ahora no|carrito"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Documents&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Hacktoberfest&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;2026&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;DEV Challenges&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;extension"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"output_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;content.js:3:  const BUY_WORDS = /añadir al carrito|añadir a la cesta|comprar ahora|add to (cart|basket|bag)|buy now|in den warenkorb|ajouter au panier|aggiungi al carrello|adicionar ao carrinho/i;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/demo" &amp;amp;&amp;amp; sed -i \
 -e 's|...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/demo" &amp;amp;&amp;amp; sed -i \
 -e 's|lang="es"|lang="en"|' \
 -e 's|Auriculares SonoMax Pro – TiendaDemo|SonoMax Pro Headphones – DemoShop|' \
 -e 's|TiendaDemo · Carrito (0)|DemoShop · Cart (0)|' \
 -e 's|Auriculares inalámbricos SonoMax Pro|SonoMax Pro Wireless Headphones|' \
 -e 's|1.284 valoraciones|1,284 ratings|' \
 -e 's|249,99 €|€249.99|' -e 's|179,9
… [468 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;13:    button { padding: 12px 24px; font-size: 16px; background: #f6ad55; border: 0; border-radius: 8px; }
22:      &amp;lt;h1&amp;gt;SonoMax Pro Wireless Headphones&amp;lt;/h1&amp;gt;
24:      &amp;lt;p&amp;gt;&amp;lt;span class="old"&amp;gt;€249.99&amp;lt;/span&amp;gt; −28%&amp;lt;/p&amp;gt;
25:      &amp;lt;p class="price"&amp;gt;€179.99&amp;lt;/p&amp;gt;
26:      &amp;lt;p&amp;gt;Shipping: €4.95 · Free over €199&amp;lt;/p&amp;gt;
27:      &amp;lt;p&amp;gt;Or 3 instalments of €60.00&amp;lt;/p&amp;gt;
28:      &amp;lt;button&amp;gt;Add to cart&amp;lt;/button&amp;gt;
33:    &amp;lt;p&amp;gt;SonoMax Cas
… [64 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Actualizo las menciones al botón en el README y vuelvo a probar a Gemma con las instrucciones ya en inglés:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; sed -i -e 's|The \*\*...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; sed -i -e 's|The \*\*Lo he comprado\*\* ("I bought it") button|The **I bought it** button|' -e 's|Con el botón \*\*Lo he comprado\*\* apuntas|Con el botón **I bought it** apuntas|' README.md &amp;amp;&amp;amp; grep -n "bought" README.md
S="&amp;lt;scratchpad&amp;gt;"
sed -i 's|"demo": "TiendaDemo.*",$|"demo": "DemoShop · Cart (0) 🎧 SonoMax Pro Wireless Headphones ⭐⭐⭐⭐☆ 1,
… [989 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;37:   - The **I bought it** button logs the purchase and subtracts it from the month.
83:   - Con el botón **I bought it** apuntas el gasto y se resta del mes.
demo      28.5s {"is_product_page":true, "product_name":"SonoMax Pro Wireless Headphones", "price":179.99, "currency":"EUR"}
listado    8.8s {"is_product_page":false,"product_name":"","price":0,"currency":""}
en        11.9s {"is_product_
… [205 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Con las instrucciones en inglés Gemma sigue acertando en los tres casos. Guardo:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git add -A &amp;amp;&amp;amp; git com...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git add -A &amp;amp;&amp;amp; git commit -q -m "Translate the whole extension and demo shop to English; keep budgets in euros

Co-Authored-By: Claude Opus 5.5 &amp;lt;noreply@anthropic.com&amp;gt;" 2&amp;gt;/dev/null; git log --oneline | head -1; git status --short&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'demo/index.html', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'extension/background.js', LF will be replaced by CRLF the next time Git touches it
warning: in the working copy of 'extension/budget.js', LF will be replaced
… [460 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Toda la extensión está ya en inglés y los presupuestos siguen en euros. Los cambios están guardados en git.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Semáforo de las tiendas:&lt;/strong&gt; "You can afford it", "You can, but it's tight" y "Not now". El botón es &lt;strong&gt;I bought it&lt;/strong&gt;, y los textos de "Thinking…" y de error también están en inglés.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Popup:&lt;/strong&gt; el resumen del mes (Free money this month, Purchases logged, Left) y el enlace a Settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La frase de Gemma:&lt;/strong&gt; ahora la escribe en inglés. Ejemplo de la prueba: &lt;em&gt;"Okay, Pablo, that SonoMax Pro sounds… intense, but hey, €320 and €11 a day could work, just chill for a bit!"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Euros:&lt;/strong&gt; EUR sigue siendo la moneda por defecto y las cantidades se escriben al estilo inglés, "€179.99".&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Las instrucciones internas que le da la extensión a Gemma&lt;/strong&gt; y los comentarios del código también están en inglés, porque el jurado puede leer el repo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;La tienda de prueba&lt;/strong&gt; está en inglés con precios en euros. El README ya nombra el botón como &lt;strong&gt;I bought it&lt;/strong&gt; en las dos versiones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;He vuelto a probar a Gemma con las instrucciones en inglés y sigue acertando en los tres casos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tienda demo:&lt;/strong&gt; elige €179.99, no el precio tachado ni el envío.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Listado de búsqueda:&lt;/strong&gt; dice correctamente que no es un producto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Página en inglés:&lt;/strong&gt; elige $749, no el precio de lista.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sigue reconociendo tiendas en español, francés, alemán, etc., porque esas palabras de "añadir al carrito" se quedan a propósito.&lt;/p&gt;

&lt;p&gt;La extensión sigue sin probarse en el navegador de principio a fin, porque eso tienes que hacerlo tú. Si ya la habías cargado, pulsa recargar en &lt;code&gt;chrome://extensions&lt;/code&gt;. La tienda de prueba sigue en &lt;strong&gt;&lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Lo que queda antes del cierre (5 oct, 06:59 UTC):&lt;br&gt;
1. Que la pruebe tu amigo y apuntar su reacción.&lt;br&gt;
2. Capturas o un GIF del semáforo en verde, amarillo y rojo.&lt;br&gt;
3. Subir el repo a GitHub, cuando me confirmes que lo publique.&lt;br&gt;
4. El post en DEV, que te dejo como borrador para que lo revises. ¿En inglés también?&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;ya estoy en chrome://extensions en modo desarrollador, ¿que hago ahora?&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;curl -s -o /dev/null -w "ollama %{http_code}\n" -H "Origin: chrome-extension:...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ curl -s -o /dev/null -w "ollama %{http_code}\n" -H "Origin: chrome-extension://x" localhost:11434/api/tags; curl -s -o /dev/null -w "demo %{http_code}\n" localhost:8000/&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;ollama 200
demo 200&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Ollama y la tienda de prueba están funcionando. Sigue estos pasos:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Cargar la extensión&lt;/strong&gt;&lt;br&gt;
- Arriba a la izquierda, pulsa &lt;strong&gt;"Cargar descomprimida"&lt;/strong&gt; (en inglés, "Load unpacked").&lt;br&gt;
- En la ventana que se abre, ve a esta carpeta y pulsa &lt;strong&gt;"Seleccionar carpeta"&lt;/strong&gt;:&lt;br&gt;
  &lt;code&gt;&lt;br&gt;
  ~\Documents\Hacktoberfest\2026\DEV Challenges\1\extension&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
  Elige la carpeta &lt;code&gt;extension&lt;/code&gt;, no la &lt;code&gt;1&lt;/code&gt; que está por encima.&lt;br&gt;
- Aparecerá la tarjeta &lt;strong&gt;Should I Buy&lt;/strong&gt; y se abrirá sola la página de configuración. Si no se abre, en la tarjeta pulsa &lt;strong&gt;Detalles&lt;/strong&gt; y luego &lt;strong&gt;Opciones de extensión&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Configurarla&lt;/strong&gt;&lt;br&gt;
- Rellena los campos con los números de tu amigo, o con unos de prueba como Income 1500, Fixed expenses 900, Savings 100 y Payday 1.&lt;br&gt;
- Abre &lt;strong&gt;"Local AI (Ollama)"&lt;/strong&gt; y pulsa &lt;strong&gt;Test connection&lt;/strong&gt;. Debe decir &lt;strong&gt;"All set ✔"&lt;/strong&gt;.&lt;br&gt;
- Pulsa &lt;strong&gt;Save&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Fijarla en la barra&lt;/strong&gt;&lt;br&gt;
- Pulsa el icono de la pieza de puzle 🧩, arriba a la derecha de Chrome, y luego la chincheta 📌 junto a Should I Buy. Así verás el icono del semáforo para abrir el resumen del mes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Probarla&lt;/strong&gt;&lt;br&gt;
- Abre &lt;strong&gt;&lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt;&lt;/strong&gt;. Abajo a la derecha saldrá "🤔 Thinking…" y, unos segundos después, el semáforo con los auriculares a €179.99.&lt;br&gt;
- Prueba también en una tienda real, por ejemplo la ficha de cualquier producto de Amazon o PcComponentes.&lt;/p&gt;

&lt;p&gt;Si en algún paso ves un error en rojo en la tarjeta de la extensión o el semáforo no aparece, pégame lo que te sale o mándame una captura.&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;veo bien la aplicación, tengo varias capturas, voy a crear en github el repo&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;¡Genial que funcione! Al crear el repo en GitHub:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hazlo &lt;strong&gt;público&lt;/strong&gt;, porque el reto pide que se pueda ver el código.&lt;/li&gt;
&lt;li&gt;Déjalo &lt;strong&gt;vacío&lt;/strong&gt;: no marques "Add a README", ni licencia, ni .gitignore. Ya los tenemos en local y, si GitHub crea los suyos, chocarían al subir.&lt;/li&gt;
&lt;li&gt;Un nombre que encaja: &lt;code&gt;should-i-buy&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cuando lo tengas, &lt;strong&gt;pásame la URL&lt;/strong&gt; y lo subo yo con tus 3 commits. Si prefieres hacerlo tú, son estos comandos desde la carpeta del proyecto:&lt;/p&gt;

&lt;pre class="highlight"&gt;&lt;code&gt;git remote add origin https://github.com/TU_USUARIO/should-i-buy.git
git branch -M main
git push -u origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Y las capturas:&lt;/strong&gt; si me dices en qué carpeta las tienes, las meto en el repo (en &lt;code&gt;docs/screenshots/&lt;/code&gt;) y las enseño en el README antes de subirlo. Quedan muy bien para el jurado y luego las reutilizamos en el post de DEV.&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;&lt;a href="https://github.com/Virien84/Should-I-Buy.git" rel="noopener noreferrer"&gt;https://github.com/Virien84/Should-I-Buy.git&lt;/a&gt;&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git ls-remote https:/...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git ls-remote https://github.com/Virien84/Should-I-Buy.git 2&amp;gt;&amp;amp;1 | head -5; echo "---"; git remote -v&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;---&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;El repo existe y está vacío. Subo el código:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git remote add origin...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git remote add origin https://github.com/Virien84/Should-I-Buy.git &amp;amp;&amp;amp; git branch -M main &amp;amp;&amp;amp; git push -u origin main 2&amp;gt;&amp;amp;1 | tail -4&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;branch 'main' set up to track 'origin/main'.
To https://github.com/Virien84/Should-I-Buy.git
 * [new branch]      main -&amp;gt; main&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git ls-remote origin ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git ls-remote origin &amp;amp;&amp;amp; git log --oneline&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;fcd27f48922d8d357488cf86e34f04971ff53318 HEAD
fcd27f48922d8d357488cf86e34f04971ff53318    refs/heads/main
fcd27f4 Translate the whole extension and demo shop to English; keep budgets in euros
c96a6a0 Rename to Should I Buy; English settings page and bilingual README
59421c6 FinDeMes: extensión que dice si te puedes permitir un producto, con Gemma en local&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;El código ya está en GitHub: &lt;strong&gt;&lt;a href="https://github.com/Virien84/Should-I-Buy" rel="noopener noreferrer"&gt;https://github.com/Virien84/Should-I-Buy&lt;/a&gt;&lt;/strong&gt;. Lo que hay en GitHub coincide con tu copia local: los 3 commits en la rama &lt;code&gt;main&lt;/code&gt;, con la extensión, la tienda de prueba, el README bilingüe y la licencia MIT. El primer commit todavía se llama "FinDeMes" en su mensaje; no pasa nada, es solo el historial.&lt;/p&gt;

&lt;p&gt;Siguientes pasos, para los que necesito dos datos tuyos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Capturas:&lt;/strong&gt; ¿en qué carpeta las tienes? Las meto en &lt;code&gt;docs/screenshots/&lt;/code&gt;, las enseño en el README y lo subo. Así el repo se ve bien cuando lo abra el jurado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;El post en DEV:&lt;/strong&gt; ¿lo escribo en inglés, como el resto? Y si tu amigo ya lo ha probado, cuéntame qué dijo, aunque sea en una frase. Esa reacción da puntos extra y es lo que más luce en el post.&lt;/li&gt;
&lt;/ol&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Las capturas están en ~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots. Los nombres deberían ser bastante explicativos. El post de DEV escríbelo en inglés, como el resto. Mi amigo lo ha probado y le ha gustado, primero, que no tarda tanto, ya que mientras el mira las características del producto, el proceso piensa y el tiempo es óptimo, y lo segundo, es que agradece mucho el comentario realista y la estimación.&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-assistant"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-assistant"&gt;
          Agent
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; ls -la screenshots; g...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; ls -la screenshots; git status --short&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;total 1612
drwxr-xr-x 1 david 197609      0 Oct  4 23:08 .
drwxr-xr-x 1 david 197609      0 Oct  4 23:06 ..
-rw-r--r-- 1 david 197609  72989 Oct  4 23:06 Data introduction.jpg
-rw-r--r-- 1 david 197609 286352 Oct  4 23:08 green light after bought it.jpg
-rw-r--r-- 1 david 197609 276901 Oct  4 23:07 green light thinking.jpg
-rw-r--r-- 1 david 197609 294467 Oct  4 23:08 green light veredict.jpg
-rw-
… [221 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Antes de subirlas las miro, por si se ve algún dato personal (números reales, pestañas, cuentas):&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\Data introduction...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\Data introduction.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;[image: screenshot]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\green light think...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\green light thinking.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;[image: screenshot]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\green light vered...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\green light veredict.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;[image: screenshot]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\green light after...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\green light after bought it.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;[image: screenshot]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\yellow light vere...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\yellow light veredict.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;[image: screenshot]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\red light thinkin...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\red light thinking.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;[image: screenshot]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-read"&gt;Read&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\red light veredic...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\screenshots\red light veredict.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;[image: screenshot]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/screenshots" &amp;amp;&amp;amp; mv "Data ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1/screenshots" &amp;amp;&amp;amp; mv "Data introduction.jpg" settings.jpg &amp;amp;&amp;amp; mv "green light thinking.jpg" green-thinking.jpg &amp;amp;&amp;amp; mv "green light veredict.jpg" green-verdict.jpg &amp;amp;&amp;amp; mv "green light after bought it.jpg" green-bought.jpg &amp;amp;&amp;amp; mv "yellow light veredict.jpg" yellow-verdict.jpg &amp;amp;&amp;amp; mv "red light thinking.jpg" red-thinking.jpg &amp;amp;&amp;amp; mv "red light veredict.jpg" 
… [21 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;green-bought.jpg
green-thinking.jpg
green-verdict.jpg
red-thinking.jpg
red-verdict.jpg
settings.jpg
yellow-verdict.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md
--- old
I built it ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md
--- old
I built it for a friend who never makes it to the end of the month.

### Why open, local AI
+++ new
I built it for a friend who never makes it to the end of the month.

### Screenshots

| 🟢 You can afford it | 🟡 You can, but it's tight | 🔴 Not now |
|---|---|---|
| ![Green verdict on Amazon](screenshots/green-verdict.jpg) | ![Yellow
… [300 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;The file ~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md has been updated successfully.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-edit"&gt;Edit&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md
--- old
La hice par...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md
--- old
La hice para un amigo que nunca llega a fin de mes.

+++ new
La hice para un amigo que nunca llega a fin de mes.

Las capturas están en la [sección en inglés](#screenshots).&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;The file ~\Documents\Hacktoberfest\2026\DEV Challenges\1\README.md has been updated successfully.&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-bash"&gt;Bash&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git add -A &amp;amp;&amp;amp; git com...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre agent-session-terminal"&gt;&lt;code&gt;$ cd "~/Documents/Hacktoberfest/2026/DEV Challenges/1" &amp;amp;&amp;amp; git add -A &amp;amp;&amp;amp; git commit -q -m "Add screenshots to the README

Co-Authored-By: Claude Opus 5.5 &amp;lt;noreply@anthropic.com&amp;gt;" 2&amp;gt;/dev/null; git push -q 2&amp;gt;&amp;amp;1 | tail -2; git ls-remote origin main; git log --oneline -1; curl -s -o /dev/null -w "%{http_code}\n" https://raw.githubusercontent.com/Virien84/Should-I-Buy/main/screenshots/green-verdict.jpg&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;warning: in the working copy of 'README.md', LF will be replaced by CRLF the next time Git touches it
de12cff8308ab58f7bab2b6fcd5d246ee25b33f2    refs/heads/main
de12cff Add screenshots to the README
200&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Las capturas ya están en GitHub. Ahora el post para DEV:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-skill"&gt;Skill&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"skill": "devrelay-publishing", "args": "Draft DEV post for Hacktoberfest We...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"skill"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"devrelay-publishing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Draft DEV post for Hacktoberfest Weekend Challenge: Build for a Friend (#hf26challenge), project Should I Buy, in English"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Launching skill: devrelay-publishing&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-toolsearch"&gt;ToolSearch&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;select:mcp__devrelay-gateway__create_article,mcp__devrelay-gateway__get_my_ar...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;select:mcp__devrelay-gateway__create_article,mcp__devrelay-gateway__get_my_articles,mcp__devrelay-gateway__list_tags,mcp__devrelay-gateway__get_article_by_path,mcp__devrelay-gateway__get_article_content&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Busco la plantilla oficial de entrega del reto y si ya tienes algún borrador:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaysearchdevtosemantic"&gt;mcp__devrelay-gateway__search_dev_to_semantic&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;Hacktoberfest Weekend Challenge Build for a Friend announcement submission te...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;Hacktoberfest Weekend Challenge Build for a Friend announcement submission template hf26challenge&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"Ok":[{"id":4793441,"title":"This is a submission for the [Hacktoberfest Weekend Challenge: Build for a Friend]","description":"This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend           What I...","tags":["devchallenge","weekendchallenge","hf26challenge"],"path":"/devapraveen/this-is-a-submission-for-the-hacktoberfest-weekend-challenge-build-for-a-friend-1751","ur
… [2022 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaygetmyarticles"&gt;mcp__devrelay-gateway__get_my_articles&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"state": "unpublished"}&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"unpublished"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Ok"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaysearchdevtosemantic"&gt;mcp__devrelay-gateway__search_dev_to_semantic&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;browser extension local LLM Ollama privacy personal finance budgeting&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;browser extension local LLM Ollama privacy personal finance budgeting&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"Ok":[{"id":4564332,"title":"A small privacy decision that changed my web calculator","description":"I built Calculator Toolkit for a narrow moment: someone has a restaurant bill, wants to check the tip...","tags":["webdev","privacy","ux","discuss"],"path":"/laconicleon/a-small-privacy-decision-that-changed-my-web-calculator-5c99","url":"https://dev.to/laconicleon/a-small-privacy-decision-that-ch
… [2170 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaygetarticlecontent"&gt;mcp__devrelay-gateway__get_article_content&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"id": 4779462}&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4779462&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"Ok":"Hacktoberfest is here, and so is the first of our [**five Hacktoberfest DEV Challenges**](https://dev.to/devteam/hacktoberfest-2026-dev-challenges-five-challenges-one-prompt-a-new-theme-every-week-1e54): a **[Weekend Challenge](https://dev.to/challenges/hacktoberfest-weekend-2026-10-01)** sized to fit into your weekend.  We've set the timing so that wherever you are in the world, you'll hav
… [9362 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;Ya tengo la plantilla oficial y no tienes ningún borrador previo. Redacto el post:&lt;/p&gt;

                &lt;/div&gt;
              &lt;div class="agent-session-tool-call"&gt;
                
                  &lt;span class="agent-session-chevron"&gt;▸&lt;/span&gt;
                  &lt;span class="tool-name tool-name-mcpdevrelaygatewaycreatearticle"&gt;mcp__devrelay-gateway__create_article&lt;/span&gt;
                    &lt;span class="tool-input-preview"&gt;{"title": "Should I Buy: a traffic light for my friend who never makes it to ...&lt;/span&gt;
                
                &lt;div class="agent-session-tool-detail"&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Input&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"title": "Should I Buy: a traffic light for my friend who never makes it to the end of the month", "description": "A browser extension that tells you, on any shop page, whether you can afford what you're looking at, powered by Gemma running locally with Ollama.", "tags": ["devchallenge", "weekendchallenge", "hf26challenge", "gemma"], "main_image": "https://raw.githubusercontent.com/Virien84/Shoul
… [9462 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                    &lt;div class="tool-section"&gt;
                      &lt;div class="tool-section-label"&gt;Output&lt;/div&gt;
                      &lt;pre class="agent-session-pre"&gt;&lt;code&gt;{"Ok":{"id":4797614,"title":"Should I Buy: a traffic light for my friend who never makes it to the end of the month","description":"A browser extension that tells you, on any shop page, whether you can afford what you're looking at, powered by Gemma running locally with Ollama.","tag_list":["devchallenge","weekendchallenge","hf26challenge","gemma"],"user":{"name":"David Anton Alvarez","username":"
… [9825 more characters trimmed]&lt;/code&gt;&lt;/pre&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
                &lt;div&gt;
                  &lt;div class="agent-session-text agent-session-text-collapse"&gt;
                    &lt;p&gt;Tienes el post en tu DEV como &lt;strong&gt;borrador&lt;/strong&gt;, sin publicar:&lt;br&gt;
&lt;strong&gt;&lt;a href="https://dev.to/virien84/should-i-buy-a-traffic-light-for-my-friend-who-never-makes-it-to-the-end-of-the-month-mn3-temp-slug-7062961/edit"&gt;https://dev.to/virien84/should-i-buy-a-traffic-light-for-my-friend-who-never-makes-it-to-the-end-of-the-month-mn3-temp-slug-7062961/edit&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Las capturas también están ya en el README del repo en GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cómo está hecho el post:&lt;/strong&gt;&lt;br&gt;
- Sigue la plantilla oficial del reto: What I Built, Demo, Code, How I Built It, Why Does Open Innovation Matter? y Prize Categories.&lt;br&gt;
- Lleva las etiquetas obligatorias &lt;code&gt;devchallenge&lt;/code&gt;, &lt;code&gt;weekendchallenge&lt;/code&gt; y &lt;code&gt;hf26challenge&lt;/code&gt;, más &lt;code&gt;gemma&lt;/code&gt;. Opta a &lt;strong&gt;Best Use of Gemma&lt;/strong&gt;.&lt;br&gt;
- Incluye tus 6 capturas, cada una con una explicación, y el repo de GitHub embebido.&lt;br&gt;
- Hay una sección &lt;strong&gt;"What my friend said"&lt;/strong&gt; con sus dos comentarios: que no se hace lento porque el modelo piensa mientras él lee las características del producto, y que valora el comentario realista y la estimación.&lt;br&gt;
- La parte técnica explica que Gemma lee la tienda pero las cuentas no las hace la IA, la precarga del modelo para que vaya rápido y el error 403 de Ollama con las extensiones.&lt;br&gt;
- Dice que lo construiste con Claude Code como agente. DEV lo marca como "some AI", que es lo honesto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Revisa estas cosas antes de publicar:&lt;/strong&gt;&lt;br&gt;
1. &lt;strong&gt;El género de tu amigo:&lt;/strong&gt; en el post me refiero a él como "he/him" porque dijiste "ese amigo". Si prefieres que no quede claro o es una amiga, lo cambio.&lt;br&gt;
2. &lt;strong&gt;La captura de configuración&lt;/strong&gt; muestra tu nombre y 1900/1100/400. Si son tus números reales y no quieres que se vean, la quito.&lt;br&gt;
3. &lt;strong&gt;"I built it in an evening":&lt;/strong&gt; cámbialo si no te parece exacto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plazo:&lt;/strong&gt; se entrega hasta las &lt;strong&gt;08:59 hora española&lt;/strong&gt; de mañana (5 oct). Se publica desde DEV con el botón &lt;strong&gt;Publish&lt;/strong&gt;, o puedes pedirme que lo publique yo.&lt;/p&gt;

&lt;p&gt;Opcional: el reto anima a enseñar la sesión con el agente y a los jueces les gusta. Puedo guardar esta conversación con DevRelay y añadirla al post en la sección "My Agent Session". ¿Quieres?&lt;/p&gt;

                  &lt;/div&gt;
                  Show more
                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="agent-session-message agent-session-user"&gt;
        &lt;div class="agent-session-role-badge agent-session-role-user"&gt;
          You
        &lt;/div&gt;
        &lt;div class="agent-session-content"&gt;
                &lt;div class="agent-session-text"&gt;
                  &lt;p&gt;sí, guarda la sesión y añádela al post&lt;/p&gt;

                &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="agent-session-footer"&gt;
    &lt;span class="agent-session-meta"&gt;
        21 of 21 messages
    &lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma:&lt;/strong&gt; Gemma 3 4B runs locally through Ollama and does both AI jobs: reading arbitrary shop pages into structured product data (with JSON-schema constrained output), and writing the short, honest verdict sentence.&lt;/li&gt;
&lt;/ul&gt;

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