<?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: Syed Asif</title>
    <description>The latest articles on DEV Community by Syed Asif (@sydasif78).</description>
    <link>https://dev.to/sydasif78</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%2F3943643%2F7aa19a6f-abf0-4d5d-9043-2d94e92e3d02.png</url>
      <title>DEV Community: Syed Asif</title>
      <link>https://dev.to/sydasif78</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sydasif78"/>
    <language>en</language>
    <item>
      <title>Building Hybrid Network Labs with netlab: Combining Containerlab and Vagrant</title>
      <dc:creator>Syed Asif</dc:creator>
      <pubDate>Mon, 06 Jul 2026 03:42:50 +0000</pubDate>
      <link>https://dev.to/sydasif78/building-hybrid-network-labs-with-netlab-combining-containerlab-and-vagrant-4ljn</link>
      <guid>https://dev.to/sydasif78/building-hybrid-network-labs-with-netlab-combining-containerlab-and-vagrant-4ljn</guid>
      <description>&lt;p&gt;Not every network operating system ships in the same format. Cisco IOSv&lt;br&gt;
and IOSvL2 are distributed as virtual machine images and require KVM —&lt;br&gt;
there are no container images for them. On the other end of the spectrum,&lt;br&gt;
Cisco IOL and Alpine Linux run natively in containers, needing only a&lt;br&gt;
few megabytes of overhead.&lt;/p&gt;

&lt;p&gt;A hybrid lab lets you run each device in its native environment: virtual&lt;br&gt;
machines for the NOSes that need them, containers for everything else.&lt;br&gt;
netlab orchestrates both backends from a single topology file, so you&lt;br&gt;
don't have to manage Vagrant and Containerlab separately.&lt;/p&gt;

&lt;p&gt;By the end of this guide you'll have built a working campus topology&lt;br&gt;
that mixes both providers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Nodes&lt;/th&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Core router&lt;/td&gt;
&lt;td&gt;R1&lt;/td&gt;
&lt;td&gt;IOSv&lt;/td&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Distribution&lt;/td&gt;
&lt;td&gt;D1, D2&lt;/td&gt;
&lt;td&gt;IOSvL2&lt;/td&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Access&lt;/td&gt;
&lt;td&gt;S1, S2&lt;/td&gt;
&lt;td&gt;IOL-L2&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosts&lt;/td&gt;
&lt;td&gt;H1, H2, H3, H4&lt;/td&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All nine nodes are defined in one &lt;code&gt;topology.yml&lt;/code&gt; and deployed with a&lt;br&gt;
single &lt;code&gt;netlab up&lt;/code&gt; command — netlab handles the cross-provider wiring,&lt;br&gt;
bridge discovery, and configuration deployment automatically.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Why Build a Hybrid Lab?
&lt;/h2&gt;

&lt;p&gt;Cisco distributes its network operating systems in different formats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IOSv and IOSvL2&lt;/strong&gt; are QEMU/KVM virtual machine images. There are no
native container images for them — they require a full VM, consuming
around 1 GB of RAM each.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IOL (IOS On Linux)&lt;/strong&gt; is a binary that runs directly on the Linux
kernel. It doesn't need a hypervisor, so it uses less CPU and memory
than the equivalent IOSv VM. Cisco's documentation notes that IOL nodes
"consume much less CPU and memory than an equivalent IOSv or CSR 1000v
node in your lab."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpine Linux&lt;/strong&gt; is a few megabytes as a container image, yet netlab
would allocate 1 GB of RAM to it if you ran it as a VM — just for
&lt;code&gt;ping&lt;/code&gt; and &lt;code&gt;bash&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building a lab with a single provider forces you to pick the least common&lt;br&gt;
denominator: run everything as VMs (wasting resources on lightweight&lt;br&gt;
nodes) or run everything as containers (excluding devices that have no&lt;br&gt;
container image). A hybrid lab avoids both tradeoffs.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Best Backend&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IOSv&lt;/td&gt;
&lt;td&gt;Vagrant/libvirt&lt;/td&gt;
&lt;td&gt;No native container image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IOSvL2&lt;/td&gt;
&lt;td&gt;Vagrant/libvirt&lt;/td&gt;
&lt;td&gt;No native container image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cisco IOL&lt;/td&gt;
&lt;td&gt;Containerlab&lt;/td&gt;
&lt;td&gt;Runs as a native Linux binary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;Containerlab&lt;/td&gt;
&lt;td&gt;Runs as a native Alpine image&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Run every device in its native environment.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  3. Prerequisites
&lt;/h2&gt;

&lt;p&gt;You need a Linux server (Ubuntu recommended) with the following toolchain&lt;br&gt;
installed. Verify each component before proceeding:&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;# KVM hardware support&lt;/span&gt;
kvm-ok

&lt;span class="c"&gt;# libvirt&lt;/span&gt;
virsh list &lt;span class="nt"&gt;--all&lt;/span&gt;

&lt;span class="c"&gt;# Vagrant + vagrant-libvirt plugin&lt;/span&gt;
vagrant &lt;span class="nt"&gt;--version&lt;/span&gt;
vagrant plugin list

&lt;span class="c"&gt;# Docker + Containerlab&lt;/span&gt;
docker &lt;span class="nt"&gt;--version&lt;/span&gt;
containerlab version

&lt;span class="c"&gt;# netlab&lt;/span&gt;
pip3 show networklab | &lt;span class="nb"&gt;grep &lt;/span&gt;Version

&lt;span class="c"&gt;# User group membership — must include libvirt, vagrant, docker&lt;/span&gt;
&lt;span class="nb"&gt;groups&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any check fails, see the &lt;a href="https://netlab.tools/install/ubuntu/" rel="noopener noreferrer"&gt;netlab Ubuntu installation guide&lt;/a&gt; for setup steps.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Understanding netlab Providers
&lt;/h2&gt;

&lt;p&gt;A virtualization provider is the backend that runs your lab devices. netlab supports three of them:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Backend&lt;/th&gt;
&lt;th&gt;Use case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;td&gt;Vagrant + KVM/QEMU&lt;/td&gt;
&lt;td&gt;VM-based NOS images&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;Containerlab + Docker&lt;/td&gt;
&lt;td&gt;Container-native devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;external&lt;/td&gt;
&lt;td&gt;Physical or pre-existing devices&lt;/td&gt;
&lt;td&gt;Hardware or unmanaged nodes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Provider Resolution
&lt;/h3&gt;

&lt;p&gt;netlab decides which provider to use for each node by checking these locations in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Per-node&lt;/strong&gt; &lt;code&gt;provider&lt;/code&gt; attribute — highest precedence&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group&lt;/strong&gt; &lt;code&gt;provider&lt;/code&gt; attribute — applied to all group members&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Topology-level&lt;/strong&gt; &lt;code&gt;provider&lt;/code&gt; — the default for all nodes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System default&lt;/strong&gt; — &lt;code&gt;libvirt&lt;/code&gt; if nothing else is set&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In our topology, &lt;code&gt;provider: libvirt&lt;/code&gt; is set at the top level. Nodes without a &lt;code&gt;provider&lt;/code&gt; attribute (R1, D1, D2) inherit it. Nodes with &lt;code&gt;provider: clab&lt;/code&gt; (S1, S2, H1–H4) override it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hybrid Mode Constraint
&lt;/h3&gt;

&lt;p&gt;When mixing providers, the primary (topology-level) provider must be &lt;code&gt;libvirt&lt;/code&gt;. &lt;code&gt;clab&lt;/code&gt; can only be a secondary (per-node) provider. This is a hard constraint — netlab needs to orchestrate the startup sequence (Vagrant first, then Containerlab) and bridge the two environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Provider-Specific Images
&lt;/h3&gt;

&lt;p&gt;Each device type can use different images depending on the provider. Set them in &lt;code&gt;defaults.devices&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;iosv.libvirt.image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cisco/iosv:15.9.M3&lt;/span&gt;
    &lt;span class="na"&gt;ioll2.clab.image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;asifsyd/cisco_iol:l2-17.12.01&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.libvirt.&lt;/code&gt; variant is used when the node runs on libvirt; the &lt;code&gt;.clab.&lt;/code&gt; variant is used when it runs on Containerlab.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Building the Topology
&lt;/h2&gt;

&lt;p&gt;Here is the complete &lt;code&gt;topology.yml&lt;/code&gt; file. It defines a campus network with a core router, two distribution switches, two access switches, and&lt;br&gt;
four hosts — each running on its native provider.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;campus&lt;/span&gt;
&lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;libvirt&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.0&lt;/span&gt;

&lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;iosv.libvirt.image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cisco/iosv:15.9.M3&lt;/span&gt;
    &lt;span class="na"&gt;iosv.warnings.paramiko&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;iosvl2.libvirt.image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cisco/iosvl2:15.2&lt;/span&gt;
    &lt;span class="na"&gt;iosvl2.warnings.paramiko&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="na"&gt;ioll2.clab.image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;asifsyd/cisco_iol:l2-17.12.01&lt;/span&gt;
    &lt;span class="na"&gt;linux.clab.image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alpine:latest&lt;/span&gt;

&lt;span class="na"&gt;nodes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;R1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;iosv&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;ospf&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;D1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;iosvl2&lt;/span&gt;
  &lt;span class="na"&gt;D2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;iosvl2&lt;/span&gt;
  &lt;span class="na"&gt;S1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ioll2&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clab&lt;/span&gt;
  &lt;span class="na"&gt;S2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ioll2&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clab&lt;/span&gt;
  &lt;span class="na"&gt;H1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clab&lt;/span&gt;
  &lt;span class="na"&gt;H2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clab&lt;/span&gt;
  &lt;span class="na"&gt;H3&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clab&lt;/span&gt;
  &lt;span class="na"&gt;H4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
    &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clab&lt;/span&gt;

&lt;span class="na"&gt;vlans&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;VLAN_10&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
    &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;H1-S1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;H4-S2&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;VLAN_20&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
    &lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;H2-S2&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;H3-S1&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;DISTRIBUTION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;members&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;D1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;D2&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;vlan&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;ospf&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;vlan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;irb&lt;/span&gt;
  &lt;span class="na"&gt;ACCESS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;members&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;S1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;S2&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;vlan&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;vlan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
  &lt;span class="na"&gt;VLAN_10&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;members&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;H1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;H4&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;routing&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;host&lt;/span&gt;
    &lt;span class="na"&gt;routing.static&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;ipv4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
        &lt;span class="na"&gt;nexthop.ipv4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;172.16.0.254&lt;/span&gt;
  &lt;span class="na"&gt;VLAN_20&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;members&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;H2&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;H3&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;linux&lt;/span&gt;
    &lt;span class="na"&gt;module&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;routing&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;host&lt;/span&gt;
    &lt;span class="na"&gt;routing.static&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;ipv4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
        &lt;span class="na"&gt;nexthop.ipv4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;172.16.1.254&lt;/span&gt;

&lt;span class="na"&gt;links&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;R1-D1&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;R1-D2&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;access_trunk&lt;/span&gt;
    &lt;span class="na"&gt;vlan.trunk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;VLAN_10&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;VLAN_20&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;members&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;D1-S1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;D1-S2&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;D2-S1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;D2-S2&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Top-Level Attributes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name: campus&lt;/code&gt; — used by netlab to name Linux bridges and container prefixes. Containers will be created as &lt;code&gt;clab-campus-&amp;lt;node&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;provider: libvirt&lt;/code&gt; — the primary virtualization provider. Nodes without their own &lt;code&gt;provider&lt;/code&gt; attribute inherit this.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;version: 1.0&lt;/code&gt; — the minimum netlab version required. If an older version tries to load this file, netlab will refuse.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  defaults.devices
&lt;/h3&gt;

&lt;p&gt;This block sets provider-specific container images and device-level settings. The syntax is &lt;code&gt;device.&amp;lt;type&amp;gt;.&amp;lt;provider&amp;gt;.attribute&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;iosv.libvirt.image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cisco/iosv:15.9.M3&lt;/span&gt;
&lt;span class="na"&gt;iosv.warnings.paramiko&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;.libvirt.&lt;/code&gt; variant tells netlab which Vagrant box to use when the node runs on libvirt. The &lt;code&gt;.clab.&lt;/code&gt; variant tells it which Docker image to use when the node runs on containerlab.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;warnings.paramiko: false&lt;/code&gt; lines suppress Ansible paramiko warnings that Cisco IOS devices trigger during configuration deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  nodes
&lt;/h3&gt;

&lt;p&gt;All nine lab devices are defined as a dictionary. Each node has a &lt;code&gt;device&lt;/code&gt; type and an optional list of configuration &lt;code&gt;module&lt;/code&gt;s.&lt;br&gt;
Nodes running on the secondary provider must include &lt;code&gt;provider: clab&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Module&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;R1&lt;/td&gt;
&lt;td&gt;iosv&lt;/td&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;td&gt;ospf&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D1&lt;/td&gt;
&lt;td&gt;iosvl2&lt;/td&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;td&gt;(from group)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D2&lt;/td&gt;
&lt;td&gt;iosvl2&lt;/td&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;td&gt;(from group)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S1&lt;/td&gt;
&lt;td&gt;ioll2&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;(from group)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S2&lt;/td&gt;
&lt;td&gt;ioll2&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;(from group)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H1&lt;/td&gt;
&lt;td&gt;linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;(from group)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H2&lt;/td&gt;
&lt;td&gt;linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;(from group)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H3&lt;/td&gt;
&lt;td&gt;linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;(from group)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H4&lt;/td&gt;
&lt;td&gt;linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;(from group)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  vlans
&lt;/h3&gt;

&lt;p&gt;Two VLANs are defined globally. The &lt;code&gt;links&lt;/code&gt; attribute within each VLAN is a shortcut — it tells netlab which switch ports are access members of that VLAN, saving you from writing out &lt;code&gt;vlan.access&lt;/code&gt; on each link:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VLAN 10&lt;/strong&gt; — Hosts H1 and H4 connected to switches S1 and S2. IP subnet is auto-assigned from the default LAN pool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VLAN 20&lt;/strong&gt; — Hosts H2 and H3 connected to switches S2 and S1.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  groups
&lt;/h3&gt;

&lt;p&gt;Groups apply shared settings to multiple nodes at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DISTRIBUTION&lt;/strong&gt; — D1 and D2 run the &lt;code&gt;vlan&lt;/code&gt; and &lt;code&gt;ospf&lt;/code&gt; modules, use IRB mode (integrated routing and bridging), and pull custom configuration from the &lt;code&gt;template/&lt;/code&gt; directory (Jinja2 files for VRRP configuration).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACCESS&lt;/strong&gt; — S1 and S2 run the &lt;code&gt;vlan&lt;/code&gt; module in pure bridging mode. They forward traffic without routing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VLAN_10&lt;/strong&gt; and &lt;strong&gt;VLAN_20&lt;/strong&gt; — Host groups that set &lt;code&gt;device: linux&lt;/code&gt;, add a static default route pointing at the VRRP virtual IP, and mark the nodes as &lt;code&gt;role: host&lt;/code&gt; (no loopback address).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  links
&lt;/h3&gt;

&lt;p&gt;Two point-to-point links connect the core router to the distribution switches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;R1-D1&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;R1-D2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A link group applies trunk attributes to all four distribution-to-access links at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;access_trunk&lt;/span&gt;
  &lt;span class="na"&gt;vlan.trunk&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;VLAN_10&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;VLAN_20&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;members&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;D1-S1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;D1-S2&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;D2-S1&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;D2-S2&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is equivalent to writing four separate link definitions with &lt;code&gt;vlan.trunk&lt;/code&gt; on each one.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Assigning Providers
&lt;/h2&gt;

&lt;p&gt;Every node in the topology uses the provider that best matches its operating system's distribution format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Provider per Node
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node&lt;/th&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;R1&lt;/td&gt;
&lt;td&gt;iosv&lt;/td&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;td&gt;IOSv is a KVM image — no container exists&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D1&lt;/td&gt;
&lt;td&gt;iosvl2&lt;/td&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;td&gt;Same as above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D2&lt;/td&gt;
&lt;td&gt;iosvl2&lt;/td&gt;
&lt;td&gt;libvirt&lt;/td&gt;
&lt;td&gt;Same as above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S1&lt;/td&gt;
&lt;td&gt;ioll2&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;IOL is a Linux binary packaged as a container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S2&lt;/td&gt;
&lt;td&gt;ioll2&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;Same as above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H1&lt;/td&gt;
&lt;td&gt;linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;Alpine runs natively as a Docker container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H2&lt;/td&gt;
&lt;td&gt;linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;Same as above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H3&lt;/td&gt;
&lt;td&gt;linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;Same as above&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H4&lt;/td&gt;
&lt;td&gt;linux&lt;/td&gt;
&lt;td&gt;clab&lt;/td&gt;
&lt;td&gt;Same as above&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;R1, D1, and D2 have no &lt;code&gt;provider&lt;/code&gt; attribute — they inherit &lt;code&gt;provider: libvirt&lt;/code&gt; from the topology level. S1, S2, and H1–H4 override with &lt;code&gt;provider: clab&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Provider Links
&lt;/h3&gt;

&lt;p&gt;When a link connects two libvirt nodes (e.g., R1–D1), netlab uses a UDP point-to-point tunnel — fast and transparent. When a link connects a libvirt node to a clab node (e.g., D1–S1), netlab automatically detects the mismatch and replaces the tunnel with a Linux bridge. Containerlab can then attach the container's vEth pair to that bridge. This happens transparently — you just define the link as &lt;code&gt;D1-S1&lt;/code&gt; and netlab does the rest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment Sequence
&lt;/h3&gt;

&lt;p&gt;Because cross-provider links require bridge name coordination, the startup order is critical:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;vagrant up&lt;/code&gt; — boots the libvirt VMs (R1, D1, D2)&lt;/li&gt;
&lt;li&gt;netlab inspects the libvirt networks to discover Linux bridge names&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;containerlab deploy&lt;/code&gt; — boots the containers (S1, S2, H1–H4), wiring them to the same bridges the VMs are connected to&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is why you &lt;strong&gt;must&lt;/strong&gt; use &lt;code&gt;netlab up&lt;/code&gt; and &lt;code&gt;netlab down&lt;/code&gt; for hybrid labs. Running &lt;code&gt;vagrant up&lt;/code&gt; or &lt;code&gt;containerlab deploy&lt;/code&gt; alone would leave the lab half-connected and hard to clean up.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Deploying the Lab
&lt;/h2&gt;

&lt;p&gt;With the topology file ready, one command creates, starts, and configures the entire lab:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Happens Step by Step
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Topology Validation and Configuration Generation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;netlab up&lt;/code&gt; calls &lt;code&gt;netlab create&lt;/code&gt; to read &lt;code&gt;topology.yml&lt;/code&gt;, merge it with system defaults, and validate the data model. It then generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vagrantfile&lt;/strong&gt; — describes the libvirt VMs (R1, D1, D2) with their box images, memory, and network interfaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;clab.yml&lt;/strong&gt; — describes the containerlab topology (S1, S2, H1–H4) with their Docker images and links&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;hosts.yml&lt;/strong&gt; + &lt;strong&gt;ansible.cfg&lt;/strong&gt; — Ansible inventory and configuration for initial device configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;netlab.snapshot.pickle&lt;/strong&gt; — the transformed topology snapshot used by all subsequent netlab commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. VM Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;netlab runs &lt;code&gt;vagrant up&lt;/code&gt; to boot the libvirt nodes. Vagrant:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Downloads the Vagrant boxes (&lt;code&gt;cisco/iosv&lt;/code&gt;, &lt;code&gt;cisco/iosvl2&lt;/code&gt;) if needed&lt;/li&gt;
&lt;li&gt;Creates KVM domains for R1, D1, and D2&lt;/li&gt;
&lt;li&gt;Creates the management network (&lt;code&gt;vagrant-libvirt&lt;/code&gt;) and data-plane bridges&lt;/li&gt;
&lt;li&gt;Powers on the VMs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;3. Bridge Discovery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the VMs running, netlab inspects the libvirt networks and discovers the Linux bridge names for each data-plane link. These bridge names are then injected into the containerlab configuration — this is the key step that makes cross-provider links work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Container Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;netlab runs &lt;code&gt;sudo containerlab deploy -t clab.yml&lt;/code&gt; to start the container nodes. Containerlab:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pulls the Docker images (&lt;code&gt;asifsyd/cisco_iol&lt;/code&gt;, &lt;code&gt;alpine:latest&lt;/code&gt;) if needed&lt;/li&gt;
&lt;li&gt;Creates containers for S1, S2, and H1–H4&lt;/li&gt;
&lt;li&gt;Attaches each container's vEth interfaces to the same Linux bridges that the VM interfaces are connected to&lt;/li&gt;
&lt;li&gt;Creates the containerlab management network (&lt;code&gt;clab&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;5. Initial Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, netlab runs &lt;code&gt;netlab initial&lt;/code&gt; to deploy device configurations via Ansible. This is a five-step process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Wait for readiness&lt;/strong&gt; — netlab polls SSH ports until all devices accept connections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Initial config&lt;/strong&gt; — hostname, interface IP addresses, descriptions, LLDP, and basic system settings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Normalize&lt;/strong&gt; — device-specific cleanup (e.g., removing default VLANs from IOSvL2)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Module config&lt;/strong&gt; — OSPF, VLANs, VRRP, and static routes as defined in the topology&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom templates&lt;/strong&gt; — any templates specified in &lt;code&gt;config:&lt;/code&gt; group attributes (for example, VRRP configuration from the &lt;code&gt;template/&lt;/code&gt; directory)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  After Deployment
&lt;/h3&gt;

&lt;p&gt;Once &lt;code&gt;netlab up&lt;/code&gt; finishes, all nine devices are running, wired, and configured. The topology is ready for traffic — hosts can ping the router, OSPF adjacencies are established, and VRRP provides gateway redundancy.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Verifying the Hybrid Lab
&lt;/h2&gt;

&lt;p&gt;Once &lt;code&gt;netlab up&lt;/code&gt; finishes, confirm that all VMs and containers are running and the network functions correctly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the VMs
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;The libvirt domain names use the lab name (&lt;code&gt;campus&lt;/code&gt;) as a prefix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; Id   Name         State
---------------------------
 3    campus_R1    running
 6    campus_D1    running
 7    campus_D2    running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check the Containers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;--format&lt;/span&gt; &lt;span class="s2"&gt;"table {{.Names}}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Containerlab uses the &lt;code&gt;clab-&amp;lt;labname&amp;gt;-&amp;lt;nodename&amp;gt;&lt;/code&gt; convention:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Names
clab-campus-S1
clab-campus-S2
clab-campus-H1
clab-campus-H2
clab-campus-H3
clab-campus-H4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Check Everything with netlab
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;This shows all nine devices in one table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lab default in /path/to/lab-02
  status: started
  provider(s): libvirt, clab
┏━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━┓
┃ node ┃ device ┃ image          ┃ mgmt IPv4       ┃ provider ┃ status    ┃
┡━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩
│ R1   │ iosv   │ cisco/iosv     │ 192.168.121.101 │ libvirt  │ Up 5 min  │
│ D1   │ iosvl2 │ cisco/iosvl2   │ 192.168.121.102 │ libvirt  │ Up 5 min  │
│ D2   │ iosvl2 │ cisco/iosvl2   │ 192.168.121.103 │ libvirt  │ Up 5 min  │
│ S1   │ ioll2  │ cisco_iol      │ 192.168.121.104 │ clab     │ Up 5 min  │
│ S2   │ ioll2  │ cisco_iol      │ 192.168.121.105 │ clab     │ Up 5 min  │
│ H1   │ linux  │ alpine:latest  │ 192.168.121.106 │ clab     │ Up 5 min  │
│ H2   │ linux  │ alpine:latest  │ 192.168.121.107 │ clab     │ Up 5 min  │
│ H3   │ linux  │ alpine:latest  │ 192.168.121.108 │ clab     │ Up 5 min  │
│ H4   │ linux  │ alpine:latest  │ 192.168.121.109 │ clab     │ Up 5 min  │
└──────┴────────┴────────────────┴─────────────────┴──────────┴───────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verify Connectivity
&lt;/h3&gt;

&lt;p&gt;From the core router, check OSPF adjacencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netlab connect R1
R1# show ip ospf neighbor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From a distribution switch, verify VLANs and VRRP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netlab connect D1
D1# show vlan brief
D1# show vrrp brief
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From a host, confirm reachability across the campus. For example,&lt;br&gt;
ping H2 (VLAN 20) from H1 (VLAN 10):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; clab-campus-H1 ping &lt;span class="nt"&gt;-c&lt;/span&gt; 3 172.16.1.7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A successful reply means the Linux bridges, VLAN trunks, OSPF routing,&lt;br&gt;
and VRRP gateway are all working correctly across both providers.&lt;/p&gt;


&lt;h2&gt;
  
  
  9. Connecting to Devices
&lt;/h2&gt;

&lt;p&gt;netlab provides a single command to connect to any lab device,&lt;br&gt;
regardless of provider.&lt;/p&gt;
&lt;h3&gt;
  
  
  netlab connect
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netlab connect R1       &lt;span class="c"&gt;# IOSv router — SSH&lt;/span&gt;
netlab connect D1       &lt;span class="c"&gt;# IOSvL2 distribution switch — SSH&lt;/span&gt;
netlab connect S1       &lt;span class="c"&gt;# IOL-L2 access switch — SSH&lt;/span&gt;
netlab connect H1       &lt;span class="c"&gt;# Alpine host — docker exec&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;netlab connect&lt;/code&gt; reads the lab snapshot to determine the correct&lt;br&gt;
connection method. For network devices (R1, D1, D2, S1, S2) it&lt;br&gt;
opens an SSH session to the management IP. For Linux containers&lt;br&gt;
(H1–H4) it uses &lt;code&gt;docker exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can also execute a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netlab connect R1 &lt;span class="nt"&gt;--show&lt;/span&gt; &lt;span class="s2"&gt;"show ip route"&lt;/span&gt;
netlab connect H1 &lt;span class="nt"&gt;--show&lt;/span&gt; &lt;span class="s2"&gt;"ifconfig"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Direct docker exec
&lt;/h3&gt;

&lt;p&gt;Linux containers can be reached directly with Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; clab-campus-H1 /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For IOL containers (S1, S2), docker exec gives you a Linux shell inside the container — not the IOS CLI. Use &lt;code&gt;netlab connect S1&lt;/code&gt;&lt;br&gt;
for the standard IOS command-line experience.&lt;/p&gt;
&lt;h3&gt;
  
  
  Manual SSH
&lt;/h3&gt;

&lt;p&gt;For VM-based nodes, SSH directly to the management IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh cisco@192.168.121.101
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Management IPs are shown by &lt;code&gt;netlab status&lt;/code&gt;. Default credentials are defined by the Vagrant box — typically &lt;code&gt;cisco&lt;/code&gt;/&lt;code&gt;cisco&lt;/code&gt; for&lt;br&gt;
IOSv boxes.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use libvirt as the primary provider&lt;/strong&gt; in hybrid labs. clab can only be a secondary provider — this is a hard netlab constraint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Containerlab only for container-native NOSes.&lt;/strong&gt; IOL, Alpine Linux, FRR, and cEOS have native container images that run efficiently under Docker. IOSv and IOSvL2 do not — they must run as VMs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always use &lt;code&gt;netlab up&lt;/code&gt; and &lt;code&gt;netlab down&lt;/code&gt;&lt;/strong&gt; for hybrid labs. Running &lt;code&gt;vagrant up&lt;/code&gt; or &lt;code&gt;containerlab deploy&lt;/code&gt; alone will leave bridges disconnected and be difficult to clean up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set provider-specific images explicitly&lt;/strong&gt; in &lt;code&gt;defaults.devices&lt;/code&gt;. This makes the topology portable and documents exactly which image each device expects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use groups to reduce duplication.&lt;/strong&gt; The DISTRIBUTION and ACCESS groups in this topology apply VLAN mode, configuration modules, and custom templates to multiple nodes with a single block of YAML.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep topology files in version control.&lt;/strong&gt; A declarative topology file coupled with netlab's automation means anyone can reproduce the exact same lab from source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use custom templates for complex configurations.&lt;/strong&gt; The &lt;code&gt;config: [template]&lt;/code&gt; group attribute pulls Jinja2 files from the &lt;code&gt;template/&lt;/code&gt; directory — useful for VRRP, interface descriptions, or any vendor-specific feature netlab does not generate natively.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  11. Conclusion
&lt;/h2&gt;

&lt;p&gt;You've built a working hybrid campus lab that mixes Cisco IOSv VMs, IOSvL2 VMs, IOL-L2 containers, and Alpine Linux containers — all&lt;br&gt;
defined in a single &lt;code&gt;topology.yml&lt;/code&gt; and deployed with one command.&lt;/p&gt;

&lt;p&gt;The key takeaway is simple: run every device in its native environment. Virtual machines for the NOSes that need them, containers for everything else, and let netlab handle the wiring between the two.&lt;/p&gt;

&lt;p&gt;This foundation can be extended in many directions: add more vendors (Juniper vSRX, Arista cEOS, Nokia SR Linux), introduce EVPN/VXLAN fabric modules, or connect the lab to external networks. Whatever path you take, the hybrid approach ensures you get the best mix of performance, resource efficiency, and device fidelity.&lt;/p&gt;

</description>
      <category>netlab</category>
      <category>containerlab</category>
      <category>vagrant</category>
      <category>libvirt</category>
    </item>
    <item>
      <title>Meet the Web Search MCP Server</title>
      <dc:creator>Syed Asif</dc:creator>
      <pubDate>Wed, 24 Jun 2026 12:28:01 +0000</pubDate>
      <link>https://dev.to/sydasif78/meet-the-web-search-mcp-server-2gpp</link>
      <guid>https://dev.to/sydasif78/meet-the-web-search-mcp-server-2gpp</guid>
      <description>&lt;h2&gt;
  
  
  Your AI Needs Eyes on the Web
&lt;/h2&gt;

&lt;p&gt;AI models are incredibly smart, but they have a blind spot. They only know what they were trained on, which means anything that happened after their training cutoff is invisible to them. Ask about last week's news, a GitHub issue from this morning, or the latest package release, and they'll either shrug or make something up.&lt;/p&gt;

&lt;p&gt;That's where the Model Context Protocol (MCP) comes in. Think of MCP as a way to give your AI a toolbox. Each tool is a small program the AI can run when it needs fresh information. A calculator tool for math, a file system tool for reading your code, and most importantly - a search tool for looking things up on the web.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/sydasif/web-search-mcp" rel="noopener noreferrer"&gt;Web Search MCP server&lt;/a&gt; is one of those toolboxes. It bundles search engines, social platforms, academic databases, and web page fetchers into a single server that any MCP-compatible AI client can use. Instead of guessing, your AI can go find the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Model Context Protocol Actually Is
&lt;/h2&gt;

&lt;p&gt;MCP is a standard way for AI applications to talk to tools and data sources. If you've used Claude Code, Cursor, or any AI coding assistant that can run commands or read files, you've already seen this idea in action - just through proprietary implementations.&lt;/p&gt;

&lt;p&gt;MCP makes it universal. Any MCP client can connect to any MCP server. Your AI doesn't care whether the server is written in Python, TypeScript, or Go. As long as it speaks MCP, the tools just work.&lt;/p&gt;

&lt;p&gt;The Web Search MCP server is written in Python using the &lt;a href="https://github.com/jlowin/fastmcp" rel="noopener noreferrer"&gt;FastMCP&lt;/a&gt; library, which handles all the protocol plumbing so the author could focus on the actual search logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Tour of the Toolbox
&lt;/h2&gt;

&lt;p&gt;The server groups its tools by what they're good at. Here's what you get out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  General Web Search
&lt;/h3&gt;

&lt;p&gt;Two search engines, one interface. DuckDuckGo for fast, free lookups. Exa as a fallback or primary provider when you need semantic search. You can scope results to a specific domain, filter by date, switch to news mode, or target a geographic region.&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;# Broad search&lt;/span&gt;
search_web&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"uv package manager"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Targeted docs search&lt;/span&gt;
search_web&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"useEffect cleanup"&lt;/span&gt;, &lt;span class="nv"&gt;domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"react.dev"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# News with region&lt;/span&gt;
search_web&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"elections"&lt;/span&gt;, &lt;span class="nv"&gt;search_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"news"&lt;/span&gt;, &lt;span class="nv"&gt;region&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-en"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Last week only&lt;/span&gt;
search_web&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Python 3.13 features"&lt;/span&gt;, &lt;span class="nv"&gt;time_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"w"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Page Fetching
&lt;/h3&gt;

&lt;p&gt;Search results give you snippets. Sometimes you need the full article. The &lt;code&gt;fetch_page&lt;/code&gt; tool extracts clean text from any URL, stripping away ads, navigation, and JavaScript cruft. It supports a dozen output formats including markdown, JSON, and plain text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fetch_page&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://docs.python.org/3/library/os.html"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Social and Community Intelligence
&lt;/h3&gt;

&lt;p&gt;This is where the server really shines. It doesn't just search the open web - it taps into the platforms where real people discuss technology.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reddit&lt;/strong&gt; searches community discussions and returns top comments with scores. This is great for finding real user opinions, troubleshooting threads, and product recommendations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hacker News&lt;/strong&gt; gives you access to technical discourse and startup discussions. The results include top comments and pre-extracted insights, so the AI can quickly understand the consensus without reading every reply.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt; lets the AI search issues and pull requests. It returns state labels, reaction counts, and top comments. This is invaluable for tracking bugs, understanding feature requests, or checking whether a breaking change has been discussed upstream.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;X/Twitter&lt;/strong&gt; provides real-time signal from breaking news and expert threads. It requires session cookies from a logged-in account, so it's not as plug-and-play as the others, but the real-time coverage is unmatched.&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;# Reddit&lt;/span&gt;
search_reddit&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Best mechanical keyboards 2024"&lt;/span&gt;,
              &lt;span class="nv"&gt;subreddits&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="s2"&gt;"MechanicalKeyboards"&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;

&lt;span class="c"&gt;# Hacker News&lt;/span&gt;
search_hackernews&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"MCP server architecture"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# GitHub&lt;/span&gt;
search_github&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"uv package manager"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# X/Twitter&lt;/span&gt;
search_x&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Llama 4 release"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Academic and Reference
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;arXiv&lt;/strong&gt; searches academic papers with Lucene field prefixes. You can search by author, category, title, or abstract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wikipedia&lt;/strong&gt; pulls factual summaries for background research.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;search_arxiv&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"transformer attention"&lt;/span&gt;, &lt;span class="nv"&gt;max_results&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10&lt;span class="o"&gt;)&lt;/span&gt;
search_wikipedia&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Model Context Protocol"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Actually Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;The server follows a clean architecture. A central &lt;code&gt;server.py&lt;/code&gt; file creates a FastMCP instance and registers each tool with the &lt;code&gt;@mcp.tool&lt;/code&gt; decorator. The tool's docstring becomes its description, which the AI reads to understand when to use it.&lt;/p&gt;

&lt;p&gt;The actual logic lives in separate modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;search/&lt;/code&gt; handles DuckDuckGo and Exa integration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;social/&lt;/code&gt; handles Reddit, Hacker News, GitHub, and X&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tools/&lt;/code&gt; handles arXiv and Wikipedia&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_http/&lt;/code&gt; provides a centralized HTTP client with consistent timeouts and error handling&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_config/&lt;/code&gt; manages rate limits and environment variables&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_models/&lt;/code&gt; defines Pydantic models for type-safe requests and responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The X/Twitter integration is the most interesting piece. Instead of using the official API (which requires expensive enterprise access), the server vendors a stripped-down version of the &lt;a href="https://github.com/steipete/bird" rel="noopener noreferrer"&gt;Bird CLI&lt;/a&gt;, a third-party tool that reverse-engineers Twitter's internal GraphQL API. This is why it needs browser session cookies rather than an API key.&lt;/p&gt;

&lt;p&gt;The server also implements a rate limiter to prevent abuse. Each social tool has three depth tiers - &lt;code&gt;quick&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt;, and &lt;code&gt;deep&lt;/code&gt; - that control how many results and comments to fetch. This lets the AI request a quick skim or a deep dive without overwhelming the source platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting It Up in Five Minutes
&lt;/h2&gt;

&lt;p&gt;You need Python 3.11 or newer and the &lt;a href="https://github.com/astral-sh/uv" rel="noopener noreferrer"&gt;uv package manager&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv tool &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/sydasif/web-search-mcp.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add it to your MCP client configuration:&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;"mcpServers"&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;"web-search"&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;"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;"web-search-mcp"&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;p&gt;That's it for basic usage. All the search tools work without any API keys or authentication.&lt;/p&gt;

&lt;p&gt;Optionally, you can set environment variables for additional features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GITHUB_TOKEN&lt;/code&gt; or the &lt;code&gt;gh&lt;/code&gt; CLI for authenticated GitHub searches&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AUTH_TOKEN&lt;/code&gt; and &lt;code&gt;CT0&lt;/code&gt; (browser cookies from x.com) for X/Twitter search&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;EXA_API_KEY&lt;/code&gt; for Exa as an alternative search provider&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Real Research Workflow in Action
&lt;/h2&gt;

&lt;p&gt;The repository includes a &lt;a href="https://github.com/sydasif/web-search-mcp/blob/main/skills/research/SKILL.md" rel="noopener noreferrer"&gt;research skill&lt;/a&gt; that shows how these tools chain together.&lt;/p&gt;

&lt;p&gt;A deep research session goes through three phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Broad discovery&lt;/strong&gt; starts with &lt;code&gt;search_web&lt;/code&gt; to map the landscape, then uses &lt;code&gt;fetch_page&lt;/code&gt; to read the most promising articles in full.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Community mining&lt;/strong&gt; fans out across Reddit, Hacker News, GitHub, and X using the platform-specific tools. Each platform reveals a different angle - HN for technical critique, Reddit for user experiences, GitHub for development signals, X for real-time reaction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Synthesis&lt;/strong&gt; combines everything into a structured report with source citations, confidence levels, and identified gaps.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The skill uses a source weighting system: official docs are highest confidence, community discussions are medium, and social media is treated as real-time signal that needs cross-referencing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Let the fallback work for you.&lt;/strong&gt; The default provider is &lt;code&gt;auto&lt;/code&gt;, which tries DuckDuckGo first and falls back to Exa if the results are empty. This handles most cases without configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Match result depth to your need.&lt;/strong&gt; Use &lt;code&gt;quick&lt;/code&gt; depth for simple answers (5 results). Use &lt;code&gt;deep&lt;/code&gt; for comprehensive research (up to 60 results). The rate limiter will thank you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use JSON output for programmatic use.&lt;/strong&gt; The default markdown output is great for human reading, but if you're building a pipeline, set &lt;code&gt;response_format="json"&lt;/code&gt; and work with the structured data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cross-reference before trusting.&lt;/strong&gt; No single platform gives you the full picture. If a claim appears on Reddit, Hacker News, and a blog post, that's stronger evidence than any one source.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Can Build With This
&lt;/h2&gt;

&lt;p&gt;The Web Search MCP server turns your AI from a static knowledge base into an active researcher. You can ask it to investigate a bug by searching GitHub issues, check community sentiment on Reddit, read the relevant documentation, and summarize everything - all in one conversation.&lt;/p&gt;

&lt;p&gt;The best next step is to install it and try a multi-source search. Ask your AI to research a topic using &lt;code&gt;search_web&lt;/code&gt; for background, &lt;code&gt;search_hackernews&lt;/code&gt; for technical discussion, and &lt;code&gt;search_github&lt;/code&gt; for current development status. You'll quickly see the difference between an AI that guesses and an AI that finds out.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Acknowledgment:&lt;/strong&gt; This blog is inspired by publicly available materials, standards, and community research or similar work. See full configuration at &lt;a href="https://github.com/sydasif/web-search-mcp/wiki" rel="noopener noreferrer"&gt;https://github.com/sydasif/web-search-mcp/wiki&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>web</category>
      <category>server</category>
      <category>fastmcp</category>
    </item>
    <item>
      <title>Refactoring and Optimization Workflows: Turning Messy Code into Clean, Fast Systems</title>
      <dc:creator>Syed Asif</dc:creator>
      <pubDate>Sat, 30 May 2026 06:35:12 +0000</pubDate>
      <link>https://dev.to/sydasif78/refactoring-and-optimization-workflows-turning-messy-code-into-clean-fast-systems-4k18</link>
      <guid>https://dev.to/sydasif78/refactoring-and-optimization-workflows-turning-messy-code-into-clean-fast-systems-4k18</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;You have working code that you dread touching. Variable names make no sense. The same logic appears in three places. It's slow on large inputs, and adding a new feature feels fragile.&lt;/p&gt;

&lt;p&gt;Refactoring fixes that — and Claude Code makes it faster. This guide covers how to clean up, restructure, and optimize code without breaking what already works: spotting design patterns in spaghetti logic, improving performance, balancing simplicity against efficiency, and applying all of it to a real-world web scraper.&lt;/p&gt;




&lt;h2&gt;
  
  
  Principles of Clean Refactoring
&lt;/h2&gt;

&lt;p&gt;Refactoring improves existing code without changing its external behavior. Not rewriting from scratch — making the code cleaner, more readable, and easier to maintain while keeping exactly what it does.&lt;/p&gt;

&lt;p&gt;Three rules to hold throughout any refactor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Maintain functional parity.&lt;/strong&gt; Output before and after must be identical for the same input.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplify structure.&lt;/strong&gt; Replace complex or duplicated logic with simpler, reusable functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increase clarity.&lt;/strong&gt; The new version should be more readable and aligned with your coding standards.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example: Refactoring an Order Calculator
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Original (works, but messy):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_order_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;quantity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;quantity&lt;/span&gt;
    &lt;span class="n"&gt;discount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;discount&lt;/span&gt;
    &lt;span class="n"&gt;tax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;tax_rate&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tax&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problems: repeated variable reassignment, all logic in one function, no docstrings, hard to unit-test.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"Refactor this order total function for clarity and maintainability. Break it into smaller, reusable functions. Preserve the exact same behavior."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Claude's refactored version:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_order_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate the total order price with discount and tax applied.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;subtotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_calculate_subtotal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;discounted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_apply_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_apply_tax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discounted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_calculate_subtotal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Compute subtotal based on item prices and quantities.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_apply_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subtotal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Apply discount to subtotal.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;subtotal&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_apply_tax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Apply tax to the discounted amount.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tax_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Validation test:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;

&lt;span class="c1"&gt;# Original inline calculation
&lt;/span&gt;&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.07&lt;/span&gt;
&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;original&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Refactored
&lt;/span&gt;&lt;span class="n"&gt;new_total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;calculate_order_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tax_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.07&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;original&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;new_total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Expected: True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;True&lt;/code&gt; confirms behavior is preserved, structure improved.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Length&lt;/td&gt;
&lt;td&gt;Single long function&lt;/td&gt;
&lt;td&gt;Modular functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Responsibility&lt;/td&gt;
&lt;td&gt;Mixed&lt;/td&gt;
&lt;td&gt;Each function handles one task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extensibility&lt;/td&gt;
&lt;td&gt;Hard to modify&lt;/td&gt;
&lt;td&gt;Easy to adjust discount or tax rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testability&lt;/td&gt;
&lt;td&gt;Hard to isolate&lt;/td&gt;
&lt;td&gt;Unit-test friendly&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Design Pattern Discovery
&lt;/h2&gt;

&lt;p&gt;Patterns often emerge in code before they're named. Claude can recognize them — Singleton, Factory, Observer — even when they developed unintentionally, and refactor them into explicit, robust implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Discovering a Singleton Pattern
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Original logger:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[LOG]: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Application started.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works in a single module. Import it into multiple modules and each gets its own instance, breaking log consistency.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"This logger creates new instances when imported in different modules. Identify the design pattern it resembles and refactor it properly."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Claude's analysis:&lt;/strong&gt; "This should be a singleton — one shared instance across the application. The basic &lt;code&gt;__new__&lt;/code&gt; override is the common introduction, but it's not thread-safe. In multi-threaded environments, two threads can check &lt;code&gt;_instance is None&lt;/code&gt; simultaneously and both create an instance."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thread-safe Singleton:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;_lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_instance&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Double-checked locking: re-check after acquiring the lock
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_instance&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_instance&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[LOG]: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;logger1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;logger2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;logger1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Application started.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;logger2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Processing data...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Same instance? &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;logger1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;logger2&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One important caveat Claude should flag:&lt;/strong&gt; for async frameworks (FastAPI, aiohttp, asyncio-based servers), &lt;code&gt;threading.Lock&lt;/code&gt; doesn't work correctly. Use &lt;code&gt;asyncio.Lock()&lt;/code&gt; with a factory method instead — &lt;code&gt;__new__&lt;/code&gt; can't be awaited. For most logging scenarios, a module-level singleton (a plain module-level instance) is simpler and avoids the problem entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optional: Factory pattern&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggerFactory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;_lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;threading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="nd"&gt;@staticmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_logger&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;LoggerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;LoggerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;LoggerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;LoggerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;LoggerFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_logger&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use this when you want to separate creation from usage — useful when the logger initialization takes arguments or depends on configuration.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern&lt;/th&gt;
&lt;th&gt;Symptom in Code&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Singleton&lt;/td&gt;
&lt;td&gt;Shared-state class instantiated repeatedly&lt;/td&gt;
&lt;td&gt;Centralized control, consistent resource access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Factory&lt;/td&gt;
&lt;td&gt;Objects created manually in multiple places&lt;/td&gt;
&lt;td&gt;Clean separation of creation and usage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Observer&lt;/td&gt;
&lt;td&gt;Event-driven callbacks without structure&lt;/td&gt;
&lt;td&gt;Decoupled, maintainable event handling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Performance Optimization
&lt;/h2&gt;

&lt;p&gt;Optimize where you have a measured bottleneck. Claude helps identify inefficiencies early, explains root causes, and proposes targeted improvements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Optimizing a Word Counter
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Original (O(n²)):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_unique_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;unique_words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;unique_words&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# O(n) scan per word
&lt;/span&gt;                    &lt;span class="n"&gt;unique_words&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique_words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each membership check scans the entire list. On a large file this compounds quickly.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"This function becomes very slow with large text files. Analyze and optimize it without changing its behavior."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Claude's reasoning:&lt;/strong&gt; "List membership checks are O(n). Replace the list with a set for O(1) average lookups. Also normalize to lowercase for consistent deduplication."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optimized (O(n)):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_unique_words&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Count unique words in a text file using a set for O(1) lookups.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;unique_words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
                &lt;span class="n"&gt;unique_words&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique_words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On a 10MB file the difference is minutes vs. milliseconds.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Focus&lt;/th&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data structure&lt;/td&gt;
&lt;td&gt;List for membership checks&lt;/td&gt;
&lt;td&gt;Replace with set&lt;/td&gt;
&lt;td&gt;O(n) → O(1) average&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Algorithm&lt;/td&gt;
&lt;td&gt;Nested iteration&lt;/td&gt;
&lt;td&gt;Simplify loop logic&lt;/td&gt;
&lt;td&gt;Better scalability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;Unbounded list growth&lt;/td&gt;
&lt;td&gt;Hash-based collection&lt;/td&gt;
&lt;td&gt;Reduced storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;I/O&lt;/td&gt;
&lt;td&gt;Synchronous DB calls in async framework&lt;/td&gt;
&lt;td&gt;Async or connection pooling&lt;/td&gt;
&lt;td&gt;Faster throughput&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Simplification vs. Efficiency
&lt;/h2&gt;

&lt;p&gt;Not every optimization is worth its complexity. Sometimes the simpler code is the better choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Filtering Even Numbers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Simple, readable version:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;filter_even_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Return all even numbers from the list.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; "Can this be optimized for performance if it needs to handle millions of integers, or should I keep it simple?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude's reasoning:&lt;/strong&gt; "List comprehensions run in C and are already fast. For most cases this is optimal. If your dataset exceeds available memory, a generator reduces memory overhead by yielding one element at a time."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory-efficient generator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;filter_even_numbers_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Yield even numbers lazily for large datasets.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Trade-off:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;filter_even_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;List comprehension:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter_even_numbers_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Generator:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Performance&lt;/th&gt;
&lt;th&gt;Memory&lt;/th&gt;
&lt;th&gt;Best Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;List comprehension&lt;/td&gt;
&lt;td&gt;Fast for small-medium&lt;/td&gt;
&lt;td&gt;Stores all results&lt;/td&gt;
&lt;td&gt;General purpose&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generator&lt;/td&gt;
&lt;td&gt;Slightly slower iteration&lt;/td&gt;
&lt;td&gt;Streams one at a time&lt;/td&gt;
&lt;td&gt;Large datasets, pipelines&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NumPy vectorized&lt;/td&gt;
&lt;td&gt;Very fast for numerics&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Numerical heavy lifting&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Simplify where clarity yields lasting value. Optimize only where you have a measured bottleneck.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example Project: Optimizing a Web Scraper
&lt;/h2&gt;

&lt;p&gt;A complete example: take a slow synchronous scraper and turn it into a concurrent, fault-tolerant pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Baseline (Slow but Correct)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;

&lt;span class="n"&gt;HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User-Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MasteringClaudeCode/1.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;html.parser&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scrape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# polite delay
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problems: synchronous (waits for each request), no retries, no concurrency, fragile error handling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimized (Concurrent, Robust)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bs4&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BeautifulSoup&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;

&lt;span class="n"&gt;HEADERS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;User-Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MasteringClaudeCode/1.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;MAX_CONCURRENCY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;REQUEST_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ClientTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# raises ClientResponseError for 4xx/5xx
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt;
        &lt;span class="n"&gt;backoff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;backoff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_fast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;soup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BeautifulSoup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lxml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# faster C-based parser
&lt;/span&gt;    &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="n"&gt;h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;soup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;h1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scrape_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_fast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scrape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;semaphore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Semaphore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAX_CONCURRENCY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;connector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TCPConnector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;MAX_CONCURRENCY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;aiohttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ClientSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HEADERS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;REQUEST_TIMEOUT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;connector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;connector&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;scrape_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;semaphore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;coro&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_completed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;coro&lt;/span&gt;
            &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key changes Claude explains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency.&lt;/strong&gt; Async I/O overlaps requests, hiding network latency. Wall time drops from &lt;code&gt;N * latency&lt;/code&gt; to roughly &lt;code&gt;latency&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection pooling.&lt;/strong&gt; &lt;code&gt;TCPConnector&lt;/code&gt; reuses connections, reducing handshake overhead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeouts and exponential backoff.&lt;/strong&gt; Fails fast on slow endpoints and recovers from transient errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster parser.&lt;/strong&gt; &lt;code&gt;lxml&lt;/code&gt; is a C-based HTML parser — significantly faster than &lt;code&gt;html.parser&lt;/code&gt; for large pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured error handling.&lt;/strong&gt; Partial failures are captured per-URL rather than crashing the pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note on &lt;code&gt;raise_for_status()&lt;/code&gt;:&lt;/strong&gt; The optimized version calls &lt;code&gt;resp.raise_for_status()&lt;/code&gt; to handle 4xx/5xx responses. This is the correct pattern — &lt;code&gt;aiohttp.ClientResponseError&lt;/code&gt; requires internal &lt;code&gt;request_info&lt;/code&gt; and &lt;code&gt;history&lt;/code&gt; arguments and should not be constructed manually.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Run it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;URLS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://httpbin.org/html&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;scrape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;URLS&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Optimization&lt;/th&gt;
&lt;th&gt;What Changed&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Concurrency&lt;/td&gt;
&lt;td&gt;Single-threaded → asyncio + semaphore&lt;/td&gt;
&lt;td&gt;Overlaps I/O, wall time ≈ one request latency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connection reuse&lt;/td&gt;
&lt;td&gt;New TCP per request → pooled&lt;/td&gt;
&lt;td&gt;Reduces handshake overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timeouts + backoff&lt;/td&gt;
&lt;td&gt;None → explicit + exponential&lt;/td&gt;
&lt;td&gt;Faster failure, automatic recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Parser&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;html.parser&lt;/code&gt; → &lt;code&gt;lxml&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;C-based, measurably faster on large HTML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error handling&lt;/td&gt;
&lt;td&gt;Exceptions crash pipeline → captured per-URL&lt;/td&gt;
&lt;td&gt;Pipeline survives partial failures&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Cost Considerations
&lt;/h2&gt;

&lt;p&gt;Token costs are real for teams running Claude at scale. A few practices keep them under control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current API pricing (May 2026, per million tokens):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Haiku 4.5&lt;/td&gt;
&lt;td&gt;$1.00&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;Simple refactors, repetitive tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sonnet 4.6&lt;/td&gt;
&lt;td&gt;$3.00&lt;/td&gt;
&lt;td&gt;$15.00&lt;/td&gt;
&lt;td&gt;General coding — best cost/quality ratio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.7&lt;/td&gt;
&lt;td&gt;$5.00&lt;/td&gt;
&lt;td&gt;$25.00&lt;/td&gt;
&lt;td&gt;Complex architecture, deep analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Prompt caching cuts input costs by up to 90%. The Batch API cuts everything 50%. Combined, costs can drop by up to 95% for high-volume workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A rough cost estimator:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;estimate_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sonnet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Estimate API cost for a single request (USD).&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;pricing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;haiku&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.00&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sonnet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;3.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;15.00&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;opus&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;5.00&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;25.00&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;# ~4 chars per token
&lt;/span&gt;    &lt;span class="n"&gt;in_tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pricing&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in_tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;in&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response_tokens&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="mi"&gt;6&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Refactor this 200-line Python class for readability.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimated cost: $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;estimate_cost&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sonnet&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cost-control habits:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Practice&lt;/th&gt;
&lt;th&gt;Why It Helps&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Match model to task complexity&lt;/td&gt;
&lt;td&gt;Haiku for simple refactors; Opus only for deep architecture work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep a 2-4 sentence project anchor&lt;/td&gt;
&lt;td&gt;Reduces repeated context tokens across turns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ask for only what you need&lt;/td&gt;
&lt;td&gt;"Return only the refactored function" cuts unnecessary output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Batch similar requests&lt;/td&gt;
&lt;td&gt;Amortizes system tokens; 50% off with the Batch API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trim context to relevant files&lt;/td&gt;
&lt;td&gt;Large irrelevant context dilutes focus and burns tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Refactoring and optimization are small, intentional improvements that compound over time. With Claude Code you can decompose tangled functions into clean modules, name the patterns that already exist in your code, replace O(n²) lookups with O(1) data structures, and scale a synchronous scraper into a concurrent pipeline — without breaking what already works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try this:&lt;/strong&gt; Pick a messy function from your own codebase. Prompt Claude: "Refactor this for clarity and maintainability. Preserve all behavior. Break it into smaller, reusable pieces." Run the validation test. Then profile before and after on real data if performance matters.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Acknowledgment:&lt;/strong&gt; Based on official Anthropic documentation and community research. Technical details reflect the state of Claude Code as of May 2026.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>claude</category>
      <category>performance</category>
      <category>softwareengineering</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Debugging and Code Review with Claude Code</title>
      <dc:creator>Syed Asif</dc:creator>
      <pubDate>Thu, 28 May 2026 13:34:42 +0000</pubDate>
      <link>https://dev.to/sydasif78/debugging-and-code-review-with-claude-code-fo8</link>
      <guid>https://dev.to/sydasif78/debugging-and-code-review-with-claude-code-fo8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;You've written the code. It looks right. But when you run it, something breaks. The error message is cryptic, the stack trace points everywhere, and you've been staring at the same five lines for an hour.&lt;/p&gt;

&lt;p&gt;Debugging is time-consuming. Claude Code makes it faster — not by magically finding bugs, but by reading your code, understanding what you intended it to do, and walking you through exactly what went wrong. This chapter covers how to use Claude Code as a debugging and code review partner: identifying bugs, automating reviews, testing fixes in real time, and building an iterative loop that improves your output.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Claude Code Approaches Debugging
&lt;/h2&gt;

&lt;p&gt;Claude Code doesn't just respond to your prompt in isolation. It runs an agentic loop: gather context, take action, verify results, repeat. For debugging, that looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Context gathering&lt;/strong&gt; — Claude reads your code, file structure, imports, and dependencies. It looks for missing definitions, misused libraries, and structural issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intent comparison&lt;/strong&gt; — Claude compares your code's actual logic against its described purpose (from your prompt, docstrings, or comments) and identifies mismatches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix and verification&lt;/strong&gt; — Claude proposes a corrected version, explains its reasoning, and generates test cases you can run immediately.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You're part of this loop. You can interrupt at any point to provide more context, redirect Claude's approach, or push back on a suggestion. Claude works autonomously but stays responsive to your input.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Fixing a Flask Discount Calculator
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Buggy code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;discount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;discount_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;discounted_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;discounted_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;discounted_price&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You expect &lt;code&gt;{"price": 100, "discount": 0.2}&lt;/code&gt; to return &lt;code&gt;80.0&lt;/code&gt;. It returns &lt;code&gt;20.0&lt;/code&gt; — the discount amount, not the final price.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"This Flask endpoint should return the final price after applying a discount, but it's returning the discount value itself. Find and fix the issue. Include the corrected code and explain what was wrong."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Claude's fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonify&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;discount&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate the final price after applying a discount.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;discount_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Missing required fields&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discount_rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid input types&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;

    &lt;span class="n"&gt;discounted_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;discount_rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;jsonify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;discounted_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;discounted_price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude's explanation: the original formula computed the discount amount (&lt;code&gt;price * discount_rate&lt;/code&gt;) instead of the final price (&lt;code&gt;price * (1 - discount_rate)&lt;/code&gt;). It also added input validation to handle missing or wrongly-typed fields — a common real-world failure mode the original code silently ignored.&lt;/p&gt;




&lt;h2&gt;
  
  
  Automated Code Review
&lt;/h2&gt;

&lt;p&gt;Claude can read, analyze, and critique code in real time — flagging logic issues, security risks, and performance problems before they hit production.&lt;/p&gt;

&lt;p&gt;The workflow is three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Context ingestion&lt;/strong&gt; — provide the relevant file or diff. Claude builds an internal model of what the code does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evaluation&lt;/strong&gt; — Claude reviews logic, structure, naming, performance, and maintainability, and explains why each issue matters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured feedback&lt;/strong&gt; — Claude returns actionable output you can use directly in pull request comments.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example: Reviewing a FastAPI Endpoint
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Code under review:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sqlite3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;database.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance this works. Claude will catch four issues: it uses synchronous SQLite inside an async framework, blocking the event loop; there's no error handling; it selects all columns with &lt;code&gt;SELECT *&lt;/code&gt; rather than explicit fields; and future parameter additions could introduce SQL injection.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"Review this FastAPI endpoint for code quality, security, and performance. Identify issues, explain their impact, and propose corrected code following current best practices."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Claude's suggested fix&lt;/strong&gt; (using the current &lt;code&gt;lifespan&lt;/code&gt; pattern — &lt;code&gt;@app.on_event&lt;/code&gt; has been deprecated since FastAPI 0.93):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;contextlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asynccontextmanager&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;databases&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Database&lt;/span&gt;

&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sqlite:///database.db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@asynccontextmanager&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Retrieve all users asynchronously.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT id, username, email FROM users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key changes: async I/O via the &lt;code&gt;databases&lt;/code&gt; library, explicit column selection, proper error handling, and the &lt;code&gt;lifespan&lt;/code&gt; context manager instead of the deprecated &lt;code&gt;@app.on_event&lt;/code&gt; decorators.&lt;/p&gt;

&lt;h3&gt;
  
  
  Review Focus Areas
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;What Claude Checks&lt;/th&gt;
&lt;th&gt;Example Feedback&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;SQL injection, unsafe evals, hardcoded secrets&lt;/td&gt;
&lt;td&gt;"Avoid string interpolation in SQL queries."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Blocking I/O, missing caching, inefficient queries&lt;/td&gt;
&lt;td&gt;"Replace sync DB calls with async equivalents."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Readability&lt;/td&gt;
&lt;td&gt;Naming, docstrings, structural clarity&lt;/td&gt;
&lt;td&gt;"Add docstrings to API routes."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compliance&lt;/td&gt;
&lt;td&gt;PEP8, project conventions, CLAUDE.md rules&lt;/td&gt;
&lt;td&gt;"Use context managers for database sessions."&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Interpreting Claude's Feedback
&lt;/h2&gt;

&lt;p&gt;Claude's suggestions are starting points, not commands. Two things determine whether to accept them:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it make sense in your environment?&lt;/strong&gt; A "best practice" in one context is wrong in another. Claude's context is limited to what you provided. If you omitted key files or constraints, its feedback will reflect those gaps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it match your intent?&lt;/strong&gt; Claude reasons about what the code probably needs. You reason about what it actually needs. Those aren't always the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Evaluating a Suggestion You Should Modify
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Original code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileReader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file_path&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nb"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Claude's feedback:&lt;/strong&gt; "Use a context manager (&lt;code&gt;with&lt;/code&gt; statement) to ensure the file closes automatically even if an error occurs."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude's suggested fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FileReader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8192&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file_path&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Read file in chunks for memory efficiency.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;iter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;FileNotFoundError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;FileNotFoundError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;File not found: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;file_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error reading file: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The developer accepted the context manager suggestion but adapted the rest for their actual needs — chunked reading for large files. Claude's reasoning ("safe file handling") was the right principle; the specific implementation needed adjustment for the workload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feedback Types
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;What It Means&lt;/th&gt;
&lt;th&gt;How to Evaluate&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Corrective&lt;/td&gt;
&lt;td&gt;Fixes an error or unsafe pattern&lt;/td&gt;
&lt;td&gt;Test in your environment before accepting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Advisory&lt;/td&gt;
&lt;td&gt;Suggests a best practice&lt;/td&gt;
&lt;td&gt;Check relevance to your project standards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Speculative&lt;/td&gt;
&lt;td&gt;"You could also..." optional improvement&lt;/td&gt;
&lt;td&gt;Evaluate the trade-off before adopting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context-limited&lt;/td&gt;
&lt;td&gt;Based on incomplete information&lt;/td&gt;
&lt;td&gt;Re-prompt with the missing files or context&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Testing Fixes in Real Time
&lt;/h2&gt;

&lt;p&gt;The fastest path from bug to fix is an iterative loop: show Claude the problem, get a fix, test it, feed results back. Claude participates in every step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The loop:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Show Claude the buggy code and describe what's wrong.&lt;/li&gt;
&lt;li&gt;Claude suggests a fix with explanation.&lt;/li&gt;
&lt;li&gt;Run the fix locally, or ask Claude to generate test cases.&lt;/li&gt;
&lt;li&gt;Feed results back — if it still fails, Claude reasons about why and adjusts.&lt;/li&gt;
&lt;li&gt;Repeat until resolved.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example: Empty List Error
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Buggy code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_average&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling &lt;code&gt;calculate_average([])&lt;/code&gt; raises &lt;code&gt;ZeroDivisionError&lt;/code&gt;.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"This function crashes on empty lists. Fix it and show how to test it."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Claude's fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_average&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate the average of a list of numbers. Returns 0 for empty lists.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Claude's tests:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculate_average&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;  &lt;span class="c1"&gt;# Expected: 20.0
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculate_average&lt;/span&gt;&lt;span class="p"&gt;([]))&lt;/span&gt;            &lt;span class="c1"&gt;# Expected: 0
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculate_average&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;           &lt;span class="c1"&gt;# Expected: 5.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Developer follow-up:&lt;/strong&gt; "Tests pass. But I'd prefer a &lt;code&gt;ValueError&lt;/code&gt; instead of returning 0 for empty lists."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude's adjustment:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_average&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Calculate the average of a list of numbers. Raises ValueError for empty input.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Cannot calculate average of an empty list.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Updated test:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculate_average&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;  &lt;span class="c1"&gt;# Expected: 20.0
&lt;/span&gt;    &lt;span class="nf"&gt;calculate_average&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;                   &lt;span class="c1"&gt;# Expected: ValueError
&lt;/span&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Caught expected exception: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One follow-up message changed the behavior contract without restarting the conversation. That's the loop working as intended.&lt;/p&gt;




&lt;h2&gt;
  
  
  Human-in-the-Loop Debugging
&lt;/h2&gt;

&lt;p&gt;Claude is most effective when you steer the reasoning rather than hand it the wheel entirely. The productive pattern is:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Your Role&lt;/th&gt;
&lt;th&gt;Claude's Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Framing&lt;/td&gt;
&lt;td&gt;Define the problem, expected behavior, and environment&lt;/td&gt;
&lt;td&gt;Build an understanding of the context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hypothesis generation&lt;/td&gt;
&lt;td&gt;Evaluate theories for relevance to your setup&lt;/td&gt;
&lt;td&gt;Propose likely causes and affected areas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation&lt;/td&gt;
&lt;td&gt;Run the code, confirm or disprove&lt;/td&gt;
&lt;td&gt;Interpret results, propose next steps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refinement&lt;/td&gt;
&lt;td&gt;Provide feedback on each fix&lt;/td&gt;
&lt;td&gt;Adjust the approach based on new information&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Example: API Timeout Bug
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Buggy code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function occasionally hangs when an API is slow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; "This function sometimes gets stuck waiting for a response. The API is valid. Can you help find out why?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude's diagnosis:&lt;/strong&gt; &lt;code&gt;requests.get()&lt;/code&gt; waits indefinitely by default. The &lt;code&gt;timeout&lt;/code&gt; parameter controls this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude's fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Request timed out.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An error occurred: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Follow-up:&lt;/strong&gt; "This works, but I still get a &lt;code&gt;JSONDecodeError&lt;/code&gt; sometimes."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude:&lt;/strong&gt; "That happens when the response isn't valid JSON — usually a server returning HTML for an error state. Check the &lt;code&gt;Content-Type&lt;/code&gt; header before parsing."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Refined version:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Response is not JSON.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid JSON in response.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Request timed out.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An error occurred: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each follow-up pushed the fix one step further. Claude didn't invent the second bug — you found it through testing and brought it back.&lt;/p&gt;




&lt;h2&gt;
  
  
  Collaborative Debugging in Practice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Example: Email Validator
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Initial code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_valid_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^[a-zA-Z0-9]+@[a-zA-Z]+\.[a-zA-Z]+$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This rejects valid addresses like &lt;code&gt;john.doe@sub.domain.org&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt; "This regex rejects some valid emails like '&lt;a href="mailto:john.doe@sub.domain.org"&gt;john.doe@sub.domain.org&lt;/a&gt;'. Debug and improve it — keep the function simple and secure."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude's diagnosis:&lt;/strong&gt; The pattern disallows dots and hyphens in both the local part and domain, and doesn't handle subdomains.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude's fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_valid_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Validate an email address. Allows dots, hyphens, and subdomains.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test suite:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;emails&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;john.doe@sub.domain.org&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user-name@company.co.uk&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invalid@domain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@missinguser.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;is_valid_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user@example.com: True
john.doe@sub.domain.org: True
user-name@company.co.uk: True
invalid@domain: False
@missinguser.com: False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;What to Do&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reporting a bug&lt;/td&gt;
&lt;td&gt;Include the error trace and source snippet&lt;/td&gt;
&lt;td&gt;Claude's reasoning improves with the full failure context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generating tests&lt;/td&gt;
&lt;td&gt;Describe expected behavior in plain English&lt;/td&gt;
&lt;td&gt;"The function should raise ValueError if input is empty"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Code review&lt;/td&gt;
&lt;td&gt;Ask Claude to review intent, not just syntax&lt;/td&gt;
&lt;td&gt;Catches logic mismatches, not only typos&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testing fixes&lt;/td&gt;
&lt;td&gt;Feed results back to Claude iteratively&lt;/td&gt;
&lt;td&gt;Enables targeted follow-up without restarting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trusting suggestions&lt;/td&gt;
&lt;td&gt;Verify in your environment&lt;/td&gt;
&lt;td&gt;Claude's context is limited to what you provided&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Framework-specific code&lt;/td&gt;
&lt;td&gt;Specify library versions&lt;/td&gt;
&lt;td&gt;Prevents Claude from suggesting deprecated APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Claude Code works best as a reasoning partner in a loop: you frame the problem, Claude proposes a diagnosis and fix, you test it and report back, Claude adjusts. The quality of that loop depends on the quality of your framing — clear descriptions of expected behavior, actual error output, and relevant context get better results than vague bug reports.&lt;/p&gt;

&lt;p&gt;You now have the mechanics for each part of that loop: context-aware bug identification, structured code review, iterative fix testing, and the human-in-the-loop phases that keep the process on track.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Next step:&lt;/strong&gt; Take a buggy function from your own codebase. Paste it into Claude with the error output and a clear description of what it should do. Work through the loop — hypothesis, fix, test, refine. The time from problem to working code will surprise you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Acknowledgment:&lt;/strong&gt; Based on official Anthropic documentation and community research. Technical details reflect the state of Claude Code as of May 2026.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>claude</category>
    </item>
    <item>
      <title>Prompting Foundations for Developers — How to Talk to Claude So It Listens</title>
      <dc:creator>Syed Asif</dc:creator>
      <pubDate>Thu, 28 May 2026 05:19:52 +0000</pubDate>
      <link>https://dev.to/sydasif78/prompting-foundations-for-developers-how-to-talk-to-claude-so-it-listens-31b4</link>
      <guid>https://dev.to/sydasif78/prompting-foundations-for-developers-how-to-talk-to-claude-so-it-listens-31b4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;You've installed Claude Code. You've sent a few prompts. But when you ask for something real — "write a login system" — the output feels generic, incomplete, or misses the point entirely.&lt;/p&gt;

&lt;p&gt;The problem is almost always the prompt. That's fixable.&lt;/p&gt;

&lt;p&gt;This chapter covers the exact structures and habits that turn vague requests into production-ready code: what Claude needs to know before it writes anything, how to trigger its reasoning instead of its pattern-matching, how to feed it multiple files without losing context, and how to lock in project-wide standards with &lt;code&gt;CLAUDE.md&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Claude Needs Before It Writes
&lt;/h2&gt;

&lt;p&gt;Before Claude produces a single line, it resolves three things from your prompt:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What to build.&lt;/strong&gt; "A login system" could mean a simple password check, a full OAuth flow, or a JWT-based API endpoint. Claude picks one. If you didn't specify, it guessed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How it should behave.&lt;/strong&gt; Should it block on errors or return structured error responses? Log failures? Validate inputs? Hash passwords? Silence on these means Claude chooses defaults — often the simplest ones.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What the result should look like.&lt;/strong&gt; A single function? A module? A class with docstrings? Raw code or code with explanation?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Leave any of these unanswered and Claude fills the gap. The output won't be wrong exactly — it just won't be what you had in mind.&lt;/p&gt;

&lt;p&gt;A useful mental check before sending: &lt;em&gt;What, How, Format.&lt;/em&gt; Three seconds to answer those three questions will consistently improve what comes back.&lt;/p&gt;




&lt;h2&gt;
  
  
  Writing Prompts That Work
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Weak vs. Strong
&lt;/h3&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"Write a function to handle user authentication."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude produces a bare-bones username/password check. No error handling, no hashing, no structure. Technically functional, not shippable.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"Write a Python function using FastAPI that handles user authentication with JWT tokens. Verify credentials against the database, issue tokens that expire in 15 minutes, and return structured JSON responses. Include docstrings and a comment explaining each step."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Four additions: framework (FastAPI), language (Python), expected behavior (JWT, expiration, JSON responses), output format (docstrings, comments). Claude now knows what "done" looks like.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chain-of-Thought Prompting
&lt;/h3&gt;

&lt;p&gt;Claude reasons more carefully when you ask it to reason before it codes. This is chain-of-thought prompting — and it's worth knowing how it fits alongside Claude's newer capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Without it:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Write a FastAPI endpoint that calculates factorial."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude often produces a recursive function with no input validation. It works for positive integers. It breaks on negatives and very large values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With it:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Before coding, outline your approach for a FastAPI endpoint that accepts a number and returns its factorial. Then write the full implementation with input validation, error handling, and comments."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude first lists its plan — input schema, recursion vs. iteration, edge cases (negative numbers, zero, large values), JSON output — then writes code that matches it. The result is safer and easier to debug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One important nuance:&lt;/strong&gt; Chain-of-thought prompting was the standard approach before Claude's &lt;em&gt;extended thinking&lt;/em&gt; feature. Extended thinking (available on Sonnet 4.6 and Opus 4.6/4.7) gives Claude a separately-budgeted reasoning pass before generating output — you can inspect that reasoning trace in the API response. For complex coding tasks, extended thinking generally produces better results than manual chain-of-thought prompting. If you're on a plan that supports it, enable it for architecture decisions, complex debugging, and multi-step refactors. Manual chain-of-thought remains useful when extended thinking isn't available or when you need the reasoning to appear inline in Claude's response.&lt;/p&gt;

&lt;p&gt;For either approach, Anthropic's docs note one consistent finding: always have Claude output its thinking. If the reasoning doesn't appear in the response, no reasoning step ran.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-File Prompts
&lt;/h3&gt;

&lt;p&gt;Real projects span multiple files. Claude handles them well — if you structure the input clearly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad approach:&lt;/strong&gt; Dump five files into a prompt with no labels. Claude loses track of which code belongs to which file and what the relationship between them is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Good approach:&lt;/strong&gt; Label each file with a clear header and state your goal upfront.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Claude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ll share two FastAPI files. Analyze how validation is handled
across both and refactor them to remove redundancy.

## FILE: validators.py
[code here]

## FILE: main.py
[code here]

Provide the complete corrected code for both files.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude reads the structure, understands the relationship between modules, and refactors across both in one pass. The 1M-token context window on Sonnet 4.6 and Opus 4.6/4.7 means you can feed in large codebases this way — many files, full documentation, test suites.&lt;/p&gt;

&lt;h3&gt;
  
  
  CLAUDE.md: Project-Wide Standards
&lt;/h3&gt;

&lt;p&gt;The blog's original framing of "system prompts" is accurate for API usage, but in Claude Code the standard mechanism is &lt;code&gt;CLAUDE.md&lt;/code&gt; — a file you place in your project root (or in subdirectories for local rules). Claude reads it automatically at session start.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;CLAUDE.md&lt;/code&gt; might contain:&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="gh"&gt;# Project Standards&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Language: Python 3.12, FastAPI 0.115
&lt;span class="p"&gt;-&lt;/span&gt; Always include docstrings on public functions
&lt;span class="p"&gt;-&lt;/span&gt; Use Pydantic v2 models for request/response schemas
&lt;span class="p"&gt;-&lt;/span&gt; Never use eval() or exec()
&lt;span class="p"&gt;-&lt;/span&gt; All database queries go through the repository layer — no raw SQL in route handlers
&lt;span class="p"&gt;-&lt;/span&gt; Secrets come from environment variables only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude automatically merges multiple &lt;code&gt;CLAUDE.md&lt;/code&gt; files based on directory structure — global rules in the root, local overrides in subdirectories. This mirrors how senior engineers think: project-wide conventions plus file-specific constraints.&lt;/p&gt;

&lt;p&gt;For API usage, system prompts work the same way — set them once, and every request in the session inherits the standards.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On security guardrails specifically:&lt;/strong&gt; treat prompts like logs. Assume they can be inspected. Don't put secrets or credentials in prompts. Lock down tool permissions to what Claude needs for the task. For anything touching authentication or access control, keep a human in the review loop.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Beginners
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Run the &lt;em&gt;What, How, Format&lt;/em&gt; check before every prompt.&lt;/li&gt;
&lt;li&gt;Paste actual error messages when debugging. Claude diagnoses errors well when it sees the full stack trace, not a paraphrase of it.&lt;/li&gt;
&lt;li&gt;Ask Claude to explain its reasoning: "Why did you choose an iterative approach over recursion?" The answer teaches you how it's modeling the problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Experienced Developers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Commit a &lt;code&gt;CLAUDE.md&lt;/code&gt; to every project. Keep it short and explicit — specific rules outperform long documentation.&lt;/li&gt;
&lt;li&gt;Label files clearly in multi-file prompts. State the goal at the top, then paste the files.&lt;/li&gt;
&lt;li&gt;Use extended thinking for complex tasks. Set effort to &lt;code&gt;xhigh&lt;/code&gt; for coding and agentic work — Anthropic's own docs recommend this as the default for most development use cases.&lt;/li&gt;
&lt;li&gt;For very long autonomous runs, use sub-agents: "You just wrote the payment processor. Now use a sub-agent to run a security review on that code." This keeps the main conversation focused while the review runs in a separate context.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common Prompting Errors
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Likely Cause&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Generic output&lt;/td&gt;
&lt;td&gt;Prompt missing framework, format, or behavior constraints&lt;/td&gt;
&lt;td&gt;Add specific language, library, and output requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Output cuts off&lt;/td&gt;
&lt;td&gt;Hitting max token limit&lt;/td&gt;
&lt;td&gt;Ask for output in sections, or summarize then expand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude ignores part of the prompt&lt;/td&gt;
&lt;td&gt;Too many instructions at once&lt;/td&gt;
&lt;td&gt;Break into sequential prompts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrong imports or syntax&lt;/td&gt;
&lt;td&gt;Missing version context&lt;/td&gt;
&lt;td&gt;Specify library versions: "FastAPI 0.115, Pydantic v2"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude contradicts earlier decisions&lt;/td&gt;
&lt;td&gt;Context drift&lt;/td&gt;
&lt;td&gt;Re-anchor: "We're still using FastAPI 0.115 with PostgreSQL"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Prompts as Dialogue
&lt;/h2&gt;

&lt;p&gt;The developers who get the most out of Claude treat prompting as a conversation, not a one-shot command. Start broad enough to test Claude's interpretation of the problem. Refine based on what comes back. Ask it to defend its choices.&lt;/p&gt;

&lt;p&gt;Each iteration improves the output. Over time you develop a sense for when to be specific and when to leave room for Claude to interpret — when a tight spec produces better code and when a looser framing surfaces a better architecture. Anthropic's own best practices guide puts it plainly: sometimes a vague prompt is exactly right, because you want to see how Claude interprets the problem before constraining it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Prompting is a skill with a short learning curve and a long ceiling. The foundations: answer &lt;em&gt;What, How, Format&lt;/em&gt; before you send anything; use chain-of-thought or extended thinking for tasks that require reasoning; label multi-file inputs clearly; store project standards in &lt;code&gt;CLAUDE.md&lt;/code&gt; so you don't repeat yourself every session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try this:&lt;/strong&gt; Take a piece of code you wrote recently. Write a weak prompt — just "improve this function." Then write a strong one using the three questions. Compare what Claude returns. The difference will be obvious, and you won't go back to vague prompts.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Acknowledgment:&lt;/strong&gt; Based on official Anthropic documentation and community research. Technical details reflect the state of Claude Code as of May 2026.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>claude</category>
    </item>
    <item>
      <title>How Claude Code Thinks: Inside Your AI Coding Assistant</title>
      <dc:creator>Syed Asif</dc:creator>
      <pubDate>Thu, 28 May 2026 04:50:14 +0000</pubDate>
      <link>https://dev.to/sydasif78/how-claude-code-thinks-inside-your-ai-coding-assistant-551o</link>
      <guid>https://dev.to/sydasif78/how-claude-code-thinks-inside-your-ai-coding-assistant-551o</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;You've set up Claude Code and sent your first prompt. Now the question is: how does it actually understand what you wrote?&lt;/p&gt;

&lt;p&gt;This guide covers what happens under the hood — how Claude reads code, what tokens and context mean in practice, and why it sometimes drops details from earlier in a conversation. Understanding these mechanics will change how you prompt.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Claude Reads Code
&lt;/h2&gt;

&lt;p&gt;Claude doesn't execute your code. It processes text. Three stages build its understanding:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Parsing and context formation.&lt;/strong&gt; Claude breaks your prompt into tokens and maps relationships between them — which function calls which, where a variable appears, how control flow branches. The output is a structural model of your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Reasoning and pattern matching.&lt;/strong&gt; Claude compares that model against patterns from training. A sorting function that resembles merge sort gets treated like merge sort. That match drives what Claude predicts you need next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Generation and justification.&lt;/strong&gt; Claude writes its response token by token, checking for coherence and safety at each step. The comments you see — "This variable is unused," "This may fail on empty lists" — come from this stage, not from running the code.&lt;/p&gt;

&lt;p&gt;Claude is probabilistic. Two similar prompts may produce different answers. That's reasoning, not a bug.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tokens and Context Windows
&lt;/h2&gt;

&lt;p&gt;A token is a small chunk of text. Claude averages 4 characters per token, or about 1.5 tokens per word in English. For code that number rises — brackets, operators, and keywords don't map cleanly to natural language tokens.&lt;/p&gt;

&lt;p&gt;Practical scale:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;print("Hello")&lt;/code&gt; is 3–4 tokens&lt;/li&gt;
&lt;li&gt;A typical function is 50–200 tokens&lt;/li&gt;
&lt;li&gt;1,000 tokens is roughly 750 words of English prose&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;context window&lt;/strong&gt; is Claude's working memory for a session. It holds your prompts, Claude's responses, uploaded files, and tool outputs — all from the same token budget. Current models as of May 2026:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Haiku 4.5&lt;/td&gt;
&lt;td&gt;200K&lt;/td&gt;
&lt;td&gt;Quick fixes, low-latency tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Sonnet 4.6&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;General coding, refactoring, multi-file work&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.6 / 4.7&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;Deep analysis, full-stack architecture, large codebases&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 1M window on Sonnet 4.6 and Opus 4.6 went live at standard pricing in March 2026. The older Claude 3 series is deprecated. Claude 3 Haiku is fully retired — requests to it now return errors.&lt;/p&gt;

&lt;p&gt;When a session fills up, Claude drops the oldest tokens first. Recent messages stay. That's why early details can go missing in long conversations.&lt;/p&gt;

&lt;p&gt;One more thing worth knowing: research has documented a &lt;strong&gt;"lost in the middle" effect&lt;/strong&gt; — attention quality drops for content buried in the center of a very large context. Put your most important constraints, framework choices, and goals at the top of a session.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Request-Response Lifecycle
&lt;/h2&gt;

&lt;p&gt;Four stages happen every time you send a prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 1 — Tokenization.&lt;/strong&gt; Claude converts your input to token IDs. It processes your message together with conversation history, loaded files, system prompts, and any command outputs. Longer sessions accumulate tokens faster because the input compounds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 2 — Context assimilation.&lt;/strong&gt; Claude merges the new prompt with history and runs self-attention, weighting which parts matter most. Constitutional AI constraints apply here — unsafe requests get flagged before generation starts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 3 — Generation.&lt;/strong&gt; Claude produces output token by token. It checks coherence and safety continuously. You'll often see Claude frame its approach before writing code — that framing is the alignment step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 4 — Memory update.&lt;/strong&gt; Claude adds the response to its in-session context. That's why "now optimize the async performance" works — Claude knows which code you mean. Close the session and that context is gone.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory and Conversation State
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Within a Session
&lt;/h3&gt;

&lt;p&gt;Claude holds everything in the active context window. As it fills, the oldest tokens drop. Re-anchoring every few turns keeps Claude oriented:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We're still on the FastAPI e-commerce API with JWT auth and PostgreSQL. Now add order history."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Across Sessions
&lt;/h3&gt;

&lt;p&gt;By default, Claude Code starts each session from scratch. Stateless architecture is simpler to reason about and easier to scale — this is intentional, not an oversight.&lt;/p&gt;

&lt;p&gt;Anthropic rolled out &lt;strong&gt;auto-memory&lt;/strong&gt; for Claude Code in early 2026. Claude now builds and maintains a &lt;code&gt;MEMORY.md&lt;/code&gt; file during sessions, storing key decisions and context that load automatically next time. The feature is on a gradual rollout; your account may need it enabled.&lt;/p&gt;

&lt;p&gt;The manual alternative: keep a &lt;code&gt;.claude/&lt;/code&gt; directory with a &lt;code&gt;context.md&lt;/code&gt; or &lt;code&gt;decisions/&lt;/code&gt; folder. Claude reads these at session start.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;session_notes.txt&lt;/code&gt; with key decisions and code snippets also works well. Paste it in at the top of each new session if auto-memory isn't available yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  API vs. IDE
&lt;/h3&gt;

&lt;p&gt;Claude Web and IDE integrations maintain context within the open session automatically. The Claude API is stateless by default — you send conversation history with each request to maintain continuity. More work, but also more control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Which Model to Use
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Use When&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Haiku 4.5&lt;/td&gt;
&lt;td&gt;200K&lt;/td&gt;
&lt;td&gt;Repetitive tasks, test generation, quick completions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sonnet 4.6&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;Everyday coding — best cost-to-capability ratio&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opus 4.6 / 4.7&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;Legacy refactors, complex multi-file reasoning, long-context analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use Haiku for "add a docstring to every function." Use Sonnet for most development work. Bring in Opus when you need to untangle something genuinely complex — a legacy monolith, an architecture decision with many constraints, a long document to reason over. Using Opus for a typo fix costs you money and time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Beginners
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Start small. Token awareness develops naturally as you work.&lt;/li&gt;
&lt;li&gt;If Claude loses track of earlier context, restate your goal explicitly.&lt;/li&gt;
&lt;li&gt;The web interface handles context management for you.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Power Users
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Front-load key facts.&lt;/strong&gt; Your framework, language, and hard constraints belong at the top of the session, not buried in message 15.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-anchor every few turns.&lt;/strong&gt; "Still on the FastAPI project, PostgreSQL backend" keeps Claude from drifting as context accumulates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Segment sessions by topic.&lt;/strong&gt; Start a new session when you switch from backend to frontend work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build explicit context for the API.&lt;/strong&gt; Send prior messages in each request, or use the &lt;code&gt;MEMORY.md&lt;/code&gt; / &lt;code&gt;.claude/&lt;/code&gt; pattern to persist decisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common Mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assuming Claude remembers yesterday.&lt;/strong&gt; It doesn't by default. Save summaries or enable auto-memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pasting 50,000-line files wholesale.&lt;/strong&gt; Large undifferentiated inputs dilute attention. Start with the relevant files and expand from there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reaching for Opus by default.&lt;/strong&gt; Sonnet 4.6 handles most development tasks well and costs significantly less.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referencing retired models.&lt;/strong&gt; Claude 3 Haiku returns errors now. Claude 3 Sonnet and Opus are deprecated. Use the 4.x series.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Claude Code is a reasoning engine with a finite but large working memory. You now understand how it reads code, how tokens accumulate across a session, the four stages it runs on every request, and how to manage context across sessions and model choices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try this:&lt;/strong&gt; Open a fresh session and build a small API across several turns. After a few exchanges, change the subject entirely, then bring Claude back to the original task. Watching how it re-anchors — or loses the thread — makes the mechanics concrete.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Acknowledgment:&lt;/strong&gt; Based on official Anthropic documentation and community research. Technical details reflect the state of Claude Code as of May 2026.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>llm</category>
      <category>programming</category>
    </item>
    <item>
      <title>Getting Started with Claude Code: Your First AI Coding Partner</title>
      <dc:creator>Syed Asif</dc:creator>
      <pubDate>Thu, 28 May 2026 04:44:35 +0000</pubDate>
      <link>https://dev.to/sydasif78/getting-started-with-claude-code-your-first-ai-coding-partner-1pf</link>
      <guid>https://dev.to/sydasif78/getting-started-with-claude-code-your-first-ai-coding-partner-1pf</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Claude Code is a pair programmer that never gets tired, explains every suggestion, and reads your entire project at once. But it's not a chat interface with a coding plugin. It's an agentic CLI that runs in your terminal, reads and writes files, manages Git, and reasons across your full codebase.&lt;/p&gt;

&lt;p&gt;This guide covers what sets Claude Code apart, how to install it, and how to run your first prompt. By the end you'll know how to treat it as a collaborator rather than an autocomplete.&lt;/p&gt;




&lt;h2&gt;
  
  
  Core Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What Claude Code Actually Is
&lt;/h3&gt;

&lt;p&gt;Claude Code is Anthropic's official command-line interface for AI-assisted development. It runs in your terminal and can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read and write files directly in your project&lt;/li&gt;
&lt;li&gt;Execute commands&lt;/li&gt;
&lt;li&gt;Manage Git workflows — branches, commits, pull requests&lt;/li&gt;
&lt;li&gt;Reason across up to 1 million tokens of codebase context&lt;/li&gt;
&lt;li&gt;Connect to external services via MCP (Model Context Protocol)&lt;/li&gt;
&lt;li&gt;Surface its reasoning in plain English before acting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It runs on Sonnet 4.6 by default for Pro users, Opus 4.6 on Max plans. Before taking any file-altering action, it asks for confirmation and shows its plan — that's the Constitutional AI framework in practice.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Claude Code Compares
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Claude Code&lt;/th&gt;
&lt;th&gt;Typical autocomplete tools&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;Agentic CLI&lt;/td&gt;
&lt;td&gt;IDE plugin or chat interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Focus&lt;/td&gt;
&lt;td&gt;Multi-file reasoning and agentic tasks&lt;/td&gt;
&lt;td&gt;Predicting the next line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context&lt;/td&gt;
&lt;td&gt;Up to 1M tokens&lt;/td&gt;
&lt;td&gt;Current file or limited window&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Actions&lt;/td&gt;
&lt;td&gt;Reads/writes files, runs commands, manages Git&lt;/td&gt;
&lt;td&gt;Suggests code you paste manually&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safety&lt;/td&gt;
&lt;td&gt;Confirms before file changes&lt;/td&gt;
&lt;td&gt;Basic filtering&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Claude Code handles large-scale refactoring, cross-file bug fixes, and infrastructure tasks end to end. It's a different category from autocomplete.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation and Your First Prompt
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Choose Your Access Method
&lt;/h3&gt;

&lt;p&gt;Three ways to use Claude Code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Claude Web (claude.ai)&lt;/strong&gt; — No installation. Good for experimenting with prompts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code CLI&lt;/strong&gt; — The core tool. Runs from any terminal, works over SSH, scriptable in CI/CD pipelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IDE Extension&lt;/strong&gt; — A VS Code extension (also works in Cursor, Windsurf, and Kiro) that surfaces inline diffs and accept/reject controls without leaving your editor.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Installing the CLI
&lt;/h4&gt;

&lt;p&gt;To install Claude Code, use one of the following methods:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;macOS, Linux, WSL:&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;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://claude.ai/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or install Node.js 18+ first, then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;claude&lt;/code&gt; in your terminal and complete the OAuth flow to authenticate. Verify with:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Install with Linux package managers
&lt;/h4&gt;

&lt;p&gt;For Debian and Ubuntu. To use the rolling channel, change both stable occurrences in the deb line: the URL path and the suite name.&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 install&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 /etc/apt/keyrings
&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://downloads.claude.ai/keys/claude-code.asc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/claude-code.asc
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [signed-by=/etc/apt/keyrings/claude-code.asc] https://downloads.claude.ai/claude-code/apt/stable stable main"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/claude-code.list
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;claude-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the GPG key fingerprint before trusting it: gpg --show-keys /etc/apt/keyrings/claude-code.asc should report 31DD DE24 DDFA B679 F42D 7BD2 BAA9 29FF 1A7E CACE.&lt;/p&gt;

&lt;p&gt;To upgrade later, run sudo apt update &amp;amp;&amp;amp; sudo apt upgrade claude-code.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting Up in VS Code
&lt;/h4&gt;

&lt;p&gt;Open the Extensions view (&lt;code&gt;Ctrl+Shift+X&lt;/code&gt; on Windows/Linux, &lt;code&gt;Cmd+Shift+X&lt;/code&gt; on Mac), search for &lt;strong&gt;Claude Code&lt;/strong&gt;, and click Install. Sign in with your Anthropic account on first launch.&lt;/p&gt;

&lt;p&gt;The extension also installs the first time you run &lt;code&gt;claude&lt;/code&gt; from VS Code's integrated terminal. It works identically in Cursor, Windsurf, and other VS Code forks.&lt;/p&gt;

&lt;p&gt;Once installed, click the Spark icon in the sidebar. You get real-time inline diffs, plan review before Claude touches any files, &lt;code&gt;@&lt;/code&gt;-mention support for specific files and line ranges, and conversation history across tabs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting Up in Cursor
&lt;/h4&gt;

&lt;p&gt;Run Claude Code from Cursor's integrated terminal for heavy agentic tasks. Use Cursor's Composer for interactive editing. The two tools operate at different speeds and task scales — they complement each other.&lt;/p&gt;

&lt;h4&gt;
  
  
  Setting Up in Zed
&lt;/h4&gt;

&lt;p&gt;Since Zed 1.0, Claude Code is native to Zed's Agent Panel via ACP (Agent Client Protocol). No separate installation. Zed is built in Rust with GPU-accelerated rendering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pick your entry point:&lt;/strong&gt; VS Code if you're already there. Cursor for deep project-wide IDE features alongside agentic work. Zed for raw performance.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2 — Your First Prompt
&lt;/h3&gt;

&lt;p&gt;Open your chosen interface and send this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Hello Claude! Please write a Python program that prints 'Hello, Claude!' and then explains, in a comment, what each line of the code does."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude responds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Assign the string 'Hello, Claude!' to the variable 'message'
&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello, Claude!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# Use the print() function to display the value of 'message' in the console
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It explained each line without being asked. That's the default behavior — Claude assumes you want to understand the code, not just copy it.&lt;/p&gt;

&lt;p&gt;Now push further:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Rewrite it in JavaScript and explain the differences."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude produces a JavaScript version and explains that &lt;code&gt;const&lt;/code&gt; replaces Python's implicit assignment and &lt;code&gt;console.log()&lt;/code&gt; replaces &lt;code&gt;print()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assign the string 'Hello, Claude!' to the variable 'message' using const&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello, Claude!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Use console.log() to display the value in the console&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 — Iterate
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Update the Python version to ask for my name, greet me personally, and show the current time."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude adds &lt;code&gt;input()&lt;/code&gt;, imports &lt;code&gt;datetime&lt;/code&gt;, and returns a runnable script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;

&lt;span class="c1"&gt;# Ask the user for their name
&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is your name? &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Greet the user by name
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello, &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Display the current system time
&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strftime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%H:%M:%S&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The current time is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each follow-up request revises Claude's reasoning and output. Treat it as a conversation, not a one-shot query.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For Beginners
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Start with the web interface — no setup, immediate feedback.&lt;/li&gt;
&lt;li&gt;Ask Claude to explain every decision. The reasoning is often more useful than the code.&lt;/li&gt;
&lt;li&gt;Make small, specific requests. Vague prompts produce vague output.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For Experienced Developers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Install the CLI and IDE extension. You'll cut context switching significantly.&lt;/li&gt;
&lt;li&gt;Use chain-of-thought prompts: ask Claude to "think step by step" before writing code on complex problems.&lt;/li&gt;
&lt;li&gt;Put your full codebase in context. Claude reads 1M tokens — use it on large files and documentation.&lt;/li&gt;
&lt;li&gt;Describe Git tasks in plain language. Claude Code creates branches, writes commit messages, and opens pull requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Common Mistakes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vague bug reports&lt;/strong&gt; produce vague fixes. Instead of "fix this bug," say: "The function should return X but returns Y. Here's the code and the error."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring Claude's explanations&lt;/strong&gt; wastes the tool's main advantage. Read the reasoning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single-prompt expectations&lt;/strong&gt; don't match how Claude works best. Iterate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Using Claude Code for line completions&lt;/strong&gt; is like using a chainsaw to slice bread. Save it for multi-file, multi-step tasks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Claude Code is an agentic CLI that reads your codebase, executes commands, manages your Git workflow, and explains every decision. You now know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it is and how it differs from autocomplete tools&lt;/li&gt;
&lt;li&gt;How to install the CLI and configure VS Code, Cursor, or Zed&lt;/li&gt;
&lt;li&gt;How to run and iterate on your first prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Next step:&lt;/strong&gt; Install the CLI, send that first "Hello, Claude!" prompt, then try something harder — ask it to refactor a real file, add error handling, or commit a change. The scope of what it can do autonomously becomes clear quickly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Acknowledgment:&lt;/strong&gt; Based on official Anthropic documentation and community research. Technical details reflect the state of Claude Code as of May 2026.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>claude</category>
      <category>networking</category>
    </item>
  </channel>
</rss>
