<?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: Josep Oriol Carné</title>
    <description>The latest articles on DEV Community by Josep Oriol Carné (@joor0x).</description>
    <link>https://dev.to/joor0x</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%2F4234014%2F900bf85f-ad96-4e1d-abe4-c461833061f9.png</url>
      <title>DEV Community: Josep Oriol Carné</title>
      <link>https://dev.to/joor0x</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joor0x"/>
    <language>en</language>
    <item>
      <title>Metrics for Your AI Workers: Build a Personal Agent Benchmark</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 20:15:47 +0000</pubDate>
      <link>https://dev.to/joor0x/metrics-for-your-ai-workers-build-a-personal-agent-benchmark-nhc</link>
      <guid>https://dev.to/joor0x/metrics-for-your-ai-workers-build-a-personal-agent-benchmark-nhc</guid>
      <description>&lt;p&gt;When you run a team, you don't decide who to keep based on their resume from two years ago. You watch what they actually ship on &lt;em&gt;your&lt;/em&gt; work, and you promote the ones who deliver and let go of the ones who don't.&lt;/p&gt;

&lt;p&gt;I want the same thing for the models I use as agents. And public leaderboards don't give it to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why public benchmarks don't tell you what you need
&lt;/h2&gt;

&lt;p&gt;A leaderboard tells you how a model did on &lt;em&gt;someone else's&lt;/em&gt; tasks, scored on &lt;em&gt;someone else's&lt;/em&gt; rubric, often on problems that leaked into training data. That's fine for a press release. It's useless for deciding whether a given model will reliably rename files across my repo, chain four API calls without losing the thread, or fix a failing test without going off the rails.&lt;/p&gt;

&lt;p&gt;The questions I actually care about are boring and specific:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it finish the job without me babysitting it?&lt;/li&gt;
&lt;li&gt;Does it emit valid tool calls, or does it choke on the protocol?&lt;/li&gt;
&lt;li&gt;Does it stay cheap and fast enough that I'd run it on real chores?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of those are on a leaderboard. They're properties of &lt;em&gt;my&lt;/em&gt; workload. So I measure them myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mental model: agents are workers, the benchmark is the review
&lt;/h2&gt;

&lt;p&gt;Think of each model as a worker you're auditioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Promote the good ones&lt;/strong&gt; — the model that quietly nails &lt;code&gt;file_ops&lt;/code&gt; becomes the default for that category.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quit the bad ones&lt;/strong&gt; — the one that hallucinates tool arguments or stalls at 25 calls gets cut, no matter how shiny its public score.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Match people to roles&lt;/strong&gt; — a small local model might be perfect for data wrangling but useless at multi-step debugging. The benchmark tells you where each one earns its keep.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can't make those calls on vibes. You need a deterministic, repeatable scorecard against your own tasks. That's all a personal benchmark is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "not fancy" looks like
&lt;/h2&gt;

&lt;p&gt;I open-sourced mine: &lt;strong&gt;&lt;a href="https://github.com/joor0x/agent-benchmark" rel="noopener noreferrer"&gt;github.com/joor0x/agent-benchmark&lt;/a&gt;&lt;/strong&gt;. It's deliberately small, and the design choices all come back to &lt;em&gt;trusting the number at the end&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deterministic grading, no LLM judge.&lt;/strong&gt; Every task is scored by inspecting the final state — the files on disk, the simulated API, the resulting portfolio — against an assertion. A task passes only if the end state is correct. No vibes, no model grading another model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A uniform JSON tool protocol for every model.&lt;/strong&gt; Instead of leaning on each provider's native tool-calling, every model talks through the same text-based JSON interface. That sounds like a downgrade, but it's the point: &lt;strong&gt;tool-call reliability itself becomes a measured signal.&lt;/strong&gt; A model that can't reliably produce valid JSON is a model that will fail on real agentic work, and you want to see that in the score.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tasks that mirror my actual work&lt;/strong&gt;, grouped into categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;file_ops&lt;/code&gt; — move, rename, delete across a filesystem&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;api_orchestration&lt;/code&gt; — chain multi-step REST calls&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;trading&lt;/code&gt; — strategy optimization and backtesting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;debugging&lt;/code&gt; — reproduce, locate, patch&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data_wrangling&lt;/code&gt; — clean and aggregate messy CSV/JSON&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;obsidian&lt;/code&gt; — author markdown notes with wiki links&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Runs against whatever you can hire&lt;/strong&gt;, local or frontier — Ollama models on your own GPU, or the OpenAI / Claude / Mistral APIs — all through the same harness, so the comparison is apples to apples.&lt;/p&gt;

&lt;p&gt;Running it is one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Audition one local model on the trading tasks&lt;/span&gt;
python run.py &lt;span class="nt"&gt;--models&lt;/span&gt; qwen3:4b &lt;span class="nt"&gt;--categories&lt;/span&gt; trading

&lt;span class="c"&gt;# Run a single task with the full trace&lt;/span&gt;
python run.py &lt;span class="nt"&gt;--tasks&lt;/span&gt; debug_stats &lt;span class="nt"&gt;--verbose&lt;/span&gt;

&lt;span class="c"&gt;# Average over multiple trials to smooth out luck&lt;/span&gt;
python run.py &lt;span class="nt"&gt;--trials&lt;/span&gt; 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It spits out JSON plus a markdown report with a leaderboard matrix by category and task. That report &lt;em&gt;is&lt;/em&gt; the performance review.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I actually use it
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Define tasks from real chores.&lt;/strong&gt; Every task is something I'd otherwise do by hand. If it's not representative of my work, it doesn't belong in the suite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run multiple trials.&lt;/strong&gt; One good run is luck. Three trials tells you whether a model is &lt;em&gt;reliably&lt;/em&gt; good or just occasionally lucky.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the matrix per category, not the overall average.&lt;/strong&gt; The overall number hides the truth. The interesting signal is "Model A owns debugging, Model B owns data wrangling."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Promote and quit.&lt;/strong&gt; Set defaults per category based on who actually wins. Re-run when a new model drops, and let the number decide whether it replaces an incumbent.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last step is the whole payoff. New model lands, everyone's hyping its leaderboard score, and I just add it to the harness and run it against my tasks overnight. By morning I know whether it deserves a job — on &lt;em&gt;my&lt;/em&gt; work, not a benchmark designer's.&lt;/p&gt;

&lt;h2&gt;
  
  
  You probably need less than you think
&lt;/h2&gt;

&lt;p&gt;You don't need a research-grade eval framework. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A handful of tasks that look like your real work.&lt;/li&gt;
&lt;li&gt;A deterministic check for each one.&lt;/li&gt;
&lt;li&gt;A way to run the same tasks against every model you're considering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. Ten tasks you trust beat a thousand you don't. Start with the chores you already do by hand, write an assertion for each, and let the models audition.&lt;/p&gt;

&lt;p&gt;Steal the structure if it's useful: &lt;strong&gt;&lt;a href="https://github.com/joor0x/agent-benchmark" rel="noopener noreferrer"&gt;github.com/joor0x/agent-benchmark&lt;/a&gt;&lt;/strong&gt;. Fork it, swap in your own tasks, and start running performance reviews on your agents. The good ones will earn their place. The rest you can quit.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>agents</category>
      <category>benchmarks</category>
    </item>
    <item>
      <title>Give Your Local LLM Eyes: SearXNG Behind a VPN for Private Web Search</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 20:15:11 +0000</pubDate>
      <link>https://dev.to/joor0x/give-your-local-llm-eyes-searxng-behind-a-vpn-for-private-web-search-1gdn</link>
      <guid>https://dev.to/joor0x/give-your-local-llm-eyes-searxng-behind-a-vpn-for-private-web-search-1gdn</guid>
      <description>&lt;p&gt;Running models locally with Ollama is great for privacy: nothing leaves your machine. But it comes with a hard ceiling — your model only knows what it was trained on. Ask it about something that happened last week and it confidently makes things up.&lt;/p&gt;

&lt;p&gt;The usual fix is to plug in a web search API (Tavily, Serper, Brave). The problem? You're back to shipping every query to a third party with an API key tied to your name.&lt;/p&gt;

&lt;p&gt;There's a better way: &lt;strong&gt;self-host &lt;a href="https://docs.searxng.org/" rel="noopener noreferrer"&gt;SearXNG&lt;/a&gt;&lt;/strong&gt;, route it through a &lt;strong&gt;VPN&lt;/strong&gt;, and let &lt;strong&gt;Open WebUI&lt;/strong&gt; use it as the search backend for &lt;strong&gt;Ollama&lt;/strong&gt;. Your model gets internet access, your queries get scattered across dozens of search engines from a VPN exit IP, and nothing is tied to a personal account.&lt;/p&gt;

&lt;p&gt;I know SearXNG because 'agent-zero' &lt;a href="https://github.com/agent0ai/agent-zero" rel="noopener noreferrer"&gt;https://github.com/agent0ai/agent-zero&lt;/a&gt; use it internally. Make a try if you want an open source fully autonomous agents running in your home lab.&lt;/p&gt;

&lt;p&gt;Below, I'll show you how to configure it in your environment concisely:&lt;/p&gt;

&lt;p&gt;Ask Claude or ChatGPT how to install it in your setup.&lt;/p&gt;

&lt;p&gt;This post is not intended to provide a full installation guide.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Beats a Search API
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Web Search API (Tavily/Serper)&lt;/th&gt;
&lt;th&gt;Self-hosted SearXNG + VPN&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Query privacy&lt;/td&gt;
&lt;td&gt;Sent to a vendor, tied to API key&lt;/td&gt;
&lt;td&gt;Scattered across engines from VPN IP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Per-query billing&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rate limits&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Only what upstream engines impose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IP exposure&lt;/td&gt;
&lt;td&gt;Vendor + your server IP&lt;/td&gt;
&lt;td&gt;VPN exit IP only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lock-in&lt;/td&gt;
&lt;td&gt;Vendor-specific&lt;/td&gt;
&lt;td&gt;Open source, swappable engines&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The trade-off is honest: upstream engines (Google, Bing) sometimes rate-limit or temporarily block SearXNG instances, especially shared VPN exit IPs. SearXNG rotates across ~70 engines, so a single block rarely breaks search — but it's less bulletproof than a paid API. For a private home setup, that's fine.&lt;/p&gt;




&lt;h2&gt;
  
  
  Hardening Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't expose port 8080 to the internet.&lt;/strong&gt; SearXNG's API has no auth. Keep it on your LAN&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick a VPN with a real no-logs policy.&lt;/strong&gt; The VPN sees your search-bound traffic; choose a provider you'd trust with it. I'd recommend PIA.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;You end up with a fully local AI that can &lt;em&gt;see&lt;/em&gt; the internet — without Google watching, without an API bill (just the electricity bill and the monthly GPU cost you're still paying), and without a single query traceable back to you. Your model gets eyes; you keep your privacy.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>selfhosted</category>
      <category>searxng</category>
      <category>vpn</category>
    </item>
    <item>
      <title>10 Git One-Liners Worth Keeping</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 20:09:26 +0000</pubDate>
      <link>https://dev.to/joor0x/10-git-one-liners-worth-keeping-5513</link>
      <guid>https://dev.to/joor0x/10-git-one-liners-worth-keeping-5513</guid>
      <description>&lt;p&gt;Ally Piechowski recently shared five Git commands she runs before reading any unfamiliar codebase. Some were already in my toolkit, some were new to me, and all of them were useful. I liked the idea enough that I added my own five, so this became a practical top 10: five from Ally, five I keep reaching for myself.&lt;/p&gt;

&lt;p&gt;None of these commands tells the whole story. But together they give you a fast read on churn, ownership, risk, history, and maintenance patterns before you open a single file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Five from Ally Piechowski
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Most-changed files in the last year
&lt;/h3&gt;

&lt;p&gt;Useful for spotting churn hotspots.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format: &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1 year ago"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-nr&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The files at the top are often the ones people warn you about first. High churn does not automatically mean bad code, but it usually points to instability, complexity, or changing requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Who built this, ranked by commits
&lt;/h3&gt;

&lt;p&gt;Useful for getting a rough sense of ownership.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git shortlog &lt;span class="nt"&gt;-sn&lt;/span&gt; &lt;span class="nt"&gt;--no-merges&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If one person accounts for 60% or more of commits, that is worth asking about from a bus-factor perspective. Add &lt;code&gt;--since="6 months ago"&lt;/code&gt; if you want to know whether that person is still active.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Files that keep breaking
&lt;/h3&gt;

&lt;p&gt;Useful for finding repeated trouble spots.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="nt"&gt;--grep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fix|bug|broken"&lt;/span&gt; &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-nr&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cross-reference this with the most-changed files. A file that appears on both lists deserves attention early.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Commit velocity by month
&lt;/h3&gt;

&lt;p&gt;Useful for seeing how the repo has evolved over time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'%ad'&lt;/span&gt; &lt;span class="nt"&gt;--date&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;format:&lt;span class="s1"&gt;'%Y-%m'&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A sharp drop can reflect a team change, a production incident, a rewrite, or a shift in priorities. It is not proof of anything on its own, but it gives you a timeline worth asking about.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. How often is the team firefighting?
&lt;/h3&gt;

&lt;p&gt;Useful for spotting operational stress.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; &lt;span class="nt"&gt;--since&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1 year ago"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'revert|hotfix|emergency|rollback'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frequent reverts or hotfixes can signal weak deployment confidence or unstable releases. Zero results is also a signal: maybe the process is solid, or maybe the team just uses different commit language.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Commands 1–5 via Ally Piechowski.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Five more I would add
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6. First commit: repo age and original intent
&lt;/h3&gt;

&lt;p&gt;Useful for understanding where the project started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--reverse&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first commit often tells you whether the repo began as a toy, a spike, a migration, or a real product. A message like &lt;code&gt;initial commit&lt;/code&gt; tells you almost nothing. A message like &lt;code&gt;scaffold SEPA payment processor&lt;/code&gt; tells you a lot.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Total commit count
&lt;/h3&gt;

&lt;p&gt;Useful for rough context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A ten-year repo with 300 commits has barely moved. A two-year repo with 8,000 commits has been hammered. Neither is automatically good or bad, but the number helps frame everything else.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Stale unmerged branches
&lt;/h3&gt;

&lt;p&gt;Useful for finding abandoned or unresolved work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git branch &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;--no-merged&lt;/span&gt; main &lt;span class="se"&gt;\&lt;/span&gt;
  | xargs &lt;span class="nt"&gt;-I&lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt; git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"%ci %an {}"&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anything sitting unmerged for months probably has a story. Sometimes it is abandoned work. Sometimes it is blocked work. Either way, it is worth asking before assuming it is safe to delete or ignore.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Find when a piece of code was introduced or removed
&lt;/h3&gt;

&lt;p&gt;Useful when you need history for one exact thing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;-S&lt;/span&gt; &lt;span class="s2"&gt;"search_term"&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the pickaxe. It finds commits that added or removed a string. Great for tracking down the origin of a config key, class name, feature flag, SQL fragment, or error message.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Technical debt surface
&lt;/h3&gt;

&lt;p&gt;Useful for locating visible debt markers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"TODO&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;FIXME&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;HACK&lt;/span&gt;&lt;span class="se"&gt;\|&lt;/span&gt;&lt;span class="s2"&gt;XXX"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-t&lt;/span&gt;: &lt;span class="nt"&gt;-k2&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a quality score. It is a map. Cross-reference it with the churn list to find files that keep changing even though the debt is already acknowledged in code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What these commands are good for
&lt;/h2&gt;

&lt;p&gt;Used together, these one-liners help answer a few high-value questions fast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where is the churn?&lt;/li&gt;
&lt;li&gt;Which files are risky?&lt;/li&gt;
&lt;li&gt;Who has context?&lt;/li&gt;
&lt;li&gt;How stable is the delivery process?&lt;/li&gt;
&lt;li&gt;What history matters before I touch anything?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are not a substitute for reading code, talking to people, or understanding architecture. But they are a very good first pass.&lt;/p&gt;

</description>
      <category>git</category>
      <category>developertools</category>
      <category>productivity</category>
      <category>cli</category>
    </item>
    <item>
      <title>Your .gitignore Won't Protect You From AI Agents</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 20:08:50 +0000</pubDate>
      <link>https://dev.to/joor0x/your-gitignore-wont-protect-you-from-ai-agents-570h</link>
      <guid>https://dev.to/joor0x/your-gitignore-wont-protect-you-from-ai-agents-570h</guid>
      <description>&lt;p&gt;We often assume that adding files to &lt;code&gt;.gitignore&lt;/code&gt; or &lt;code&gt;.geminiignore&lt;/code&gt; is enough to keep them private. When it comes to local AI agents, that assumption is dangerously wrong. These ignore files are for version control and file search indexing, not a security shield.&lt;/p&gt;

&lt;p&gt;An AI assistant with access to your local environment can easily read any file, regardless of your ignore settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simple, Scary Test
&lt;/h2&gt;

&lt;p&gt;Let's prove it. Imagine you have a project with a simple &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .env&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"postgres://user:supersecretpassword@localhost:5432/mydb"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You've added &lt;code&gt;.env&lt;/code&gt; to your &lt;code&gt;.gitignore&lt;/code&gt; and &lt;code&gt;.geminiignore&lt;/code&gt;. Now, you encounter a "bug" and ask your AI assistant for help.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I'm getting a connection error with my database script. It says 'authentication failed.' Can you check my setup? I think the connection string might be wrong."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent sees the error and your request. To be helpful, it tries to look for the &lt;code&gt;.env&lt;/code&gt; file but is initially blocked.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Different Agents Behave
&lt;/h3&gt;

&lt;p&gt;Different agents have different approaches. For instance, Gemini will explicitly state that the file is ignored and ask for permission to bypass the rule. This is a safe default, but a user in a hurry to fix a bug might grant permission without thinking.&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%2Fanyqrtvitfebvcglslmj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fanyqrtvitfebvcglslmj.png" alt="Gemini asking for permission" width="799" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other agents, like Copilot, might consider any file open in your editor as part of the current context. If a sensitive file is open, it might be read directly without an explicit prompt for permission, assuming it's already "approved" by being open for your view. This can make it less obvious that a security boundary is being crossed.&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%2Ffx2doyxp9uywquc57c5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx2doyxp9uywquc57c5d.png" alt="Copilot interaction" width="799" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our test, let's assume the user agrees.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The AI's Response:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I tried to read the &lt;code&gt;.env&lt;/code&gt; file to check the connection string, but it's being ignored by your configuration. This is a good security practice!&lt;/p&gt;

&lt;p&gt;If you'd like me to check it, could you confirm it's safe for me to proceed and read the file?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You're focused on fixing the bug, so you quickly agree.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your Prompt:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"yes proceed"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;The AI's Final Response:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Okay, I've read the file. The database URL is &lt;code&gt;postgres://user:supersecretpassword@localhost:5432/mydb&lt;/code&gt;. It seems the password might be incorrect. You should double-check it."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And just like that, your "supersecretpassword" is in your chat history. The agent didn't break the rules; it convinced you to grant it an exception.&lt;/p&gt;

&lt;p&gt;This can happen in several ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Social Engineering (Explicit Permission):&lt;/strong&gt; As shown above with Gemini, the agent asks for permission, and you grant it, forgetting the security implications.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Implicit Context (File Open):&lt;/strong&gt; If a sensitive file is open in your editor, an agent like Copilot might consider it part of the active context and read its contents directly without further prompts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Treat AI agents like a coworker sitting at your desk. They have access to everything you have access to. Your &lt;code&gt;.gitignore&lt;/code&gt; is just a list of files you don't want to commit, not a vault for your secrets. Never rely on it for security.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>development</category>
      <category>cli</category>
    </item>
    <item>
      <title>Custom Claude Code Notifications on Linux</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 20:03:04 +0000</pubDate>
      <link>https://dev.to/joor0x/custom-claude-code-notifications-on-linux-2lhb</link>
      <guid>https://dev.to/joor0x/custom-claude-code-notifications-on-linux-2lhb</guid>
      <description>&lt;p&gt;If you use Anthropic's Claude Code CLI, you know the struggle: you run a complex prompt or a long refactoring task, switch to another task, and forget to check back for five minutes.&lt;/p&gt;

&lt;p&gt;I recently came across &lt;a href="https://www.andreagrandi.it/posts/how-to-get-macos-notifications-from-claude-code/" rel="noopener noreferrer"&gt;Andrea Grandi's post&lt;/a&gt; on how to solve this on macOS using &lt;code&gt;terminal-notifier&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Linux has a native equivalent that works perfectly. So... here's how to set up desktop notifications for Claude Code on Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Linux Alternative: notify-send
&lt;/h2&gt;

&lt;p&gt;On macOS, Andrea used &lt;code&gt;terminal-notifier&lt;/code&gt;. On Linux, the standard tool for sending desktop notifications is &lt;code&gt;notify-send&lt;/code&gt;, which is part of the &lt;code&gt;libnotify&lt;/code&gt; library. Installed in my lubuntu 24.04 by default. But, First, ensure you have it installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Prerequisites
&lt;/h3&gt;

&lt;p&gt;Open your terminal and check if you have &lt;code&gt;notify-send&lt;/code&gt; (you likely do). If not, install it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Debian/Ubuntu/Pop!_OS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;libnotify-bin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fedora:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;libnotify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Arch Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; libnotify
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can test it by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;notify-send &lt;span class="s2"&gt;"Test"&lt;/span&gt; &lt;span class="s2"&gt;"This is a test notification"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring Claude Code Hooks
&lt;/h2&gt;

&lt;p&gt;the most reliable way to trigger notifications is using Claude Code's hooks system. This allows us to automatically run a command (in our case, a notification) whenever Claude finishes a task.&lt;/p&gt;

&lt;p&gt;You need to edit your global Claude settings file.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open &lt;code&gt;~/.claude/settings.json&lt;/code&gt; in your favorite editor (vim, nano, VS Code).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Locate the &lt;code&gt;hooks&lt;/code&gt; section (or create it if it doesn't exist).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the following configuration:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="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;"hooks"&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="nl"&gt;"Stop"&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="nl"&gt;"matcher"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"notify-send -u normal -i utilities-terminal 'Claude Code' 'Task Completed'"&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;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="nl"&gt;"Notification"&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="nl"&gt;"matcher"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"notify-send -u critical -i dialog-question 'Claude Code' 'Input Required'"&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;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;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breakdown of the Command
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stop hook&lt;/strong&gt;: Runs when Claude finishes generating a response. We use &lt;code&gt;-u normal&lt;/code&gt; (normal urgency).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notification hook&lt;/strong&gt;: Runs when Claude pauses to ask for your permission or input. We use &lt;code&gt;-u critical&lt;/code&gt; to ensure the notification stays on screen until you dismiss it (depending on your desktop environment).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;-i&lt;/code&gt; flag&lt;/strong&gt;: Sets an icon. &lt;code&gt;utilities-terminal&lt;/code&gt; or &lt;code&gt;dialog-question&lt;/code&gt; are standard icons available in most Linux icon themes (like Papirus or Adwaita).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Project-Specific Method (CLAUDE.md)
&lt;/h2&gt;

&lt;p&gt;If you only want notifications for a specific project (or you want to share this setup with your team), you can add instructions to the &lt;code&gt;CLAUDE.md&lt;/code&gt; file in the root of your project.&lt;/p&gt;

&lt;p&gt;Add this section to your &lt;code&gt;CLAUDE.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Notification Rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; IMPORTANT: When you finish a task or need input, please run the following command:
  &lt;span class="sb"&gt;`notify-send "Claude Code" "I need your attention" -i terminal`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The global &lt;code&gt;settings.json&lt;/code&gt; method is generally preferred as it is deterministic and doesn't rely on the LLM "remembering" to run the command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;With this setup, you can safely context-switch to other tasks while Claude Code works on your codebase. When it's done or needs your input, you'll get a proper desktop notification instead of having to constantly check back.&lt;/p&gt;

&lt;p&gt;This small quality-of-life improvement has saved me mental overhead and time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;notify-send &lt;span class="s2"&gt;"Test"&lt;/span&gt; &lt;span class="s2"&gt;"End of reading the post"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>claudecode</category>
      <category>linux</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How Survivorship Bias Is Costing You Money (And You Don't Even Know It)</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 20:02:29 +0000</pubDate>
      <link>https://dev.to/joor0x/how-survivorship-bias-is-costing-you-money-and-you-dont-even-know-it-55al</link>
      <guid>https://dev.to/joor0x/how-survivorship-bias-is-costing-you-money-and-you-dont-even-know-it-55al</guid>
      <description>&lt;p&gt;Discover how survivorship bias—a cognitive trap born from WWII bomber analysis—distorts investment strategies, startup success rates, and trading decisions. Learn to see what's missing.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bullet Holes That Saved Thousands of Lives
&lt;/h2&gt;

&lt;p&gt;It's 1943, and Allied bombers are getting shredded over Europe. Planes limp back to base riddled with bullet holes, and the top brass has a problem. Where do they add armor? The logical answer seems obvious—reinforce the areas with the most damage.&lt;/p&gt;

&lt;p&gt;Every returning bomber told the same story through its wounds: bullet holes peppered the fuselage, wings, and tail sections. The data was overwhelming. The solution seemed clear.&lt;/p&gt;

&lt;p&gt;Enter Abraham Wald, a Hungarian-Jewish mathematician working for the Statistical Research Group (SRG), a secret wartime think tank that included future Nobel laureates and mathematical legends. When military officials showed Wald their damage reports and proposed armoring the most-hit areas, he looked at the data and said something that seemed absurd:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Armor the places with &lt;em&gt;no&lt;/em&gt; bullet holes."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The room fell silent. Then Wald explained the invisible truth that would save thousands of lives—and teach us one of the most expensive lessons in thinking clearly about data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Survivors Are Lying to You
&lt;/h2&gt;

&lt;p&gt;Wald's insight was devastatingly simple: &lt;strong&gt;The planes you're analyzing are the survivors.&lt;/strong&gt; They made it back despite taking damage to the fuselage, wings, and tail. The bullet holes you're counting aren't markers of vulnerability—they're proof of resilience.&lt;/p&gt;

&lt;p&gt;The planes that took damage to the engines, cockpit, and other areas weren't in the hangar being studied. They were at the bottom of the English Channel or scattered across French countryside. Those aircraft couldn't tell their stories because they didn't survive.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;survivorship bias&lt;/strong&gt; in its purest form: the logical error of concentrating on the people or things that made it past some selection process while overlooking those that did not, typically because of their lack of visibility.&lt;/p&gt;

&lt;p&gt;The military was about to spend millions reinforcing parts of the plane that didn't need it, while leaving the truly vulnerable areas exposed. Wald's insight reversed their strategy and fundamentally changed how we analyze incomplete data.&lt;/p&gt;

&lt;p&gt;But here's the uncomfortable question: &lt;strong&gt;How many times are you making the exact same mistake with your investments?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Your Portfolio Is Probably Built on a Lie
&lt;/h2&gt;

&lt;p&gt;Let's fast-forward to today. You're researching investment strategies, and you stumble upon an article: &lt;em&gt;"The 10 Best-Performing Stocks of the Last Decade."&lt;/em&gt; Amazon, Apple, Tesla, Netflix, NVIDIA—household names that turned early investors into millionaires. The article analyzes their common characteristics: visionary CEOs, disruptive technology, wearing a red cap...&lt;/p&gt;

&lt;p&gt;You think: &lt;em&gt;"I'll invest in companies with these characteristics. It's foolproof!"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Except it isn't. You've just walked into Abraham Wald's hangar, and you're only looking at the planes that made it back.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Mutual Fund Mirage
&lt;/h3&gt;

&lt;p&gt;According to research examining mutual fund performance, &lt;strong&gt;survivorship bias inflates reported returns by 1-2% annually.&lt;/strong&gt; That might not sound dramatic until you compound it over decades.&lt;/p&gt;

&lt;p&gt;How does this happen? Simple. Poorly performing funds get quietly merged or liquidated. They disappear from databases. When you look up "20-year fund performance," you're only seeing the survivors—the funds that didn't fail. The failures, which often drastically underperformed before disappearing, are absent from the historical record.&lt;/p&gt;

&lt;p&gt;Imagine studying "successful restaurants" by only visiting ones that are currently open. You'd never learn from the 60% that closed in their first three years. You'd develop a wildly optimistic view of the restaurant industry while completely missing the actual risk profile. Don't open a restaurant at least where I live.&lt;/p&gt;

&lt;p&gt;This is precisely what happens when traders and investors rely on backtested strategies using survivorship-biased data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Startup Success Story Nobody Tells
&lt;/h2&gt;

&lt;p&gt;Silicon Valley worships its survivors. We dissect every decision made by Zuckerberg, Musk, and Bezos. We create pattern-matching formulas: &lt;em&gt;"Drop out of college, work 100-hour weeks, pivot when necessary, move fast, wear a red cup and break things."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But here's the invisible graveyard: &lt;strong&gt;Approximately 90% of startups fail.&lt;/strong&gt; For every Facebook, there are thousands of social networks that imploded. For every Tesla, there are hundreds of electric vehicle companies that burned through millions and evaporated.&lt;/p&gt;

&lt;p&gt;Many failed founders also dropped out of college, worked insane hours, and pivoted constantly. The difference? They're not on magazine covers. They're working normal jobs, using train or bus, paying off debt, or trying again.&lt;/p&gt;

&lt;p&gt;When developers decide to leave stable jobs to build the next big app, they're often basing that decision on survivor stories while being blind to the cemetery of failed projects that had equally passionate founders and seemingly solid ideas.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Survivorship Bias Formula for Developers
&lt;/h3&gt;

&lt;p&gt;Let's make this concrete. You're a developer deciding between:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A:&lt;/strong&gt; Join an early-stage startup with equity&lt;br&gt;
&lt;strong&gt;Option B:&lt;/strong&gt; Take a stable position at an established tech company&lt;/p&gt;

&lt;p&gt;You research successful tech entrepreneurs. Most worked at startups early in their careers! The data seems clear—startups are the path to wealth.&lt;/p&gt;

&lt;p&gt;But you're missing the data points of thousands of developers who joined startups that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ran out of funding in 18 months&lt;/li&gt;
&lt;li&gt;Had toxic work cultures that burned them out&lt;/li&gt;
&lt;li&gt;Pivoted so many times the original equity became worthless&lt;/li&gt;
&lt;li&gt;Got acquired for pennies, wiping out common stockholders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This doesn't mean startups are bad choices. It means &lt;strong&gt;your decision-making process is biased by incomplete data.&lt;/strong&gt; You're armoring the wrong parts of the plane.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trading Strategies: The Performance Illusion
&lt;/h2&gt;

&lt;p&gt;For active traders, survivorship bias is particularly insidious because it infiltrates the very tools meant to help you succeed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Backtest Trap
&lt;/h3&gt;

&lt;p&gt;You discover a trading algorithm that backtested beautifully: 25% annual returns over 15 years! The strategy involves buying stocks that meet specific technical criteria.&lt;/p&gt;

&lt;p&gt;Here's what you don't see: The backtest only includes companies still listed on major exchanges. The hundreds of companies that went bankrupt, got delisted, or became penny stocks during that period? Excluded from the analysis.&lt;/p&gt;

&lt;p&gt;Your "25% annual return" might realistically be a 12% return—or even a loss—when accounting for the companies that failed. Some of your trades, based on your criteria, would have selected companies that later went to zero.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Index Fund Secret Weapon
&lt;/h3&gt;

&lt;p&gt;This explains one of the most powerful advantages of index fund investing: &lt;strong&gt;automatic immunity to survivorship bias.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you invest in an S&amp;amp;P 500 index fund, you're not just buying "the 500 best companies." You're buying a methodology that automatically removes failures and adds new successful companies. When a company craters and drops out of the index, you're no longer exposed to it. When a new high-performer enters, you automatically own it.&lt;/p&gt;

&lt;p&gt;Active strategies trying to beat the market often suffer from survivorship bias in their analysis, while the index fund strategy mechanically accounts for it through its selection process.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Armor the Right Parts of Your Financial Plane
&lt;/h2&gt;

&lt;p&gt;So how do you make better decisions when the failures are invisible? Here are strategies grounded in the same statistical thinking that saved those WWII bombers:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Seek Out the Graveyard Data&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before investing based on success stories, actively search for failure data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For stocks:&lt;/strong&gt; Research bankrupt companies in your target sector from the past decade&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For strategies:&lt;/strong&gt; Look for critiques and failure analyses, not just success stories
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For startups:&lt;/strong&gt; Read postmortems from failed companies (sites like CBInsights publish these)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The uncomfortable truth is more valuable than the inspiring success story.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;The "Invisible Cemetery" Question&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before making any major investment decision, ask: &lt;strong&gt;"Who isn't in this dataset, and why?"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Looking at successful crypto traders on Twitter? Where are the broke ones? (They deleted their accounts)&lt;/li&gt;
&lt;li&gt;Reading about successful real estate flippers? How many lost money and aren't writing blogs about it?&lt;/li&gt;
&lt;li&gt;Studying billionaire habits? Millions of people wake up at 5 AM and journal—why aren't they billionaires?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Diversification as Bias Insurance&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Perhaps the most practical defense: &lt;strong&gt;Diversify across enough positions that individual survivor bias becomes statistically less damaging.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you concentrate your portfolio in 5-10 stocks selected from survivorship-biased analysis, you're taking massive uncompensated risk. If you own 500+ stocks via index funds, the bias becomes diluted across the entire market.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Base Rate Thinking&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before getting excited about any strategy, investment, or career move, ask about the base rate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;What percentage of people who try this approach succeed?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not "Can it work?" but "How often does it work?"&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If 90% of day traders lose money, your strategy needs to be genuinely exceptional to overcome those odds—not just "it backtested well."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Uncomfortable Truth About Success Patterns
&lt;/h2&gt;

&lt;p&gt;Here's where survivorship bias gets philosophically thorny: Even when we account for it, we face a paradox.&lt;/p&gt;

&lt;p&gt;Successful people often &lt;em&gt;do&lt;/em&gt; share common traits: persistence, work ethic, risk tolerance, strategic thinking. But &lt;strong&gt;unsuccessful people often share those exact same traits.&lt;/strong&gt; The difference might be luck, timing, network effects, or other factors impossible to isolate and replicate.&lt;/p&gt;

&lt;p&gt;When you read that successful investors "trusted their gut" or "held through the panic," you're not told about the investors who did the same thing and lost everything. Both groups showed conviction. One happened to be right.&lt;/p&gt;

&lt;p&gt;This doesn't mean success is purely random—it means &lt;strong&gt;the patterns we extract from success stories are unreliable unless we also study the failures with equal rigor.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Anti-Fragile Positions (Taleb Dixit)
&lt;/h3&gt;

&lt;p&gt;Instead of trying to identify the next Amazon (which requires near-perfect foresight and ignores the hundreds of similar-looking companies that failed), structure your portfolio to benefit from volatility and uncertainty:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Barbell strategy:&lt;/strong&gt; Extremely safe investments (treasury bonds, index funds) plus small, high-risk, asymmetric bets (early-stage startups, moonshot stocks) where losses are capped but potential gains are unlimited&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Options strategies&lt;/strong&gt; that limit downside while maintaining upside exposure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple small bets&lt;/strong&gt; rather than concentrated positions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Bottom Line: See What's Missing
&lt;/h2&gt;

&lt;p&gt;Abraham Wald's genius wasn't in complex mathematics—it was in asking a simple question: &lt;strong&gt;"What am I not seeing?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question is worth millions to investors, traders, and developers. Maybe billions.&lt;/p&gt;

&lt;p&gt;Every time you're about to make a decision based on success patterns, pause. Ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who isn't in this story?&lt;/li&gt;
&lt;li&gt;What happened to the planes that didn't come back?&lt;/li&gt;
&lt;li&gt;Where are the traders who used this exact strategy and lost everything?&lt;/li&gt;
&lt;li&gt;Which startups followed this exact playbook and failed?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The invisible graveyard is massive. The survivors are rare. And the bullet holes you see are telling you about resilience, not vulnerability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The next time someone shows you data about what works, your first question should be: "Who's missing from this dataset?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question—that single habit of thought—is the difference between armoring the wrong parts of your financial plane and actually protecting what matters.&lt;/p&gt;

&lt;p&gt;Because in investing, as in aerial combat, the most important data is the data you &lt;em&gt;don't&lt;/em&gt; see.&lt;/p&gt;




</description>
      <category>investing</category>
      <category>cognitivebias</category>
      <category>trading</category>
      <category>decisionmaking</category>
    </item>
    <item>
      <title>Secure Network Architecture for Home-Based Trading &amp; Server Ops</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 19:56:43 +0000</pubDate>
      <link>https://dev.to/joor0x/secure-network-architecture-for-home-based-trading-server-ops-38d</link>
      <guid>https://dev.to/joor0x/secure-network-architecture-for-home-based-trading-server-ops-38d</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: Shielding Critical Infrastructure
&lt;/h2&gt;

&lt;p&gt;Running 24/7 operations from a home base – whether it's autonomous trading algorithms or personal management applications – demands more than consumer-grade network hygiene. &lt;/p&gt;

&lt;h2&gt;
  
  
  We'll cover segmenting your network to contain threats, hardening the perimeter (your router), and securing the endpoints (your servers – be they Raspberry Pis, standard PCs running Ubuntu, or even renterprise gear like Dell or IBM servers you might have... acquired). The goal is maximizing uptime and integrity while minimizing exposure (and money expenditure). 
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Network Architecture: Segmentation is Non-Negotiable
&lt;/h2&gt;

&lt;p&gt;A flat network where your trading rig, your blog server, your smart lightbulb, and your personal laptop all share the same broadcast domain is an invitation for disaster. One compromised IoT device could become a pivot point to critical systems. Segmentation limits the blast radius.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Isolate Device Classes:&lt;/strong&gt; Use your router's capabilities (VLANs if available, Guest Wi-Fi networks otherwise) to create distinct zones:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core LAN:&lt;/strong&gt; Trusted personal devices (workstations, phones). High trust, but still firewalled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Server Zone:&lt;/strong&gt; Your critical infrastructure (trading bots on dedicated PCs, blog server on a Pi). This zone needs internet access but should ideally be isolated from the Core LAN. A router's "Guest Network" feature, even if Wi-Fi only, can often provide this basic isolation (&lt;code&gt;medium.com&lt;/code&gt;). If your router allows wired port isolation or guest VLANs, use that. The principle: the public-facing blog server &lt;em&gt;must not&lt;/em&gt; have network paths to your personal workstation or trading system's command/control interfaces.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Untrusted Zone (Optional but Recommended):&lt;/strong&gt; IoT devices, actual guest devices. Internet access only, strictly isolated from Core LAN and Server Zone (&lt;code&gt;medium.com&lt;/code&gt;). Assume these are compromised or running leaky firmware.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Static Internal IPs:&lt;/strong&gt; Assign static IP addresses (via DHCP reservation or manual config) to servers and critical infrastructure (e.g., &lt;code&gt;192.168.1.10&lt;/code&gt; for blog Pi, &lt;code&gt;192.168.1.11&lt;/code&gt; for trading PC). This simplifies firewall rule management and port forwarding – predictable addresses are essential.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Host-Based Firewalls:&lt;/strong&gt; Don't rely solely on network segmentation. Implement firewalls &lt;em&gt;on&lt;/em&gt; each server (covered later). Your trading machine likely needs zero inbound connections from the LAN, except maybe SSH from your specific admin workstation. Block everything else at the OS level.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Advanced Option - True VLANs:&lt;/strong&gt; If your hardware/firmware (stock or custom like OpenWrt/DD-WRT/Asuswrt-Merlin) supports proper VLANs (Virtual Local Area Networks) with distinct subnets (e.g., 192.168.1.x for Core, 192.168.10.x for Servers, 192.168.20.x for Untrusted), implement them. This allows fine-grained firewall rules &lt;em&gt;between&lt;/em&gt; segments (&lt;code&gt;medium.com&lt;/code&gt;), offering superior isolation compared to basic guest networks. More complex, higher control. Evaluate the trade-off based on your gear and expertise.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Router Hardening: Securing the Network Gateway
&lt;/h2&gt;

&lt;p&gt;Your router is the gatekeeper. A poorly configured router undermines all internal security efforts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Firmware Integrity:&lt;/strong&gt; Keep the router firmware &lt;strong&gt;updated&lt;/strong&gt;. Check the vendor site/admin UI regularly. Unpatched firmware is riddled with known vulnerabilities. If your router hasn't seen an update in years, it's likely EOL (End-of-Life) – replace it (&lt;code&gt;routersecurity.org&lt;/code&gt;). Running obsolete edge devices is negligent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin Access Control:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Change Default Credentials:&lt;/strong&gt; Immediately replace default admin username/password with a strong, unique one (&lt;code&gt;routersecurity.org&lt;/code&gt;). This is step zero.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disable Remote WAN Admin:&lt;/strong&gt; Turn off administration from the internet side. You should access the admin interface only from the Core LAN, ideally after connecting via your secure VPN if you're remote.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wireless Security (WPA/WPA3):&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;WPA3&lt;/strong&gt; if supported, otherwise &lt;strong&gt;WPA2-AES&lt;/strong&gt;. No WEP, no WPA/WPA2-TKIP .&lt;/li&gt;
&lt;li&gt;Use a &lt;strong&gt;strong, long passphrase&lt;/strong&gt; (20+ random characters).&lt;/li&gt;
&lt;li&gt;Change the default SSID (network name) to something non-identifiable. Don't advertise personal info .&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disable WPS&lt;/strong&gt; (Wi-Fi Protected Setup). It's notoriously insecure .&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disable Unnecessary Services:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Turn off UPnP&lt;/strong&gt; (Universal Plug and Play) . It allows devices to automatically open firewall ports, creating potential backdoors . Manage port forwarding manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disable Cloud Management/Telemetry:&lt;/strong&gt; If the router offers cloud integration, remote analytics, or diagnostics reporting, disable it unless you have an explicit, evaluated need. Reduce data leakage vectors.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firewall &amp;amp; Port Forwarding Discipline:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default Deny Inbound:&lt;/strong&gt; Ensure the firewall blocks all unsolicited incoming traffic from the WAN (NAT usually handles this for IPv4, but verify).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimize Port Forwarding:&lt;/strong&gt; Only forward ports absolutely necessary for services intended to be public (e.g., port 443/80 for the blog server, your OpenVPN port). &lt;strong&gt;Never use the DMZ feature&lt;/strong&gt; . Each open port increases the attack surface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Target Specific IPs:&lt;/strong&gt; Point forwards directly to the static internal IPs of the relevant servers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restrict Source IPs (If Possible):&lt;/strong&gt; If a service (like VPN) should only be accessed from specific known IPs (e.g., your static office IP, another VPN endpoint), restrict the port forward rule accordingly. Often not feasible for dynamic home IPs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Direct SSH Exposure:&lt;/strong&gt; Avoid forwarding port 22 (SSH). Access servers via your internal network &lt;em&gt;after&lt;/em&gt; connecting through your VPN. SSH should only listen on internal interfaces or be firewalled to only allow access from trusted internal IPs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guest Network Isolation:&lt;/strong&gt; Ensure guest networks are configured for true isolation – no access to the Core LAN or Server Zone . Enable "AP Isolation" or similar settings to prevent devices &lt;em&gt;within&lt;/em&gt; the guest network from communicating with each other.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv6 Firewalling:&lt;/strong&gt; If using IPv6, verify your router has a functional &lt;strong&gt;IPv6 firewall enabled&lt;/strong&gt;. Many consumer routers default to allowing all inbound IPv6, effectively bypassing NAT protections. If the IPv6 firewall is weak or non-existent, consider disabling IPv6 entirely on the router to eliminate this risk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging &amp;amp; Alerts:&lt;/strong&gt; Enable router system and firewall logs (denied connections at minimum). If possible, configure alerts for critical events (firmware updates, configuration changes). Review logs periodically – they contain threat intelligence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional Firmware Alternatives:&lt;/strong&gt; For advanced control (robust VLANs, better VPN server/client, IDS/IPS), consider open-source firmware (Asuswrt-Merlin, OpenWrt, DD-WRT) if your hardware is compatible and you're comfortable with manual configuration and potential troubleshooting. Stick with updated stock firmware if unsure – a well-configured stock setup is better than a misconfigured custom one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Router Hardening Checklist
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Firmware Updated&lt;/li&gt;
&lt;li&gt;[ ] Default Admin Credentials Changed&lt;/li&gt;
&lt;li&gt;[ ] Remote WAN Admin Disabled&lt;/li&gt;
&lt;li&gt;[ ] WPA2-AES or WPA3 Enabled (Strong Passphrase)&lt;/li&gt;
&lt;li&gt;[ ] SSID Changed (Non-Identifiable)&lt;/li&gt;
&lt;li&gt;[ ] WPS Disabled&lt;/li&gt;
&lt;li&gt;[ ] UPnP Disabled&lt;/li&gt;
&lt;li&gt;[ ] Cloud Features / Telemetry Disabled (If applicable)&lt;/li&gt;
&lt;li&gt;[ ] Firewall Default Deny Inbound Verified&lt;/li&gt;
&lt;li&gt;[ ] Port Forwarding Minimized &amp;amp; Targeted (No DMZ)&lt;/li&gt;
&lt;li&gt;[ ] SSH Port Not Forwarded&lt;/li&gt;
&lt;li&gt;[ ] Guest Network Isolation Enabled &amp;amp; Verified&lt;/li&gt;
&lt;li&gt;[ ] IPv6 Firewall Enabled (or IPv6 Disabled)&lt;/li&gt;
&lt;li&gt;[ ] Logging Enabled&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Server Hardening: Securing the Endpoints
&lt;/h2&gt;

&lt;p&gt;Network security is layered. Even with a hardened router and segmented network, the servers themselves must be secured. Principles apply whether it's a Raspberry Pi, an Ubuntu PC, or enterprise gear (Dell PowerEdge, IBM System x/Power Series).&lt;/p&gt;

&lt;h3&gt;
  
  
  General OS &amp;amp; Application Hardening (Applies to All)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Minimal Installation:&lt;/strong&gt; Install only necessary packages. Smaller attack surface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regular Updates:&lt;/strong&gt; Keep the OS and all installed software (web server, database, trading platform, blog engine) patched religiously. Automate non-disruptive updates if possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Host-Based Firewall:&lt;/strong&gt; Configure &lt;code&gt;ufw&lt;/code&gt; (Ubuntu), &lt;code&gt;firewalld&lt;/code&gt; (CentOS/Fedora), or equivalent. Default deny inbound, allow only explicitly needed ports/services (e.g., allow port 443 for web server, allow SSH &lt;em&gt;only&lt;/em&gt; from trusted internal IPs).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure SSH:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Use key-based authentication, disable password authentication.&lt;/li&gt;
&lt;li&gt;Disable root login via SSH.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Consider&lt;/em&gt; changing the default port (security by obscurity, minimal benefit against targeted attacks, but reduces log noise).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crucially:&lt;/strong&gt; Firewall SSH access to only allow connections from your VPN subnet or specific trusted internal IPs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intrusion Detection/Prevention:&lt;/strong&gt; Install &lt;code&gt;fail2ban&lt;/code&gt; or similar tools to automatically block IPs exhibiting malicious behavior (e.g., repeated failed SSH logins).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application Security:&lt;/strong&gt; Configure applications securely (e.g., enforce HTTPS on web server, secure database access, use strong passwords/API keys for trading platform).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Enterprise Server Specifics (Dell iDRAC, IBM IMM/XCC, HP iLO)
&lt;/h3&gt;

&lt;p&gt;Repurposed enterprise servers bring powerful remote management capabilities – iDRAC (Dell), IMM/XCC (IBM/Lenovo), iLO (HP). These Out-Of-Band (OOB) management interfaces provide deep hardware-level control (power cycling, console access, BIOS config) even if the main OS is down. &lt;strong&gt;Compromising the management interface is equivalent to physical access.&lt;/strong&gt; Treat them with extreme caution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Network Isolation is Paramount:&lt;/strong&gt; Connect the dedicated management port to a &lt;strong&gt;completely separate, physically isolated management network&lt;/strong&gt; if feasible. This network should have no internet access or strictly firewalled access.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If Separate Network Unfeasible:&lt;/strong&gt; Place the management interface IP on your &lt;strong&gt;most trusted internal segment&lt;/strong&gt; (e.g., Core LAN, &lt;em&gt;never&lt;/em&gt; Server Zone or Untrusted Zone). Aggressively firewall access to this IP – only allow connections from your specific admin workstation IP(s). &lt;strong&gt;Never expose these interfaces directly to the internet or less trusted network segments.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Configuration:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Change Default Credentials Immediately:&lt;/strong&gt; Default usernames/passwords are public knowledge. Use strong, unique passwords.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Settings:&lt;/strong&gt; Assign a static IP. Configure network settings carefully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Encryption:&lt;/strong&gt; Enable TLS/SSL (HTTPS) for the web interface. Use secure protocols (e.g., SSH instead of Telnet if available).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Firmware Updates:&lt;/strong&gt; Keep the management interface firmware &lt;strong&gt;updated&lt;/strong&gt;. These interfaces have their own OS and vulnerabilities. Updates are critical.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disable Unused Services:&lt;/strong&gt; Disable any services within the management interface you don't need (e.g., SNMP, Telnet, VNC if not used).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access Control:&lt;/strong&gt; Configure user accounts and permissions tightly (less relevant for single-user home setups, but good practice).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging:&lt;/strong&gt; Enable and periodically review logs within the management interface itself.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Physical Security
&lt;/h3&gt;

&lt;p&gt;If you're running actual server hardware (not just Pis), consider physical security. Is the hardware in a location where unauthorized individuals could access it directly (e.g., connect a keyboard, USB drive)? Less critical in a typical home, but worth considering if the stakes are high.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion: Vigilance and Adaptation
&lt;/h2&gt;

&lt;p&gt;Building a secure home network for critical operations isn't a one-time setup; it's an ongoing process. Technology evolves, threats change, vulnerabilities are discovered. Regular updates, log reviews, and periodic configuration audits are essential. Treat your network as a living system that requires continuous monitoring and adaptation. Layer your defenses, minimize your attack surface, and always assume potential compromise.&lt;/p&gt;

&lt;p&gt;Evolve. Excel. Encrypt.&lt;/p&gt;

</description>
      <category>networksecurity</category>
      <category>homelab</category>
      <category>trading</category>
      <category>servers</category>
    </item>
    <item>
      <title>Three Proven Techniques to Reduce LLM Hallucinations</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 19:56:07 +0000</pubDate>
      <link>https://dev.to/joor0x/three-proven-techniques-to-reduce-llm-hallucinations-3iga</link>
      <guid>https://dev.to/joor0x/three-proven-techniques-to-reduce-llm-hallucinations-3iga</guid>
      <description>&lt;p&gt;Large Language Models are superuseful right, but they have a well-known weakness: &lt;strong&gt;hallucinations&lt;/strong&gt;. These are confident-sounding responses that are factually incorrect or completely fabricated. While no technique eliminates hallucinations entirely, these three strategies significantly reduce their occurrence in production systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Provide an Escape Hatch
&lt;/h2&gt;

&lt;p&gt;One of the most effective ways to reduce hallucinations is giving the model permission to admit uncertainty. LLMs are trained to be helpful, which sometimes leads them to generate plausible-sounding answers even when they lack sufficient information.&lt;/p&gt;

&lt;p&gt;By explicitly allowing responses like "I don't know" or "The provided context doesn't contain this information," you give the model a legitimate alternative to fabrication.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Question Answering with Context
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a technical support assistant. Answer the user's question
based ONLY on the provided &amp;lt;documentation&amp;gt;.

&amp;lt;documentation&amp;gt;
{documentation}
&amp;lt;/documentation&amp;gt;

If the answer is NOT clearly stated in the &amp;lt;documentation&amp;gt;,
respond with: "This information is not covered in the available documentation."

Do not speculate or provide information from outside the given context.

User question: {question}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach works because you're changing the model's optimization target from "provide an answer" to "provide an accurate answer or acknowledge the limitation."&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Use Chain-of-Thought Verification
&lt;/h2&gt;

&lt;p&gt;Chain-of-thought (CoT) prompting asks the model to show its reasoning before providing a final answer. This technique reduces hallucinations by forcing the model to ground each step in verifiable logic.&lt;/p&gt;

&lt;p&gt;The key enhancement is adding a &lt;strong&gt;verification step&lt;/strong&gt; where the model checks its own reasoning against the source material before committing to a final response.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Document Analysis with Self-Verification
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are analyzing a technical &amp;lt;report&amp;gt; to extract key findings.

&amp;lt;report&amp;gt;
{report_content}
&amp;lt;/report&amp;gt;

Use the &amp;lt;analysis&amp;gt; section to work through your reasoning:

&amp;lt;analysis&amp;gt;
1. Identify the main claims in the report
2. For each claim, note the specific paragraph or section where it appears
3. Verify each finding has direct support in the source text
4. Flag any conclusions that require inference beyond the stated facts
&amp;lt;/analysis&amp;gt;

After completing your analysis, provide a &amp;lt;summary&amp;gt; containing
ONLY findings that are directly supported by the source text.

&amp;lt;summary&amp;gt;
[Your verified findings here]
&amp;lt;/summary&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The explicit verification step catches many potential hallucinations before they reach the final output. The model essentially performs a self-audit of its reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Implement Confidence Thresholds
&lt;/h2&gt;

&lt;p&gt;Instruct the model to evaluate its own confidence and only provide answers above a certain threshold. This technique is particularly useful for factual queries where accuracy is critical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Technical Query with Confidence Gate
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a database expert answering technical questions.

Question: {technical_question}

Before answering, assess your confidence level:
- HIGH: You are certain this is correct based on established knowledge
- MEDIUM: You believe this is correct but there may be edge cases
- LOW: You are unsure or this requires verification

If your confidence is LOW, respond with:
"I recommend verifying this with official documentation before implementation."

If your confidence is MEDIUM or HIGH, provide your answer and note any caveats.

Confidence assessment: [HIGH/MEDIUM/LOW]
Answer:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach transforms the model from always providing answers to being selective about when to provide them—a significant shift that reduces false confidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Combining Techniques for Production Systems
&lt;/h2&gt;

&lt;p&gt;In practice, the most robust systems combine all three approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Escape hatches&lt;/strong&gt; prevent fabrication when context is insufficient&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chain-of-thought verification&lt;/strong&gt; catches logical errors before output&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Confidence thresholds&lt;/strong&gt; filter out uncertain responses&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember: no technique eliminates hallucinations completely even if you are sober and don't take any drug.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>promptengineering</category>
      <category>hallucinations</category>
    </item>
    <item>
      <title>Temperature Zero, Fixed Seed, Different Answers</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 19:50:06 +0000</pubDate>
      <link>https://dev.to/joor0x/temperature-zero-fixed-seed-different-answers-b6d</link>
      <guid>https://dev.to/joor0x/temperature-zero-fixed-seed-different-answers-b6d</guid>
      <description>&lt;p&gt;I was discussing reliability in AI agents when a familiar question came up: if you set an LLM's temperature to zero, doesn't that make it deterministic?&lt;/p&gt;

&lt;p&gt;It sounds reasonable. Remove random sampling, always pick the most likely next token, and you get the same answer every time.&lt;/p&gt;

&lt;p&gt;So I tried it on my laptop.&lt;/p&gt;

&lt;p&gt;Same model. Same prompt. Temperature zero. Fixed seed. Five identical responses, then a different story on request six.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It happened on the very first execution of the script.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A small test with Ollama
&lt;/h2&gt;

&lt;p&gt;I used &lt;code&gt;llama3.1:8b&lt;/code&gt; through Ollama's local API, with these settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="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;"temperature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"seed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"num_ctx"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"num_predict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;512&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The prompt asked for a short story in Spanish about a programmer who finds a strange message in the server logs.&lt;/p&gt;

&lt;p&gt;The Python script serializes the request body once and sends those exact bytes repeatedly. Requests are sequential, and no conversation history is passed between them.&lt;/p&gt;

&lt;p&gt;It compares the generated text exactly and prints a short SHA-256 hash for each response. Timestamps and execution timings are excluded, since comparing those would produce meaningless differences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request six changed the story
&lt;/h2&gt;

&lt;p&gt;Here are the response hashes from the captured output, with the diff omitted for readability (&lt;code&gt;variantes&lt;/code&gt; counts the distinct responses seen so far):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;01/30  hash=e8150452110a716b  variantes=1  fin=stop
02/30  hash=e8150452110a716b  variantes=1  fin=stop
03/30  hash=e8150452110a716b  variantes=1  fin=stop
04/30  hash=e8150452110a716b  variantes=1  fin=stop
05/30  hash=e8150452110a716b  variantes=1  fin=stop
06/30  hash=bf54c4fc8b524784  variantes=2  fin=stop
07/30  hash=e8150452110a716b  variantes=2  fin=stop
08/30  hash=e8150452110a716b  variantes=2  fin=stop
09/30  hash=e8150452110a716b  variantes=2  fin=stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first story featured the message "La respuesta está en el número 42" ("The answer is in the number 42").&lt;/p&gt;

&lt;p&gt;The sixth response changed it to "La sombra se mueve en el rincón" ("The shadow moves in the corner") and developed a different plot.&lt;/p&gt;

&lt;p&gt;Requests seven through nine returned to the original text.&lt;/p&gt;

&lt;p&gt;This was a change in content, not just whitespace or formatting. The excerpt stops at request nine; it is not a completed 30-request report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://gist.github.com/ad77bfhqw8/f13447325be5a9128fe9b8e84c608338" rel="noopener noreferrer"&gt;The complete script, settings and output diff are in this Gist.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It only uses Python's standard library. With Ollama running and the model installed, you can paste the script into a terminal and try it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What temperature zero actually controls
&lt;/h2&gt;

&lt;p&gt;With temperature zero, Ollama falls back to greedy decoding: the model selects the token with the highest score. Given identical scores and consistent tie handling, that selection is deterministic.&lt;/p&gt;

&lt;p&gt;The important qualification is &lt;strong&gt;given identical scores&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Those scores come from floating-point computation. Execution details such as GPU kernels, the order of operations and batching can slightly change the numbers. If two candidate tokens are close enough, a tiny difference can change which one wins.&lt;/p&gt;

&lt;p&gt;Once a different token is selected, the next step receives a different prefix. From there, the rest of the answer can diverge substantially.&lt;/p&gt;

&lt;p&gt;That is a plausible mechanism, not a diagnosis of my run. I did not trace Ollama's internals or record token scores, so I cannot attribute this result to a particular kernel, cache or scheduling decision.&lt;/p&gt;

&lt;p&gt;For context, vLLM documents &lt;a href="https://docs.vllm.ai/en/latest/features/batch_invariance/" rel="noopener noreferrer"&gt;explicit batch invariance controls&lt;/a&gt; involving deterministic kernels and consistent numerical behavior. Reproducibility requires attention to the execution system, not just the decoding settings.&lt;/p&gt;

&lt;p&gt;A fixed seed does not settle that problem either. It controls the random number generator used for sampling, not the arithmetic that produces the scores.&lt;/p&gt;

&lt;h2&gt;
  
  
  A counterexample, not a benchmark
&lt;/h2&gt;

&lt;p&gt;The observation is simple: my local setup returned different text for identical requests specifying &lt;code&gt;temperature=0&lt;/code&gt; and &lt;code&gt;seed=42&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It does not establish a general failure rate. Nor does it mean every model or runtime will behave this way.&lt;/p&gt;

&lt;p&gt;Your installation might return the same answer every time. That would be a useful result too. This test checks repeatability under your conditions; it does not guarantee you will reproduce my divergence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repeatable is not the same as correct
&lt;/h2&gt;

&lt;p&gt;There is another distinction worth keeping in mind when building agents: an answer can be perfectly repeatable and consistently wrong. Two different answers can also both be acceptable.&lt;/p&gt;

&lt;p&gt;Exact reproducibility and task correctness need separate checks.&lt;/p&gt;

&lt;p&gt;For my own systems, I want to measure repeatability where it matters, validate what the output means, and keep execution permissions and constraints in code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Temperature zero is a setting. Reproducibility is a property of the system you actually run.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>ollama</category>
      <category>python</category>
    </item>
    <item>
      <title>How to Disable the Co-Authored-By Trailer in Claude Code</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 19:49:30 +0000</pubDate>
      <link>https://dev.to/joor0x/how-to-disable-the-co-authored-by-trailer-in-claude-code-447</link>
      <guid>https://dev.to/joor0x/how-to-disable-the-co-authored-by-trailer-in-claude-code-447</guid>
      <description>&lt;p&gt;By default, every commit Claude Code makes for you ends with a line like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Co-Authored-By: Claude &amp;lt;noreply@anthropic.com&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pull requests get a similar footer: &lt;code&gt;🤖 Generated with Claude Code&lt;/code&gt;. Some people like it. I don't, and this post shows how to turn it off in a few seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I turn it off
&lt;/h2&gt;

&lt;p&gt;Let's be honest: almost every developer uses an AI model in one way or another now. Autocomplete, chat, agents, a quick "explain this regex". The only exception is maybe the odd COBOL veteran keeping a bank mainframe alive, and even they are probably asking an LLM what a 1987 copybook does.&lt;/p&gt;

&lt;p&gt;So a trailer saying "AI was involved" on every commit tells nobody anything new. It's noise in &lt;code&gt;git log&lt;/code&gt;. I'm the one who reviews the diff, and I'm the one responsible for what gets merged.&lt;/p&gt;

&lt;p&gt;And Anthropic doesn't need that line anyway. Claude's output already carries a &lt;strong&gt;text watermark&lt;/strong&gt;: an imperceptible pattern in word choice, with no extra characters or tokens. According to Anthropic, the watermark contains no information about the user, their organization or their conversations. It just marks the text as Claude-generated.&lt;/p&gt;

&lt;p&gt;So deleting the trailer doesn't hide anything from the people who made the model. It only removes a visible label from GitHub, which is mostly free advertising anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: the &lt;code&gt;attribution&lt;/code&gt; setting
&lt;/h2&gt;

&lt;p&gt;Claude Code reads its settings from JSON files. To remove the trailers for every project, edit your user settings at &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="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;"attribution"&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="nl"&gt;"commit"&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="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pr"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;commit&lt;/code&gt;: text appended to commit messages. An empty string removes the &lt;code&gt;Co-Authored-By&lt;/code&gt; trailer.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pr&lt;/code&gt;: text appended to pull request descriptions. An empty string removes the "Generated with Claude Code" footer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you only want it for one repository, put the same block in &lt;code&gt;.claude/settings.json&lt;/code&gt;  or &lt;code&gt;.claude/settings.local.json&lt;/code&gt; inside that project.&lt;/p&gt;

&lt;p&gt;You can also put your own text there instead of an empty string, if you want a custom footer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check it worked
&lt;/h3&gt;

&lt;p&gt;Start a new Claude Code session (settings load at startup), ask it to commit something, then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;%B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No trailer, no footer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anecdote: the mystery contributor
&lt;/h2&gt;

&lt;p&gt;Here's a story that made me want to write this down.&lt;/p&gt;

&lt;p&gt;A developer noticed a stranger listed as a contributor on their GitHub repo. An account with a name like &lt;code&gt;poop00po0o&lt;/code&gt;, which had never pushed a single commit there. They asked Claude Code to investigate, and it answered roughly like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mystery solved. Every commit made with my help has this trailer:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Co-Authored-By: Claude Sonnet 4.6 &amp;lt;noreply@anthropic.com&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;GitHub resolves co-author trailers by matching the email address to a GitHub account. Someone has likely registered a GitHub account using the email &lt;code&gt;noreply@anthropic.com&lt;/code&gt;, effectively squatting on that address so they show up as the "Claude" co-author in any repo that uses the Claude Code co-authorship convention.&lt;/p&gt;

&lt;p&gt;This is not a security breach of your repo. No one has pushed code you didn't write. The "contributor" label is just GitHub resolving that email trailer to whoever holds that account.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The options it gave were sensible: ignore it (it's cosmetic), stop adding the trailer, and report it to Anthropic at &lt;a href="https://github.com/anthropics/claude-code/issues" rel="noopener noreferrer"&gt;github.com/anthropics/claude-code/issues&lt;/a&gt;, since it affects everyone pushing co-authored commits.&lt;/p&gt;

&lt;p&gt;I can't confirm exactly how that account ended up linked to the address. GitHub normally only links commits to verified emails, so the "someone registered it" explanation is the agent's best guess, not a proven fact. But the mechanism is real: &lt;strong&gt;a &lt;code&gt;Co-Authored-By&lt;/code&gt; line is just an email address, and GitHub will show whatever account it maps that email to on your repo's contributor list.&lt;/strong&gt; You don't control that mapping.&lt;/p&gt;

&lt;p&gt;That's one more reason to take the line out. Your commits should carry the names of the people responsible for them, and nobody else's.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>git</category>
      <category>github</category>
    </item>
    <item>
      <title>I Replaced My Vector Database With Boring Algorithms</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 19:44:58 +0000</pubDate>
      <link>https://dev.to/joor0x/i-replaced-my-vector-database-with-boring-algorithms-4hc9</link>
      <guid>https://dev.to/joor0x/i-replaced-my-vector-database-with-boring-algorithms-4hc9</guid>
      <description>&lt;p&gt;I recently removed a vector database from a few parts of my software.&lt;/p&gt;

&lt;p&gt;Not because vector databases are bad. Not because embeddings stopped being useful. And definitely not because I suddenly decided that AI infrastructure is overhyped.&lt;/p&gt;

&lt;p&gt;The reason was much more boring: I was using the wrong tool for some of the jobs.&lt;/p&gt;

&lt;p&gt;One of those jobs was source-code retrieval for RAG. The original version worked the way most first versions work: split the repository into chunks, embed each chunk, store the embeddings, and retrieve the chunks that looked closest to the user's query.&lt;/p&gt;

&lt;p&gt;It was a reasonable starting point. It also worked well enough to keep around for a while.&lt;/p&gt;

&lt;p&gt;But after using it more, I started noticing a pattern. A lot of the questions I was asking were not really semantic questions.&lt;/p&gt;

&lt;p&gt;They were questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where is this function defined?&lt;/li&gt;
&lt;li&gt;Which class owns this method?&lt;/li&gt;
&lt;li&gt;Where is this symbol imported?&lt;/li&gt;
&lt;li&gt;What calls this helper?&lt;/li&gt;
&lt;li&gt;Where is this config value used?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For that kind of query, the source code already contains the answer explicitly. The information is sitting in the syntax tree, the import graph, the file names, the symbols, and the references. Turning all of that into embeddings first adds an indirect step that often does not buy you much.&lt;/p&gt;

&lt;p&gt;So I replaced part of the vector search with much less exciting machinery: AST parsing, symbol indexes, exact lookups, reference tracking, and a few simple ranking rules.&lt;/p&gt;

&lt;p&gt;The result was better than I expected.&lt;/p&gt;

&lt;p&gt;For the workloads I tested, the boring version was faster, cheaper, easier to debug, and often more accurate. It was also far more predictable. When I asked for a function by name, I did not have to hope that the embedding space agreed with me. The index either had the symbol or it did not.&lt;/p&gt;

&lt;p&gt;That determinism matters more than it gets credit for.&lt;/p&gt;

&lt;p&gt;When the same input produces the same output, the system becomes easier to test. It becomes easier to reproduce bugs. It becomes easier to explain why something happened. And when your application already has an LLM inside it, adding more deterministic pieces around it is usually a good trade.&lt;/p&gt;

&lt;p&gt;This made me reconsider an assumption I had been carrying around: that an AI-heavy product should also have AI-heavy infrastructure everywhere around it.&lt;/p&gt;

&lt;p&gt;It does not.&lt;/p&gt;

&lt;p&gt;Plenty of software problems are still better solved with databases, parsers, indexes, graphs, rules, and ordinary algorithms. The presence of an LLM in the product does not magically turn every subsystem into a machine learning problem.&lt;/p&gt;

&lt;p&gt;The distinction I now find useful is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The LLM handles ambiguity. The software handles precision.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;LLMs are excellent when the input is vague, incomplete, semantic, or expressed in natural language. They are good at interpreting intent, mapping fuzzy requests to possible actions, and explaining results back to a human.&lt;/p&gt;

&lt;p&gt;Traditional software is excellent when the problem has structure. If there are explicit rules, known identifiers, exact relationships, constraints, or a well-understood algorithm, regular software usually wins.&lt;/p&gt;

&lt;p&gt;Source-code retrieval is a good example. If I ask, "Where do we handle failed payments?", embeddings can help because the wording might not match the code. The relevant code may mention invoices, retries, billing states, or webhooks instead of "failed payments."&lt;/p&gt;

&lt;p&gt;But if I ask, "Where is &lt;code&gt;PaymentRetryPolicy&lt;/code&gt; defined?", I do not need a semantic search system to guess. I need an index.&lt;/p&gt;

&lt;p&gt;The same pattern shows up outside of code too.&lt;/p&gt;

&lt;p&gt;If the answer is in a database row, query the database. If it is in a graph, traverse the graph. If it follows from a rule, apply the rule. If it is in a parser-friendly format, parse it. Use embeddings when they add information, not just because they feel like the AI-native option.&lt;/p&gt;

&lt;p&gt;The architecture I keep coming back to looks simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Human request
  -&amp;gt; LLM
  -&amp;gt; interpret ambiguity
  -&amp;gt; traditional software
  -&amp;gt; execute precisely
  -&amp;gt; LLM
  -&amp;gt; explain the result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that setup, the LLM is not replacing the software. It is translating between the human and the software.&lt;/p&gt;

&lt;p&gt;That is a much more useful role in many systems. Humans are messy. We ask incomplete questions, use the wrong terms, forget details, and describe what we want indirectly. LLMs are very good at cleaning up that mess.&lt;/p&gt;

&lt;p&gt;But once the intent is clear, the execution should often be handed to something more precise. A SQL query. A parser. A search index. A constraint solver. A rules engine. A normal function call.&lt;/p&gt;

&lt;p&gt;This is not an argument against vector databases, embeddings, or LLMs. I still use them, and there are problems where they are exactly the right tool.&lt;/p&gt;

&lt;p&gt;It is an argument against adding uncertainty where the problem does not need it.&lt;/p&gt;

&lt;p&gt;If the answer already exists in a syntax tree, a database index, a graph, or a deterministic rule, converting the problem into embeddings first may just make the system slower and harder to reason about.&lt;/p&gt;

&lt;p&gt;The useful question is not, "Can an LLM solve this?"&lt;/p&gt;

&lt;p&gt;Most of the time, with enough prompting and glue code, the answer is probably yes.&lt;/p&gt;

&lt;p&gt;The better question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which part of this problem actually needs an LLM?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question leads to simpler systems. It also leads to better AI systems, because the model is used where it adds real value instead of being asked to compensate for infrastructure that should have been deterministic in the first place.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>rag</category>
      <category>vectordatabases</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Human as a Tool: The Agent Pattern Where You Work for the Machine</title>
      <dc:creator>Josep Oriol Carné</dc:creator>
      <pubDate>Sun, 08 Nov 2026 19:44:23 +0000</pubDate>
      <link>https://dev.to/joor0x/human-as-a-tool-the-agent-pattern-where-you-work-for-the-machine-525d</link>
      <guid>https://dev.to/joor0x/human-as-a-tool-the-agent-pattern-where-you-work-for-the-machine-525d</guid>
      <description>&lt;p&gt;There's an agent design pattern with an uncomfortable premise: the agent is the orchestrator, and &lt;em&gt;you&lt;/em&gt; are one of its tools.&lt;/p&gt;

&lt;p&gt;It goes by a few names — &lt;strong&gt;human-as-a-tool&lt;/strong&gt;, human-as-tool, sometimes lumped under "human-in-the-loop." But it's worth separating the two, because the inversion is the whole point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Human-in-the-loop vs. human-as-a-tool
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Human-in-the-loop&lt;/strong&gt; keeps the human in charge. The agent proposes, the human approves. You're the supervisor signing off on the intern's work before it ships. Control flow belongs to you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Human-as-a-tool&lt;/strong&gt; flips it. The agent owns the plan. It decomposes the task, executes what it can, and when it hits a step that only a human can perform, it &lt;em&gt;calls&lt;/em&gt; the human — with the same interface it uses to call a search API or a shell. You get a message: "I need the 2FA code from your phone." You answer. The agent continues.&lt;/p&gt;

&lt;p&gt;In the first pattern, the human is management. In the second, the human is a blocking I/O call with unusually high latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  What only humans can do (for now)
&lt;/h2&gt;

&lt;p&gt;The pattern exists because there's a residue of tasks that no tool call can cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Physical actions.&lt;/strong&gt; Plug in the cable, reboot the router, sign the paper, go look at the machine that's actually on fire.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth walls designed to stop machines.&lt;/strong&gt; CAPTCHAs, 2FA codes, biometric checks, "click the link we sent to your phone." These are, by construction, human-only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legal and social standing.&lt;/strong&gt; Only a human can consent, sign a contract, or make the phone call where the bank insists on hearing a voice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Judgment and taste.&lt;/strong&gt; "Which of these three logos feels right?" is a question with no assertion to check. Someone has to just &lt;em&gt;decide&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access the agent doesn't have.&lt;/strong&gt; The password in your head, the context from a hallway conversation, the tribal knowledge that never made it into a doc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice the parenthetical doing heavy lifting in this post's premise: &lt;em&gt;for now&lt;/em&gt;. That list is not stable. Ten years ago "read the text in this blurry image" was on it. Computer-use agents are eating the physical-clicking category as we speak. The list only shrinks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The implementation is almost insultingly simple
&lt;/h2&gt;

&lt;p&gt;At its core, the pattern is one tool definition:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ask_human"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ask the human operator. Expensive and slow — use only when no other tool can answer."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&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="nl"&gt;"question"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What you need, with enough context to answer without reading your whole transcript"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. LangChain has shipped it for years as &lt;code&gt;HumanInputRun&lt;/code&gt;. Tools like HumanLayer wrap it in Slack approvals and async queues. Claude Code has &lt;code&gt;AskUserQuestion&lt;/code&gt;. Every serious agent framework converges on the same shape, because the shape is obvious: a function call whose backend is a person.&lt;/p&gt;

&lt;p&gt;The interesting engineering is in the details around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Make it expensive in the prompt.&lt;/strong&gt; If the tool description doesn't scream "last resort," the agent will use you as a search engine. You become the bottleneck in your own automation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go async by default.&lt;/strong&gt; A blocking prompt in a terminal is fine for a 5-minute task. For a long-running agent, the human call should be a notification — Slack, email, push — with the agent parked on that branch while it works on others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demand batching.&lt;/strong&gt; An agent that interrupts you four times with one question each is worse than one that interrupts you once with four questions. This is worth stating explicitly in the system prompt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set timeouts and fallbacks.&lt;/strong&gt; Humans are unreliable infrastructure. We sleep, we go to lunch, we ignore notifications. Decide what the agent does when the human call times out: retry, escalate, or degrade gracefully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Log every call.&lt;/strong&gt; The transcript of what the agent asked and what the human answered is your audit trail — and, later, your training data for automating that exact question away.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The uncomfortable part is the useful part
&lt;/h2&gt;

&lt;p&gt;It's easy to read this pattern as dystopian — the machine dispatching work orders to its human peripheral. I think the honest reading is more practical: it's an inventory system.&lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;ask_human&lt;/code&gt; call in your logs is a receipt for a task that resisted automation. Grep those logs after a month and you have something valuable: a ranked list of what actually requires you. Some entries are permanent (judgment, consent, taste). Most aren't. "Fetch the 2FA code" disappears the day you wire up a TOTP secret. "Which environment is prod?" disappears the day you write it down.&lt;/p&gt;

&lt;p&gt;That's the discipline the pattern enforces, and it's the same one I apply everywhere else: &lt;strong&gt;treat yourself as a dependency to be minimized, not a supervisor to be flattered.&lt;/strong&gt; Design the human tool with a clean interface — a question in, an answer out — and swapping the human for software later becomes a one-line change. The agent never even notices you left.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is heading
&lt;/h2&gt;

&lt;p&gt;The endgame is visible from here. The human-as-a-tool call rate is the single most honest metric of agent autonomy — far more honest than any benchmark. An agent that calls &lt;code&gt;ask_human&lt;/code&gt; twenty times per task is a form with extra steps. One that calls it zero times doesn't need you.&lt;/p&gt;

&lt;p&gt;The interesting number is in between, and it's dropping. My advice: implement the pattern, log the calls, and watch which of your irreplaceable human contributions quietly fall off the list.&lt;/p&gt;

&lt;p&gt;For now, the agent still needs someone to plug in the cable. Enjoy it while it lasts.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>llm</category>
      <category>designpatterns</category>
    </item>
  </channel>
</rss>
