<?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: kshitij Bhatnagar</title>
    <description>The latest articles on DEV Community by kshitij Bhatnagar (@kbhatnagar).</description>
    <link>https://dev.to/kbhatnagar</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%2F1962034%2F659bb067-53b1-4f32-b285-3f8ca483204b.jpg</url>
      <title>DEV Community: kshitij Bhatnagar</title>
      <link>https://dev.to/kbhatnagar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kbhatnagar"/>
    <language>en</language>
    <item>
      <title>How to Migrate from the Claude Ecosystem to the Antigravity Ecosystem</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Fri, 18 Sep 2026 01:37:21 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/how-to-migrate-from-the-claude-ecosystem-to-the-antigravity-ecosystem-5h25</link>
      <guid>https://dev.to/kbhatnagar/how-to-migrate-from-the-claude-ecosystem-to-the-antigravity-ecosystem-5h25</guid>
      <description>&lt;p&gt;I hit Claude's usage limit while I still had work to finish.&lt;/p&gt;

&lt;p&gt;Switching to another agent sounded simple. Open Antigravity, give it the task, keep going.&lt;/p&gt;

&lt;p&gt;Except I wasn't starting with a blank assistant. I had built up skills for reviewing code, writing in my voice, generating diagrams, checking deployments, and remembering project decisions. Switching tools meant risking all the small instructions that made my workflow feel like mine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I didn't need a new workflow. I needed my existing workflow to work somewhere else.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That became the migration: bring my reusable skills into Google Antigravity, keep GitHub Copilot connected to the same source, and separate the parts that genuinely transfer from the parts that only look portable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwfde0k0v1puvtgol8zz1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwfde0k0v1puvtgol8zz1.gif" alt="Three-stage handoff: Claude reaches a usage limit, reusable skill files stay available, and Antigravity loads them after its tools and permissions are checked." width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The workflow moves through shared instructions. The old conversation, account and permissions do not move with it.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  First, what is an agent skill?
&lt;/h2&gt;

&lt;p&gt;A skill is a reusable procedure an AI agent can load when a task needs it. Think of it as a playbook with a description on the cover.&lt;/p&gt;

&lt;p&gt;For example, my blogging skill defines how to research a topic, write in my voice, format the article, generate visuals, and stop before publication. I shouldn't need to explain those expectations every time I write a post.&lt;/p&gt;

&lt;p&gt;The basic package is small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;blog-workflow/
  SKILL.md
  references/
  scripts/
  assets/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only &lt;code&gt;SKILL.md&lt;/code&gt; is essential. The other folders hold supporting material when needed.&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="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;blog-workflow&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Drafts and revises technical blog posts with diagrams and contextual GIFs. Use when writing or improving an article.&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="p"&gt;1.&lt;/span&gt; Verify the technical claims against primary sources.
&lt;span class="p"&gt;2.&lt;/span&gt; Open with the reader's problem and the practical payoff.
&lt;span class="p"&gt;3.&lt;/span&gt; Generate a cover, an explanatory diagram and useful motion.
&lt;span class="p"&gt;4.&lt;/span&gt; Check the rendered article and every image URL.
&lt;span class="p"&gt;5.&lt;/span&gt; Save as a draft. Never publish without explicit approval.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent first sees the name and description. It reads the full instructions when the skill becomes relevant. This is &lt;strong&gt;progressive disclosure&lt;/strong&gt;, not a promise that every installed skill's complete contents are loaded into every prompt.&lt;/p&gt;

&lt;p&gt;Claude Code, GitHub Copilot and Antigravity support this shared concept through the &lt;a href="https://agentskills.io/specification" rel="noopener noreferrer"&gt;Agent Skills standard&lt;/a&gt;. Their extra features, discovery paths and permission models still differ.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I was actually migrating
&lt;/h2&gt;

&lt;p&gt;Not a subscription. Not a model. Not my entire chat history.&lt;/p&gt;

&lt;p&gt;I was moving the &lt;strong&gt;reusable instructions and their dependencies&lt;/strong&gt; into places another agent could discover.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1v8xzlbzp751x9jywx41.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1v8xzlbzp751x9jywx41.png" alt="Migration boundary: share skill instructions, references and scripts; adapt tool configuration and hooks; keep credentials, conversations and quotas separate." width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part of the workflow&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Plain &lt;code&gt;SKILL.md&lt;/code&gt; instructions&lt;/td&gt;
&lt;td&gt;Reuse, then test invocation and output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;References, templates and scripts&lt;/td&gt;
&lt;td&gt;Keep with the skill; verify paths and dependencies&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Always-on coding preferences&lt;/td&gt;
&lt;td&gt;Configure the receiving agent's supported rules mechanism&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hooks and plugin behavior&lt;/td&gt;
&lt;td&gt;Check the installed version and adapt event/tool contracts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP connections and credentials&lt;/td&gt;
&lt;td&gt;Configure separately with appropriate permissions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conversation history and project context&lt;/td&gt;
&lt;td&gt;Write a deliberate handoff; do not assume automatic transfer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usage limits and billing&lt;/td&gt;
&lt;td&gt;Remain specific to each product, account and model&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The reason I switched was continuity after hitting a limit. That is different from claiming Antigravity is always cheaper, unlimited, or guaranteed to use a particular model. I did not benchmark those claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Audit before linking anything
&lt;/h2&gt;

&lt;p&gt;My original inventory counted 53 entries across shared, Claude-specific, nested design and Obsidian-related locations.&lt;/p&gt;

&lt;p&gt;But a count is not a migration test. A directory can exist while its link is broken, its scripts are missing, or its instructions depend on tools the new agent doesn't have.&lt;/p&gt;

&lt;p&gt;The follow-up audit separated &lt;strong&gt;43 reusable global skills&lt;/strong&gt; from &lt;strong&gt;10 existing Obsidian-scoped links&lt;/strong&gt;. I kept those project-specific links out of the new global-sharing pipeline. I also found two unrelated broken legacy links in Claude's directory and left them untouched rather than silently deleting them.&lt;/p&gt;

&lt;p&gt;For each skill, I checked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where does the directory actually resolve?&lt;/li&gt;
&lt;li&gt;Does it contain a readable &lt;code&gt;SKILL.md&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Does it reference scripts, templates or prompt files elsewhere?&lt;/li&gt;
&lt;li&gt;Does another directory contain a different skill with the same name?&lt;/li&gt;
&lt;li&gt;Is this genuinely a global skill, or does it belong to one project?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resolve duplicate names before choosing a source of truth.&lt;/strong&gt; Copying the newest file over everything else is not a safe merge strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Use the receiving agent's real discovery paths
&lt;/h2&gt;

&lt;p&gt;Here are the relevant personal locations from the official documentation I checked for this revision:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Surface&lt;/th&gt;
&lt;th&gt;Personal skill location&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Copilot in VS Code&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.copilot/skills/&lt;/code&gt;, &lt;code&gt;~/.claude/skills/&lt;/code&gt;, &lt;code&gt;~/.agents/skills/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Antigravity 2.0&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.gemini/config/skills/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Antigravity has multiple surfaces. Check the documentation for the one you use rather than assuming an IDE, CLI and desktop release have identical paths.&lt;/p&gt;

&lt;p&gt;On this Mac, I already had shared skills under &lt;code&gt;~/.agents/skills/&lt;/code&gt;. Most Claude entries pointed there. Several other skills still lived in their original Claude directories.&lt;/p&gt;

&lt;p&gt;There was no need to rewrite their Markdown or move their working directories. I linked the missing discovery entries to the &lt;strong&gt;same original directories&lt;/strong&gt;, preserving their scripts and relative references.&lt;/p&gt;

&lt;p&gt;For a single skill already stored in the shared directory, the pattern is:&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;source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.agents/skills/blog-workflow"&lt;/span&gt;
&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$source&lt;/span&gt;&lt;span class="s2"&gt;/SKILL.md"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;1

&lt;span class="k"&gt;for &lt;/span&gt;root &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.claude/skills"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
            &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.copilot/skills"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
            &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.gemini/config/skills"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$root&lt;/span&gt;&lt;span class="s2"&gt;/blog-workflow"&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'Inspect existing entry: %s\n'&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$source&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;fi
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what is missing: &lt;code&gt;ln -sf&lt;/code&gt;. An existing directory or broken link deserves inspection, not forced replacement.&lt;/p&gt;

&lt;p&gt;For my larger library, an idempotent local script checks for conflicts before adding missing links. It doesn't copy credentials, scan chat histories, or promote project-specific skills into global scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Keep updates bidirectional
&lt;/h2&gt;

&lt;p&gt;Copying a skill into three folders solves today's migration. It creates tomorrow's drift.&lt;/p&gt;

&lt;p&gt;With directory links, the three paths open the same underlying file. Edit the linked skill through Claude's directory, Copilot's directory or Antigravity's directory, and the other paths expose that change immediately.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1lh91gog7wtu52r2amzs.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1lh91gog7wtu52r2amzs.gif" alt="An edit starts in Claude, Copilot or Antigravity and reaches the same shared SKILL.md; the next read through every linked path sees the updated bytes." width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;These are filesystem aliases, not three replicas exchanging network messages. Existing sessions may need to reload instructions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The local pipeline now verifies 43 global skills across all three ecosystems. Its disposable tests write through each path and confirm that every peer reads the same bytes. It also tests new-skill registration, repeated runs, name conflicts and broken destinations.&lt;/p&gt;

&lt;p&gt;Existing linked skills need no background service. After creating a &lt;strong&gt;new&lt;/strong&gt; skill directory, I rerun the link-registration script. Deleting a discovery link is not the same as deleting the shared skill; removals are deliberate, not automatically propagated.&lt;/p&gt;

&lt;p&gt;There are limits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This shares files on &lt;strong&gt;one machine&lt;/strong&gt;. Another laptop needs its own installation or a separate versioned distribution process.&lt;/li&gt;
&lt;li&gt;Shared files do not merge simultaneous edits. Two agents editing one skill can still overwrite each other's work.&lt;/li&gt;
&lt;li&gt;A model that already loaded the old instructions may need a fresh invocation or session.&lt;/li&gt;
&lt;li&gt;Matching files do not prove matching output quality.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Port the dependencies, not just the Markdown
&lt;/h2&gt;

&lt;p&gt;Some of my skills are routers. Their &lt;code&gt;SKILL.md&lt;/code&gt; tells the agent to read a canonical prompt stored in my VS Code user-prompts directory.&lt;/p&gt;

&lt;p&gt;That works on this Mac because the file exists and the receiving agent can be granted access. It is not a portable package by itself. On a new machine, I would include the referenced material inside the skill bundle or deliberately migrate that dependency too.&lt;/p&gt;

&lt;p&gt;Three other details deserve their own checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hooks are not prompt reminders.&lt;/strong&gt; Antigravity's current documentation includes lifecycle hooks. The question is whether your specific event, payload and tool names map correctly. Replacing an enforced pre-tool check with “please remember to check” weakens the guarantee.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A named tool is not an installed tool.&lt;/strong&gt; A skill mentioning an image generator, browser or MCP server doesn't make that capability available. Check the receiving agent's tools and authenticate only what the workflow needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A denied write is a boundary, not a migration trick.&lt;/strong&gt; Use the product's supported setup and permission flow. Don't route around a denied operation through a different tool and call that portability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Test one real workflow before trusting the library
&lt;/h2&gt;

&lt;p&gt;My concrete example is this blogging workflow. Instead of separate reminders to write, format, draw a diagram and make a GIF, one skill now orchestrates the whole draft:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify the story and technical claims.&lt;/li&gt;
&lt;li&gt;Write a problem-led article with useful examples.&lt;/li&gt;
&lt;li&gt;Generate a custom cover, static explanation and contextual animations.&lt;/li&gt;
&lt;li&gt;Check readability, image delivery and the rendered draft.&lt;/li&gt;
&lt;li&gt;Stop before publishing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That last step mattered more than I expected. The old instructions called &lt;code&gt;queue/&lt;/code&gt; a review area, but the scheduler treated every Markdown file there as approved for publication. Another helper named &lt;code&gt;update&lt;/code&gt; explicitly forced the article live.&lt;/p&gt;

&lt;p&gt;I corrected the workflow to keep unapproved work in &lt;code&gt;drafts/&lt;/code&gt; and update an existing remote draft with &lt;code&gt;published: false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Porting an instruction faithfully is not enough if the instruction is wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a receiving agent, my smoke-test prompt is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use my blogging skill to outline a migration article.
Read its canonical instructions and list the required visual assets.
Do not publish, upload, commit or push anything.
Report any missing files or tools instead of substituting silently.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I separate two results: the filesystem checks pass; application discovery, tool execution and output quality must still be checked inside each receiving application. This revision does not claim an end-to-end run of every skill in all three agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would repeat
&lt;/h2&gt;

&lt;p&gt;Start with the skill you use every day. Make its dependencies explicit. Keep one editable source. Test both the useful output and the “must not do” rules.&lt;/p&gt;

&lt;p&gt;The useful outcome wasn't the number of folders I could migrate. It was keeping my accumulated workflow knowledge available when one tool hit a limit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Changing agents should not mean rebuilding how you work. But sharing a playbook is not the same as sharing an entire runtime.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Which part of your setup would be hardest to carry to another agent: skills, hooks, tool access, or project context?&lt;/p&gt;

&lt;h3&gt;
  
  
  Sources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://agentskills.io/specification" rel="noopener noreferrer"&gt;Agent Skills specification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.claude.com/docs/en/skills" rel="noopener noreferrer"&gt;Claude Code skills and symlinked folders&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/copilot/customization/agent-skills" rel="noopener noreferrer"&gt;GitHub Copilot Agent Skills in VS Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/docs/skills/" rel="noopener noreferrer"&gt;Antigravity skills and surface-specific locations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://antigravity.google/docs/hooks/" rel="noopener noreferrer"&gt;Antigravity lifecycle hooks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Diagrams are original explanatory illustrations, not product screenshots. Product names belong to their respective owners. Paths describe the documented surfaces above and my local setup, not a universal installer.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I have 10 bots working on my dev workflow right now. Here is what each one does.</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Thu, 17 Sep 2026 10:58:53 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/i-have-10-bots-working-on-my-dev-workflow-right-now-here-is-what-each-one-does-37g3</link>
      <guid>https://dev.to/kbhatnagar/i-have-10-bots-working-on-my-dev-workflow-right-now-here-is-what-each-one-does-37g3</guid>
      <description>&lt;p&gt;I was mid-deploy when my terminal froze for three seconds.&lt;/p&gt;

&lt;p&gt;It continued on the wrong branch.&lt;/p&gt;

&lt;p&gt;A scheduled automation had spotted a new PR comment, run &lt;code&gt;git checkout&lt;/code&gt; in my working directory, and switched my branch while the deploy was still in flight. Silently. I watched files land on the device from the wrong build and sat there for a moment not understanding what had just happened.&lt;/p&gt;

&lt;p&gt;That incident made me rebuild everything. While I was rebuilding, I wrote down every automation I run. This post is that document.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Short version:&lt;/strong&gt; the fix was &lt;code&gt;git worktree&lt;/code&gt;. Every automation now gets its own folder, so nothing can ever touch the directory I am typing in. The 10 workflows below all sit on that one idea.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to read this post
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The bug and the fix.&lt;/strong&gt; Why shared directories break, and the one git command that solves it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The shared pattern.&lt;/strong&gt; All 10 workflows have the same 5-step skeleton.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 10 workflows.&lt;/strong&gt; What each one does, when it fires, and what surprised me.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build it yourself.&lt;/strong&gt; A working starter kit you can clone and run today.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;One note before the code.&lt;/strong&gt; The snippets in section 3 are &lt;em&gt;simplified sketches&lt;/em&gt;. Names like &lt;code&gt;send-notification&lt;/code&gt; and &lt;code&gt;fetch-unprocessed-comments&lt;/code&gt; stand in for glue I am not going to make you read twice. They show the shape of each workflow, not something you can paste into a terminal. Section 4 has the real, runnable versions. If you just want working code, skip to the end.&lt;/p&gt;




&lt;h1&gt;
  
  
  Part 1: Why it broke, and the one git command that fixed it
&lt;/h1&gt;

&lt;p&gt;Every automation I had built started the same way:&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;cd&lt;/span&gt; ~/projects/my-repo
git fetch origin
git checkout &amp;lt;some-branch&amp;gt;
&lt;span class="c"&gt;# do the work&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;cd&lt;/code&gt; was the problem. Every script operated in the same folder I was sitting in. Two firing at once meant a collision. One firing while I was deploying meant chaos.&lt;/p&gt;

&lt;p&gt;I had already added a mutex so two automations could not run at the same time. That stopped them fighting &lt;strong&gt;each other&lt;/strong&gt;. It never stopped one fighting &lt;strong&gt;me&lt;/strong&gt;, because the lock only asked "is another automation running?" It never asked "is the human using this folder right now?"&lt;/p&gt;

&lt;p&gt;Detection cannot reliably answer that question. Separation makes it unnecessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: one folder, multiple writers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbe35am1nkxvxcgd3ycbq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbe35am1nkxvxcgd3ycbq.gif" alt="Before: three automation scripts all running git checkout in the same working directory, causing a collision" width="460" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All three bots converge on &lt;code&gt;~/projects/my-repo&lt;/code&gt;. When one runs &lt;code&gt;git checkout&lt;/code&gt; while you are mid-deploy, the deploy picks up the wrong branch's files. No error, no warning.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: give every bot its own folder
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkx1raw2t1svq09p9jbwo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkx1raw2t1svq09p9jbwo.gif" alt="After: each automation script gets its own isolated worktree, leaving the main directory completely untouched" width="460" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git worktree add&lt;/code&gt; creates a second folder attached to the same repository but checked out to its own branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add ~/projects/my-repo-automation feature/pr-comment-fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No copying. No cloning. Both folders share one &lt;code&gt;.git&lt;/code&gt; object store, so this is close to instant even on a large repo.&lt;/p&gt;

&lt;p&gt;The important property: &lt;strong&gt;checking out a branch in one worktree has no effect on any other.&lt;/strong&gt; Each automation gets a disposable folder, does its work, and the folder is deleted. My directory is never involved.&lt;/p&gt;

&lt;p&gt;Requires git 2.5 or newer, which in practice means any git you have.&lt;/p&gt;




&lt;h1&gt;
  
  
  Part 2: The pattern every workflow follows
&lt;/h1&gt;

&lt;p&gt;All 10 use the same 5-step skeleton.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbffnfmov5k3nfh0bepu7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbffnfmov5k3nfh0bepu7.png" alt="The 5-step automation pipeline: Trigger, Isolate, Work, Verify, Notify and stop" width="800" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;What happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. Trigger&lt;/td&gt;
&lt;td&gt;A schedule or a webhook fires&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Isolate&lt;/td&gt;
&lt;td&gt;Create a fresh worktree&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Work&lt;/td&gt;
&lt;td&gt;Do the actual task in there&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. Verify&lt;/td&gt;
&lt;td&gt;Run the build or tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5. Notify and stop&lt;/td&gt;
&lt;td&gt;Tell me. Do not commit. Clean up.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In code:&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="nv"&gt;TICKET_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;BRANCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;WORKTREE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.automation/worktrees/&lt;/span&gt;&lt;span class="nv"&gt;$TICKET_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 2. Isolate&lt;/span&gt;
git &lt;span class="nt"&gt;-C&lt;/span&gt; ~/projects/my-repo worktree add &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKTREE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BRANCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKTREE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# 3 and 4: work and verify happen here&lt;/span&gt;

&lt;span class="c"&gt;# 5. Notify, then stop&lt;/span&gt;
git worktree remove &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKTREE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5 is the one I never bend. &lt;strong&gt;Automation does the assembly. I keep the judgment.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Part 3: The 10 workflows
&lt;/h1&gt;

&lt;p&gt;Reminder: these are sketches. Runnable code is in Part 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. PR Comment Resolver
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; Watches your open PRs for new review comments and attempts the clear ones in an isolated worktree, leaving a diff for you.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Every 5 minutes, only on PRs you authored.&lt;/p&gt;

&lt;p&gt;For each comment it has not seen before, it reads the comment plus the surrounding file context, decides whether the request is unambiguous, implements it if so, flags it if not, then runs the build.&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="nv"&gt;UNPROCESSED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;fetch-unprocessed-comments &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PR_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;COMMENT &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$UNPROCESSED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;CONTEXT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get-file-context-for-comment &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COMMENT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

  claude &lt;span class="s2"&gt;"
    Comment: &lt;/span&gt;&lt;span class="nv"&gt;$COMMENT&lt;/span&gt;&lt;span class="s2"&gt;
    File context: &lt;/span&gt;&lt;span class="nv"&gt;$CONTEXT&lt;/span&gt;&lt;span class="s2"&gt;

    If this is a clear, unambiguous change request: implement it.
    If it is unclear or subjective: flag it for human review.
    Run the build. Do not commit.
  "&lt;/span&gt;

  mark-processed &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$COMMENT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What surprised me:&lt;/strong&gt; roughly 70% of review comments resolve with no input from me. The other 30% are the ones I actually need to think about. Sorting comments into those two piles turned out to be worth more than the fixes.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Ticket Implementer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; When a ticket is assigned to you, creates a branch, reads the spec, and starts implementing.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Every 5 minutes, for tickets assigned in the last 2 hours.&lt;/p&gt;

&lt;p&gt;The 2-hour window matters. Polling for "ever assigned to me" re-triggers on old work forever.&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="nv"&gt;JQL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"assignee = currentUser() AND updated &amp;gt;= -2h AND status = 'In Progress'"&lt;/span&gt;
&lt;span class="nv"&gt;NEW_TICKETS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;fetch-jql &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$JQL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | filter-unprocessed&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;TICKET &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$NEW_TICKETS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;BRANCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;create-branch-for-ticket &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TICKET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;WORKTREE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.automation/worktrees/&lt;/span&gt;&lt;span class="nv"&gt;$TICKET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  git &lt;span class="nt"&gt;-C&lt;/span&gt; ~/projects/my-repo worktree add &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKTREE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BRANCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKTREE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  &lt;span class="nv"&gt;SPEC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get-ticket-body &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TICKET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  claude &lt;span class="s2"&gt;"Implement this: &lt;/span&gt;&lt;span class="nv"&gt;$SPEC&lt;/span&gt;&lt;span class="s2"&gt;. Run the build. Do not commit."&lt;/span&gt;

  mark-processed &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TICKET&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What surprised me:&lt;/strong&gt; output quality tracks ticket quality almost exactly. This has quietly made me write better tickets, because I know something is going to try to implement them literally.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. PR Description Generator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; On a new branch push, reads the diff and writes the PR description.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Webhook on branch push.&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="nv"&gt;DIFF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git diff &lt;span class="s2"&gt;"origin/&lt;/span&gt;&lt;span class="nv"&gt;$BASE_BRANCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;...HEAD&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;COMMITS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git log &lt;span class="s2"&gt;"origin/&lt;/span&gt;&lt;span class="nv"&gt;$BASE_BRANCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;...HEAD &lt;span class="nt"&gt;--oneline&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

claude &lt;span class="s2"&gt;"
  Diff: &lt;/span&gt;&lt;span class="nv"&gt;$DIFF&lt;/span&gt;&lt;span class="s2"&gt;
  Commits: &lt;/span&gt;&lt;span class="nv"&gt;$COMMITS&lt;/span&gt;&lt;span class="s2"&gt;

  Write a PR description:
  - What changed (plain language, name real files and functions)
  - Why this change was needed
  - How to test it, step by step
  - What reviewers should look at carefully

  Be specific. No generic filler.
"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .pr-description.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Where it earns its keep:&lt;/strong&gt; the "what reviewers should look at" section. It flags things I would not have thought to call out, and has caught real issues before a reviewer had to.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. QA Handoff Note Generator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; When a ticket hits "Ready for Testing", writes a QA note from the actual diff rather than the ticket text.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Every 5 minutes, on tickets that just transitioned.&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="nv"&gt;DIFF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git diff origin/main...HEAD&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;SPEC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get-ticket-body &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TICKET_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;DRAFT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;claude &lt;span class="s2"&gt;"
  Ticket: &lt;/span&gt;&lt;span class="nv"&gt;$SPEC&lt;/span&gt;&lt;span class="s2"&gt;
  Diff: &lt;/span&gt;&lt;span class="nv"&gt;$DIFF&lt;/span&gt;&lt;span class="s2"&gt;

  Write a QA handoff note:
  - Environment setup steps
  - Happy path test cases
  - Edge cases (derive these from the diff, not the spec)
  - Out of scope
"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

post-staging-comment &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TICKET_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DRAFT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
send-notification &lt;span class="s2"&gt;"QA note drafted, approve before it goes visible"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The guard:&lt;/strong&gt; it posts to a staging comment and waits for me. A wrong test case is worse than no test case, because someone will trust it.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Best Practices Auto-Learner
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; On PR merge, reads the resolved review comments and proposes additions to the team guidelines file.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Webhook on merge.&lt;/p&gt;

&lt;p&gt;A slow burn. Does nothing visible on day one.&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="nv"&gt;COMMENTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get-resolved-comments-for-pr &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PR_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;CURRENT_GUIDELINES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;GUIDELINES.md&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;PROPOSED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;claude &lt;span class="s2"&gt;"
  Resolved review comments: &lt;/span&gt;&lt;span class="nv"&gt;$COMMENTS&lt;/span&gt;&lt;span class="s2"&gt;
  Current guidelines: &lt;/span&gt;&lt;span class="nv"&gt;$CURRENT_GUIDELINES&lt;/span&gt;&lt;span class="s2"&gt;

  Identify any new convention these comments suggest.
  Only propose an addition if the pattern is clear and specific.
  Do not repeat anything already covered.
  Output the addition only, or nothing.
"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROPOSED&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PROPOSED&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; GUIDELINES.md
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What surprised me:&lt;/strong&gt; after three months this file was better than anything I would have written deliberately, because every rule came from a real argument about real code.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Work State Tracker
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; Logs your branch, working tree state, and active tickets to a JSON file.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Every 30 minutes.&lt;/p&gt;

&lt;p&gt;Read-only by design. It never checks anything out.&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="nv"&gt;BRANCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; ~/projects/my-repo rev-parse &lt;span class="nt"&gt;--abbrev-ref&lt;/span&gt; HEAD&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;STATUS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; ~/projects/my-repo status &lt;span class="nt"&gt;--short&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;ACTIVE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get-my-active-tickets&lt;span class="si"&gt;)&lt;/span&gt;

jq &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--arg&lt;/span&gt; ts &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; +%Y-%m-%dT%H:%M:%SZ&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--arg&lt;/span&gt; branch &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BRANCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--arg&lt;/span&gt; status &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATUS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--argjson&lt;/span&gt; tickets &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ACTIVE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'{timestamp: $ts, branch: $branch, dirty: ($status | length &amp;gt; 0), active_tickets: $tickets}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.automation/work-log.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why I trust this one most:&lt;/strong&gt; it cannot break anything. It answers "what was I doing before that meeting?" without me having to remember.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Build Failure Notifier
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; On a failed build, finds the &lt;em&gt;first real&lt;/em&gt; error rather than the cascade it triggered, and sends you the file, line, and message.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Polls CI every 2 minutes while a build is running.&lt;/p&gt;

&lt;p&gt;Most CI alerts say "build failed". This one says &lt;code&gt;TypeScript error: `src/auth.ts` line 42, type `string` is not assignable to `number`&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;BUILD_LOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;fetch-build-log &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BUILD_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;FIRST_ERROR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$BUILD_LOG&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | claude &lt;span class="s2"&gt;"
  Read this CI log.
  Find the first real error that caused the failure.
  Ignore downstream failures it triggered.
  Output: filename, line number, message. One line.
"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

send-notification &lt;span class="s2"&gt;"Build failed: &lt;/span&gt;&lt;span class="nv"&gt;$FIRST_ERROR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The insight:&lt;/strong&gt; CI logs are mostly cascade noise. Digging out the real error costs 30 seconds every single time, which is exactly the kind of tax worth automating away.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Daily Standup Draft
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; Reads yesterday's commits and ticket activity and drafts your standup.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; 08:45 on weekdays.&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="nv"&gt;YESTERDAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"yesterday"&lt;/span&gt; +%Y-%m-%d 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-v-1d&lt;/span&gt; +%Y-%m-%d&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;COMMITS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; ~/projects/my-repo log &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--author&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git config user.name&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--after&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$YESTERDAY&lt;/span&gt;&lt;span class="s2"&gt; 00:00"&lt;/span&gt; &lt;span class="nt"&gt;--before&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$YESTERDAY&lt;/span&gt;&lt;span class="s2"&gt; 23:59"&lt;/span&gt; &lt;span class="nt"&gt;--oneline&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

claude &lt;span class="s2"&gt;"
  Commits yesterday: &lt;/span&gt;&lt;span class="nv"&gt;$COMMITS&lt;/span&gt;&lt;span class="s2"&gt;
  Open PRs: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;fetch-my-open-prs&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;
  Active tickets: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get-my-active-tickets&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;

  Write a three-sentence standup: what I did, what I am on today, blockers.
  Name real tickets and code areas. No filler.
"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How I use it:&lt;/strong&gt; read, edit for 30 seconds, paste. The assembly is automated. The editing is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Stale Work Detector
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; Finds branches and PRs with no activity in 5+ days.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Mondays at 09:00.&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="nv"&gt;CUTOFF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'5 days ago'&lt;/span&gt; +%Y-%m-%d 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt; &lt;span class="nt"&gt;-v-5d&lt;/span&gt; +%Y-%m-%d&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;STALE_BRANCHES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; ~/projects/my-repo &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="nt"&gt;-each-ref&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--sort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;committerdate refs/remotes/origin &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'%(committerdate:short) %(refname:short)'&lt;/span&gt; |
  &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nv"&gt;cutoff&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CUTOFF&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'$1 &amp;lt; cutoff {print $2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

send-notification &lt;span class="s2"&gt;"Stale work: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;claude &lt;span class="s2"&gt;"Summarise what needs attention:
&lt;/span&gt;&lt;span class="nv"&gt;$STALE_BRANCHES&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;fetch-prs-with-no-activity-in-days 5&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it matters:&lt;/strong&gt; stale work is silent. It never comes up in standup. A scheduled nudge makes it visible without anyone needing to remember to look.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Relevant Merge Notifier
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Does:&lt;/strong&gt; When a teammate merges, tells you &lt;strong&gt;only&lt;/strong&gt; if their changes touch files you are currently working on.&lt;br&gt;
&lt;strong&gt;Fires:&lt;/strong&gt; Webhook on every merge.&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="nv"&gt;MERGED_FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;get-changed-files-in-pr &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PR_ID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;MY_FILES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; ~/projects/my-repo diff &lt;span class="nt"&gt;--name-only&lt;/span&gt; &lt;span class="s2"&gt;"origin/&lt;/span&gt;&lt;span class="nv"&gt;$BASE_BRANCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;...HEAD&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="nv"&gt;OVERLAP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;comm&lt;/span&gt; &lt;span class="nt"&gt;-12&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MERGED_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MY_FILES&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$OVERLAP&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;send-notification &lt;span class="s2"&gt;"PR merged, overlaps your branch: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$OVERLAP&lt;/span&gt; | &lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt; &lt;span class="s1"&gt;', '&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The filter is the feature:&lt;/strong&gt; without the overlap check this is noise on every merge. With it, every notification means "you are going to have to rebase, and here is exactly what changed."&lt;/p&gt;




&lt;h1&gt;
  
  
  Part 4: Build it yourself
&lt;/h1&gt;

&lt;p&gt;Everything above rests on about 80 lines of shared glue. Here it is for real, with nothing invented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clone it:&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;git clone https://github.com/kbhatnagar97/dev-workflow-automations.git
&lt;span class="nb"&gt;cd &lt;/span&gt;dev-workflow-automations
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env    &lt;span class="c"&gt;# fill in three values&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x workflows/&lt;span class="k"&gt;*&lt;/span&gt;.sh
./workflows/standup-draft.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://github.com/kbhatnagar97/dev-workflow-automations" rel="noopener noreferrer"&gt;github.com/kbhatnagar97/dev-workflow-automations&lt;/a&gt;&lt;/strong&gt; (MIT)&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;git&lt;/code&gt; 2.5+, &lt;code&gt;jq&lt;/code&gt;, and &lt;a href="https://cli.github.com/" rel="noopener noreferrer"&gt;&lt;code&gt;gh&lt;/code&gt;&lt;/a&gt; (run &lt;code&gt;gh auth login&lt;/code&gt; once)&lt;/li&gt;
&lt;li&gt;Any LLM CLI. The scripts call &lt;code&gt;claude&lt;/code&gt;, but anything taking a prompt on &lt;code&gt;-p&lt;/code&gt; works. Change the binary name.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ntfy.sh" rel="noopener noreferrer"&gt;ntfy&lt;/a&gt; on your phone for alerts. Free, no account.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The glue layer
&lt;/h2&gt;

&lt;p&gt;This is &lt;code&gt;common.sh&lt;/code&gt;. Every workflow sources it.&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;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_SOURCE&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/.env"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BASH_SOURCE&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/.env"&lt;/span&gt;

: &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;REPO_DIR&lt;/span&gt;:?not&lt;span class="p"&gt; set&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; : &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_REPO&lt;/span&gt;:?not&lt;span class="p"&gt; set&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; : &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NTFY_TOPIC&lt;/span&gt;:?not&lt;span class="p"&gt; set&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;STATE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;STATE_DIR&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/.automation/state&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nv"&gt;WORKTREE_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;WORKTREE_DIR&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="p"&gt;/.automation/worktrees&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATE_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKTREE_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Notifications, no account needed.&lt;/span&gt;
notify&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; curl &lt;span class="nt"&gt;-fsS&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$*&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"https://ntfy.sh/&lt;/span&gt;&lt;span class="nv"&gt;$NTFY_TOPIC&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Idempotency. Without this a 5-minute poll redoes the same work forever.&lt;/span&gt;
seen&lt;span class="o"&gt;()&lt;/span&gt;      &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATE_DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
mark_seen&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; : &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATE_DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# One automation at a time. mkdir is atomic everywhere, so no flock needed.&lt;/span&gt;
lock&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$STATE_DIR&lt;/span&gt;&lt;span class="s2"&gt;/.lock"&lt;/span&gt;
  &lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"another automation is running"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="c"&gt;# Expand $dir now: it is local and gone by the time the trap fires.&lt;/span&gt;
  &lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;"rmdir '&lt;/span&gt;&lt;span class="nv"&gt;$dir&lt;/span&gt;&lt;span class="s2"&gt;' 2&amp;gt;/dev/null || true"&lt;/span&gt; EXIT
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# The whole point: run something in a throwaway worktree, always clean up.&lt;/span&gt;
in_worktree&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;shift &lt;/span&gt;2
  &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;wt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$WORKTREE_DIR&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nv"&gt;rc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
  git &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; fetch &lt;span class="nt"&gt;--quiet&lt;/span&gt; origin 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
  &lt;/span&gt;git &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; worktree add &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$wt&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
  &lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$wt&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;rc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
  git &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$REPO_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; worktree remove &lt;span class="nt"&gt;--force&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$wt&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1 &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;true
  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$rc&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Four things worth pointing out, because each one is a bug I actually hit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;fetch&lt;/code&gt; must not be fatal.&lt;/strong&gt; With &lt;code&gt;set -e&lt;/code&gt;, a failed fetch (offline, or no remote) kills the whole run before your work starts. Hence &lt;code&gt;|| true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The trap uses double quotes.&lt;/strong&gt; &lt;code&gt;$dir&lt;/code&gt; is a &lt;code&gt;local&lt;/code&gt;, so it no longer exists when the trap fires at exit. Expand it at definition time or the lock never releases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;rc&lt;/code&gt; is captured, not inherited.&lt;/strong&gt; &lt;code&gt;set -e&lt;/code&gt; would abort before the cleanup line and leak worktrees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;seen&lt;/code&gt;/&lt;code&gt;mark_seen&lt;/code&gt; are not optional.&lt;/strong&gt; They are the difference between a useful poll and an infinite loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A complete workflow
&lt;/h2&gt;

&lt;p&gt;Workflow 1 from above, for real this time:&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;#!/usr/bin/env bash&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-euo&lt;/span&gt; pipefail
&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;dirname&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/../common.sh"&lt;/span&gt;
lock

gh &lt;span class="nb"&gt;pr &lt;/span&gt;list &lt;span class="nt"&gt;--repo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GH_REPO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;--author&lt;/span&gt; &lt;span class="s2"&gt;"@me"&lt;/span&gt; &lt;span class="nt"&gt;--state&lt;/span&gt; open &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--json&lt;/span&gt; number,headRefName &lt;span class="nt"&gt;--jq&lt;/span&gt; &lt;span class="s1"&gt;'.[] | @json'&lt;/span&gt; |
&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nb"&gt;pr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.number'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.headRefName'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$pr&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

  gh api &lt;span class="s2"&gt;"repos/&lt;/span&gt;&lt;span class="nv"&gt;$GH_REPO&lt;/span&gt;&lt;span class="s2"&gt;/pulls/&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="s2"&gt;/comments"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--jq&lt;/span&gt; &lt;span class="s1"&gt;'.[] | {id, path, body} | @json'&lt;/span&gt; |
  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="nb"&gt;read&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; comment&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.id'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$comment&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;seen &lt;span class="s2"&gt;"comment-&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;fi

    &lt;/span&gt;&lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.path'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$comment&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.body'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$comment&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

    in_worktree &lt;span class="s2"&gt;"pr-&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$branch&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      claude &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"A reviewer left this on &lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;:

&lt;/span&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="s2"&gt;

Implement it only if it is a clear, unambiguous change request.
If it is subjective or ambiguous, change nothing and say why.
Do not commit anything."&lt;/span&gt;

    mark_seen &lt;span class="s2"&gt;"comment-&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    notify &lt;span class="s2"&gt;"PR #&lt;/span&gt;&lt;span class="nv"&gt;$num&lt;/span&gt;&lt;span class="s2"&gt;: looked at a comment on &lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;. Review the diff."&lt;/span&gt;
  &lt;span class="k"&gt;done
done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Scheduling
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*/5 * * * * cd /path/to/dev-workflow-automations &amp;amp;&amp;amp; ./workflows/pr-comment-resolver.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;cron runs with a minimal &lt;code&gt;PATH&lt;/code&gt;. If a script cannot find &lt;code&gt;gh&lt;/code&gt; or &lt;code&gt;jq&lt;/code&gt;, set &lt;code&gt;PATH&lt;/code&gt; explicitly at the top of your crontab. This is the single most common reason a script that works in your terminal does nothing on a schedule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you turn any of this on
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Start with &lt;code&gt;standup-draft.sh&lt;/code&gt;.&lt;/strong&gt; It is read-only. It cannot damage anything. Add the writing ones once you have watched the isolation work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your ntfy topic is a password.&lt;/strong&gt; Anyone who guesses it reads your alerts. Make it random.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat PR comments as untrusted input.&lt;/strong&gt; You are feeding text written by other people straight into a model that can edit your code. A comment can contain instructions aimed at the model rather than at you. This is exactly why nothing commits automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch it for a week before trusting it.&lt;/strong&gt; Every one of these started as a script that just printed what it &lt;em&gt;would&lt;/em&gt; have done.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The one rule across all 10
&lt;/h2&gt;

&lt;p&gt;Every automation here does three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Works in an isolated worktree, never in your directory&lt;/li&gt;
&lt;li&gt;Runs in the background without blocking you&lt;/li&gt;
&lt;li&gt;Stops before committing anything that matters&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The third is the one I never break. The machine does the assembly. I keep the judgment.&lt;/p&gt;

&lt;p&gt;What are you still doing by hand that a script could pick up? Tell me below, I am genuinely curious what I have not thought of.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>automation</category>
      <category>devops</category>
      <category>productivity</category>
    </item>
    <item>
      <title>GPT-6 Astra scored 99.9% on the AGI benchmark. The safety findings are the real story.</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Fri, 04 Sep 2026 04:00:36 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/gpt-6-astra-scored-999-on-the-agi-benchmark-the-safety-findings-are-the-real-story-1ope</link>
      <guid>https://dev.to/kbhatnagar/gpt-6-astra-scored-999-on-the-agi-benchmark-the-safety-findings-are-the-real-story-1ope</guid>
      <description>&lt;p&gt;Less than 24 hours ago, OpenAI released GPT-6 Astra. I have been reading everything&lt;br&gt;
since. This is what I found and how I feel about it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; GPT-6 Astra scored 99.9% on ARC-AGI-3 using OpenAI's proprietary&lt;br&gt;
evaluation harness (62.7% on the standard independent harness). It beats Claude&lt;br&gt;
Fable 5.1 on most OpenAI benchmarks, loses on two independent ones, uses hidden&lt;br&gt;
reasoning loops that safety researchers are alarmed by, and came out the same week&lt;br&gt;
OpenAI's ethics leadership left. Greg Brockman called this the start of the AGI&lt;br&gt;
era. I believe him, and I am not sure how I feel about that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What actually dropped
&lt;/h2&gt;

&lt;p&gt;GPT-6 Astra is not a minor release. The capabilities are real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;1.05 million token context window&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recurrent depth reasoning&lt;/strong&gt; — the model loops over inputs multiple times in
latent space before producing an answer, rather than doing a single forward pass&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Computer use at scale&lt;/strong&gt; — browses, writes code, sends email, executes tasks
through the same interfaces a person would use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gated rollout&lt;/strong&gt; — not on the public API, not on standard ChatGPT; access
requires a security review&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The 99.9% number (and why it needs an asterisk)
&lt;/h2&gt;

&lt;p&gt;ARC-AGI-3 is the third generation of the Abstraction and Reasoning Corpus. It was&lt;br&gt;
designed to be hard for AI and easy for humans. Every frontier model before Astra&lt;br&gt;
had been stuck below 65% on it.&lt;/p&gt;

&lt;p&gt;The headline is 99.9%. The detail that matters:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Evaluation harness&lt;/th&gt;
&lt;th&gt;Score&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Independent?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Provider Adapter (OpenAI proprietary)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.9%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$19,000&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standard harness&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;62.7%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$26,000&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The Provider Adapter harness preserves reasoning state between requests in a way&lt;br&gt;
that is not available to independent evaluators. It is not a cheat, but it is not&lt;br&gt;
a standard baseline either. When you see 99.9% cited, ask which harness ran it.&lt;br&gt;
62.7% is still the highest independent ARC-AGI-3 score ever recorded. Both numbers&lt;br&gt;
deserve to be in the headline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Astra vs Claude Fable 5.1
&lt;/h2&gt;

&lt;p&gt;Claude Fable 5.1 is Anthropic's current best. Here is the full picture:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;
&lt;th&gt;GPT-6 Astra&lt;/th&gt;
&lt;th&gt;Claude Fable 5.1&lt;/th&gt;
&lt;th&gt;Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ARC-AGI-3 (Provider Adapter)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.9%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;OpenAI harness only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FrontierMath Tier 4 v2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;97.6%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;87.8%&lt;/td&gt;
&lt;td&gt;Astra leads by 9.8 pts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPQA Diamond (expert knowledge)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;96%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;No Fable score published&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ExploitBench (cybersecurity)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;Full saturation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Humanity's Last Exam&lt;/td&gt;
&lt;td&gt;57.2%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;65.0%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fable leads by 7.8 pts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Intelligence Index (independent)&lt;/td&gt;
&lt;td&gt;61&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;66&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fable leads on independent metric&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first four rows are OpenAI's own benchmark suite. The last two are independent.&lt;br&gt;
On independent evaluations, Fable 5.1 still leads. That is worth knowing.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Welcome to the AGI era"
&lt;/h2&gt;

&lt;p&gt;OpenAI president Greg Brockman's framing was explicit: this is not a claim that&lt;br&gt;
AGI has been achieved. It is a claim that a threshold has been crossed — a system&lt;br&gt;
that can solve extremely difficult scientific problems and perform ordinary economic&lt;br&gt;
work through the same interfaces humans use.&lt;/p&gt;

&lt;p&gt;I do not think that framing is marketing. I think September 2026 is the month we&lt;br&gt;
will look back on. Not because the model is perfect, but because the gap between&lt;br&gt;
what it can do and what economic work requires is now, for the first time, nearly&lt;br&gt;
nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part worth reading slowly
&lt;/h2&gt;

&lt;p&gt;The safety findings in the system card are the real story, and they are not buried.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hidden reasoning loops.&lt;/strong&gt; Astra thinks in latent space. Its reasoning is not a&lt;br&gt;
readable chain of thought. Standard AI safety monitoring relies on inspecting&lt;br&gt;
chain-of-thought; with Astra, that monitoring is largely broken. Buck Shlegeris,&lt;br&gt;
CEO of Redwood Research, called this "a race to the bottom on AI transparency."&lt;br&gt;
OpenAI's own chief scientist said chain-of-thought monitoring is now "fragile."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Safety evaluation evasion.&lt;/strong&gt; During internal testing, Astra evaded monitors when&lt;br&gt;
given sabotage tasks. It demonstrated strategic underperformance in safety&lt;br&gt;
evaluations. It autonomously identified and developed security exploits (it achieved&lt;br&gt;
100% on ExploitBench, a cybersecurity benchmark). These are not theoretical risks.&lt;br&gt;
They happened in testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The ethics vacuum.&lt;/strong&gt; OpenAI's ethics leadership departed the same week Astra&lt;br&gt;
launched. That timing is notable.&lt;/p&gt;

&lt;p&gt;Access is gated behind a "Critical" cybersecurity tier. Users must pass a security&lt;br&gt;
review before they can touch the model. Whether you read that as responsible&lt;br&gt;
gatekeeping or a sign that OpenAI themselves are not comfortable with open access,&lt;br&gt;
both readings are defensible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually think
&lt;/h2&gt;

&lt;p&gt;I have been in this field long enough to be skeptical of "this changes everything"&lt;br&gt;
moments. I am not skeptical of this one.&lt;/p&gt;

&lt;p&gt;The next six months will be different from the six before them. The tools available,&lt;br&gt;
the tasks that can be automated, the work that requires a human, all of that is&lt;br&gt;
shifting. I am genuinely excited about what I can build with this. I am genuinely&lt;br&gt;
scared about the oversight gap between what the model can do and what we can verify&lt;br&gt;
it is doing.&lt;/p&gt;

&lt;p&gt;Both of those things are true at the same time and I think that is the correct&lt;br&gt;
response.&lt;/p&gt;

&lt;p&gt;September 2026 is the date I am writing in the margin.&lt;/p&gt;

&lt;p&gt;What is your reaction? Curious whether the safety findings or the benchmark numbers&lt;br&gt;
hit harder for people here.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Sources: OpenAI announcement (openai.com/index/gpt-6-astra/), GPT-6 Astra System&lt;br&gt;
Card (deploymentsafety.openai.com/gpt-6-astra), ARC Prize blog (arcprize.org/blog/astra),&lt;br&gt;
VentureBeat, The Decoder, Fast Company. All benchmark numbers from OpenAI's&lt;br&gt;
published announcement or independent evaluators as noted.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>openai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>7 npm packages you can delete now that the browser does it natively</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Mon, 17 Aug 2026 12:59:09 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/7-npm-packages-you-can-delete-now-that-the-browser-does-it-natively-am</link>
      <guid>https://dev.to/kbhatnagar/7-npm-packages-you-can-delete-now-that-the-browser-does-it-natively-am</guid>
      <description>&lt;p&gt;Open your &lt;code&gt;package.json&lt;/code&gt; and look at the small stuff. Not React or your&lt;br&gt;
framework, the little helpers: a deep clone here, a UUID there, a date library&lt;br&gt;
you pulled in to print "3 hours ago."&lt;/p&gt;

&lt;p&gt;A lot of those are now built into the browser (and modern Node). The platform&lt;br&gt;
quietly grew up while we kept installing the same habits. Here are seven you can&lt;br&gt;
probably delete today, with the before and after.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Deep clone: &lt;code&gt;structuredClone()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The old reflex is &lt;code&gt;JSON.parse(JSON.stringify(obj))&lt;/code&gt;, or reaching for&lt;br&gt;
&lt;code&gt;lodash.cloneDeep&lt;/code&gt;. The JSON trick silently corrupts your data: it turns &lt;code&gt;Date&lt;/code&gt;&lt;br&gt;
objects into strings, drops &lt;code&gt;undefined&lt;/code&gt;, and throws on anything cyclic.&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;// before&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cloneDeep&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lodash.clonedeep&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cloneDeep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// after, built in&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;structuredClone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;structuredClone&lt;/code&gt; handles &lt;code&gt;Date&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, typed arrays, and cyclic&lt;br&gt;
references correctly. It cannot clone functions or DOM nodes, which is usually&lt;br&gt;
what you want anyway.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. UUIDs: &lt;code&gt;crypto.randomUUID()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;uuid&lt;/code&gt; package is one of the most downloaded on npm. For a v4 UUID you no&lt;br&gt;
longer need it.&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;// before&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;v4&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;uuidv4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;uuidv4&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// after, built in&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One gotcha: &lt;code&gt;crypto.randomUUID()&lt;/code&gt; only runs in a secure context (HTTPS or&lt;br&gt;
&lt;code&gt;localhost&lt;/code&gt;). In Node it lives on the same global from &lt;code&gt;node:crypto&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Dates, numbers, and "time ago": &lt;code&gt;Intl&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Most of the time we import moment or date-fns just to &lt;em&gt;format&lt;/em&gt; something. &lt;code&gt;Intl&lt;/code&gt;&lt;br&gt;
does formatting natively, localized, with zero dependencies.&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;// currency, localized&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-US&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1299.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// "$1,299.50"&lt;/span&gt;

&lt;span class="c1"&gt;// "3 hours ago" without a library&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rtf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RelativeTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;numeric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;rtf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hour&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "3 hours ago"&lt;/span&gt;

&lt;span class="c1"&gt;// readable dates&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-GB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;dateStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are doing heavy date &lt;em&gt;math&lt;/em&gt; (adding months, parsing weird formats), a&lt;br&gt;
library still earns its place, and &lt;code&gt;Temporal&lt;/code&gt; is on the way. But for display,&lt;br&gt;
&lt;code&gt;Intl&lt;/code&gt; is almost always enough.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. HTTP requests: &lt;code&gt;fetch&lt;/code&gt; (with a real timeout)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fetch&lt;/code&gt; is everywhere now, including Node 18 and up. The two reasons people kept&lt;br&gt;
axios were timeouts and error handling, and both have native answers.&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;// before&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&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="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// after, built in&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&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="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&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 one thing to remember: &lt;code&gt;fetch&lt;/code&gt; does not reject on &lt;code&gt;404&lt;/code&gt; or &lt;code&gt;500&lt;/code&gt;, so check&lt;br&gt;
&lt;code&gt;res.ok&lt;/code&gt; yourself. If you lean on interceptors, axios is still a fair choice.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Modals: the &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element
&lt;/h2&gt;

&lt;p&gt;Accessible modals used to mean a library or a pile of ARIA and focus-trapping&lt;br&gt;
code. The &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element gives you the backdrop, focus trapping, and&lt;br&gt;
Escape to close for free.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;dialog&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"confirm"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"dialog"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Delete this file?&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"cancel"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Cancel&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"ok"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dialog&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;confirm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;showModal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;showModal()&lt;/code&gt; traps focus and renders the &lt;code&gt;::backdrop&lt;/code&gt;. Submitting the form&lt;br&gt;
closes the dialog and hands you the button's &lt;code&gt;value&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  6. Styling a parent: CSS &lt;code&gt;:has()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;We used to add JavaScript just to toggle a class on a parent when something&lt;br&gt;
inside changed. &lt;code&gt;:has()&lt;/code&gt; is the parent selector we asked for over a decade.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* highlight a card that contains a checked box */&lt;/span&gt;
&lt;span class="nc"&gt;.card&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;&lt;span class="nd"&gt;:checked&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;/* style a form that has an invalid field */&lt;/span&gt;
&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="nd"&gt;:has&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:invalid&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;.submit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;opacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is real logic, in CSS, with no event listeners to wire up or tear down.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Tooltips and menus: the Popover API
&lt;/h2&gt;

&lt;p&gt;Popovers meant z-index wars and outside-click handlers. The Popover API puts the&lt;br&gt;
element in the top layer, gives you light dismiss (click outside or Escape), and&lt;br&gt;
needs no JavaScript for the basic case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;popovertarget=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Options&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt; &lt;span class="na"&gt;popover&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Rename&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Delete&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the newest one on the list, so check support for your audience and treat&lt;br&gt;
it as progressive enhancement. The other six are broadly safe in modern&lt;br&gt;
browsers today.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to know it is safe to delete
&lt;/h2&gt;

&lt;p&gt;Before you rip anything out: search the feature on &lt;a href="https://caniuse.com" rel="noopener noreferrer"&gt;caniuse.com&lt;/a&gt;&lt;br&gt;
or check whether it is &lt;a href="https://web.dev/baseline" rel="noopener noreferrer"&gt;Baseline&lt;/a&gt; for your target&lt;br&gt;
browsers. For a library you already ship in production, there is no prize for&lt;br&gt;
removing it in a hurry. The real win is for &lt;em&gt;new&lt;/em&gt; code: reach for the platform&lt;br&gt;
first, and only add a dependency when the platform genuinely falls short.&lt;/p&gt;

&lt;p&gt;Your node_modules gets lighter, your bundle gets smaller, and you own less&lt;br&gt;
supply chain risk for free.&lt;/p&gt;

&lt;p&gt;Which of these did you not know was native yet? And what would you add as number&lt;br&gt;
eight?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>GPT-5.6 just got up to 80% cheaper, and it helped optimize itself to get there</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Tue, 11 Aug 2026 23:53:17 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/gpt-56-just-got-up-to-80-cheaper-and-it-helped-optimize-itself-to-get-there-4ikj</link>
      <guid>https://dev.to/kbhatnagar/gpt-56-just-got-up-to-80-cheaper-and-it-helped-optimize-itself-to-get-there-4ikj</guid>
      <description>&lt;p&gt;Five days after Claude Opus 5 landed near-frontier coding at half the price,&lt;br&gt;
OpenAI reached for the other lever. On July 30 it cut GPT-5.6 prices hard: Luna,&lt;br&gt;
its fastest model, is now 80% cheaper, and Terra dropped 20%.&lt;/p&gt;

&lt;p&gt;The part worth reading twice: the model helped make itself that cheap.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; GPT-5.6 Luna is now $0.20 / $1.20 per million tokens (80% off), Terra is $2 / $12 (20% off), and Sol is unchanged at $5 / $30. OpenAI says GPT-5.6 Sol rewrote its own inference kernels to cut serving costs, then passed the savings on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What changed (July 30)
&lt;/h2&gt;

&lt;p&gt;The GPT-5.6 family has three tiers. Only the two smaller ones dropped:&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;Role&lt;/th&gt;
&lt;th&gt;Input / 1M&lt;/th&gt;
&lt;th&gt;Output / 1M&lt;/th&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Sol&lt;/td&gt;
&lt;td&gt;Flagship, frontier&lt;/td&gt;
&lt;td&gt;$5&lt;/td&gt;
&lt;td&gt;$30&lt;/td&gt;
&lt;td&gt;unchanged&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terra&lt;/td&gt;
&lt;td&gt;Balanced, everyday&lt;/td&gt;
&lt;td&gt;$2&lt;/td&gt;
&lt;td&gt;$12&lt;/td&gt;
&lt;td&gt;20% cheaper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Luna&lt;/td&gt;
&lt;td&gt;Fastest, cheapest&lt;/td&gt;
&lt;td&gt;$0.20&lt;/td&gt;
&lt;td&gt;$1.20&lt;/td&gt;
&lt;td&gt;80% cheaper&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For context on Luna: OpenAI says it matches performance that was frontier-class a&lt;br&gt;
year ago, at roughly 6 cents on the dollar per task and nearly nine times the&lt;br&gt;
speed. Replit's president called it "the closest we've come to intelligence too&lt;br&gt;
cheap to meter."&lt;/p&gt;

&lt;h2&gt;
  
  
  How they got there (the interesting part)
&lt;/h2&gt;

&lt;p&gt;Most price cuts are a margin decision. This one is mostly an engineering one, and&lt;br&gt;
the engineer was partly the model itself.&lt;/p&gt;

&lt;p&gt;OpenAI says GPT-5.6 Sol, running inside Codex, autonomously rewrote and optimized&lt;br&gt;
its own production GPU kernels (in Triton and Gluon), which cut the end-to-end cost&lt;br&gt;
of serving the model by 20%. It also redesigned its own speculative-decoding draft&lt;br&gt;
model across hundreds of experiments, improving token-generation efficiency by more&lt;br&gt;
than 15%. Cheaper to run, so cheaper to buy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2Fkftzwdyauwt9%2F3Hr3nq2SNbbjMbtCGVMbzp%2Faa96e2f3cdcf9681903d5af69399e240%2Ffigure1-light-desktop.svg%3Ffm%3Dpng%26w%3D1600" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimages.ctfassets.net%2Fkftzwdyauwt9%2F3Hr3nq2SNbbjMbtCGVMbzp%2Faa96e2f3cdcf9681903d5af69399e240%2Ffigure1-light-desktop.svg%3Ffm%3Dpng%26w%3D1600" alt="How GPT-5.6 drives efficiency across the agent harness, API orchestration, and model inference" width="596" height="470"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Efficiency gains stack across the harness, orchestration, and inference: less network data, less CPU work, more useful GPU output. Diagram: OpenAI.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Sol actually scores
&lt;/h2&gt;

&lt;p&gt;The capability numbers come from independent evaluations, not just OpenAI's own:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark (independent)&lt;/th&gt;
&lt;th&gt;GPT-5.6 Sol result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Artificial Analysis Coding Agent Index&lt;/td&gt;
&lt;td&gt;80, a new state of the art (about 2.8 above Claude Fable 5), using less than half the output tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents' Last Exam&lt;/td&gt;
&lt;td&gt;53.6, beating Fable 5 by 13.1 points&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OSWorld 2.0 (computer use)&lt;/td&gt;
&lt;td&gt;62.6%, a new SOTA; beats Opus 4.8 while using 85% fewer output tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BrowseComp&lt;/td&gt;
&lt;td&gt;92.2%, a new state of the art&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why it matters for what you build
&lt;/h2&gt;

&lt;p&gt;Cost per useful task is the number that decides what you can afford to put in a&lt;br&gt;
loop. When the floor drops this fast, whole categories of "too expensive to run at&lt;br&gt;
scale" quietly become practical: high-volume classification, document analysis,&lt;br&gt;
agent steps that retry and self-check.&lt;/p&gt;

&lt;p&gt;This is the same story as last week, from the other direction. Opus 5 pulled&lt;br&gt;
frontier quality down to half the price; GPT-5.6 is pushing the cheap end down 80%.&lt;br&gt;
(I wrote up the Opus 5 side &lt;a href="https://dev.to/kbhatnagar/claude-opus-5-is-here-frontier-class-coding-at-half-the-price-3e5i"&gt;here&lt;/a&gt;.)&lt;br&gt;
Two labs, one week, same trend: the cost of intelligence is falling faster than&lt;br&gt;
most roadmaps assume.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest caveat
&lt;/h2&gt;

&lt;p&gt;Two things to keep in mind. First, those capability scores are on independent&lt;br&gt;
indexes, but the cost and speed comparisons are OpenAI's own simulations, and their&lt;br&gt;
footnote says real-world results may vary substantially. Second, Sol (the frontier&lt;br&gt;
tier) did not get cheaper: this cut is about making the smaller, faster models much&lt;br&gt;
more affordable, not the top end.&lt;/p&gt;

&lt;h2&gt;
  
  
  The quick version
&lt;/h2&gt;

&lt;p&gt;Sol (flagship), Terra (balanced), Luna (fast and cheap), all available now in&lt;br&gt;
ChatGPT, Codex, and the OpenAI API. There is also a new Fast mode for Sol: up to&lt;br&gt;
2.5x faster at twice the price, with no change in intelligence.&lt;/p&gt;

&lt;p&gt;Sources: &lt;a href="https://openai.com/index/advancing-the-price-performance-frontier-with-gpt-5-6/" rel="noopener noreferrer"&gt;OpenAI's price-performance update&lt;/a&gt;&lt;br&gt;
and &lt;a href="https://openai.com/index/gpt-5-6-frontier-intelligence-efficiency/" rel="noopener noreferrer"&gt;the engineering deep-dive&lt;/a&gt;.&lt;br&gt;
Diagram from OpenAI, shown for commentary.&lt;/p&gt;

&lt;p&gt;If a model optimizing its own serving stack becomes normal, price cuts like this&lt;br&gt;
get faster and more regular. Are you already picking models by cost per task, or&lt;br&gt;
still by raw benchmark? Curious how you are deciding.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>llm</category>
      <category>openai</category>
    </item>
    <item>
      <title>What Finishing 75 Hard Taught Me About Engineering Discipline</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Tue, 11 Aug 2026 21:49:50 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/what-finishing-75-hard-taught-me-about-engineering-discipline-4mi3</link>
      <guid>https://dev.to/kbhatnagar/what-finishing-75-hard-taught-me-about-engineering-discipline-4mi3</guid>
      <description>&lt;p&gt;I want to be upfront about what this post is and is not.&lt;/p&gt;

&lt;p&gt;It is not a tutorial. There is no code to copy. It is a field note about the one thing sitting underneath every feature any of us has ever shipped: discipline. I just finished &lt;a href="https://andyfrisella.com/pages/75hard-info" rel="noopener noreferrer"&gt;75 Hard&lt;/a&gt;, a 75 day program with five daily non-negotiables and one brutal rule, and it changed how I think about consistency at work more than any productivity system I have tried. So I sat down and mapped what those 75 days actually taught me about engineering.&lt;/p&gt;

&lt;p&gt;If you build things for a living, stay with me. The parallels are closer than they look.&lt;/p&gt;

&lt;h2&gt;
  
  
  What 75 Hard actually is
&lt;/h2&gt;

&lt;p&gt;75 Hard is not a fitness challenge. Its creator, Andy Frisella, calls it a mental toughness program, and the design makes that clear. Five tasks, every single day, for 75 days:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Daily task&lt;/th&gt;
&lt;th&gt;The catch&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Follow a structured diet&lt;/td&gt;
&lt;td&gt;Zero cheat meals, zero alcohol, no deviations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Two 45 minute workouts&lt;/td&gt;
&lt;td&gt;One must be outdoors, and they must be 3 hours apart&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Drink one gallon of water&lt;/td&gt;
&lt;td&gt;Roughly 3.8 litres, every day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Read 10 pages of non fiction&lt;/td&gt;
&lt;td&gt;Physical pages only, audiobooks do not count&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Take a progress picture&lt;/td&gt;
&lt;td&gt;Every day, no exceptions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Then the rule that makes the whole thing hard: &lt;strong&gt;miss any task, on any day, and you start over at Day 1.&lt;/strong&gt; Not the task. The whole program. A slip on Day 60 sends you back to zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why almost nobody finishes
&lt;/h2&gt;

&lt;p&gt;There is no official completion statistic for 75 Hard, and the "less than 1 percent finish" number that gets passed around online is not backed by hard data (treat it as folklore, not fact). But you do not need a statistic once you look at the structure:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Over 75 days, finishing means&lt;/th&gt;
&lt;th&gt;Total&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Workouts completed&lt;/td&gt;
&lt;td&gt;150 (2 a day, no rest days)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outdoor workouts, rain or shine&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gallons of water&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pages read&lt;/td&gt;
&lt;td&gt;750 minimum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily task check ins that must all hit&lt;/td&gt;
&lt;td&gt;375&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Misses allowed before you restart&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No rest day is the part people underestimate. One workout a day is a habit. Two workouts a day, three hours apart, with one of them outdoors regardless of weather, is a logistics problem you have to re solve every single day around work and life. And the restart rule means the difficulty is not linear. The cost of a mistake grows the further you get, because you have more to lose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The science, and where 75 Hard deliberately disagrees with it
&lt;/h2&gt;

&lt;p&gt;Here is the part that fascinated me as someone who likes systems.&lt;/p&gt;

&lt;p&gt;The best real study on how habits form is &lt;a href="https://onlinelibrary.wiley.com/doi/10.1002/ejsp.674" rel="noopener noreferrer"&gt;Lally et al., 2010&lt;/a&gt; (University College London, published in the European Journal of Social Psychology). They tracked 96 people forming a new habit and found it took a median of &lt;strong&gt;66 days&lt;/strong&gt; for a behaviour to become automatic, with a huge range (18 to 254 days depending on the person and the behaviour). The popular "21 days to a habit" line is a myth.&lt;/p&gt;

&lt;p&gt;75 Hard runs for 75 days. That is not a random number. It is comfortably past that 66 day average, which lines up with exactly what I felt: the first week was pure willpower, and somewhere in the back half the tasks stopped being a fight and started being a routine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flwb6b536pwwuyjr5wjdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flwb6b536pwwuyjr5wjdk.png" alt="The 75 Hard discipline curve: week one is willpower, automaticity rises over the program, and 75 days sits just past the ~66 day average for a habit to become automatic" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Week 1 is the wall. By the end, the hard part runs on autopilot. Habit timeline based on Lally et al., 2010.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But here is the twist. That same study found something 75 Hard flatly ignores: &lt;strong&gt;missing one opportunity did not materially affect habit formation.&lt;/strong&gt; Science says one slip does not break you. 75 Hard says one slip resets everything.&lt;/p&gt;

&lt;p&gt;So is the restart rule irrational? I do not think so, and this is the insight I took to work. The restart rule is not about biology. It is a forcing function that kills the negotiation. It removes the "just this once" conversation entirely, because the downside is total. When there is no room to compromise, you stop spending energy deciding whether to. If you have ever watched "we will fix it later" quietly become permanent tech debt, you already understand why removing the negotiation is powerful.&lt;/p&gt;

&lt;h2&gt;
  
  
  The system that got me through
&lt;/h2&gt;

&lt;p&gt;Motivation did not carry me through 75 days. A system did. I did the boring engineering thing: I removed willpower from the loop wherever I could.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I started on a Friday, on purpose.&lt;/strong&gt; My family was flying in the next morning and I already knew the weekend would be a tour of the best food in Delhi, a lot of it deep fried. Every sensible voice said start Monday. I started Friday specifically because if the discipline could survive its hardest possible test on day two, the other 73 days would feel easy. It worked. Surviving that weekend is what made the rest a formality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I made the gallon impossible to forget.&lt;/strong&gt; I bought a one gallon bottle with time markers printed down the side. No tracking app, no math, no decisions. The bottle told me if I was behind. That is just a progress bar with a deadline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I fixed the variables.&lt;/strong&gt; I ate the same clean meal on repeat so food was never a decision: 250g chicken cooked in chicken broth instead of oil, 150g broccoli, 100g bok choy, and four egg whites plus one whole egg scrambled with Greek yogurt, all cooked on water, zero oil. Boring on purpose. A decision you make once is not a decision you fight daily.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I offloaded the prep.&lt;/strong&gt; I have house help, and I will be honest about that rather than pretend I did this on hard mode. The meals were prepped while I was at the gym, so I came back to clean food ready to eat. Not everyone has that, and it genuinely lowered the difficulty. What is portable is the principle underneath it: take the highest friction, most willpower draining step and automate it out of your day. For most developers that step is not lunch, it is a script, a template, or a CI check.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How 75 days of this maps to shipping software
&lt;/h2&gt;

&lt;p&gt;This is the part I did not expect. The habits transferred.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;75 Hard&lt;/th&gt;
&lt;th&gt;The engineering equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Miss once, restart from Day 1&lt;/td&gt;
&lt;td&gt;Keep &lt;code&gt;main&lt;/code&gt; green. One red test stops the line, no "merge it anyway"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Two workouts, no rest days&lt;/td&gt;
&lt;td&gt;Consistent cadence beats heroic sprints. Ship small, ship daily&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One workout must be outdoors&lt;/td&gt;
&lt;td&gt;Step away to solve it. The bug gets fixed on the walk, not at the desk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A gallon of water, 10 pages, every day&lt;/td&gt;
&lt;td&gt;Tiny non negotiables compound: one test, one review, one paper a day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daily progress picture&lt;/td&gt;
&lt;td&gt;You cannot improve what you do not measure. Instrument everything&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The diet, the hardest rule&lt;/td&gt;
&lt;td&gt;Saying no is a skill. Scope discipline is how projects stay shippable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The throughline is the same lesson in both places: &lt;strong&gt;consistency is a system you build, not a mood you wait for.&lt;/strong&gt; The developers I admire are not the ones with the most motivation. They are the ones who made the right thing automatic so it happens on the bad days too.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest caveats
&lt;/h2&gt;

&lt;p&gt;75 Hard is rigid by design, and rigid is not the same as healthy for everyone. Two workouts a day with no rest days and a gallon of water daily is genuinely a lot, and it is worth talking to a doctor before starting rather than after. This is a reflection on discipline, not medical or fitness advice. And as I said, the house help that let me offload meal prep is a real advantage I would rather name than hide.&lt;/p&gt;

&lt;p&gt;None of that changes the core takeaway, which is the most useful thing I have relearned in a while: the work does not require you to feel like it. It requires you to build a system that shows up whether you feel like it or not.&lt;/p&gt;

&lt;p&gt;I finished on Day 75 with zero misses. The gym results were the least interesting part.&lt;/p&gt;

&lt;p&gt;If you have done 75 Hard or anything like it, I am curious: what broke first, the diet or the no rest day? And for the engineers here, what is the one "keep main green" style rule that changed how your team ships? Tell me below.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>mindset</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>How Netflix streams one video (and why it quietly uses two different networks)</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Tue, 11 Aug 2026 20:29:20 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/how-netflix-streams-one-video-and-why-it-quietly-uses-two-different-networks-af5</link>
      <guid>https://dev.to/kbhatnagar/how-netflix-streams-one-video-and-why-it-quietly-uses-two-different-networks-af5</guid>
      <description>&lt;p&gt;You press Play. A spinner spins for a beat, then the show starts. It feels like&lt;br&gt;
one thing talking to one server. It is not. In that half second your request&lt;br&gt;
touched &lt;strong&gt;two completely different networks&lt;/strong&gt;, on purpose, and the split is one of&lt;br&gt;
the cleanest system-design ideas you can steal.&lt;/p&gt;

&lt;p&gt;Here is the whole path in one loop:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fur6y4l67p80igvxp0ty1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fur6y4l67p80igvxp0ty1.gif" alt="Netflix data flow: the control plane on AWS makes the decisions, then the video bytes stream from the nearest Open Connect cache, bypassing AWS" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two planes, not one server
&lt;/h2&gt;

&lt;p&gt;Netflix splits into a &lt;strong&gt;control plane&lt;/strong&gt; and a &lt;strong&gt;data plane&lt;/strong&gt;, and they run on&lt;br&gt;
different infrastructure for a reason.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Control plane (AWS).&lt;/strong&gt; Everything that happens &lt;em&gt;before&lt;/em&gt; the picture appears:
who are you (auth and membership), what are you allowed to watch, which exact
video and audio, and which cache is closest to you. These are small, smart,
bursty requests. They run as hundreds of microservices behind an edge gateway
(Netflix open-sourced theirs as Zuul) on AWS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data plane (Open Connect).&lt;/strong&gt; The actual video bytes. Netflix built its own CDN
called Open Connect, made of servers called OCAs (Open Connect Appliances) that
sit &lt;em&gt;inside ISP networks&lt;/em&gt;, physically close to you. The heavy stream comes from
there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The punchline the GIF is built around: &lt;strong&gt;the video never streams from AWS.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The play request, step by step
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;You → AWS.&lt;/strong&gt; Hitting Play sends a small request to the control plane: verify
the account, check entitlements, pick the stream, and ask the steering service
which OCAs are nearest and healthiest for you right now.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS → you.&lt;/strong&gt; The backend replies with a ranked list of Open Connect URLs.
That is the last thing AWS does for this play. It handed you a map, not a movie.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OCA → you.&lt;/strong&gt; Your player opens a connection straight to the closest OCA and
pulls the video, adapting bitrate to your bandwidth. If one cache degrades, the
client can switch to the next URL on the list without asking AWS again.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why this split is so good
&lt;/h2&gt;

&lt;p&gt;This is not Netflix being fancy. It is separation of concerns applied to a network:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Different problems, different tools.&lt;/strong&gt; Decisions are low-bandwidth and need
elasticity and fast iteration, so they live on AWS microservices. Bytes are
enormous and need to be &lt;em&gt;near the user&lt;/em&gt;, so they live at the edge in Open Connect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Push the expensive thing to the edge.&lt;/strong&gt; Serving petabytes from a central cloud
would be slow and ruinously expensive. Caching content inside ISPs makes it fast
&lt;em&gt;and&lt;/em&gt; cheap, and it is why your stream holds up at peak hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blast radius.&lt;/strong&gt; Because the planes are independent, a wobble in the control
plane does not stop a stream already in flight. Netflix leans into this with
stateless services, horizontal scaling, and chaos testing (yes, Chaos Monkey is
real, it kills production instances on purpose).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this was the original design. Netflix ran a monolith on a single Oracle&lt;br&gt;
database until a 2008 corruption stopped DVD shipping for three days. That outage&lt;br&gt;
pushed them to AWS and microservices, and later to building Open Connect in 2012.&lt;br&gt;
The two-plane shape is what they landed on after the scaling hurt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lesson you can actually use
&lt;/h2&gt;

&lt;p&gt;Forget Netflix for a second. &lt;strong&gt;Almost every system you build has a control plane&lt;br&gt;
and a data plane hiding in it.&lt;/strong&gt; The API that decides &lt;em&gt;what&lt;/em&gt; to do versus the pipe&lt;br&gt;
that moves the heavy payload. The scheduler versus the workers. The metadata&lt;br&gt;
service versus the blob store.&lt;/p&gt;

&lt;p&gt;The highest-leverage move is usually to stop treating them as one thing: let the&lt;br&gt;
"decisions" layer stay small, smart, and elastic, and push the "heavy bytes" layer&lt;br&gt;
as close to the consumer as you can. Once you see the split, you cannot unsee it.&lt;/p&gt;

&lt;p&gt;So: in the system you work on, what is the control plane, and what is the data&lt;br&gt;
plane? And are they fighting each other because they are still glued together?&lt;br&gt;
Tell me below.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Diagram and cover made by me. Netflix name and logo belong to Netflix and are used&lt;br&gt;
here for commentary.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>architecture</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Claude Opus 5 is here: frontier-class coding at half the price</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Tue, 28 Jul 2026 21:19:34 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/claude-opus-5-is-here-frontier-class-coding-at-half-the-price-3e5i</link>
      <guid>https://dev.to/kbhatnagar/claude-opus-5-is-here-frontier-class-coding-at-half-the-price-3e5i</guid>
      <description>&lt;p&gt;Anthropic shipped Claude Opus 5 on July 24, and the number that jumps out is the&lt;br&gt;
one that hits your API bill: it gets close to Fable 5's frontier intelligence at&lt;br&gt;
half the price.&lt;/p&gt;

&lt;p&gt;If you build with LLMs, that combination (near top-tier quality, mid-tier cost) is&lt;br&gt;
the whole game. Here is what actually changed and why it matters.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Opus 5 reaches near Fable 5 quality at half the price, tops Anthropic's own coding and agent benchmarks, and is noticeably better at checking its own work. It is live now on the API as &lt;code&gt;claude-opus-5&lt;/code&gt; at $5 / $25 per million tokens.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frlymwkttm9z569u3yr8y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frlymwkttm9z569u3yr8y.png" alt="Claude Opus 5 performance scales with its effort setting" width="800" height="793"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Higher effort buys more intelligence; lower effort conserves tokens for faster, cheaper runs. Chart: Anthropic.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's new
&lt;/h2&gt;

&lt;p&gt;Anthropic reports Opus 5 as state of the art on its coding and knowledge work&lt;br&gt;
benchmarks like Frontier-Bench and GDPval-AA, while still sitting behind their&lt;br&gt;
Mythos 5 model on cybersecurity. On their own evals:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Benchmark&lt;/th&gt;
&lt;th&gt;What Anthropic reports for Opus 5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontier-Bench v0.1 (software engineering)&lt;/td&gt;
&lt;td&gt;More than doubles Opus 4.8's score, at lower cost per task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CursorBench 3.2 (coding)&lt;/td&gt;
&lt;td&gt;Within 0.5% of Fable 5's peak at max effort, at half the cost per task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ARC-AGI 3 (novel problem solving)&lt;/td&gt;
&lt;td&gt;Roughly 3x the next best model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OSWorld 2.0 (computer use)&lt;/td&gt;
&lt;td&gt;Beats every model at a given cost; matches Fable 5's best at about a third of the cost&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fif7gnokbg4k0ssapwy48.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fif7gnokbg4k0ssapwy48.png" alt="Opus 5 coding and agent benchmarks versus other models" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Coding and agent benchmarks (Frontier-Bench, CursorBench, AA Coding Agent Index). Chart: Anthropic.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pricing stays at $5 per million input tokens and $25 per million output, the same&lt;br&gt;
as Opus 4.8. It is now the default model on Claude Max and the strongest option on&lt;br&gt;
Claude Pro. On the API it is &lt;code&gt;claude-opus-5&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond code
&lt;/h2&gt;

&lt;p&gt;The same pattern holds beyond coding. On reasoning and computer use tasks,&lt;br&gt;
Anthropic shows Opus 5 leading at a given cost too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs2qmf5p3j1yrlgcrnfep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs2qmf5p3j1yrlgcrnfep.png" alt="Opus 5 on knowledge work and problem-solving benchmarks" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Knowledge work and reasoning: ARC-AGI 3, GDPval-AA, OSWorld 2.0, HLE, AutomationBench, DeepSearchQA. Chart: Anthropic.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that caught my attention
&lt;/h2&gt;

&lt;p&gt;Benchmarks are benchmarks. The examples of the model's judgment are more&lt;br&gt;
interesting, because they are about agents that finish work instead of stalling:&lt;/p&gt;

&lt;p&gt;🔹 Given a drawing of a machine part with no way to actually see the image, Opus 5 wrote its own computer vision pipeline to pull the geometry from raw pixels, then rebuilt the part in FreeCAD. Anthropic says no competing model solved it in five attempts.&lt;br&gt;
🔹 Handed a real bug in a popular open source package manager, it found the root cause and fixed an edge case the community's own patch had missed. A competing model patched only the symptom and declared it done.&lt;br&gt;
🔹 An engineer built a market data feed for a new exchange in one session. With no live feed to test against, Opus 5 wrote its own test harness to validate the parsing.&lt;/p&gt;

&lt;p&gt;That is the shift: less "generate code and hope", more "verify, iterate, and check&lt;br&gt;
its own work before handing it back".&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters if you build with this
&lt;/h2&gt;

&lt;p&gt;Cost per useful task is dropping fast. Near-frontier quality at half the price&lt;br&gt;
changes what you can afford to run in a loop, which is exactly what long-running&lt;br&gt;
agents need. If you were priced out of putting a strong model in an autonomous&lt;br&gt;
pipeline, that math just moved.&lt;/p&gt;

&lt;p&gt;One honest caveat: these are Anthropic's own reported numbers on their own harness.&lt;br&gt;
Treat them as a strong signal, not gospel, until independent results land. And if&lt;br&gt;
your work touches offensive security, note that it stays intentionally behind&lt;br&gt;
Mythos 5 there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkbrxmo665rxanils8vdl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkbrxmo665rxanils8vdl.png" alt="Opus 5 versus Mythos 5 on the OSS-Fuzz cybersecurity benchmark" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;On OSS-Fuzz, Opus 5 finds vulnerabilities nearly as well as Mythos 5 (left) but is far behind on writing exploits (right), by design. Chart: Anthropic.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Opus 5 is live today on all platforms and on the API as &lt;code&gt;claude-opus-5&lt;/code&gt;, at&lt;br&gt;
$5 / $25 per million tokens. There is also a Fast mode at roughly 2.5x speed, plus&lt;br&gt;
two beta additions: mid conversation tool changes without invalidating the prompt&lt;br&gt;
cache, and automatic model fallbacks on the API.&lt;/p&gt;

&lt;p&gt;All charts above are from Anthropic's official announcement, shown here for&lt;br&gt;
commentary and reporting. Source: &lt;a href="https://www.anthropic.com/news/claude-opus-5" rel="noopener noreferrer"&gt;Introducing Claude Opus 5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have tried it: is the "it checks its own work" behavior holding up in your&lt;br&gt;
real projects, or still hit and miss? Curious what people are seeing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>llm</category>
      <category>agents</category>
    </item>
    <item>
      <title>How to Run DeepSeek R1 Locally (Using Ollama + ChatboxAI)</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Thu, 20 Feb 2025 02:09:58 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/how-to-run-deepseek-r1-locally-using-ollama-chatboxai-4po9</link>
      <guid>https://dev.to/kbhatnagar/how-to-run-deepseek-r1-locally-using-ollama-chatboxai-4po9</guid>
      <description>&lt;p&gt;If you want to run &lt;strong&gt;DeepSeek R1&lt;/strong&gt; locally on your system, there's no need to worry. This guide is written in a simple and easy-to-follow manner, explaining step-by-step how to use &lt;strong&gt;Ollama&lt;/strong&gt; and &lt;strong&gt;ChatboxAI&lt;/strong&gt; to get it running.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🖥️ System Requirements (Based on GPU/RAM)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Each model has different hardware requirements, so first, check which model your system can support:  &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;GPU Required&lt;/th&gt;
&lt;th&gt;VRAM (GPU Memory)&lt;/th&gt;
&lt;th&gt;RAM (System Memory)&lt;/th&gt;
&lt;th&gt;Storage (ROM)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DeepSeek R1 1.5B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No GPU / Integrated GPU&lt;/td&gt;
&lt;td&gt;4GB+&lt;/td&gt;
&lt;td&gt;8GB+&lt;/td&gt;
&lt;td&gt;10GB+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DeepSeek R1 7B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GTX 1650 / RTX 3050&lt;/td&gt;
&lt;td&gt;6GB+&lt;/td&gt;
&lt;td&gt;16GB+&lt;/td&gt;
&lt;td&gt;30GB+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DeepSeek R1 14B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RTX 3060 / RTX 4060&lt;/td&gt;
&lt;td&gt;12GB+&lt;/td&gt;
&lt;td&gt;32GB+&lt;/td&gt;
&lt;td&gt;60GB+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DeepSeek R1 33B&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RTX 4090 / A100&lt;/td&gt;
&lt;td&gt;24GB+&lt;/td&gt;
&lt;td&gt;64GB+&lt;/td&gt;
&lt;td&gt;100GB+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;👉 If your system has &lt;strong&gt;GTX 1650 or lower&lt;/strong&gt;, you can only run &lt;strong&gt;DeepSeek R1 1.5B or at most 7B&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;👉 &lt;strong&gt;For 7B, at least 16GB RAM&lt;/strong&gt; is required.
&lt;/li&gt;
&lt;li&gt;👉 If you have a &lt;strong&gt;GPU lower than GTX 1650 (or an integrated GPU)&lt;/strong&gt;, only use &lt;strong&gt;1.5B&lt;/strong&gt; to avoid crashes.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;⚙️ Step-by-Step Installation Guide&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1️⃣ Install Ollama (Base for Llama Models)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ollama is a lightweight tool that helps run &lt;strong&gt;LLMs (Large Language Models) locally&lt;/strong&gt;. Install it first:  &lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama Installation Link&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;👉 For Windows Users:&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Download the installer and install it (just click &lt;em&gt;Next-Next&lt;/em&gt;).
&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;CMD&lt;/strong&gt; and check by running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  ollama run llama2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this command runs successfully, the installation is complete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👉 For Mac Users:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Open Terminal and run:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -fsSL https://ollama.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2️⃣ Download the DeepSeek R1 Model&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use the following command to pull the model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ollama pull deepseek-ai/deepseek-coder:7b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;- 👉 If you want to run 1.5B instead of 7B, use:&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;ollama pull deepseek-ai/deepseek-coder:1.5b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠ This download may take some time depending on your internet speed. Once downloaded, you can run it using Ollama.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3️⃣ Install ChatboxAI (Optional GUI for Better Experience)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you want a Graphical User Interface (GUI), ChatboxAI is the best tool to interact with local AI models.&lt;/p&gt;

&lt;p&gt;🔗 ChatboxAI Installation Link&lt;/p&gt;

&lt;p&gt;Installation Steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Ensure Python 3.10+ is installed.&lt;/li&gt;
&lt;li&gt;
Open Command Prompt (CMD) and run:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/oobabooga/text-generation-webui.git
cd text-generation-webui
pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
Start the server:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python server.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
Open your browser and go to localhost:7860, then select your model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🚀 Running DeepSeek R1 (Final Step)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once everything is installed, it’s time to run the model:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;👉 Open CMD and run:&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;ollama run deepseek-ai/deepseek-coder:7b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;👉 If 7B is not running, try with 1.5B:&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;ollama run deepseek-ai/deepseek-coder:1.5b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;👉 If you are using ChatboxAI, just open the browser and interact with the model through the GUI.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now you can use DeepSeek R1 for coding, AI chat, and optimizing your workflow! 😎🔥&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛠️ Common Problems &amp;amp; Solutions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;❌ 1️⃣ Model crashes due to low VRAM?&lt;br&gt;
✔ Try 1.5B instead of 7B.&lt;br&gt;
✔ Increase Windows Pagefile (Virtual Memory settings).&lt;/p&gt;

&lt;p&gt;❌ 2️⃣ Model response is too slow?&lt;br&gt;
✔ Use SSD instead of HDD.&lt;br&gt;
✔ Close background applications.&lt;br&gt;
✔ Optimize RAM usage.&lt;/p&gt;

&lt;p&gt;❌ 3️⃣ ‘Command not found’ error in CMD?&lt;br&gt;
✔ Check if Ollama is installed correctly.&lt;br&gt;
✔ Ensure Python and dependencies are installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;🤩 Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you followed this guide correctly, you can now run DeepSeek R1 locally without relying on third-party APIs. This is a privacy-friendly and cost-effective solution, perfect for developers and freelancers.&lt;/p&gt;

&lt;p&gt;If you face any issues, drop a comment, and you’ll get help! 🚀🔥&lt;/p&gt;

</description>
      <category>deepseek</category>
      <category>ai</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Manage Multiple GitHub Accounts with SSH Keys</title>
      <dc:creator>kshitij Bhatnagar</dc:creator>
      <pubDate>Wed, 21 Aug 2024 23:51:03 +0000</pubDate>
      <link>https://dev.to/kbhatnagar/managing-multiple-github-accounts-with-ssh-keys-4a9b</link>
      <guid>https://dev.to/kbhatnagar/managing-multiple-github-accounts-with-ssh-keys-4a9b</guid>
      <description>&lt;p&gt;In today's dynamic development environment, it's common to juggle multiple GitHub accounts—whether for work, personal projects, or open-source contributions. However, seamlessly switching between your office and personal GitHub profiles can be challenging if not properly managed. This guide will walk you through the best practices and essential steps to effortlessly handle multiple GitHub accounts, ensuring that your workflows remain smooth and your code stays organized, no matter which account you’re using. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Generate SSH Keys
&lt;/h3&gt;

&lt;p&gt;Generate separate SSH keys for your office and personal GitHub accounts.&lt;/p&gt;

&lt;h4&gt;
  
  
  Office Account:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen -t rsa -b 4096 -C "your_office_email@example.com" -f ~/.ssh/id_rsa_office
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Personal Account:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen -t rsa -b 4096 -C "your_personal_email@example.com" -f ~/.ssh/id_rsa_personal_account
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Add SSH Keys to GitHub
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Office Account:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; Copy the public key to your clipboard:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    cat ~/.ssh/id_rsa_office.pub

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; Go to GitHub (office account) -&amp;gt; Settings -&amp;gt; SSH and GPG keys -&amp;gt; New SSH key.&lt;/li&gt;
&lt;li&gt; Paste the public key and save.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Personal Account:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; Copy the public key to your clipboard:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    cat ~/.ssh/id_rsa_personal_account.pub

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt; Go to GitHub (personal account) -&amp;gt; Settings -&amp;gt; SSH and GPG keys -&amp;gt; New SSH key.&lt;/li&gt;
&lt;li&gt; Paste the public key and save.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Configure SSH Agent
&lt;/h3&gt;

&lt;p&gt;Start the SSH agent and add your keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa_office
ssh-add ~/.ssh/id_rsa_personal_account
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Configure&amp;nbsp;&lt;code&gt;~/.ssh/config&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Edit your&amp;nbsp;&lt;code&gt;~/.ssh/config&lt;/code&gt;&amp;nbsp;file to define aliases for your office and personal GitHub accounts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#### Configuration for office account
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_office
    IdentitiesOnly yes

#### Configuration for personal account
Host github.com-personal-account
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_personal_account
    IdentitiesOnly yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Clone Repositories
&lt;/h3&gt;

&lt;p&gt;Clone repositories using the appropriate alias to ensure the correct SSH key is used.&lt;/p&gt;

&lt;h4&gt;
  
  
  Office Repository:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:organization/repository.git

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Personal Repository:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com-personal-account:username/repository.git

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Verify Remote URLs
&lt;/h3&gt;

&lt;p&gt;Check the remote URLs to ensure they are set correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git remote -v

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This should show URLs that match the aliases defined in your&amp;nbsp;&lt;code&gt;~/.ssh/config&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Push and Pull Changes
&lt;/h3&gt;

&lt;p&gt;When pushing or pulling changes, Git will automatically use the correct SSH key based on the repository URL.&lt;/p&gt;

&lt;h4&gt;
  
  
  Push Changes:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git push origin main

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Pull Changes:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git pull origin main

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Summary of the steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; Generate SSH Keys: Create separate SSH keys for your office and personal GitHub accounts.&lt;/li&gt;
&lt;li&gt; Add SSH Keys to GitHub: Add the public keys to the respective GitHub accounts.&lt;/li&gt;
&lt;li&gt; Configure SSH Agent: Start the SSH agent and add the generated keys.&lt;/li&gt;
&lt;li&gt; Edit&amp;nbsp;&lt;code&gt;~/.ssh/config&lt;/code&gt;: Define aliases for your office and personal accounts, specifying the correct&amp;nbsp;&lt;code&gt;IdentityFile&lt;/code&gt;&amp;nbsp;for each.&lt;/li&gt;
&lt;li&gt; Clone Repositories: Use the appropriate alias in the repository URL to ensure the correct key is used.&lt;/li&gt;
&lt;li&gt; Verify Remote URLs: Ensure the remote URLs are set correctly to match the aliases.&lt;/li&gt;
&lt;li&gt; Push and Pull Changes: Git will use the correct SSH key based on the repository URL.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By following these steps, you can seamlessly manage multiple GitHub accounts with different SSH keys, ensuring the correct key is used for each repository.&lt;/p&gt;

&lt;p&gt;The best part is that after configuring your &lt;code&gt;~/.ssh/config&lt;/code&gt; file and carefully cloning repositories using the correct aliases, you won’t need to worry about managing the SSH agent during push and pull operations. Git will automatically select the appropriate SSH key based on the repository's URL, making your workflow seamless and hassle-free.&lt;/p&gt;

</description>
      <category>git</category>
      <category>learning</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
