<?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: Anup Karanjkar</title>
    <description>The latest articles on DEV Community by Anup Karanjkar (@akaranjkar08).</description>
    <link>https://dev.to/akaranjkar08</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%2F235395%2Fca502edd-b701-43c6-8324-7b07fefe0f24.jpg</url>
      <title>DEV Community: Anup Karanjkar</title>
      <link>https://dev.to/akaranjkar08</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akaranjkar08"/>
    <language>en</language>
    <item>
      <title>JSON-LD Rich Results 2026: What Google Still Shows</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Wed, 11 Nov 2026 04:36:16 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/json-ld-rich-results-2026-what-google-still-shows-3519</link>
      <guid>https://dev.to/akaranjkar08/json-ld-rich-results-2026-what-google-still-shows-3519</guid>
      <description>&lt;p&gt;&lt;strong&gt;As of November 10, 2026, Google no longer shows FAQ rich results for any site.&lt;/strong&gt; The feature stopped appearing on May 7, 2026, per Google's &lt;a href="https://developers.google.com/search/updates#faq-deprecation" rel="noopener noreferrer"&gt;Search Central documentation changelog&lt;/a&gt;, and Google removed the FAQ docs on June 15, 2026. It is the latest cut in a cleanup that started with HowTo in 2023, took out the sitelinks search box in 2024, and cut six more types in 2025 (Google announced seven, then kept Book actions in a limited form). What still works is the list on Google's &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/search-gallery" rel="noopener noreferrer"&gt;structured data search gallery&lt;/a&gt;: Article, Product, Review snippet, Breadcrumb, Organization, Local business, Video, Event, Recipe, Job posting, Software app and a handful of others. Below: a status table with dates and sources for every type, minimal JSON-LD for the five types most sites need, and a testing workflow that won't send you chasing a feature Google has already removed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How we checked:&lt;/strong&gt; the WOWHOW team read Google's search gallery, the Search Central changelog, the relevant Search Central blog posts and each feature's documentation page on November 10, 2026. Every status below links to the Google page it comes from. Where Google's own wording is narrower than "shown" or "retired", the table says so.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Retired: FAQ (May 7, 2026), HowTo (September 13, 2023), sitelinks search box (November 21, 2024), Course info, Estimated salary, Learning video, Special announcement, Vehicle listing, ClaimReview (phased out in 2025) and Practice problem (docs removed January 6, 2026).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Limited: Breadcrumbs show on desktop only, Book actions is restricted to large book providers, Dataset markup feeds Dataset Search rather than Google Search, and Event results require a physical venue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Still documented: Article, Product (snippets and merchant listings), Review snippet, Organization, Local business, Video, Recipe, Job posting, Software app, Q&amp;amp;A, Discussion forum, Profile page, Education Q&amp;amp;A, Math solver, Carousel, Employer aggregate rating, Subscription and paywalled content and more.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Valid markup makes a page eligible. Google states plainly that it does not guarantee a rich result.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rich result status in November 2026
&lt;/h2&gt;

&lt;p&gt;The table sorts every type we could pin to a Google source. "Still shown" means the type sits in the current search gallery with a live documentation page. Dates are when the change took effect or, where Google gave no effective date, when it was announced.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rich result type&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Google source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Article | Still shown | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/article" rel="noopener noreferrer"&gt;Article docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Product (product snippet, merchant listing) | Still shown | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/product" rel="noopener noreferrer"&gt;Product docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Review snippet | Still shown, no self-serving reviews for LocalBusiness or Organization | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/review-snippet" rel="noopener noreferrer"&gt;Review snippet docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Organization | Still shown | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/organization" rel="noopener noreferrer"&gt;Organization docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Local business | Still shown | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/local-business" rel="noopener noreferrer"&gt;Local business docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Video | Still shown | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/video" rel="noopener noreferrer"&gt;Video docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Recipe, Job posting, Software app | Still shown | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/search-gallery" rel="noopener noreferrer"&gt;Search gallery&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Q&amp;amp;A, Discussion forum | Still shown | Properties expanded March 24, 2026 | &lt;a href="https://developers.google.com/search/updates" rel="noopener noreferrer"&gt;Changelog&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Profile page | Still shown | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/profile-page" rel="noopener noreferrer"&gt;Profile page docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Carousel (ItemList) | Still shown, only combined with Course list, Movie, Recipe or Restaurant markup | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/carousel" rel="noopener noreferrer"&gt;Carousel docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Employer aggregate rating | Still shown, in Google's job search experience | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/employer-rating" rel="noopener noreferrer"&gt;Employer rating docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Subscription and paywalled content | Still documented: tells Google content is paywalled, not cloaked | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/paywalled-content" rel="noopener noreferrer"&gt;Paywalled content docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Education Q&amp;amp;A, Math solver, Course list, Movie, Vacation rental, Image metadata | Still shown | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/search-gallery" rel="noopener noreferrer"&gt;Search gallery&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Breadcrumb | Limited: desktop only | January 23, 2025 | &lt;a href="https://developers.google.com/search/blog/2025/01/simplifying-breadcrumbs" rel="noopener noreferrer"&gt;Search Central blog&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Event | Limited: physical venues only | June 5, 2025 | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/event" rel="noopener noreferrer"&gt;Event docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Speakable | Limited: US, English, Google Home devices | Current | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/speakable" rel="noopener noreferrer"&gt;Speakable docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Book actions | Limited: large book providers only | Kept November 5, 2025 | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/book" rel="noopener noreferrer"&gt;Book actions docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Dataset | Dataset Search only, not Google Search | November 5, 2025 | &lt;a href="https://developers.google.com/search/updates" rel="noopener noreferrer"&gt;Changelog&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| FAQ | Retired | May 7, 2026 | &lt;a href="https://developers.google.com/search/updates#faq-deprecation" rel="noopener noreferrer"&gt;Changelog&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Practice problem | Retired | Docs removed January 6, 2026 | &lt;a href="https://developers.google.com/search/blog/2025/11/update-on-our-efforts" rel="noopener noreferrer"&gt;Search Central blog&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Course info, Estimated salary, Learning video, Special announcement, Vehicle listing | Retired | Announced June 12, 2025; docs removed September 9, 2025 | &lt;a href="https://developers.google.com/search/blog/2025/06/simplifying-search-results" rel="noopener noreferrer"&gt;Search Central blog&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| ClaimReview (fact check) | Retired from Search; still read by Fact Check Explorer | Announced June 12, 2025 | &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/factcheck" rel="noopener noreferrer"&gt;Fact check docs&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| Sitelinks search box | Retired | November 21, 2024 | &lt;a href="https://developers.google.com/search/blog/2024/10/sitelinks-search-box" rel="noopener noreferrer"&gt;Search Central blog&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;| HowTo | Retired | September 13, 2023 | &lt;a href="https://developers.google.com/search/blog/2023/08/howto-faq-changes" rel="noopener noreferrer"&gt;Search Central blog&lt;/a&gt; |&lt;/p&gt;

&lt;p&gt;Google's 2023, 2024 and June 2025 retirement posts each say the change does not affect ranking. The June 2025 announcement put it as "This update won't affect how pages are ranked." Losing a rich result changes how a listing looks, not where it sits.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happened to FAQ rich results
&lt;/h2&gt;

&lt;p&gt;FAQ went in two steps. On August 8, 2023, Google &lt;a href="https://developers.google.com/search/blog/2023/08/howto-faq-changes" rel="noopener noreferrer"&gt;limited FAQ rich results&lt;/a&gt; to "well-known, authoritative government and health websites." For everyone else the accordion under the blue link disappeared that week. That restriction no longer matters: on May 8, 2026 Google added a deprecation notice saying the feature "will no longer appear in Google Search starting May 7, 2026," and on June 15, 2026 it removed the documentation entirely. Government and health sites lost it too.&lt;/p&gt;

&lt;p&gt;You don't have to strip &lt;code&gt;FAQPage&lt;/code&gt; markup out of your templates. Google's 2023 post said "there's no need to proactively remove it" because "structured data that's not being used does not cause problems for Search." The sitelinks search box post made the same point about unsupported markup: it "won't cause issues in Search, and won't trigger errors in Search Console reports." Remove it when you next touch the template, to keep your HTML lean. Don't schedule a sprint for it.&lt;/p&gt;

&lt;p&gt;The visible FAQ section on the page is a separate question. It can still answer a reader's follow-up, and it still gives Google plain text to work with. Keep the content; just stop expecting a rich result from the markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimal JSON-LD for the types most sites need
&lt;/h2&gt;

&lt;p&gt;Google recommends JSON-LD "if your site's setup allows it," per its &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data" rel="noopener noreferrer"&gt;intro to structured data&lt;/a&gt;. Each example below is the smallest block that meets the required properties on the linked Google page. Swap in your own values, and make sure the markup describes content a visitor can actually see on the page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Article or BlogPosting
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/article" rel="noopener noreferrer"&gt;Article docs&lt;/a&gt; say: "There are no required properties; instead, add the properties that apply to your content." These five are the ones most templates can fill reliably.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"BlogPosting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"headline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"How to Replace a Bike Chain"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/photos/chain-1x1.jpg"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"datePublished"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2026-11-10T08:00:00-05:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"dateModified"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"2026-11-10T08:00:00-05:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Example Cycles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://example.com/about"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  BreadcrumbList
&lt;/h3&gt;

&lt;p&gt;The only required property is &lt;code&gt;itemListElement&lt;/code&gt;, an ordered list of &lt;code&gt;ListItem&lt;/code&gt; entries, per the &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/breadcrumb" rel="noopener noreferrer"&gt;breadcrumb docs&lt;/a&gt;. Expect it on desktop results only.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"BreadcrumbList"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"itemListElement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ListItem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Guides"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"item"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://example.com/guides"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ListItem"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"position"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Repairs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"item"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://example.com/guides/repairs"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Product (product snippet)
&lt;/h3&gt;

&lt;p&gt;Product snippets need a &lt;code&gt;name&lt;/code&gt; plus at least one of &lt;code&gt;review&lt;/code&gt;, &lt;code&gt;aggregateRating&lt;/code&gt; or &lt;code&gt;offers&lt;/code&gt;, per the &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/product-snippet" rel="noopener noreferrer"&gt;product snippet docs&lt;/a&gt;. Stores that want merchant listing features should follow the stricter &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/merchant-listing" rel="noopener noreferrer"&gt;merchant listing requirements&lt;/a&gt; instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Product"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Trail Pro Bike Chain, 12-speed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://example.com/photos/trail-pro-chain.jpg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"offers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;39.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"priceCurrency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;"availability"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://schema.org/InStock"&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;h3&gt;
  
  
  Organization
&lt;/h3&gt;

&lt;p&gt;No required properties here either, per the &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/organization" rel="noopener noreferrer"&gt;Organization docs&lt;/a&gt;. Put it on your home page or About page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Organization"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Example Cycles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"logo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://example.com/logo-512.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"sameAs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"https://www.linkedin.com/company/example-cycles"&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;h3&gt;
  
  
  SoftwareApplication
&lt;/h3&gt;

&lt;p&gt;Required: &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;offers.price&lt;/code&gt; (use 0 for a free app) and either &lt;code&gt;aggregateRating&lt;/code&gt; or &lt;code&gt;review&lt;/code&gt;, per the &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/software-app" rel="noopener noreferrer"&gt;software app docs&lt;/a&gt;. The rating has to come from real reviews shown on the page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"SoftwareApplication"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Example Route Planner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"operatingSystem"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Android"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"applicationCategory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"TravelApplication"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"offers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"Offer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;"aggregateRating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"AggregateRating"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"ratingValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;"ratingCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;812&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;Wrap any of these in &lt;code&gt;&amp;lt;script type="application/ld+json"&amp;gt;&lt;/code&gt;. Our free &lt;a href="https://dev.to/tools/schema-generator"&gt;schema markup generator&lt;/a&gt; builds Article, Product, Organization, BreadcrumbList, LocalBusiness, Event, Recipe and VideoObject blocks with a form and a one-click Rich Results Test link. It also still offers FAQPage and HowTo, which are valid schema.org but no longer produce Google rich results.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to test without chasing dead features
&lt;/h2&gt;

&lt;p&gt;Each tool answers a different question, so use them in this order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://search.google.com/test/rich-results" rel="noopener noreferrer"&gt;Rich Results Test&lt;/a&gt;&lt;/strong&gt; tells you which Google rich result types a URL or code snippet is eligible for. Google removes retired types from it: when Course info, ClaimReview and four others went, Google said they "will be removed from Search Console rich result reporting, the Rich Result Test, and the list of Search appearance filters." A retired type simply stops appearing in the test.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://validator.schema.org/" rel="noopener noreferrer"&gt;Schema Markup Validator&lt;/a&gt;&lt;/strong&gt; checks "syntax and compliance of markup with schema.org standards," in Google's &lt;a href="https://developers.google.com/search/blog/2020/12/structured-data-testing-tool-update" rel="noopener noreferrer"&gt;description&lt;/a&gt;. It does not check Google rich result types. Use it for types Google doesn't consume, or to catch a misspelled property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Search Console rich result reports&lt;/strong&gt; show errors and warnings for indexed pages, grouped by type. Google's docs suggest deploying a few pages first, checking them with the URL Inspection tool, then watching the relevant rich result status report after indexing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Search Console Performance report&lt;/strong&gt;, filtered by search appearance, is where you see whether a rich result actually earned impressions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then check the rest of the listing. Your title and meta description still do most of the work in a plain result, so preview them with the &lt;a href="https://dev.to/tools/meta-tags-previewer"&gt;meta tags previewer&lt;/a&gt;. Our &lt;a href="https://dev.to/blogs/meta-tags-seo-guide-developers-2026"&gt;developer guide to meta tags&lt;/a&gt; covers the tags that matter next to your JSON-LD.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eligible is not the same as shown
&lt;/h2&gt;

&lt;p&gt;Google's &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/sd-policies" rel="noopener noreferrer"&gt;structured data policies&lt;/a&gt; say it directly: "Google does not guarantee that your structured data will show up in search results, even if your page is marked up correctly according to the Rich Results Test." A clean test result means you passed the entry check. Whether the rich result appears for a given query depends on Google. Treat markup as a prerequisite and measure what happens in Search Console instead of assuming it.&lt;/p&gt;

&lt;p&gt;The same page lists common reasons markup gets ignored, including "The content referred to by the structured data is hidden from the user" and markup that "is not representative of the main content of the page." Reviews have their own trap. Self-serving reviews are spelled out in the &lt;a href="https://developers.google.com/search/docs/appearance/structured-data/review-snippet" rel="noopener noreferrer"&gt;review snippet docs&lt;/a&gt;: LocalBusiness and Organization reviews only count from sites that review other businesses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do FAQ rich results still work in 2026?
&lt;/h3&gt;

&lt;p&gt;No. Google stopped showing FAQ rich results on May 7, 2026 and removed the documentation on June 15, 2026. The 2023 exception for government and health sites ended with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Will leftover FAQPage or HowTo markup hurt my rankings?
&lt;/h3&gt;

&lt;p&gt;No. Google has said unused structured data does not cause problems for Search, and its HowTo, sitelinks search box and June 2025 retirement posts all say the change does not affect ranking. You can remove it whenever it suits you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which rich result types should a typical business site use?
&lt;/h3&gt;

&lt;p&gt;Organization on the home page, BreadcrumbList on deep pages, Article or BlogPosting on posts, and Product, LocalBusiness, Event or SoftwareApplication where the page really is one of those things.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is JSON-LD better than Microdata for Google?
&lt;/h3&gt;

&lt;p&gt;Google says all three formats are equally fine when valid, but recommends JSON-LD because it is easiest to implement and maintain at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why doesn't my valid markup show a rich result?
&lt;/h3&gt;

&lt;p&gt;Valid markup only makes a page eligible. Google does not guarantee display, and it skips markup that breaks its policies, such as markup describing hidden content or self-serving reviews.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do breadcrumbs still appear on mobile?
&lt;/h3&gt;

&lt;h2&gt;
  
  
  No. Since January 23, 2025, Google shows breadcrumbs in the visible URL on desktop only. Mobile results show the domain. Breadcrumb markup is still supported.
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/json-ld-rich-results-2026-which-still-work" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>jsonldrich</category>
      <category>whichrich</category>
      <category>googlerich</category>
      <category>faqrich</category>
    </item>
    <item>
      <title>Docker Run to Compose: Flag Conversion Guide (2026)</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Wed, 11 Nov 2026 04:19:06 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/docker-run-to-compose-flag-conversion-guide-2026-4ioo</link>
      <guid>https://dev.to/akaranjkar08/docker-run-to-compose-flag-conversion-guide-2026-4ioo</guid>
      <description>&lt;p&gt;&lt;strong&gt;There is no 1:1 mapping from &lt;code&gt;docker run&lt;/code&gt; flags to Compose service keys.&lt;/strong&gt; Some flags map cleanly (&lt;code&gt;-p&lt;/code&gt; → &lt;code&gt;ports&lt;/code&gt;, &lt;code&gt;-e&lt;/code&gt; → &lt;code&gt;environment&lt;/code&gt;). Some map to a key that looks right but behaves differently (&lt;code&gt;--restart&lt;/code&gt; is not &lt;code&gt;deploy.restart_policy&lt;/code&gt;). And some have no Compose equivalent at all because the behavior belongs to the CLI invocation, not the service definition (&lt;code&gt;--rm&lt;/code&gt;, &lt;code&gt;-d&lt;/code&gt;, &lt;code&gt;-it&lt;/code&gt;). This guide maps 31 flags a typical &lt;code&gt;docker run&lt;/code&gt; command might use, cites &lt;a href="https://docs.docker.com/reference/cli/docker/container/run/" rel="noopener noreferrer"&gt;Docker's own CLI reference&lt;/a&gt; and the &lt;a href="https://docs.docker.com/reference/compose-file/services/" rel="noopener noreferrer"&gt;Compose Specification&lt;/a&gt; for every claim, and runs real commands through our free &lt;a href="https://dev.to/tools/docker-run-to-compose"&gt;Docker Run to Compose converter&lt;/a&gt; to show what it actually outputs today — including three parsing bugs we found while writing this.&lt;/p&gt;

&lt;p&gt;Use the method below if you want to convert by hand, use the &lt;a href="https://dev.to/tools/docker-run-to-compose"&gt;converter&lt;/a&gt; for anything with the flags it supports, and read the "what the converter gets wrong" section before you trust its output on a command with &lt;code&gt;--rm&lt;/code&gt;, &lt;code&gt;-it&lt;/code&gt;, or &lt;code&gt;--privileged&lt;/code&gt; sitting right before the image name.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to convert a docker run command to Compose
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Split the command into one flag (or flag pair) at a time — do not try to convert the whole line in your head.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Look up each flag in the reference table below to find its Compose service key, or confirm it has none.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For anything with no listed key (&lt;code&gt;--rm&lt;/code&gt;, &lt;code&gt;-d&lt;/code&gt;, &lt;code&gt;-it&lt;/code&gt;, &lt;code&gt;--pull&lt;/code&gt;), decide whether the behavior belongs in &lt;code&gt;docker compose run&lt;/code&gt;/&lt;code&gt;up&lt;/code&gt; flags instead of the YAML.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste the result into the &lt;a href="https://dev.to/tools/docker-run-to-compose"&gt;converter&lt;/a&gt; to catch formatting mistakes, then diff it against your hand conversion with the &lt;a href="https://dev.to/tools/diff-checker"&gt;diff checker&lt;/a&gt; if the two disagree.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The full flag-to-Compose-key reference
&lt;/h2&gt;

&lt;p&gt;Compose key names and defaults below are quoted from the &lt;a href="https://docs.docker.com/reference/compose-file/services/" rel="noopener noreferrer"&gt;Compose Specification services reference&lt;/a&gt; unless noted otherwise.[2] CLI flag defaults are from the &lt;a href="https://docs.docker.com/reference/cli/docker/container/run/" rel="noopener noreferrer"&gt;docker container run reference&lt;/a&gt;.[1]&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;docker run flag&lt;/th&gt;
&lt;th&gt;Compose key&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| &lt;code&gt;-p&lt;/code&gt;, &lt;code&gt;--publish&lt;/code&gt; | &lt;code&gt;ports&lt;/code&gt; | Short form &lt;code&gt;[HOST:]CONTAINER[/PROTOCOL]&lt;/code&gt;. No host IP means it binds &lt;code&gt;0.0.0.0&lt;/code&gt; — reachable from outside, in both the flag and the key. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;-v&lt;/code&gt;, &lt;code&gt;--volume&lt;/code&gt; | &lt;code&gt;volumes&lt;/code&gt; (short form) | Same syntax both places. A missing host directory is created automatically by both the CLI and Compose's short/long bind syntax. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--mount&lt;/code&gt; | &lt;code&gt;volumes&lt;/code&gt; (long form, &lt;code&gt;type: bind&lt;/code&gt;) | Different defaults — see "Short volumes vs. &lt;code&gt;--mount&lt;/code&gt;" below. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;-e&lt;/code&gt;, &lt;code&gt;--env&lt;/code&gt; | &lt;code&gt;environment&lt;/code&gt; | Map or array form. &lt;code&gt;-e NAME&lt;/code&gt; with no &lt;code&gt;=&lt;/code&gt; copies the value from your shell at runtime — Compose resolves it the same way, and unsets it if the variable isn't exported. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--env-file&lt;/code&gt; | &lt;code&gt;env_file&lt;/code&gt; | Compose processes multiple files top-down (last one wins) and defaults &lt;code&gt;required: true&lt;/code&gt; — a missing file is an error unless you set &lt;code&gt;required: false&lt;/code&gt;. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--name&lt;/code&gt; | &lt;code&gt;container_name&lt;/code&gt; | Must match &lt;code&gt;[a-zA-Z0-9][a-zA-Z0-9_.-]+&lt;/code&gt;. Setting it stops Compose from scaling that service past one container. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--restart&lt;/code&gt; | &lt;code&gt;restart&lt;/code&gt; | Same four values as the CLI (&lt;code&gt;no&lt;/code&gt;, &lt;code&gt;always&lt;/code&gt;, &lt;code&gt;on-failure[:max-retries]&lt;/code&gt;, &lt;code&gt;unless-stopped&lt;/code&gt;). Not the same key as &lt;code&gt;deploy.restart_policy&lt;/code&gt; — see below. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--network&lt;/code&gt;, &lt;code&gt;--net&lt;/code&gt; | &lt;code&gt;networks&lt;/code&gt; | A service with no &lt;code&gt;networks:&lt;/code&gt; joins the implicit &lt;code&gt;default&lt;/code&gt; network instead of none. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--network-alias&lt;/code&gt; | &lt;code&gt;networks.&amp;lt;name&amp;gt;.aliases&lt;/code&gt; | Nested under the network entry, not a top-level key. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;-u&lt;/code&gt;, &lt;code&gt;--user&lt;/code&gt; | &lt;code&gt;user&lt;/code&gt; | Same &lt;code&gt;name|uid[:group|gid]&lt;/code&gt; format. Defaults to the image's user (commonly &lt;code&gt;root&lt;/code&gt;) if unset. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;-w&lt;/code&gt;, &lt;code&gt;--workdir&lt;/code&gt; | &lt;code&gt;working_dir&lt;/code&gt; | Creates the directory inside the container if the image doesn't already have it. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--entrypoint&lt;/code&gt; | &lt;code&gt;entrypoint&lt;/code&gt; | A non-null value here makes Compose ignore the image's default &lt;code&gt;CMD&lt;/code&gt;, same as the CLI flag ignores it. |&lt;/p&gt;

&lt;p&gt;| trailing command/args | &lt;code&gt;command&lt;/code&gt; | Overrides image &lt;code&gt;CMD&lt;/code&gt;. Unlike a Dockerfile's &lt;code&gt;CMD&lt;/code&gt;, Compose does not run it through the image's &lt;code&gt;SHELL&lt;/code&gt; automatically. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--cap-add&lt;/code&gt; / &lt;code&gt;--cap-drop&lt;/code&gt; | &lt;code&gt;cap_add&lt;/code&gt; / &lt;code&gt;cap_drop&lt;/code&gt; | Lists of capability strings, same names both places. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--device&lt;/code&gt; | &lt;code&gt;devices&lt;/code&gt; | &lt;code&gt;HOST_PATH:CONTAINER_PATH[:CGROUP_PERMISSIONS]&lt;/code&gt; in both. Under &lt;code&gt;--privileged&lt;/code&gt;/&lt;code&gt;privileged: true&lt;/code&gt;, only the specified cgroup permissions are ignored — the device mapping itself still applies, and the container gets every other host device too. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--init&lt;/code&gt; | &lt;code&gt;init&lt;/code&gt; | Boolean in Compose (&lt;code&gt;init: true&lt;/code&gt;) vs. a bare flag on the CLI. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--read-only&lt;/code&gt; | &lt;code&gt;read_only&lt;/code&gt; | Boolean in Compose (&lt;code&gt;read_only: true&lt;/code&gt;) vs. a bare flag on the CLI. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--tmpfs&lt;/code&gt; | &lt;code&gt;tmpfs&lt;/code&gt; | A path, or a list of paths/&lt;code&gt;path:options&lt;/code&gt;. Compose's options are &lt;code&gt;mode&lt;/code&gt;, &lt;code&gt;uid&lt;/code&gt;, &lt;code&gt;gid&lt;/code&gt;. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--health-cmd&lt;/code&gt; / &lt;code&gt;--health-interval&lt;/code&gt; / &lt;code&gt;--health-timeout&lt;/code&gt; / &lt;code&gt;--health-retries&lt;/code&gt; / &lt;code&gt;--health-start-period&lt;/code&gt; | &lt;code&gt;healthcheck.test&lt;/code&gt; / &lt;code&gt;.interval&lt;/code&gt; / &lt;code&gt;.timeout&lt;/code&gt; / &lt;code&gt;.retries&lt;/code&gt; / &lt;code&gt;.start_period&lt;/code&gt; | Compose's docs say it "has the same default values" as a Dockerfile &lt;code&gt;HEALTHCHECK&lt;/code&gt;, without restating the numbers. The CLI defaults it does list: &lt;code&gt;--health-interval&lt;/code&gt;, &lt;code&gt;--health-timeout&lt;/code&gt; and &lt;code&gt;--health-start-period&lt;/code&gt; all default to &lt;code&gt;0s&lt;/code&gt;. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--memory&lt;/code&gt;, &lt;code&gt;-m&lt;/code&gt; / &lt;code&gt;--cpus&lt;/code&gt; | &lt;code&gt;deploy.resources.limits.memory&lt;/code&gt; / &lt;code&gt;.cpus&lt;/code&gt; | The Compose Specification defines this key with no Swarm-only wording — what that does and doesn't prove is below.[3] A flatter &lt;code&gt;mem_limit:&lt;/code&gt; / top-level &lt;code&gt;cpus:&lt;/code&gt; pair is also valid and must stay consistent with the deploy values if both are present. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;-l&lt;/code&gt;, &lt;code&gt;--label&lt;/code&gt; | &lt;code&gt;labels&lt;/code&gt; | Map or array of &lt;code&gt;key=value&lt;/code&gt;. The &lt;code&gt;com.docker.compose&lt;/code&gt; prefix is reserved — using it in your own label is a Compose error. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;-h&lt;/code&gt;, &lt;code&gt;--hostname&lt;/code&gt; | &lt;code&gt;hostname&lt;/code&gt; | Must be a valid RFC 1123 hostname in both. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--add-host&lt;/code&gt; | &lt;code&gt;extra_hosts&lt;/code&gt; | &lt;code&gt;HOSTNAME=IP&lt;/code&gt; short form (also accepts &lt;code&gt;:&lt;/code&gt; since Compose 2.24.1). &lt;code&gt;host-gateway&lt;/code&gt; resolves to the host's internal IP either way.[1] |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--privileged&lt;/code&gt; | &lt;code&gt;privileged&lt;/code&gt; | Boolean in Compose. Docker's own wording: "extended privileges," disables the default seccomp/AppArmor profile — the CLI docs warn "a container with &lt;code&gt;--privileged&lt;/code&gt; is not a securely sandboxed process." |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--shm-size&lt;/code&gt; | &lt;code&gt;shm_size&lt;/code&gt; | Byte-value string, same format. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--ulimit&lt;/code&gt; | &lt;code&gt;ulimits&lt;/code&gt; | CLI format is &lt;code&gt;type=soft[:hard]&lt;/code&gt;; Compose takes an integer (single limit) or a &lt;code&gt;{soft, hard}&lt;/code&gt; map per ulimit type. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--log-driver&lt;/code&gt; / &lt;code&gt;--log-opt&lt;/code&gt; | &lt;code&gt;logging.driver&lt;/code&gt; / &lt;code&gt;logging.options&lt;/code&gt; | Defaults are platform-specific on both sides — neither doc lists a universal default driver. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;-i&lt;/code&gt;/&lt;code&gt;--interactive&lt;/code&gt;, &lt;code&gt;-t&lt;/code&gt;/&lt;code&gt;--tty&lt;/code&gt; (&lt;code&gt;-it&lt;/code&gt;) | &lt;code&gt;stdin_open&lt;/code&gt;, &lt;code&gt;tty&lt;/code&gt; | Two separate booleans — the Compose docs say &lt;code&gt;stdin_open&lt;/code&gt; is "the same as running a container with the &lt;code&gt;-i&lt;/code&gt; flag" and &lt;code&gt;tty&lt;/code&gt; is "the same as running a container with the &lt;code&gt;-t&lt;/code&gt; or &lt;code&gt;--tty&lt;/code&gt; flag." No combined &lt;code&gt;-it&lt;/code&gt;-style shorthand key. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--rm&lt;/code&gt; | &lt;em&gt;none&lt;/em&gt; | No service key. See below. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;-d&lt;/code&gt;, &lt;code&gt;--detach&lt;/code&gt; | &lt;em&gt;none&lt;/em&gt; (CLI flag on &lt;code&gt;up&lt;/code&gt;/&lt;code&gt;run&lt;/code&gt;) | Not a service key. &lt;code&gt;docker compose up -d&lt;/code&gt; has the flag; the YAML itself has nothing to set. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--platform&lt;/code&gt; | &lt;code&gt;platform&lt;/code&gt; | &lt;code&gt;os[/arch[/variant]]&lt;/code&gt;, e.g. &lt;code&gt;linux/arm64/v8&lt;/code&gt;. CLI flag needs daemon API 1.32+. |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;--pull&lt;/code&gt; | &lt;code&gt;pull_policy&lt;/code&gt; | CLI only has &lt;code&gt;always&lt;/code&gt;/&lt;code&gt;missing&lt;/code&gt;/&lt;code&gt;never&lt;/code&gt; (default &lt;code&gt;missing&lt;/code&gt;). Compose's &lt;code&gt;pull_policy&lt;/code&gt; adds &lt;code&gt;build&lt;/code&gt;, &lt;code&gt;daily&lt;/code&gt;, &lt;code&gt;weekly&lt;/code&gt;, &lt;code&gt;every_&amp;lt;duration&amp;gt;&lt;/code&gt;, and &lt;code&gt;if_not_present&lt;/code&gt; as an alias for &lt;code&gt;missing&lt;/code&gt;. |&lt;/p&gt;

&lt;h2&gt;
  
  
  No Compose key: --rm, -d, -it
&lt;/h2&gt;

&lt;p&gt;Three of the most common flags in any &lt;code&gt;docker run&lt;/code&gt; line have nothing to write in the YAML, because they describe how you want to run the container right now, not how the service is defined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--rm&lt;/code&gt;&lt;/strong&gt; has no service key because &lt;code&gt;docker compose up&lt;/code&gt; doesn't have a &lt;code&gt;--rm&lt;/code&gt; flag at all — it isn't in the command's options table.[6] When the &lt;code&gt;up&lt;/code&gt; command exits, Docker's docs say only that "all containers are stopped," not removed.[6] &lt;code&gt;docker compose run&lt;/code&gt; does have &lt;code&gt;--rm&lt;/code&gt;, documented as "Automatically remove the container when it exits," but it's opt-in — every example in the docs adds it explicitly, the same as plain &lt;code&gt;docker run&lt;/code&gt;.[7] If you relied on &lt;code&gt;--rm&lt;/code&gt; to keep a host clean of one-off containers, that's a habit to carry into whichever Compose subcommand you actually use, not a line to add to &lt;code&gt;compose.yaml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;-d&lt;/code&gt;/&lt;code&gt;--detach&lt;/code&gt;&lt;/strong&gt; is the same shape of answer: it's a flag on &lt;code&gt;docker compose up&lt;/code&gt; (and &lt;code&gt;run&lt;/code&gt;), not a service key.[6] &lt;code&gt;docker compose up -d&lt;/code&gt; gets you the same background-and-print-ID behavior you'd get from &lt;code&gt;docker run -d&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;-it&lt;/code&gt;&lt;/strong&gt; (short for &lt;code&gt;-i -t&lt;/code&gt;) is the one case where the CLI flag does have Compose keys — &lt;code&gt;stdin_open: true&lt;/code&gt; and &lt;code&gt;tty: true&lt;/code&gt; — but they only matter if you're running &lt;code&gt;docker compose run&lt;/code&gt; or attaching interactively; they're inert for a background &lt;code&gt;docker compose up&lt;/code&gt; service that nothing ever attaches to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Short volume syntax vs. --mount: who creates the directory
&lt;/h2&gt;

&lt;p&gt;Here's a divergence that bites people the other direction from what they expect. Docker's bind-mount docs are explicit: &lt;code&gt;-v&lt;/code&gt;/&lt;code&gt;--volume&lt;/code&gt; "automatically creates the directory on the host for you" if it's missing, while "&lt;code&gt;--mount&lt;/code&gt; does not automatically create a directory if the specified mount path does not exist on the host" — you get an error instead, unless you add the separate &lt;code&gt;bind-create-src&lt;/code&gt; option.[8]&lt;/p&gt;

&lt;p&gt;You'd expect Compose's long &lt;code&gt;type: bind&lt;/code&gt; syntax, which maps to &lt;code&gt;--mount&lt;/code&gt;, to inherit that fail-on-missing-path default. It doesn't. The Compose Specification sets &lt;code&gt;bind.create_host_path&lt;/code&gt; to default to &lt;code&gt;true&lt;/code&gt;: "Creates a directory at the source path on host if there is nothing present."[2] So a typo'd host path under Compose's short &lt;em&gt;or&lt;/em&gt; long volume syntax silently becomes an empty directory instead of an error — the opposite of what the raw &lt;code&gt;--mount&lt;/code&gt; flag it's modeled on would do. If you want the CLI's fail-closed behavior inside Compose, set &lt;code&gt;create_host_path: false&lt;/code&gt; explicitly on the long form.&lt;/p&gt;

&lt;h2&gt;
  
  
  --restart is not deploy.restart_policy
&lt;/h2&gt;

&lt;p&gt;The plain &lt;code&gt;restart:&lt;/code&gt; key takes the same four values as &lt;code&gt;docker run --restart&lt;/code&gt; — &lt;code&gt;no&lt;/code&gt;, &lt;code&gt;always&lt;/code&gt;, &lt;code&gt;on-failure[:max-retries]&lt;/code&gt;, &lt;code&gt;unless-stopped&lt;/code&gt; — and the Compose docs point straight at the &lt;code&gt;docker run --restart&lt;/code&gt; reference for what they mean.[2] That's the key our converter uses, and it's the right one for a direct flag conversion.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;deploy.restart_policy&lt;/code&gt; is a different, Swarm-service-shaped schema entirely: &lt;code&gt;condition&lt;/code&gt; (&lt;code&gt;none&lt;/code&gt;/&lt;code&gt;on-failure&lt;/code&gt;/&lt;code&gt;any&lt;/code&gt;, defaulting to &lt;code&gt;any&lt;/code&gt;), &lt;code&gt;delay&lt;/code&gt; (default &lt;code&gt;0&lt;/code&gt;), &lt;code&gt;max_attempts&lt;/code&gt; (default unlimited) and &lt;code&gt;window&lt;/code&gt;, the evaluation period before Swarm decides a restart succeeded.[3] If you're copying a block from a Swarm stack file into a non-Swarm &lt;code&gt;compose.yaml&lt;/code&gt; and expect it to behave like &lt;code&gt;--restart&lt;/code&gt;, don't — it's a different four fields with no &lt;code&gt;window&lt;/code&gt; or &lt;code&gt;condition&lt;/code&gt; equivalent on the plain &lt;code&gt;restart:&lt;/code&gt; key, and the Compose docs themselves note that when &lt;code&gt;deploy.restart_policy&lt;/code&gt; isn't set, Compose falls back to the service's &lt;code&gt;restart&lt;/code&gt; field.[3]&lt;/p&gt;

&lt;h2&gt;
  
  
  --memory and --cpus: what deploy.resources.limits actually traces back to
&lt;/h2&gt;

&lt;p&gt;The common advice online is that the entire &lt;code&gt;deploy:&lt;/code&gt; section — including &lt;code&gt;resources.limits&lt;/code&gt; — is a Swarm-only artifact that plain &lt;code&gt;docker compose up&lt;/code&gt; silently ignores unless you pass &lt;code&gt;--compatibility&lt;/code&gt;. That advice has one real citation behind it, and it's more than eight years old: a GitHub thread opened February 17, 2018, about the original Python &lt;code&gt;docker-compose&lt;/code&gt; v1, not the Go-based Compose v2 plugin you almost certainly have installed now (the one invoked as &lt;code&gt;docker compose&lt;/code&gt;, no hyphen).&lt;/p&gt;

&lt;p&gt;Here's exactly what that thread shows, because it gets misquoted a lot: a Docker maintainer, in a July 31, 2018 comment, ran &lt;code&gt;docker-compose --compatibility up -d&lt;/code&gt; — the legacy v1 binary, with the compatibility flag explicitly set — against a file with &lt;code&gt;resources.limits.cpus: '0.50'&lt;/code&gt; and a 50M memory limit. &lt;code&gt;docker inspect&lt;/code&gt; on the resulting container reported &lt;code&gt;"Memory": 52428800&lt;/code&gt; and &lt;code&gt;"NanoCpus": 500000000&lt;/code&gt;, matching the YAML.[9] That proves the translation mechanism existed in 2018 — for v1, with the flag set. It says nothing about v2 with no flag. The same maintainer's own framing in that thread is that &lt;code&gt;deploy&lt;/code&gt; options are "scheduling options for swarm-mode services," and Compose "deploys local containers," so there's no orchestrator to apply them to on its own.[9] An October 3, 2023 reply in the same thread adds only that v2 "now uses the compose-specification file format which does not use a version" — it doesn't say whether &lt;code&gt;resources.limits&lt;/code&gt; applies without Swarm or without &lt;code&gt;--compatibility&lt;/code&gt; today.[9]&lt;/p&gt;

&lt;p&gt;What we can confirm from Docker's current docs: the Compose Specification defines &lt;code&gt;resources.limits&lt;/code&gt; as a plain key with no Swarm-only or version-gating language anywhere on the page — a real difference from the versioned v3 schema that 2018 thread was arguing about.[3] The &lt;code&gt;docker compose up&lt;/code&gt; command reference has no &lt;code&gt;--compatibility&lt;/code&gt; flag at all; it isn't in the options table.[6] What we could not confirm anywhere on docs.docker.com is whether a plain &lt;code&gt;docker compose up&lt;/code&gt;, no flags, actually enforces &lt;code&gt;resources.limits&lt;/code&gt; on a single engine today. Don't take our converter's &lt;code&gt;deploy.resources.limits&lt;/code&gt; output on faith: run &lt;code&gt;docker compose up -d&lt;/code&gt; on your own file and check &lt;code&gt;docker inspect &amp;lt;container&amp;gt;&lt;/code&gt; for &lt;code&gt;Memory&lt;/code&gt;/&lt;code&gt;NanoCpus&lt;/code&gt; against the YAML before you rely on it in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked example: a Node API, by hand
&lt;/h2&gt;

&lt;p&gt;Here's a realistic &lt;code&gt;docker run&lt;/code&gt; line and its hand-written Compose equivalent, using the mappings above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run -d --name api \
  -p 3000:3000 \
  -v ./logs:/app/logs \
  -v appdata:/data \
  -e &lt;span class="nv"&gt;NODE_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production \
  -e &lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres://admin:secret@db:5432/myapp \
  --network app-net \
  --restart unless-stopped \
  --memory 512m --cpus 0.5 \
  node:20-alpine node server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:20-alpine&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./logs:/app/logs&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="s"&gt;appdata:/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"postgres://admin:secret@db:5432/myapp"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-net&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;512m&lt;/span&gt;
          &lt;span class="na"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"0.5"&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node server.js&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;appdata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-net&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;-d&lt;/code&gt; doesn't appear anywhere in the YAML — you'd run this with &lt;code&gt;docker compose up -d&lt;/code&gt; instead, as covered above.&lt;/p&gt;

&lt;h2&gt;
  
  
  We ran that exact command through our own converter
&lt;/h2&gt;

&lt;p&gt;Rather than hand-wave that our &lt;a href="https://dev.to/tools/docker-run-to-compose"&gt;Docker Run to Compose converter&lt;/a&gt; "handles this," we ran it. The tool runs entirely in the browser, so we extracted its parsing logic unmodified and ran it against the command above, pasted as a single line. Here is the actual output, byte for byte:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:20-alpine&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./logs:/app/logs&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="s"&gt;appdata:/data&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;NODE_ENV&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"postgres://admin:secret@db:5432/myapp"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-net&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;512m&lt;/span&gt;
          &lt;span class="na"&gt;cpus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"0.5"&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node server.js&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;appdata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-net&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That matches the hand conversion exactly, as long as the command lands in the textarea as one line. For the flags it supports — &lt;code&gt;-p&lt;/code&gt;, &lt;code&gt;-v&lt;/code&gt;, &lt;code&gt;-e&lt;/code&gt;, &lt;code&gt;--name&lt;/code&gt;, &lt;code&gt;--restart&lt;/code&gt;, &lt;code&gt;--network&lt;/code&gt;, &lt;code&gt;--memory&lt;/code&gt;, &lt;code&gt;--cpus&lt;/code&gt;, and a trailing command — the converter is reliable on single-line input. (&lt;code&gt;-d&lt;/code&gt; is also recognized, but produces no YAML either way, same as covered above — it's a CLI flag, not a service key.) "As long as it's one line" turns out to matter a lot, which is the first bug below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three bugs we found while testing it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Bug 1: its own placeholder example breaks the tool
&lt;/h3&gt;

&lt;p&gt;The converter's input box ships with this exact placeholder text, shown in gray before you type anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run -d --name nginx \
  -p 80:80 -p 443:443 \
  -v /data/nginx:/etc/nginx \
  --restart always \
  nginx:alpine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste that in verbatim — line breaks and trailing backslashes included, exactly as it's formatted in the placeholder — and the actual output is four parse errors plus one "parsed" service that isn't nginx at all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not parse: "  -p 80:80 -p 443:443 \..."
Could not parse: "  -v /data/nginx:/etc/nginx \..."
Could not parse: "  --restart always \..."
Could not parse: "  nginx:alpine..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The one "parsed" service that results has &lt;code&gt;image: \&lt;/code&gt; — a lone backslash as the image name, with no quotes around it (the converter's YAML writer never quotes &lt;code&gt;image&lt;/code&gt;). The root cause: the component splits the textarea's contents into lines on every &lt;code&gt;\n&lt;/code&gt; &lt;em&gt;before&lt;/em&gt; handing each line to the parser, and treats every line as an independent &lt;code&gt;docker run&lt;/code&gt; invocation. The parser itself does have code to collapse a trailing &lt;code&gt;\&lt;/code&gt; plus newline into a space — but by the time a line reaches that code, the newlines are already gone, so that collapse logic never has anything to do. A multi-line, backslash-continued command, which is how Docker's own docs and most READMEs format anything with more than two or three flags, has to be joined into one line before you paste it in. The box's own example doesn't follow that rule.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug 2: --rm immediately before the image fails outright
&lt;/h3&gt;

&lt;p&gt;Everything outside the supported flag set goes through a generic "skip this flag, and skip the next token too if it doesn't look like another flag" fallback. That fallback assumes every unrecognized flag takes exactly one value. Boolean flags that take &lt;em&gt;no&lt;/em&gt; value break it, and two of the most common ones are &lt;code&gt;--rm&lt;/code&gt; and &lt;code&gt;-it&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Feed the converter &lt;code&gt;docker run --rm nginx:alpine&lt;/code&gt; on its own and it fails outright:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Could not parse: "docker run --rm nginx:alpine..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happens: the parser sees &lt;code&gt;--rm&lt;/code&gt;, doesn't recognize it, advances past it, and then — because the next token (&lt;code&gt;nginx:alpine&lt;/code&gt;) doesn't start with a dash — treats the image name as &lt;code&gt;--rm&lt;/code&gt;'s value and skips it too. There's nothing left to become the image, so the whole line errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug 3: -it before the image silently produces the wrong service
&lt;/h3&gt;

&lt;p&gt;This one is worse than Bug 2, because it doesn't error — it silently produces the wrong service. The cause is &lt;code&gt;-it&lt;/code&gt; alone. Feed the converter &lt;code&gt;docker run -it ubuntu:24.04 bash&lt;/code&gt; and the real output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-it&lt;/code&gt; is an unrecognized flag, so the generic fallback skips it, then checks whether the next token looks like another flag. &lt;code&gt;ubuntu:24.04&lt;/code&gt; doesn't, so the fallback swallows it as &lt;code&gt;-it&lt;/code&gt;'s "value" too, discarding the real image entirely. The next bare token, &lt;code&gt;bash&lt;/code&gt; — which was supposed to be the command — gets assigned as the image instead, because it's the first non-flag token the parser ever reaches. The output has no error, looks plausible, and is completely wrong. Putting &lt;code&gt;--rm&lt;/code&gt; in front of it, as in &lt;code&gt;docker run --rm -it ubuntu:24.04 bash&lt;/code&gt;, doesn't change the outcome: &lt;code&gt;-it&lt;/code&gt; starts with a dash, so &lt;code&gt;--rm&lt;/code&gt;'s own fallback skips only itself, leaving &lt;code&gt;-it&lt;/code&gt; to eat &lt;code&gt;ubuntu:24.04&lt;/code&gt; exactly as before. We confirmed a different failure mode with &lt;code&gt;--privileged&lt;/code&gt; and &lt;code&gt;--init&lt;/code&gt; placed directly before an image with no trailing command: both make the converter report "Could not parse" for the same reason &lt;code&gt;--rm&lt;/code&gt; alone does in Bug 2 — there's no bare token left over to become the image.&lt;/p&gt;

&lt;p&gt;The practical rule until this is fixed: never put a zero-argument flag — &lt;code&gt;--rm&lt;/code&gt;, &lt;code&gt;-it&lt;/code&gt;, &lt;code&gt;--privileged&lt;/code&gt;, &lt;code&gt;--init&lt;/code&gt;, &lt;code&gt;--read-only&lt;/code&gt;, or any other flag that takes no value — directly before the image. Put it anywhere else in the flag list, then check the image name in the tool's "Parsed N services" summary before you trust the YAML.&lt;/p&gt;

&lt;h2&gt;
  
  
  Flags the converter silently drops today
&lt;/h2&gt;

&lt;p&gt;Everything in the reference table that isn't &lt;code&gt;-d&lt;/code&gt;, &lt;code&gt;-p&lt;/code&gt;, &lt;code&gt;-v&lt;/code&gt;, &lt;code&gt;-e&lt;/code&gt;, &lt;code&gt;--name&lt;/code&gt;, &lt;code&gt;--restart&lt;/code&gt;, &lt;code&gt;--network&lt;/code&gt;/&lt;code&gt;--net&lt;/code&gt;, &lt;code&gt;--memory&lt;/code&gt;/&lt;code&gt;-m&lt;/code&gt;, or &lt;code&gt;--cpus&lt;/code&gt; gets silently discarded — no error, no warning, just absent from the output. We confirmed this by running a command with sixteen of them at once, pasted as a single line (multi-line input here hits the same parsing failure as Bug 1 above):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run --user 1000:1000 -w /app --entrypoint /bin/sh --cap-add SYS_PTRACE --device /dev/snd:/dev/snd --health-cmd &lt;span class="s2"&gt;"curl -f http://localhost/ || exit 1"&lt;/span&gt; --health-interval 30s --health-retries 3 --label com.example.app=web --hostname web1 --add-host db.local:10.0.0.5 --platform linux/amd64 --pull always --mount &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bind,source=/data,target=/data --env-file ./app.env --network-alias web myorg/app:1.2.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actual output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myorg/app:1.2.3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every one of those sixteen flags — &lt;code&gt;--user&lt;/code&gt;, &lt;code&gt;-w&lt;/code&gt;, &lt;code&gt;--entrypoint&lt;/code&gt;, &lt;code&gt;--cap-add&lt;/code&gt;, &lt;code&gt;--device&lt;/code&gt;, all three health flags we passed, &lt;code&gt;--label&lt;/code&gt;, &lt;code&gt;--hostname&lt;/code&gt;, &lt;code&gt;--add-host&lt;/code&gt;, &lt;code&gt;--platform&lt;/code&gt;, &lt;code&gt;--pull&lt;/code&gt;, &lt;code&gt;--mount&lt;/code&gt;, &lt;code&gt;--env-file&lt;/code&gt;, and &lt;code&gt;--network-alias&lt;/code&gt; — vanished. None of these happened to collide with the image-eating bug above (each one here is immediately followed by its own value, not by the image), so you get a clean, valid, silently-incomplete &lt;code&gt;compose.yaml&lt;/code&gt; rather than an error or a wrong image. Add the keys for these by hand from the reference table above — they're the right Compose keys, the tool just doesn't write them yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting .env files along the way
&lt;/h2&gt;

&lt;p&gt;If your &lt;code&gt;docker run&lt;/code&gt; command used &lt;code&gt;--env-file app.env&lt;/code&gt;, the Compose key is &lt;code&gt;env_file: [app.env]&lt;/code&gt; — a one-line swap, since Compose reads the same &lt;code&gt;VAR=value&lt;/code&gt; format. Where it gets messier is when a long &lt;code&gt;-e&lt;/code&gt;/&lt;code&gt;--env&lt;/code&gt; list should become an &lt;code&gt;env_file&lt;/code&gt; instead for readability, or vice versa. Our free &lt;a href="https://dev.to/tools/env-file-converter"&gt;.env file converter&lt;/a&gt; handles reshaping between &lt;code&gt;.env&lt;/code&gt;, JSON, and shell-export formats if you're restructuring environment variables as part of the migration rather than just converting flag syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does docker compose up remove containers the way docker run --rm does?
&lt;/h3&gt;

&lt;p&gt;No. &lt;code&gt;docker compose up&lt;/code&gt; has no &lt;code&gt;--rm&lt;/code&gt; flag — Docker's own reference for the command confirms it isn't in the options table — and stopping the command only stops containers, it doesn't remove them.[6] &lt;code&gt;docker compose run&lt;/code&gt; has &lt;code&gt;--rm&lt;/code&gt;, but like plain &lt;code&gt;docker run&lt;/code&gt;, it's opt-in, not default.[7]&lt;/p&gt;

&lt;h3&gt;
  
  
  Why did my converted compose.yaml create an empty folder instead of erroring?
&lt;/h3&gt;

&lt;p&gt;Because both Compose's short and long bind-mount syntax default to creating a missing host directory (&lt;code&gt;bind.create_host_path: true&lt;/code&gt;), the same way &lt;code&gt;-v&lt;/code&gt; does on the CLI.[2] If you want a typo to fail loudly instead, add &lt;code&gt;create_host_path: false&lt;/code&gt; to the long volume form.&lt;/p&gt;

&lt;h3&gt;
  
  
  Will deploy.resources.limits actually limit my container without Swarm?
&lt;/h3&gt;

&lt;p&gt;We couldn't confirm that from Docker's own docs either way. The Compose Specification defines &lt;code&gt;resources.limits&lt;/code&gt; with no Swarm-only language,[3] but the only runtime demonstration we found is more than eight years old and used the legacy v1 CLI with &lt;code&gt;--compatibility&lt;/code&gt; explicitly set — not today's v2 plugin with no flag.[9] Check it yourself: run &lt;code&gt;docker compose up -d&lt;/code&gt; and compare &lt;code&gt;docker inspect&lt;/code&gt;'s &lt;code&gt;Memory&lt;/code&gt;/&lt;code&gt;NanoCpus&lt;/code&gt; fields against your YAML.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I just copy my --restart value into deploy.restart_policy?
&lt;/h3&gt;

&lt;p&gt;No — they're different schemas. &lt;code&gt;restart:&lt;/code&gt; takes the same four values as the CLI flag. &lt;code&gt;deploy.restart_policy&lt;/code&gt; uses &lt;code&gt;condition&lt;/code&gt;/&lt;code&gt;delay&lt;/code&gt;/&lt;code&gt;max_attempts&lt;/code&gt;/&lt;code&gt;window&lt;/code&gt;, a Swarm-service shape with no 1:1 mapping back to the simple flag.[3]&lt;/p&gt;

&lt;h3&gt;
  
  
  What should I do with flags the converter drops?
&lt;/h3&gt;

&lt;p&gt;Add them by hand using the Compose key from the reference table above. None of the dropped flags in our test run broke the output — they're just missing from it, so the fix is additive, not corrective.&lt;/p&gt;

&lt;p&gt;Once you have a complete &lt;code&gt;compose.yaml&lt;/code&gt;, the next step is making it production-ready — health check ordering, secrets, and resource limits that actually hold under load are covered in our &lt;a href="https://dev.to/blogs/docker-compose-production-nodejs-redis-postgres-2026"&gt;Docker Compose for production guide&lt;/a&gt;. Paste your own command into the &lt;a href="https://dev.to/tools/docker-run-to-compose"&gt;Docker Run to Compose converter&lt;/a&gt;, then check anything with a zero-argument flag before the image against the "Parsed N services" summary it shows you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/reference/cli/docker/container/run/" rel="noopener noreferrer"&gt;docker container run, Docker CLI reference, Docker Inc. (accessed November 5, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/reference/compose-file/services/" rel="noopener noreferrer"&gt;Services top-level element, Compose Specification, Docker Inc. (accessed November 5, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/reference/compose-file/deploy/" rel="noopener noreferrer"&gt;Deploy top-level element, Compose Specification, Docker Inc. (accessed November 5, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/reference/compose-file/volumes/" rel="noopener noreferrer"&gt;Volumes top-level element, Compose Specification, Docker Inc. (accessed November 5, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/reference/compose-file/networks/" rel="noopener noreferrer"&gt;Networks top-level element, Compose Specification, Docker Inc. (accessed November 5, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/reference/cli/docker/compose/up/" rel="noopener noreferrer"&gt;docker compose up, Docker CLI reference, Docker Inc. (accessed November 5, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/reference/cli/docker/compose/run/" rel="noopener noreferrer"&gt;docker compose run, Docker CLI reference, Docker Inc. (accessed November 5, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.docker.com/engine/storage/bind-mounts/" rel="noopener noreferrer"&gt;Bind mounts, Docker Engine storage docs, Docker Inc. (accessed November 5, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  9. &lt;a href="https://github.com/docker/compose/pull/5684" rel="noopener noreferrer"&gt;docker/compose pull request #5684, maintainer comment thread, GitHub (accessed November 5, 2026)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/docker-run-to-docker-compose-flags-conversion-guide-2026" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dockerrun</category>
      <category>dockercompose</category>
      <category>convertdocker</category>
    </item>
    <item>
      <title>Claude Code in Visual Studio 2026: 5 Ways to Run It Today</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Tue, 03 Nov 2026 14:23:56 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/claude-code-in-visual-studio-2026-5-ways-to-run-it-today-590f</link>
      <guid>https://dev.to/akaranjkar08/claude-code-in-visual-studio-2026-5-ways-to-run-it-today-590f</guid>
      <description>&lt;p&gt;&lt;strong&gt;As of November 2, 2026, Anthropic does not ship a Claude Code extension for Visual Studio 2026.&lt;/strong&gt; The official docs cover VS Code, Cursor and JetBrains IDEs, and tell users of other editors to run the &lt;code&gt;claude&lt;/code&gt; CLI in their editor's integrated terminal.[1][12] The GitHub feature request for a native Visual Studio 2026 extension, issue #15942, has been open since January 1, 2026 and had 480 thumbs-up reactions when we read it. None of the comments GitHub displays without expanding the thread comes from Anthropic staff.[2] That leaves five ways to run it today: the CLI in Visual Studio's terminal with a plain-text workflow, or one of four community extensions linked in that thread. Two of them, firish's and cv4vs Agents, connect the CLI to Visual Studio over the same IDE channel the official VS Code extension uses; dliedke's and nachum-shmilovitz-66's drive the CLI their own way.[3][11] This post compares all five, shows the setup commands, and shows which files the firish extension writes into your repo (and how to check the others), which most install guides skip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How we researched this:&lt;/strong&gt; the WOWHOW editorial team compared these extensions from their Visual Studio Marketplace listings, their READMEs and the Anthropic and Microsoft docs on November 2, 2026. We did not install them on a Visual Studio 2026 build, so every feature claim below is what the project documents, not what we measured.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No official Visual Studio 2026 extension exists. Anthropic's plugins cover VS Code, Cursor and other VS Code forks, and JetBrains IDEs; Visual Studio gets the CLI-in-a-terminal route.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Claude Code for Visual Studio (firish, v1.21.0, about 10,600 installs) is the closest thing to the VS Code experience: native diffs, Error List diagnostics, Roslyn lookups and a debugger Claude can read. VS 2026 only.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Claude Code Extension for Visual Studio (dliedke, v298.0, about 345,000 installs) is the most installed. It supports VS 2022 and 2026 and nine other agents besides Claude Code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;claude-code-visualstudio (nachum-shmilovitz-66) is the only one that reaches back to VS 2017.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;cv4vs Agents (Corsinvest, v1.15.0, 415 installs) is the newest entrant: VS 2022 and 2026, native diffs, debugger tools, GPL-3.0 license.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;All four are unofficial, need the Claude Code CLI plus a paid Claude plan or another supported provider, and two ride an undocumented protocol that a CLI update can break.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why there is no official Visual Studio extension yet
&lt;/h2&gt;

&lt;p&gt;Claude Code's IDE support is built around a small local protocol. The editor extension runs an MCP server named &lt;code&gt;ide&lt;/code&gt; bound to &lt;code&gt;127.0.0.1&lt;/code&gt; on a random port between 10000 and 65535, speaks unencrypted &lt;code&gt;ws://&lt;/code&gt;, and writes a fresh auth token to a lock file at &lt;code&gt;~/.claude/ide/&amp;lt;port&amp;gt;.lock&lt;/code&gt;. The CLI reads that file and sends the token in an &lt;code&gt;X-Claude-Code-Ide-Authorization&lt;/code&gt; header.[1] That is how diff viewing and diagnostic sharing reach the terminal agent.&lt;/p&gt;

&lt;p&gt;Anthropic implements the editor side of that protocol for VS Code and for JetBrains IDEs, and the VS Code extension also installs in forks such as Cursor, Kiro and Devin Desktop. The JetBrains plugin runs the same &lt;code&gt;ide&lt;/code&gt; MCP server with the same lock file and &lt;code&gt;X-Claude-Code-Ide-Authorization&lt;/code&gt; header.[12] Visual Studio is a different product with a different extension model (VSIX on .NET, not a VS Code extension), so none of that code carries over. The docs never name Visual Studio. The phrase "Visual Studio Marketplace" appears only because that is where Anthropic publishes the VS Code extension.[1]&lt;/p&gt;

&lt;p&gt;The demand is clear. The issue author writes that they rely on "Visual Studio 2026 for C++ and Win32 system-level development (e.g., global hooks, drivers)" and asks for a native VSIX "that provides feature parity with the existing VS Code extension": a chat panel, native diffs, context from open files, selections and build errors, and &lt;code&gt;/ide&lt;/code&gt; support.[2] The issue carries the labels &lt;code&gt;area:ide&lt;/code&gt;, &lt;code&gt;enhancement&lt;/code&gt; and &lt;code&gt;platform:windows&lt;/code&gt;. Most of the thread is developers linking their own workarounds. That is where the four extensions below came from.&lt;/p&gt;

&lt;p&gt;The catch for anyone planning around this: an open issue with 480 reactions is not a roadmap. Pick a workaround on its merits, not on the hope that an official build lands next month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step zero: install the CLI on Windows
&lt;/h2&gt;

&lt;p&gt;Every option here, including all four extensions, drives the real &lt;code&gt;claude&lt;/code&gt; binary. None of them makes model calls itself. Install the CLI first. From PowerShell, using the native installer in Anthropic's setup docs:[7]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# PowerShell (prompt shows PS C:\). No admin rights needed.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;irm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://claude.ai/install.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Open a NEW terminal, then confirm the install&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;doctor&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;claude doctor&lt;/code&gt; prints read-only install and settings diagnostics without starting a session. If you prefer a package manager, &lt;code&gt;winget install Anthropic.ClaudeCode&lt;/code&gt; works too. WinGet installs do not auto-update, though, so you need &lt;code&gt;winget upgrade Anthropic.ClaudeCode&lt;/code&gt; on a schedule unless you set &lt;code&gt;CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE=1&lt;/code&gt; in settings.json &lt;code&gt;env&lt;/code&gt;, which makes Claude Code run the upgrade for you (it can fail while &lt;code&gt;claude.exe&lt;/code&gt; is running). The native installer, by contrast, updates itself in the background.[7]&lt;/p&gt;

&lt;p&gt;Two Windows details matter for Visual Studio users. First, Git for Windows is optional: with it, Claude Code uses Git Bash for its Bash tool; without it, it runs commands through PowerShell. If Claude Code cannot find Git Bash, point it there in &lt;code&gt;settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"CLAUDE_CODE_GIT_BASH_PATH"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Program Files&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Git&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;bin&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;bash.exe"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second, sandboxing is not supported on native Windows. Only WSL 2 supports it.[7] Most Visual Studio solutions (MSBuild, .NET Framework, Win32, drivers) need the native Windows toolchain, so you will usually run without the sandbox. That makes the permission prompts your main safety net, and it is the strongest argument for an extension that routes every edit through a diff you approve.&lt;/p&gt;

&lt;p&gt;Last prerequisite: a paid plan. Claude Code needs a Pro, Max, Ultra, Team, Enterprise or Console account. The free claude.ai plan does not include it.[7] Paste the JSON above into the &lt;a href="https://dev.to/tools/json-formatter"&gt;JSON formatter&lt;/a&gt; before saving if you are editing settings by hand. A stray backslash in a Windows path is the most common reason the file fails to load.&lt;/p&gt;

&lt;h2&gt;
  
  
  Option 1: the built-in terminal, no extension
&lt;/h2&gt;

&lt;p&gt;This is the route Anthropic documents for editors without a plugin.[1] Open Visual Studio's terminal window (View &amp;gt; Terminal), &lt;code&gt;cd&lt;/code&gt; to the folder that holds your &lt;code&gt;.sln&lt;/code&gt;, and run &lt;code&gt;claude&lt;/code&gt;. The agent reads and edits files on disk, runs &lt;code&gt;dotnet build&lt;/code&gt; or &lt;code&gt;msbuild&lt;/code&gt;, and Visual Studio picks up the changed files.&lt;/p&gt;

&lt;p&gt;What you lose is everything the IDE protocol carries. No native diff for approving edits, no Error List feed, no selection context. You approve edits as text diffs in the terminal, and you paste build errors in by hand. For small, well-tested repos that is fine. In a large solution, where one wrong edit to a shared header triggers a long rebuild, the missing diff view hurts.&lt;/p&gt;

&lt;p&gt;A short &lt;code&gt;CLAUDE.md&lt;/code&gt; at the solution root closes part of the gap, because it tells the agent how to build and test without you repeating it each session:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# CLAUDE.md (solution root)&lt;/span&gt;
&lt;span class="gu"&gt;## Build&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Build: dotnet build MyApp.sln -c Debug
&lt;span class="p"&gt;-&lt;/span&gt; Test:  dotnet test MyApp.sln --no-build
&lt;span class="p"&gt;-&lt;/span&gt; Never edit files under obj/ or bin/.

&lt;span class="gu"&gt;## Conventions&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Target framework: net10.0. Do not retarget projects.
&lt;span class="p"&gt;-&lt;/span&gt; Treat compiler warnings in src/Core as errors; fix them, do not suppress.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Swap in your own solution name and commands. If you keep a set of rules files you reuse across repos, the &lt;a href="https://dev.to/product/claude-md-production-rules"&gt;Production CLAUDE.md and AGENTS.md Rule Pack&lt;/a&gt; is a starting point.&lt;/p&gt;

&lt;h2&gt;
  
  
  firish, dliedke and nachum-shmilovitz-66 compared
&lt;/h2&gt;

&lt;p&gt;Issue #15942 links four community extensions.[2] The table covers three of them: the two with the most Visual Studio Marketplace installs (dliedke and firish) and the only one that supports VS 2017 and 2019 (nachum-shmilovitz-66, which ships its VSIX files through GitHub Releases rather than the Marketplace). The fourth, cv4vs Agents, gets its own section after them. All four are free, unofficial, and not affiliated with Anthropic. The figures below come from each project's Marketplace listing or README on November 2, 2026.&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;Claude Code for Visual Studio (firish)&lt;/th&gt;
&lt;th&gt;Claude Code Extension for Visual Studio (dliedke)&lt;/th&gt;
&lt;th&gt;claude-code-visualstudio (nachum-shmilovitz-66)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Visual Studio versions | 2026 only | 2022 and 2026, x64 or ARM64, Windows 11 | 2017 (15.7+), 2019, 2022, 2026 |&lt;/p&gt;

&lt;p&gt;| How it talks to Claude Code | Implements the IDE protocol: WebSocket + lock file + MCP | Native chat tab (default) or embedded agent terminal | WebView2 chat; drives &lt;code&gt;claude&lt;/code&gt; via stream-json over stdin/stdout |&lt;/p&gt;

&lt;p&gt;| Edit review | &lt;strong&gt;Visual Studio's native diff, accept or reject&lt;/strong&gt; | Tab showing uncommitted Git changes; opt-in per-file Keep/Undo of agent changes (no per-edit accept/reject listed) | Inline diff in chat plus an "Open diff" button for the native VS window |&lt;/p&gt;

&lt;p&gt;| Build errors to the agent | Error List diagnostics for C# and C++ | Sends build errors and warnings (opt-in) | Error List included in context |&lt;/p&gt;

&lt;p&gt;| Debugger access | Reads call stacks, variables and threads; can step and set breakpoints with an opt-in toggle (managed .NET) | Sends unhandled exceptions with their stack trace while debugging (opt-in); F5, Ctrl+F5 and Shift+F5 forwarded from the embedded terminal. No variable or breakpoint access listed | Reads call stack, locals and exception when paused (verified on C#/.NET) |&lt;/p&gt;

&lt;p&gt;| Other agents | Claude Code only | Also Codex, Cursor Agent, Open Code, Devin, PI, Antigravity, Reasonix, Qwen Code, Grok | Claude Code only |&lt;/p&gt;

&lt;p&gt;| Installs / stars | About 10,600 installs, 104 stars | About 345,000 installs | 9 stars |&lt;/p&gt;

&lt;p&gt;| License | MIT | MIT per listing, plus a no-derivative-extensions clause | MIT |&lt;/p&gt;

&lt;p&gt;Sources for the table: the firish README and listing,[3][4] the dliedke listing,[5] and the nachum-shmilovitz-66 README.[6]&lt;/p&gt;

&lt;h3&gt;
  
  
  firish: the closest to the VS Code experience
&lt;/h3&gt;

&lt;p&gt;This one rebuilds the editor half of Anthropic's protocol inside Visual Studio. On launch it starts a localhost WebSocket server, writes the lock file to &lt;code&gt;~/.claude/ide/&amp;lt;port&amp;gt;.lock&lt;/code&gt;, and launches &lt;code&gt;claude&lt;/code&gt; with &lt;code&gt;ENABLE_IDE_INTEGRATION&lt;/code&gt; and the bridge port, so the CLI connects and speaks MCP over the socket.[3] Then it adds two more MCP servers: &lt;code&gt;vs-debug&lt;/code&gt; for the debugger, tests and builds, and &lt;code&gt;vs-semantic&lt;/code&gt;, a read-only server backed by the live Roslyn workspace for find-references, go-to-definition, call hierarchies and decompile.&lt;/p&gt;

&lt;p&gt;For .NET work, the debugger access stands out. While you are paused at a breakpoint, Claude can read the call stack, locals and threads, and with an opt-in toggle it can step and set breakpoints itself. Test Explorer integration lets it re-run only failing tests.[3]&lt;/p&gt;

&lt;p&gt;The README is honest about the limits. The protocol is "undocumented and version-fragile, so a &lt;code&gt;claude&lt;/code&gt; update could change it." It was tested against &lt;code&gt;claude&lt;/code&gt; 2.1.223, which is older than current CLI releases, so check the extension's release notes before updating the CLI. Debugger features target managed .NET code, so native C++ runtime inspection is not covered, even though C++ compiler diagnostics are. Diagnostics need a loaded project, and ARM64 Windows support is labeled experimental.[3] If you are the Win32 and drivers developer who opened issue #15942, that debugger gap is the one that matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  dliedke: the most installed, and not only for Claude
&lt;/h3&gt;

&lt;p&gt;With about 345,000 installs at version 298.0, this is the extension most Visual Studio users actually have.[5] New installs default to "Native mode", a chat in its own document tab. You can switch to an embedded terminal that runs the agent inside a Visual Studio tool window, which is also the fallback for agents that cannot run in native mode. Claude Code is the only agent shown in the picker by default. The others, Codex and Grok among them, are opt-in.&lt;/p&gt;

&lt;p&gt;It does more Visual Studio-specific chores than the others: TFVC checkout, a &lt;code&gt;git pull&lt;/code&gt; before the first prompt, opt-in sending of build errors, a commit-message generator, and a GitHub Issues window that fixes issues on separate branches. It also covers VS 2022, which firish does not. The trade-off is depth. Its debugger hooks are thin: while you debug, it can send unhandled exceptions with their stack trace to the agent (opt-in, under Settings &amp;gt; Automation), and since version 9.0 it forwards F5, Ctrl+F5 and Shift+F5 from the embedded terminal to Visual Studio's debug commands.[5] The listing does not mention reading locals, setting breakpoints or Roslyn lookups, so outside those exception reports Claude sees your code the way the CLI does, not the way Visual Studio does.&lt;/p&gt;

&lt;h3&gt;
  
  
  nachum-shmilovitz-66: for teams stuck on older Visual Studio
&lt;/h3&gt;

&lt;p&gt;If your solution still builds only in Visual Studio 2017 or 2019, this is the only option of the four. It ships a separate VSIX per Visual Studio family and runs the &lt;code&gt;claude&lt;/code&gt; CLI as a long-lived process, exchanging stream-json over stdin and stdout. Because it drives the real CLI, it inherits your login, &lt;code&gt;CLAUDE.md&lt;/code&gt;, MCP servers and settings. It offers four permission modes (Ask before edits, Edit automatically, Plan mode and Auto mode), and in Ask before edits every tool call raises an allow or deny card.[6] With 9 stars it is also the least battle-tested. Read the source before you deploy it to a team.&lt;/p&gt;

&lt;h3&gt;
  
  
  cv4vs Agents (Corsinvest): the fourth extension in the thread
&lt;/h3&gt;

&lt;p&gt;Its author posted it to issue #15942 on August 5, 2026 as "VS 2022 and 2026, GPL-3.0".[2] The Marketplace listing, published by Corsinvest Srl, shows version 1.15.0, 415 installs and a free price tag. That is far behind firish's 10,600 and dliedke's 345,000.[11] The listing says the real &lt;code&gt;claude.exe&lt;/code&gt; runs in an embedded terminal "connected to the IDE over the same channel the official VS Code extension uses", and the author's issue comment lists &lt;code&gt;/ide&lt;/code&gt; support.[11][2] The README says the extension "drives the real &lt;code&gt;claude.exe&lt;/code&gt;" instead of forking the CLI, through a WebView2 chat pane and a ConPTY terminal pane. Visual Studio reaches the agent as 80 MCP tools covering navigation, references, rename, diagnostics, build, Test Explorer and the live debugger. Every edit shows as an inline diff and opens in Visual Studio's native side-by-side diff.[10]&lt;/p&gt;

&lt;p&gt;On VS 2022 it fills the gap firish leaves. Its listing names breakpoints, tracepoints, stepping, locals and the call stack, which neither dliedke's listing nor the nachum-shmilovitz-66 README mentions for breakpoints or stepping.[11] The listing says its diagnostics keep working in C++, F# and TypeScript, but it does not say which runtimes the debugger supports. Two cautions. The license is GPL-3.0-only, not MIT, so check it against your company's tooling policy first. And the README does not say which files the extension writes into your workspace, so run the &lt;code&gt;git status&lt;/code&gt; check below after the first launch.[10]&lt;/p&gt;

&lt;h2&gt;
  
  
  What these extensions write into your repo
&lt;/h2&gt;

&lt;p&gt;Here is the part that bites teams later. The firish extension installs a PreToolUse hook into your workspace's &lt;code&gt;.claude/settings.json&lt;/code&gt; to route edits to the Visual Studio diff, and registers its debugger shim in the workspace &lt;code&gt;.mcp.json&lt;/code&gt;.[3] Both files usually live in version control, and the extension also writes PowerShell helper scripts (&lt;code&gt;.ps1&lt;/code&gt; files) into &lt;code&gt;.claude/&lt;/code&gt;. Commit them unreviewed and every teammate's Claude Code session picks up a hook and an MCP server that points at an extension they may not have installed.&lt;/p&gt;

&lt;p&gt;Check what changed right after the first launch:&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;# From the solution root, after launching the extension once&lt;/span&gt;
git status &lt;span class="nt"&gt;--short&lt;/span&gt; .claude/ .mcp.json
git diff &lt;span class="nt"&gt;--&lt;/span&gt; .claude/settings.json .mcp.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then decide on purpose. Either commit the entries and make the extension a team requirement, or keep them out of your commits. Per the README, the extension writes its helper scripts (including the &lt;code&gt;vs-mcp-shim.ps1&lt;/code&gt; registered in &lt;code&gt;.mcp.json&lt;/code&gt;) into your workspace's &lt;code&gt;.claude/&lt;/code&gt; folder and merges its hook into &lt;code&gt;.claude/settings.json&lt;/code&gt; on every launch and connect. It overwrites the scripts unless you delete their &lt;code&gt;vs:auto-managed&lt;/code&gt; marker line.[3] So the &lt;code&gt;git status&lt;/code&gt; check above will list the &lt;code&gt;.ps1&lt;/code&gt; files too, and they come back after every launch. The &lt;a href="https://dev.to/tools/diff-checker"&gt;diff checker&lt;/a&gt; helps when you are comparing a teammate's settings file against yours.&lt;/p&gt;

&lt;p&gt;The README also flags a trust change. Since CLI 2.1.222, project hooks are tied to workspace trust, so after an update the hook can stop firing until you trust the folder again. The README's fix for a related issue is to remove duplicate project entries in &lt;code&gt;~/.claude.json&lt;/code&gt; that differ only by path casing.[3] Windows paths are case-insensitive, but that JSON file treats &lt;code&gt;C:\Repos\App&lt;/code&gt; and &lt;code&gt;c:\repos\app&lt;/code&gt; as two projects.&lt;/p&gt;

&lt;p&gt;On the network side, the firish bridge binds to 127.0.0.1 only, checks the lock-file token on every connection, never logs the token, and makes no network or LLM calls of its own.[3] That matches the protection model in Anthropic's own docs, where the lock file sits at &lt;code&gt;0600&lt;/code&gt; permissions inside a &lt;code&gt;0700&lt;/code&gt; directory.[1] To see which bridges are live on your machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# PowerShell: list active IDE lock files (one per running bridge)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-ChildItem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;USERPROFILE&lt;/span&gt;&lt;span class="s2"&gt;\.claude\ide"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*.&lt;/span&gt;&lt;span class="nf"&gt;lock&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the firish panel says "Waiting for CLI", its troubleshooting section says to click Launch Claude Code, or to run &lt;code&gt;/ide&lt;/code&gt; in a &lt;code&gt;claude&lt;/code&gt; terminal and pick Visual Studio.[3]&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Copilot's Claude support is a different product
&lt;/h2&gt;

&lt;p&gt;This causes a lot of confusion. VS Code can run Claude as a third-party agent harness inside Copilot Chat, controlled by the &lt;code&gt;chat.agentHost.claudeAgent.enabled&lt;/code&gt; setting and billed either through a Copilot subscription or your own API key.[9] That page covers VS Code only. We found no Microsoft or GitHub documentation of the same Claude harness in Visual Studio 2026.&lt;/p&gt;

&lt;p&gt;What Copilot in Visual Studio does share with Claude Code is the skills folder. GitHub's April 30, 2026 changelog says Visual Studio now discovers agent skills from &lt;code&gt;.claude/skills/&lt;/code&gt; and &lt;code&gt;.agents/skills/&lt;/code&gt; as well as &lt;code&gt;.github/skills/&lt;/code&gt;.[8] So a skill you write for Claude Code in that folder also shows up for Copilot in Visual Studio. That is useful if half your team uses each tool. It is not the same as running Claude Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which one to install
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your situation&lt;/th&gt;
&lt;th&gt;Pick&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| .NET on VS 2026, want native diffs and debugger context | &lt;strong&gt;firish, Claude Code for Visual Studio&lt;/strong&gt; |&lt;/p&gt;

&lt;p&gt;| VS 2022, want native diffs plus breakpoints and stepping, GPL-3.0 is acceptable | Corsinvest, cv4vs Agents (newest, 415 installs) |&lt;/p&gt;

&lt;p&gt;| VS 2022, or a team that also uses Codex or another agent | dliedke, Claude Code Extension for Visual Studio |&lt;/p&gt;

&lt;p&gt;| Solution pinned to VS 2017 or 2019 | nachum-shmilovitz-66, claude-code-visualstudio |&lt;/p&gt;

&lt;p&gt;| Native C++ or drivers, where the nachum-shmilovitz-66 README verifies its debugger on C#/.NET only and says C/C++ is expected to work but not yet tested | Terminal route plus a strict &lt;code&gt;CLAUDE.md&lt;/code&gt;; revisit when issue #15942 moves |&lt;/p&gt;

&lt;p&gt;| Locked-down machine, no third-party VSIX allowed | Terminal route |&lt;/p&gt;

&lt;p&gt;Whichever you choose, pin the CLI if your bridge is protocol-fragile. Setting &lt;code&gt;"autoUpdatesChannel": "stable"&lt;/code&gt; in &lt;code&gt;settings.json&lt;/code&gt; gives you a build that is about a week old and skips releases with major regressions,[7] which leaves the extension author time to catch up after a protocol change. Our &lt;a href="https://dev.to/blogs/claude-code-2-1-293-to-2-1-302-changelog-october-2026"&gt;October Claude Code changelog breakdown&lt;/a&gt; shows how often those releases land. For agent sessions that run unattended while you are in the debugger, set a hard budget first (see the &lt;a href="https://dev.to/product/claude-code-spend-guard"&gt;Claude Code Spend Guard&lt;/a&gt;). If you are still choosing between agents rather than editors, start with our &lt;a href="https://dev.to/blogs/best-ai-coding-tools-2026-complete-guide"&gt;roundup of the best AI coding tools for 2026&lt;/a&gt;, and see the &lt;a href="https://dev.to/blogs/claude-code-plugin-marketplace-package-publish-2026"&gt;plugin marketplace guide&lt;/a&gt; for packaging the skills and hooks you build along the way. For a ready-made set of settings, hooks and rules, see the &lt;a href="https://dev.to/product/claude-code-production-pack"&gt;Claude Code Production Pack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Install one extension, launch it once, and run &lt;code&gt;git diff -- .claude/settings.json .mcp.json&lt;/code&gt; before your next commit. Whatever shows up there is now part of your team's setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is there an official Claude Code extension for Visual Studio 2026?
&lt;/h3&gt;

&lt;p&gt;No. Anthropic ships plugins for VS Code (and forks such as Cursor) and for JetBrains IDEs, and points other editors to the CLI in an integrated terminal. Feature request #15942 for Visual Studio 2026 is still open.[1][2][12]&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the VS Code Claude Code extension work in Visual Studio?
&lt;/h3&gt;

&lt;p&gt;No. Visual Studio uses its own VSIX extension model, so VS Code extensions do not install in it. The Claude Code extension installs in VS Code and its forks only.[1]&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need a paid Claude plan to use these extensions?
&lt;/h3&gt;

&lt;p&gt;Usually. All four extensions drive the Claude Code CLI, and the CLI needs a Pro, Max, Ultra, Team, Enterprise or Console account, or a third-party provider such as Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry.[7] cv4vs Agents also documents profiles for other Anthropic-compatible endpoints, with OpenRouter and Ollama among its examples.[10]&lt;/p&gt;

&lt;h3&gt;
  
  
  Does any extension support Visual Studio 2022?
&lt;/h3&gt;

&lt;p&gt;Yes. The dliedke and cv4vs Agents extensions support 2022 and 2026, and the nachum-shmilovitz-66 project supports 2017 through 2026. The firish extension is 2026 only, with a 2022 build "planned if there is demand".[3][5][6][11]&lt;/p&gt;

&lt;h3&gt;
  
  
  Can Claude Code debug native C++ in Visual Studio?
&lt;/h3&gt;

&lt;p&gt;None of these extensions documents tested native C++ debugger inspection. The firish debugger features are documented for managed .NET code. The nachum-shmilovitz-66 README verifies its debugger on C#/.NET only and says C/C++ is expected to work but not yet tested. The dliedke listing only promises to send unhandled exceptions with their stack trace, without naming a language. The cv4vs Agents listing names breakpoints, stepping and locals but not which runtimes they cover. Claude can still read C++ compiler errors through firish's Error List integration, and cv4vs Agents says its diagnostics work in C++.[3][5][6][11]&lt;/p&gt;

&lt;h3&gt;
  
  
  Will a Claude Code update break my extension?
&lt;/h3&gt;

&lt;p&gt;It can. The firish README calls the IDE protocol "undocumented and version-fragile". Use the stable update channel and check the extension's release notes after a CLI update.[3][7]&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/ide-integrations" rel="noopener noreferrer"&gt;IDE integrations, Claude Code Docs, Anthropic (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/anthropics/claude-code/issues/15942" rel="noopener noreferrer"&gt;Add support for Visual Studio 2026 Integration, anthropics/claude-code issue #15942, opened January 1, 2026 (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/firish/claude_code_vs" rel="noopener noreferrer"&gt;firish/claude_code_vs README, GitHub (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=firish.bridgev1" rel="noopener noreferrer"&gt;Claude Code for Visual Studio, Visual Studio Marketplace (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=dliedke.ClaudeCodeExtension" rel="noopener noreferrer"&gt;Claude Code Extension for Visual Studio, Visual Studio Marketplace (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/nachum-shmilovitz-66/claude-code-visualstudio" rel="noopener noreferrer"&gt;nachum-shmilovitz-66/claude-code-visualstudio README, GitHub (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/setup" rel="noopener noreferrer"&gt;Advanced setup, Claude Code Docs, Anthropic (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.blog/changelog/2026-04-29-github-copilot-in-visual-studio-april-update/" rel="noopener noreferrer"&gt;GitHub Copilot in Visual Studio, April update, GitHub Changelog, April 30, 2026 (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.visualstudio.com/docs/copilot/agents/third-party-agents" rel="noopener noreferrer"&gt;Third-party agents, Visual Studio Code Docs (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/Corsinvest/cv4vs-agents" rel="noopener noreferrer"&gt;Corsinvest/cv4vs-agents README, GitHub (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=Corsinvest.cv4vs-agents" rel="noopener noreferrer"&gt;cv4vs Agents, Visual Studio Marketplace (accessed November 2, 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  12. &lt;a href="https://code.claude.com/docs/en/jetbrains" rel="noopener noreferrer"&gt;JetBrains IDEs, Claude Code Docs, Anthropic (accessed November 2, 2026)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/claude-code-visual-studio-2026-extension-setup-guide" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>visualstudio</category>
    </item>
    <item>
      <title>Claude API OpenTelemetry Tracing: Console Setup for 2026</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Tue, 20 Oct 2026 19:16:46 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/claude-api-opentelemetry-tracing-console-setup-for-2026-bdp</link>
      <guid>https://dev.to/akaranjkar08/claude-api-opentelemetry-tracing-console-setup-for-2026-bdp</guid>
      <description>&lt;p&gt;&lt;strong&gt;Since 14 October 2026 the Claude API can send one OpenTelemetry trace per request or Managed Agents session to the observability backend you already run, and the first thing to decide is the destination's content mode: Metadata only or Full content.&lt;/strong&gt;[4] Metadata only exports identifiers, timing, status and token counts. Full content also exports prompts and responses, and they then live under your backend's retention rules, not Anthropic's.[2] The feature is in public beta. An organization admin adds a destination in the Claude Console, you need no code changes for the server-side half, and an optional SDK half adds client spans that join the same trace. This post covers what each half does, the exact Console fields, a Honeycomb walk-through, the span names worth knowing, and what the docs say about limits and delivery.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Two independent halves: API spans (emitted by Anthropic, delivered to a destination you register) and SDK spans (emitted by the &lt;code&gt;anthropic&lt;/code&gt; package in your process).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only an organization admin can add a destination. Developers can view them.[1]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The destination content mode and the SDK content mode are separate settings. The SDK setting has no effect on API spans.[3]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delivery is at least once and best effort. Do not build billing from spans; use the Usage and Cost API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Up to 10 destinations per organization, HTTPS on port 443, a hostname rather than an IP, and no &lt;code&gt;/v1/traces&lt;/code&gt; suffix in the base URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Claude Code and Agent SDK telemetry is a different system with different environment variables.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What you get: server-side spans and client-side spans
&lt;/h2&gt;

&lt;p&gt;Anthropic describes the feature as OpenTelemetry trace export from Claude Managed Agents, the Messages API and the Claude SDKs, with traces following the OpenTelemetry GenAI semantic conventions.[4] In practice that is two separate pipelines that you can run alone or together.[2]&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;SDK spans&lt;/th&gt;
&lt;th&gt;API spans&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Emitted by | The &lt;code&gt;anthropic&lt;/code&gt; package inside your process | The Claude API, inside Anthropic |&lt;/p&gt;

&lt;p&gt;| Configured | In code or with &lt;code&gt;ANTHROPIC_OPEN_TELEMETRY_*&lt;/code&gt; variables, plus your own OTel exporter | As a destination in the Claude Console, Admin API or CLI |&lt;/p&gt;

&lt;p&gt;| Who can turn it on | Anyone who can change the application | Organization admin |&lt;/p&gt;

&lt;p&gt;| Covers | Each request your client sends, tools run by the tool runner, other calls such as file uploads | Each model run, server tools such as web search, compaction, Managed Agents turns |&lt;/p&gt;

&lt;p&gt;| Span kind | CLIENT for requests, INTERNAL for tools | SERVER for requests, INTERNAL for steps |&lt;/p&gt;

&lt;p&gt;| Content control | &lt;code&gt;traces.content_mode&lt;/code&gt; on the client | Content mode on the destination |&lt;/p&gt;

&lt;p&gt;| Coverage | Clients that use the SDK | Any client, SDK or not |&lt;/p&gt;

&lt;p&gt;The SDK sends a W3C &lt;code&gt;traceparent&lt;/code&gt; header and the API parents its spans under it, so both halves land in one trace when they go to the same backend.[3] If your sampler drops a trace, the sampled flag in that header is off and the API emits nothing for the request. A request that arrives with no &lt;code&gt;traceparent&lt;/code&gt; still gets API spans, in a new trace.[3]&lt;/p&gt;

&lt;p&gt;Which half do you want? If you only need to know why a Managed Agents session went sideways or what a model run cost in tokens, the destination alone is enough, and it covers every client including ones you do not control. If you want the span for your own tool code, or the request wrapped inside your web handler's span, add the SDK half. Teams already tracking agent behavior at the application layer can pair this with the &lt;a href="https://dev.to/product/ai-agent-failure-mode-instrumentation-pack"&gt;AI Agent Observability and Failure-Mode Instrumentation Pack&lt;/a&gt; for the alerting side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decide the content mode before you click Add destination
&lt;/h2&gt;

&lt;p&gt;Every destination and every SDK client has a content mode.[2]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Metadata only&lt;/strong&gt; (&lt;code&gt;metadata_only&lt;/code&gt; in the SDK) is the default. Spans carry identifiers, timing, status, token counts, and text you choose to expose, such as agent and tool names and MCP server names.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Full content&lt;/strong&gt; (&lt;code&gt;content&lt;/code&gt; in the SDK) adds model prompts and responses, including the system prompt, the input messages and the output messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Attributes that hold prompts and responses are tagged Content in the span reference.[8]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full content is what makes traces useful for debugging and for building evals from real traffic. It is also a copy of your users' conversations, sitting in a third-party system. The docs say plainly that the platform stores it under its own access and retention settings and that you should check those meet your requirements.[2] The cookbook's production checklist is blunter: keep &lt;code&gt;metadata_only&lt;/code&gt; until your data policy allows otherwise.[3]&lt;/p&gt;

&lt;p&gt;Three details that change the decision:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Even in Metadata only, the SDK still exports tool names and descriptions, agent names, MCP server names and the &lt;code&gt;conversation_id&lt;/code&gt; you set, so do not put user data in that ID.[3]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your organization has a HIPAA, FERPA or K-12 data-handling restriction with Anthropic, destinations export only metadata whatever the setting says. SDK spans are not affected by that rule.[2]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With zero data retention, Full content is still allowed for Messages API requests, and the API holds the exported content in memory only until delivery. Claude Managed Agents is not ZDR eligible, and its retention is unchanged by OpenTelemetry.[2]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fourth thing is size. With Full content each span holds up to 0.75 MB of content by default. Over the limit, request spans drop the system prompt and the earliest messages first and set &lt;code&gt;anthropic.content.truncated&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.[2] If your backend rejects large payloads, lower the cap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up a Console destination
&lt;/h2&gt;

&lt;p&gt;You need the admin role in the Console organization, an OTLP/HTTP endpoint that accepts protobuf at an HTTPS URL on port 443, and credentials for it. If you run your own OpenTelemetry Collector, its OTLP/HTTP receiver listens on port 4318 by default, so put HTTPS on 443 in front of it or reconfigure the receiver.[1]&lt;/p&gt;

&lt;p&gt;Open the organization's OpenTelemetry settings page in the Console, click &lt;strong&gt;Add destination&lt;/strong&gt;, and fill in the fields below.[1]&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What to enter&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Provider | A listed platform, or Custom. A listed platform replaces the endpoint and headers fields with its own details, such as an API key. |&lt;/p&gt;

&lt;p&gt;| Name | Optional label. |&lt;/p&gt;

&lt;p&gt;| OTLP endpoint URL | Base HTTPS URL with a hostname, not an IP. A path prefix is allowed. Do not add &lt;code&gt;/v1/traces&lt;/code&gt;, because the API adds it. |&lt;/p&gt;

&lt;p&gt;| Request headers | Your platform's auth header. The Console does not show the values again after you save. |&lt;/p&gt;

&lt;p&gt;| Content mode | Metadata only or Full content. |&lt;/p&gt;

&lt;p&gt;| Workspaces | All, Selected, or All except. |&lt;/p&gt;

&lt;p&gt;| OTLP traces endpoint URL | Optional, under Advanced settings. Use it when your platform receives traces somewhere other than the base URL plus &lt;code&gt;/v1/traces&lt;/code&gt;. Same host as the base URL. |&lt;/p&gt;

&lt;p&gt;| Maximum content size in MB | Optional, Full content only. Empty means as much as the API allows. |&lt;/p&gt;

&lt;p&gt;Save it, open the destination's More actions menu and click &lt;strong&gt;Test&lt;/strong&gt;. A test span named &lt;code&gt;anthropic.test&lt;/code&gt; should reach your platform.[1] Then send a real request from the playground or your app. The Delivery column should read Healthy within about a minute, and in your backend you filter on &lt;code&gt;service.name&lt;/code&gt; equal to &lt;code&gt;claude-platform&lt;/code&gt; to find the API spans.[1]&lt;/p&gt;

&lt;p&gt;Prefer code over clicking? The same settings exist in the Admin API behind the &lt;code&gt;telemetry-destinations-2026-08-11&lt;/code&gt; beta header, with a matching CLI command and SDK methods. The create call takes &lt;code&gt;endpoint_url&lt;/code&gt;, &lt;code&gt;headers&lt;/code&gt;, &lt;code&gt;traces.content_mode&lt;/code&gt; and &lt;code&gt;workspaces.type&lt;/code&gt;.[1]&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing workspaces
&lt;/h3&gt;

&lt;p&gt;A destination only receives spans from workspaces it covers, and the API sends to every enabled destination that covers the workspace where the request or session runs. All includes the Default Workspace and workspaces created later. That is a useful privacy lever: send the production workspace with Metadata only to your main backend and a staging workspace with Full content to a separate project.[1]&lt;/p&gt;

&lt;h2&gt;
  
  
  One backend end to end: Honeycomb
&lt;/h2&gt;

&lt;p&gt;Honeycomb has a Claude Platform page, and it is the cleanest example because the Console has a built-in Honeycomb provider.[6]&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;In the Console, open the OpenTelemetry settings and clear any workspace filter so it shows All.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click Add destination and pick &lt;strong&gt;Honeycomb&lt;/strong&gt; as the Provider. Optionally name it, for example Honeycomb production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep the default US region, which uses &lt;code&gt;https://api.honeycomb.io&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste a Honeycomb Ingest API key. Honeycomb notes that the key needs permission to create datasets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Leave Dataset empty. Honeycomb names it &lt;code&gt;claude-platform&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose the content mode and the workspaces, then click Add destination.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;EU teams cannot pick EU in the region picker. Honeycomb documents two workarounds: edit the destination and set the OTLP endpoint URL to &lt;code&gt;https://api.eu1.honeycomb.io&lt;/code&gt;, or choose Custom with that URL and a request header named &lt;code&gt;x-honeycomb-team&lt;/code&gt; holding the ingest key.[6]&lt;/p&gt;

&lt;p&gt;To find a trace, open the environment that matches your key, go to Query, choose the &lt;code&gt;claude-platform&lt;/code&gt; dataset and run the query, then click a point and View trace. Managed Agents conversations show up in Honeycomb's Agent Timeline, while Messages API requests carry no conversation ID, so you find those as plain traces.[6]&lt;/p&gt;

&lt;p&gt;Grafana Cloud has a dedicated guide for Claude Platform traces, linked from Anthropic's overview.[2] Its general OTLP page shows the endpoint pattern &lt;code&gt;https://otlp-gateway-&amp;lt;REGION&amp;gt;.grafana.net/otlp&lt;/code&gt; and says to take the exact OTLP endpoint and a generated token from your stack's OpenTelemetry tile.[7] Anthropic's overview lists Datadog, Langfuse, LangSmith, New Relic, PostHog, Sentry, Splunk, Arize AI, Braintrust and Databricks as partner platforms too, each with its own setup page. Follow each vendor's own page for its exact endpoint and headers.[2]&lt;/p&gt;

&lt;h2&gt;
  
  
  What a trace looks like
&lt;/h2&gt;

&lt;p&gt;Span names follow one rule. They start with &lt;code&gt;anthropic.&lt;/code&gt; followed by the API method with dots and without &lt;code&gt;beta&lt;/code&gt;, so &lt;code&gt;client.messages.create()&lt;/code&gt; becomes &lt;code&gt;anthropic.messages.create&lt;/code&gt; and &lt;code&gt;client.beta.sessions.events.send()&lt;/code&gt; becomes &lt;code&gt;anthropic.sessions.events.send&lt;/code&gt;.[3] Under a Messages API request, the API adds spans for each model request and for each server tool or MCP connector tool it runs.[2]&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Span&lt;/th&gt;
&lt;th&gt;Emitted by&lt;/th&gt;
&lt;th&gt;What it marks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| &lt;code&gt;anthropic.messages.create&lt;/code&gt; | SDK (CLIENT) and API (SERVER) | One Messages API request |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;anthropic.model_request&lt;/code&gt; | API | One model run inside a request or turn |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;anthropic.messages.tool_runner&lt;/code&gt; | SDK | The whole tool-runner loop |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;anthropic.custom_tool_use &amp;lt;name&amp;gt;&lt;/code&gt; | SDK | A tool you run yourself |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;anthropic.tool_use &amp;lt;name&amp;gt;&lt;/code&gt; | API | A server tool such as web search, or a prebuilt toolset tool such as bash |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;anthropic.mcp_tool_use &amp;lt;name&amp;gt;&lt;/code&gt; | API and SDK | An MCP tool; the API span carries &lt;code&gt;anthropic.mcp.server.name&lt;/code&gt; |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;anthropic.session.turn&lt;/code&gt; | API | One agent turn in a Managed Agents session |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;anthropic.session.outcome_evaluation&lt;/code&gt; | API | An outcome evaluation in a session |&lt;/p&gt;

&lt;p&gt;| &lt;code&gt;anthropic.compaction&lt;/code&gt; | API | Context compaction |&lt;/p&gt;

&lt;p&gt;Attribute names come from the GenAI conventions plus an &lt;code&gt;anthropic.&lt;/code&gt; namespace. The ones you will actually query on:[3]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gen_ai.operation.name&lt;/code&gt; with values &lt;code&gt;chat&lt;/code&gt;, &lt;code&gt;invoke_agent&lt;/code&gt; and &lt;code&gt;execute_tool&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gen_ai.request.model&lt;/code&gt; and &lt;code&gt;gen_ai.response.model&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;gen_ai.usage.input_tokens&lt;/code&gt; and &lt;code&gt;gen_ai.usage.output_tokens&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;anthropic.message.stop_reason&lt;/code&gt;, which the cookbook says to alert on when it equals &lt;code&gt;max_tokens&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;anthropic.request.id&lt;/code&gt;, which matches the &lt;code&gt;request-id&lt;/code&gt; header and joins SDK spans to API spans&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;anthropic.session.id&lt;/code&gt; and &lt;code&gt;gen_ai.conversation.id&lt;/code&gt; for grouping a whole session or one thread of it&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One gotcha will bite anyone building cost dashboards. &lt;code&gt;gen_ai.usage.input_tokens&lt;/code&gt; already includes cache-read and cache-creation tokens, so adding the cache attributes on top double counts.[3] Token usage also repeats across several spans of one request. For a Messages API request, sum either the API &lt;code&gt;anthropic.messages.create&lt;/code&gt; spans or their &lt;code&gt;anthropic.model_request&lt;/code&gt; children, never both, plus &lt;code&gt;anthropic.compaction&lt;/code&gt; if present. For a Managed Agents session, sum &lt;code&gt;anthropic.model_request&lt;/code&gt; and &lt;code&gt;anthropic.session.outcome_evaluation&lt;/code&gt;.[2] If you want a dollar figure before you build any of that, &lt;a href="https://dev.to/tools/agent-run-cost-simulator"&gt;the agent run cost simulator&lt;/a&gt; gives a quick estimate from run length and token assumptions.&lt;/p&gt;

&lt;p&gt;To read a Managed Agents session as a transcript, group spans by &lt;code&gt;gen_ai.conversation.id&lt;/code&gt; for one thread, or by &lt;code&gt;anthropic.session.id&lt;/code&gt; across traces for the whole session, since a session's spans can sit in several traces.[2] For background on the sandbox those sessions run in, see &lt;a href="https://dev.to/blogs/claude-managed-agents-self-hosted-sandbox-mcp-tunnels-enterprise-guide-2026"&gt;our Managed Agents self-hosted sandbox guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the SDK half
&lt;/h2&gt;

&lt;p&gt;The Python cookbook registers a tracer provider before the first traced call and then builds the client with no tracing arguments. The OTLP exporter reads the standard &lt;code&gt;OTEL_EXPORTER_OTLP_ENDPOINT&lt;/code&gt; and &lt;code&gt;OTEL_EXPORTER_OTLP_HEADERS&lt;/code&gt; variables.[3] To switch the client to Full content, pass &lt;code&gt;open_telemetry={"traces": {"content_mode": "content"}}&lt;/code&gt; or set &lt;code&gt;ANTHROPIC_OPEN_TELEMETRY_TRACES_CONTENT_MODE=content&lt;/code&gt;. Defaults are propagation on, &lt;code&gt;metadata_only&lt;/code&gt;, and a 750,000-byte content cap.[3]&lt;/p&gt;

&lt;p&gt;Version check: the cookbook installs &lt;code&gt;anthropic&amp;gt;=1.14.0&lt;/code&gt; (its sample output still prints 1.13.0).[3] PyPI shows 1.14.0 published on 14 October 2026, the launch day, and 1.16.0 as the latest on 20 October, so run &lt;code&gt;pip show anthropic&lt;/code&gt; and upgrade if you are below 1.14.0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Code and the Agent SDK are a different setup
&lt;/h2&gt;

&lt;p&gt;Do not mix these up. Claude Code and the Agent SDK export their own telemetry from the CLI process, enabled with &lt;code&gt;CLAUDE_CODE_ENABLE_TELEMETRY=1&lt;/code&gt; and a per-signal exporter variable, with traces additionally needing &lt;code&gt;CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1&lt;/code&gt;.[5] Their spans are named &lt;code&gt;claude_code.interaction&lt;/code&gt;, &lt;code&gt;claude_code.llm_request&lt;/code&gt; and &lt;code&gt;claude_code.tool&lt;/code&gt;, and the service name defaults to &lt;code&gt;claude-code&lt;/code&gt;.[5] The Agent SDK docs add one hard rule: never set the &lt;code&gt;console&lt;/code&gt; exporter, because the SDK uses standard output as its message channel.[5] Content there is opt-in through separate variables such as &lt;code&gt;OTEL_LOG_USER_PROMPTS&lt;/code&gt;.[5] If you track what Claude Code itself changes between releases, our &lt;a href="https://dev.to/blogs/claude-code-2-1-293-to-2-1-302-changelog-october-2026"&gt;Claude Code 2.1.293 to 2.1.302 changelog&lt;/a&gt; is the place to start.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits, delivery and beta caveats
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;What the docs say&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Destinations per organization | 10, including disabled ones |&lt;/p&gt;

&lt;p&gt;| Selected workspaces per destination | 1,000 |&lt;/p&gt;

&lt;p&gt;| Request headers per destination | 20; name up to 128 bytes, value up to 4,096 bytes, all together 16,384 bytes |&lt;/p&gt;

&lt;p&gt;| Endpoint URL length | 2,048 characters |&lt;/p&gt;

&lt;p&gt;| Delivery guarantee | At least once, best effort. Spans can arrive twice or be lost. |&lt;/p&gt;

&lt;p&gt;| Compression | First request is gzip. On a 400 or 415 the API resends without compression. |&lt;/p&gt;

&lt;p&gt;| Retries | A limited number of later retries after timeouts, connection, TLS or DNS failures, and 408, 429 or 5xx responses |&lt;/p&gt;

&lt;p&gt;| Timeouts | 5 seconds for the TLS handshake, 5 seconds for response headers, 10 seconds per delivery in total |&lt;/p&gt;

&lt;p&gt;| Auto-disable | On any 3xx redirect, on a hostname that resolves to a non-public IP, or after 24 hours of failed deliveries |&lt;/p&gt;

&lt;p&gt;All of that comes from the API setup page.[1] Two practical consequences. First, deduplicate on trace ID plus span ID if your backend does not do it for you. Second, a redirecting endpoint is fatal, so use the final URL, not the one your vendor forwards from.&lt;/p&gt;

&lt;p&gt;On sampling, the docs say nothing about Anthropic-side sampling rates. What they do say is that the sampled flag in your &lt;code&gt;traceparent&lt;/code&gt; controls whether the API emits spans for a request at all.[1] On cost, neither the launch article nor the docs state a price for the export, so treat that as unconfirmed and watch your backend's ingest bill instead.[4]&lt;/p&gt;

&lt;p&gt;The beta wording is direct: span names and attributes can change during the beta, and the feature is provided under your agreement with Anthropic including the Beta Services section of the Service Specific Terms.[8] Pin your dashboards to a small set of attributes and expect to touch them again. And do not bill from spans. The overview says exported spans are not a complete record of API usage; use the Usage API for that.[2]&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do I need to change my application code to get API spans?
&lt;/h3&gt;

&lt;p&gt;No. The destination is configured in the Console and covers every client in the organization, SDK or not. Code changes are only needed if you also want SDK spans or want API spans nested under your own spans.[1]&lt;/p&gt;

&lt;h3&gt;
  
  
  Who can add a destination?
&lt;/h3&gt;

&lt;p&gt;The admin role in the Console organization. With the developer role you can view destinations. A developer who is also a Workspace Admin can add or remove their own workspace on a Selected destination.[1]&lt;/p&gt;

&lt;h3&gt;
  
  
  Does setting the SDK to metadata_only stop prompts reaching my backend?
&lt;/h3&gt;

&lt;p&gt;Not for API spans. The destination content mode is independent, and the SDK content setting has no effect on API spans. Set both deliberately.[3]&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use these spans to calculate my bill?
&lt;/h3&gt;

&lt;p&gt;No. Delivery is best effort, callers can switch off sampling per request, and Anthropic points to the Usage API for accounting.[2]&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://platform.claude.com/docs/en/manage-claude/opentelemetry/api" rel="noopener noreferrer"&gt;Set up OpenTelemetry with the Claude API (Claude docs)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://platform.claude.com/docs/en/manage-claude/opentelemetry" rel="noopener noreferrer"&gt;OpenTelemetry for the Claude API (Claude docs)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://platform.claude.com/cookbook/observability-opentelemetry-tracing" rel="noopener noreferrer"&gt;Tracing Claude API and Managed Agents with OpenTelemetry (Claude cookbook)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://claude.com/resources/articles/agent-observability-on-the-claude-platform" rel="noopener noreferrer"&gt;Agent observability on the Claude Platform (Anthropic, 14 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/agent-sdk/observability" rel="noopener noreferrer"&gt;Observability with OpenTelemetry (Agent SDK docs)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.honeycomb.io/send-data/use-cases/claude-platform" rel="noopener noreferrer"&gt;Send Claude Platform traces to Honeycomb (Honeycomb docs)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://grafana.com/docs/grafana-cloud/send-data/otlp/send-data-otlp/" rel="noopener noreferrer"&gt;Send OTLP data to Grafana Cloud (Grafana docs)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  8. &lt;a href="https://platform.claude.com/docs/en/api/opentelemetry/spans" rel="noopener noreferrer"&gt;OpenTelemetry span reference (Claude docs)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/claude-api-opentelemetry-tracing-managed-agents-setup-2026" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudeapi</category>
      <category>managedagents</category>
      <category>claudeopentelemetry</category>
      <category>claudeconsole</category>
    </item>
    <item>
      <title>Muse Spark Open: Hardware, License and Cost to Self-Host</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Tue, 20 Oct 2026 19:16:11 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/muse-spark-open-hardware-license-and-cost-to-self-host-4gah</link>
      <guid>https://dev.to/akaranjkar08/muse-spark-open-hardware-license-and-cost-to-self-host-4gah</guid>
      <description>&lt;p&gt;&lt;strong&gt;Almost nobody should self-host Muse Spark Open: the model card asks for at least 700 GB of VRAM even in NVFP4, so for anything under billions of tokens a month the hosted endpoint at $1.25 per million input tokens is the cheaper and simpler route.&lt;/strong&gt; Meta released the open-weight 816B-parameter mixture-of-experts model on 15 October 2026[1]. Only 42B parameters are active per token, which helps speed but does nothing for memory: every expert still has to sit in RAM. Below: the weight arithmetic with the real file sizes, a comparison of three ways to run it, what the license says, and how Meta's benchmark numbers stack up against the reported competition.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;816B total parameters, 42B active, 1M-token context, BF16 and NVFP4 weights[2].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The BF16 repo holds 1.64 TB of safetensors across 65 shards[3]; the NVFP4 repo is 533 GB across 127 shards[8]. The card lists 700 GB of VRAM for NVFP4 and 2 TB for BF16.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Two M5 Ultra Mac Studios (up to 512 GB unified memory each) can hold the model in an MLX quant, per Meta[1]. Eight 80 GB H100s (640 GB) fall under the card's 700 GB line, and the NVFP4 build targets Blackwell GPUs anyway[8].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;OpenRouter listed it at $1.25 input and $4.25 output per million tokens on 20 October 2026[4].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;License: use, fine-tuning, distillation and redistribution are allowed. Selling it as a Model-as-a-Service (API access to outputs) once you and your affiliates pass $20 million in gross revenue in any consecutive 12 months needs a separate agreement with Meta[7].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Meta's own table has it trailing Kimi K3, GLM 5.3 and Qwen3.8 on Terminal-Bench 2.1 and the Artificial Analysis Intelligence Index[5].&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Meta actually released
&lt;/h2&gt;

&lt;p&gt;Muse Spark Open is the open-weight sibling of the earlier closed Muse Spark; our &lt;a href="https://dev.to/blogs/meta-muse-spark-ai-model-small-models-obsolete-2026"&gt;earlier Muse Spark post&lt;/a&gt; covers that one. This release is natively multimodal, built for coding and agentic work, and carries a 1M-token context window[1].&lt;/p&gt;

&lt;p&gt;The model card gives the architecture: a mixture-of-experts with 256 experts and 8 activated per token, 62 layers, a hidden dimension of 8192, and a 1.8B-parameter perception encoder. The Hugging Face metadata reports 822B parameters, the headline figure of 816B comes from Meta, and the gap is probably the encoder and embeddings, though the card does not say so[2].&lt;/p&gt;

&lt;p&gt;Weights ship in BF16 and NVFP4. Inference support listed on the card covers SGLang, vLLM, Hugging Face Transformers, TensorRT-LLM, Unsloth and llama.cpp, with MLX for the Mac Studio setup[2]. Meta lists API hosting on Baseten, Fireworks AI, Groq, Modal, Nebius, OpenRouter and Together AI, with weight downloads also offered through Amazon SageMaker AI, Google Cloud Model Garden, Hugging Face and Microsoft Foundry Models[1].&lt;/p&gt;

&lt;h2&gt;
  
  
  The memory math, with the real file sizes
&lt;/h2&gt;

&lt;p&gt;Weight memory is parameter count times bytes per parameter. It is the floor, not the total.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;BF16:&lt;/strong&gt; 816 billion x 2 bytes = 1,632 GB, about 1.63 TB.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NVFP4:&lt;/strong&gt; 816 billion x 0.5 byte = 408 GB is the floor. The real NVFP4 repo (Muse-Spark-Open-816B-A42B-NVFP4) is 533 GB across 127 shards, because of the per-block scale factors and tensors kept at higher precision[8].&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The arithmetic lines up with the repo. The safetensors shards total 1,644,333,393,864 bytes, or 1.64 TB (1.50 TiB), spread over 65 files: 62 shards of roughly 26 GB (two at about 29.6 GB), two of about 0.55 GB and one of about 3.8 GB[3]. The extra 12 GB or so over the 816B x 2-byte estimate is the roughly 6B parameters the headline figure leaves out (the 1.8B perception encoder and the two 1.66B embedding matrices); the Hugging Face metadata counts 822B parameters, almost all BF16 plus about 0.13B in F32[2].&lt;/p&gt;

&lt;p&gt;The card then asks for more than the weights alone: at least 700 GB of VRAM for NVFP4 and 2 TB for BF16[2]. The NVFP4 checkpoint is 533 GB, so the card's 700 GB figure leaves roughly 167 GB for KV cache, activations and runtime overhead (the card does not break the number down). Push toward the 1M-token window and the cache grows with it. No KV-cache size per token is published in the model card or launch posts, so treat any long-context budget as a guess until measured.&lt;/p&gt;

&lt;p&gt;One point that trips people up: 42B active parameters means each token touches about 5% of the weights, which makes decoding far cheaper per token than a dense 816B model. It does not let you load 42B worth of experts. The router can pick any expert on any token, so all of them stay resident.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three ways to run it, side by side
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Memory available&lt;/th&gt;
&lt;th&gt;What fits&lt;/th&gt;
&lt;th&gt;Cost basis&lt;/th&gt;
&lt;th&gt;Makes sense when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| 2x Mac Studio (M5 Ultra, MLX) | Up to 512 GB each, 1,024 GB pooled[1] | A 3-bit or 4-bit MLX quant (Hugging Face points to the oQ3e and oQ4e community builds[8]). Not BF16 (2 TB). The NVFP4 checkpoint targets NVIDIA Blackwell, not Apple silicon. | Hardware purchase, then power. Meta publishes no tokens-per-second figure; Hugging Face's launch post reports 18 tokens/s for a 2-bit llama.cpp quant on a Mac Ultra. | Private local work, one or two users, data that cannot leave the building |&lt;/p&gt;

&lt;p&gt;| 8x 80 GB H100-class server | 640 GB total | Neither build by the card numbers. NVFP4 needs 700 GB and Blackwell-class GPUs. | Hourly GPU rental or purchase | Not on its own. Step up to 141 GB H200-class parts (8x = 1,128 GB), the NVFP4 recipe Hugging Face validates for the full 1M-token context. |&lt;/p&gt;

&lt;p&gt;| Hosted API | Provider's problem | The full model, up to the 1M window | Per token: $1.25 input and $4.25 output per million on OpenRouter[4] | Everything below sustained, high-volume traffic |&lt;/p&gt;

&lt;p&gt;The H100 row is plain arithmetic: 8 x 80 GB = 640 GB, which is under the 700 GB the card lists. That does not mean it is impossible with aggressive tuning, only that the card does not claim it. A node of 141 GB accelerators clears the bar, and Hugging Face validates it: its Inference Endpoints recipe runs the NVFP4 build on 8 x H200 141 GB at the full 1,048,576-token context, or on 8 x RTX Pro 6000 98 GB at 131,072 tokens[8]. The vLLM reference for NVFP4 needs Blackwell-class GPUs, so an H100 box is out. Check the vLLM and SGLang docs for the current tested configuration before you rent anything.&lt;/p&gt;

&lt;p&gt;On the Mac route, Meta calls it "the first model in its class to run on your desktop using two Apple M5 Ultra Mac Studios with the latest MLX framework" and says the two machines behave "like one supercomputer with a terabyte of unified memory"[1]. Read that as a capability claim, not a speed claim. Memory bandwidth on the chip is listed at 1.2 TB/s, which sets the ceiling for decoding. The only measured figure published is Hugging Face's 18 tokens/s for a 2-bit llama.cpp quant on a Mac Ultra[8], a lossy build, so it does not extrapolate to the MLX setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  What hosted access costs
&lt;/h2&gt;

&lt;p&gt;On 20 October 2026 the OpenRouter model list showed Muse Spark Open at $1.25 per million input tokens and $4.25 per million output tokens, with a context of about 1.05M tokens. Five providers were listed (Modal, Together, Nebius, Fireworks and BaseTen), all at the same price[4]. Providers reached directly rather than through OpenRouter (Groq, Baseten, Modal and the rest) may price differently; their own rate cards were not checked, so confirm before you commit. OpenRouter's model page also notes the model is not currently available through EU in-region routing[6].&lt;/p&gt;

&lt;p&gt;A worked example with those listed prices: a coding agent that reads 10 million input tokens and writes 2 million output tokens in a month pays 10 x $1.25 + 2 x $4.25 = $12.50 + $8.50 = $21.00. Use the &lt;a href="https://dev.to/tools/ai-model-cost-calculator"&gt;AI model cost calculator&lt;/a&gt; to plug in your own volumes, and the &lt;a href="https://dev.to/tools/token-counter"&gt;AI token counter&lt;/a&gt; to measure what your prompts really weigh before you estimate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where self-hosting breaks even
&lt;/h3&gt;

&lt;p&gt;The break-even is a division you can do yourself: monthly hardware cost divided by your blended price per million tokens. At a 4:1 input-to-output mix, the listed prices blend to (4 x $1.25 + $4.25) / 5 = $1.85 per million tokens. Take a hypothetical $10,000 per month of dedicated GPU capacity. You would need to push about 5.4 billion tokens through it every month, with the cluster busy, just to match the API bill. That is the figure of $10,000 divided by $1.85, rounded. The $10,000 is an illustration, not a quote; substitute your real rental or amortised cost.&lt;/p&gt;

&lt;p&gt;Two things push the number against you. Idle GPUs bill the same as busy ones, and you also carry the engineering time for upgrades, batching and failure handling. Two things push it for you: a hard data-residency requirement, and traffic so steady that the hardware never idles.&lt;/p&gt;

&lt;h2&gt;
  
  
  The license, clause by clause
&lt;/h2&gt;

&lt;p&gt;The weights ship under the Muse Model License, a version titled "Muse Spark Open" and dated 15 October 2026[7]. The clauses below are taken from the full LICENSE.md text (8,299 bytes[3])[7]. The weights are also gated: you must accept the license on Hugging Face and submit a form before you can download. Read the file itself before you build a product on this.&lt;/p&gt;

&lt;p&gt;What the license allows: use, modification including fine-tuning, distillation, merging, publishing, sublicensing and selling copies, subject to conditions. Meta claims no ownership of outputs.&lt;/p&gt;

&lt;p&gt;What it restricts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Attribution.&lt;/strong&gt; You must prominently display "Built with Muse Spark Open" in the user interface of each product or service that uses the model or any Derivative, or in its documentation, website or settings menu. Derivatives include any model fine-tuned, distilled or otherwise improved using the weights or their outputs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model-as-a-Service threshold.&lt;/strong&gt; If you or your affiliates give third parties API-style access to the model (or a Derivative) where they receive its outputs, and your combined gross revenue passes $20 million in any consecutive 12 months, you must notify Meta and sign a separate written agreement before offering it. Internal use, research, any commercial activity that is not Model as a Service, and using it to power features of your own product are excepted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Usage Policy.&lt;/strong&gt; It is incorporated into the license and prohibits illegal activity, harassment, unlicensed professional practice, malware and deceptive content.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Age.&lt;/strong&gt; Not intended for individuals under 18.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No warranty.&lt;/strong&gt; The software is provided "AS IS" and Meta disclaims liability for derivatives.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meta describes the terms as limited commercial terms that let many developers use the model for free[1]. The practical read: a startup, an agency or an internal tool is comfortably inside the line. A company reselling hosted inference at scale is not. This is a custom license, not Apache 2.0 or MIT, so it will not pass a procurement checklist that only whitelists OSI-approved licenses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarks: Meta's numbers and the competition
&lt;/h2&gt;

&lt;p&gt;Everything in this table comes from the comparison table on Meta's model card (Muse Spark Open at xhigh reasoning; rival scores as Meta lists them, with some self-reported per MarkTechPost)[2][5]. Treat all of it as vendor-reported until independent evaluations land.&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;Muse Spark Open&lt;/th&gt;
&lt;th&gt;Kimi K3&lt;/th&gt;
&lt;th&gt;GLM 5.3&lt;/th&gt;
&lt;th&gt;Qwen3.8&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| MCP-Atlas | 89.2 | 82.3 | 84.2 | 84.5 |&lt;/p&gt;

&lt;p&gt;| Terminal-Bench 2.1 (Terminus 2) | 76.4 | 85.0 | 83.9 | 82.0 |&lt;/p&gt;

&lt;p&gt;| DeepSWE 1.1 | 60 | 68 | 67 | 57 |&lt;/p&gt;

&lt;p&gt;| Toolathlon Verified | 72.8 | 76.5 | 73.0 | 72.5 |&lt;/p&gt;

&lt;p&gt;| HLE with tools | 61.0 | 56.0 | 62.5 | 56.2 |&lt;/p&gt;

&lt;p&gt;| Artificial Analysis Intelligence Index | 39 | 44 | 45 | 40 |&lt;/p&gt;

&lt;p&gt;The pattern: Muse Spark Open leads on MCP-Atlas, which measures tool use over the Model Context Protocol, and on HLE-Diamond without tools (26.1 against Kimi K3's 22.2) and ZeroBench with tools (50.0 against 41.0)[5]. It trails on the terminal and software-engineering tests that matter most for a coding agent. MarkTechPost's own conclusion is that the most-capable-US-open-weight claim holds while Chinese open models still lead overall on the intelligence index, and it flags that the headline claim comes from Meta[5].&lt;/p&gt;

&lt;p&gt;The card also reports a GPQA Diamond score of 89.0, OSWorld Verified at 80.4 and Terminal-Bench 2.1 at 76.4[2]. On safety, the card lists FORTRESS adversarial scores (ARS 5.8, ORS 17.4, lower is better) and StrongREJECT v2 at 0.5[2].&lt;/p&gt;

&lt;h2&gt;
  
  
  When it beats paying for a closed model
&lt;/h2&gt;

&lt;p&gt;Pick it over a closed API when you need weights you control: fine-tuning on private data, a fixed model version that cannot be deprecated under you, or a data-handling rule that forbids third-party inference. Pick it for tool-use-heavy agents, where the MCP-Atlas result is the strongest in the table.&lt;/p&gt;

&lt;p&gt;Skip it when your workload is a terminal-driven coding agent and you can get a higher Terminal-Bench score elsewhere, or when your volume sits well under the billions-of-tokens break-even above. For the cost side of the closed-versus-open choice, our &lt;a href="https://dev.to/blogs/deepseek-v4-1-flash-1017-update-peak-off-peak-pricing-guide-2026"&gt;DeepSeek V4.1 Flash pricing guide&lt;/a&gt; works through the same per-token arithmetic for another open-weight model.&lt;/p&gt;

&lt;p&gt;A sensible first step costs almost nothing: send your real prompts to the hosted endpoint, measure quality on your own tasks, and only then price hardware. Benchmark tables decide very little; your own eval set decides most of it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How much memory does Muse Spark Open need?
&lt;/h3&gt;

&lt;p&gt;The model card lists at least 700 GB of VRAM for the NVFP4 build and 2 TB for BF16[2]. The raw BF16 weights are 1.64 TB on disk[3]; the rest of the requirement is KV cache and runtime overhead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I run it on a single GPU or a laptop?
&lt;/h3&gt;

&lt;p&gt;No. Even at 4-bit the NVFP4 checkpoint is 533 GB on disk before any cache or overhead[8]. Meta's showcase hardware is two M5 Ultra Mac Studios with up to 512 GB of unified memory each[1]. Hugging Face's launch post lists llama.cpp GGUF quants (Q2_K, Q4_K_S and Q8 tested on Apple Silicon), but even a 2-bit file of an 816B model needs hundreds of gigabytes[8].&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Muse Spark Open free for commercial use?
&lt;/h3&gt;

&lt;p&gt;Mostly. Per the license, commercial use is allowed with attribution, and the main restriction is a separate agreement if you sell it as a Model-as-a-Service and you and your affiliates pass $20 million in gross revenue in any consecutive 12 months[7]. Read the full LICENSE.md before relying on this summary.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much does the hosted API cost?
&lt;/h3&gt;

&lt;p&gt;OpenRouter listed $1.25 per million input tokens and $4.25 per million output tokens on 20 October 2026[4]. Prices change, so recheck on the day.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does 42B active parameters mean I only need 42B worth of memory?
&lt;/h3&gt;

&lt;p&gt;No. The router can send any token to any expert, so all 816B parameters stay loaded. The 42B figure governs compute per token, not memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://research.meta.ai/blog/muse-spark-open" rel="noopener noreferrer"&gt;Meta AI Research, Muse Spark Open announcement, 15 October 2026&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://huggingface.co/meta-models/Muse-Spark-Open-816B-A42B" rel="noopener noreferrer"&gt;Hugging Face model card, meta-models/Muse-Spark-Open-816B-A42B&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://huggingface.co/api/models/meta-models/Muse-Spark-Open-816B-A42B/tree/main" rel="noopener noreferrer"&gt;Hugging Face repository file listing (shard sizes, LICENSE.md size); NVFP4 repo listing at the same path under Muse-Spark-Open-816B-A42B-NVFP4&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://openrouter.ai/meta/muse-spark-open" rel="noopener noreferrer"&gt;OpenRouter, Meta: Muse Spark Open model page and endpoints, pricing as viewed 20 October 2026&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.marktechpost.com/2026/10/15/meta-muse-spark-open-816b-open-weight-model/" rel="noopener noreferrer"&gt;MarkTechPost, Meta Muse Spark Open 816B coverage with Meta's comparison table&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://openrouter.ai/meta/muse-spark-open" rel="noopener noreferrer"&gt;OpenRouter, Meta: Muse Spark Open model page (EU routing note)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://huggingface.co/meta-models/Muse-Spark-Open-816B-A42B/blob/main/LICENSE.md" rel="noopener noreferrer"&gt;Muse Model License (LICENSE.md), version Muse Spark Open, 15 October 2026&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  8. &lt;a href="https://huggingface.co/blog/meta-muse-spark-open" rel="noopener noreferrer"&gt;Hugging Face blog, Muse Spark Open launch post (NVFP4 repo, deployment recipes, GGUF and MLX quants)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/muse-spark-open-weights-hardware-license-cost-2026" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>musespark</category>
      <category>musemodel</category>
      <category>metaopen</category>
      <category>selfhost</category>
    </item>
    <item>
      <title>.NET 11 RC2: What Is New and Whether to Upgrade From 8 or 10</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Tue, 20 Oct 2026 19:15:38 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/net-11-rc2-what-is-new-and-whether-to-upgrade-from-8-or-10-43h2</link>
      <guid>https://dev.to/akaranjkar08/net-11-rc2-what-is-new-and-whether-to-upgrade-from-8-or-10-43h2</guid>
      <description>&lt;p&gt;&lt;strong&gt;.NET 11 RC2, published on 13 October 2026, is the final release candidate and ships with a go-live license, but the practical advice is split by where you start: .NET 8 teams must move before 10 November 2026 and should land on .NET 10, while .NET 10 teams have until November 2028 and can wait for .NET 11 GA.&lt;/strong&gt;[1] .NET 11 is a Standard Term Support release, so it gets two years of patches, from 10 November 2026 to 9 November 2028.[2] This post covers what is new in RC2, the support table for .NET 8 to 11, the upgrade steps and the breaking-changes list, and how to decide between shipping on RC2 and waiting.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;RC2 (11.0.0-rc.2, 13 Oct 2026) is production-usable under the go-live license, but Microsoft has not published a GA date on the RC2 post.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;.NET 11 is STS: supported from 10 Nov 2026 to 9 Nov 2028 per the release notes README.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;.NET 8 and .NET 9 both reach end of support on 10 Nov 2026. .NET 10 (LTS) runs to 14 Nov 2028.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;C# 15 adds union types, closed hierarchies, collection expression arguments, extension indexers and labeled break and continue, all still marked preview on the docs page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On .NET 8: go to .NET 10 now. On .NET 10: stay put, test on RC2 in CI, move after GA if you want the new features.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What RC2 is and what the go-live license means
&lt;/h2&gt;

&lt;p&gt;The .NET team published the RC2 announcement on 13 October 2026. It is the second release candidate, it includes a go-live support license, and the post says it can be used in production.[1] The release notes list the sequence: preview 1 on 10 February, preview 7 on 11 August, RC1 on 8 September, and 11.0.0-rc.2 on 13 October.[2]&lt;/p&gt;

&lt;p&gt;One thing matters for planning: the support policy page lists RC2 under go-live releases with an end-of-support date of 10 November 2026, the same day .NET 8 and 9 expire.[3] So RC2 is not a version you can sit on. If you deploy it, you commit to moving to the GA build when it appears.&lt;/p&gt;

&lt;p&gt;The same day, Microsoft shipped the October servicing releases: .NET 10.0.13 (SDK 10.0.402), .NET 9.0.21 (SDK 9.0.319) and .NET 8.0.32 (SDK 8.0.426), each dated 13 October 2026. Their release metadata lists 44, 42 and 40 CVE fixes respectively.[7] Patch whatever you run today before you plan the bigger move.&lt;/p&gt;

&lt;p&gt;The RC2 post lists tooling support in Visual Studio 2026 Insiders and in Visual Studio Code with the C# Dev Kit. It names no exact GA date.[1]&lt;/p&gt;

&lt;h2&gt;
  
  
  What is new in RC2 that a working team will notice
&lt;/h2&gt;

&lt;p&gt;RC2 is a polish release, not a feature drop. The announcement is organised by area, and most items are small. Here are the ones that change day-to-day work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Libraries and runtime
&lt;/h3&gt;

&lt;p&gt;The libraries section lists incremental CBOR reading, experimental composite ML-KEM and HPKE APIs, DataAnnotations messages formatted with attribute-specific arguments, and a configurable initial HTTP/2 concurrency.[1] The ML-KEM and HPKE items are the post-quantum cryptography work; the post labels them experimental, so do not build a production protocol on them yet. On the runtime side, the only listed change is that file locking on iOS and tvOS is disabled by default.&lt;/p&gt;

&lt;h3&gt;
  
  
  SDK, MSBuild and NuGet
&lt;/h3&gt;

&lt;p&gt;The SDK now accepts quoted values in file-level directives and allows MSBuild properties inside launch-profile arguments. MSBuild gets faster wildcard matching during project evaluation, which helps repositories with large glob-heavy projects. NuGet lets you set a minimum package publication age from the CLI, a useful guard against grabbing a package version that was published minutes ago, which is the window supply-chain attacks rely on.[1]&lt;/p&gt;

&lt;h3&gt;
  
  
  ASP.NET Core, MAUI, Windows Forms and F
&lt;/h3&gt;

&lt;p&gt;In ASP.NET Core, the QuickGrid virtualization APIs are no longer experimental. .NET MAUI gains a way to create apps with C# UI, Apple Icon Composer asset support, XAML authoring and Hot Reload work, and updates for .NET for Android and Apple platforms. Windows Forms adds a KioskModeManager component, deferred form reveal, suspension of painting and layout during bulk updates, and new analyzers that guide the Designer. F# gets runtime async support, &lt;code&gt;reraise&lt;/code&gt; in computation expressions, fewer allocations in FSharp.Core collections and lower compiler memory use.[1]&lt;/p&gt;

&lt;p&gt;The RC2 post does not list C# features itself. It points to the C# 15 page, which is where the language changes live.&lt;/p&gt;

&lt;h2&gt;
  
  
  C# 15 in one table
&lt;/h2&gt;

&lt;p&gt;The Microsoft Learn page for C# 15 lists six feature areas and calls C# 15 the latest preview release.[4] Treat that wording as the status: the page last updated on 14 September 2026, before RC2, so check it again before you depend on any of these.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;Status note on the docs page&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Collection expression arguments | A &lt;code&gt;with(...)&lt;/code&gt; first element passes capacity or a comparer to the collection constructor | Listed under C# 15 |&lt;/p&gt;

&lt;p&gt;| Union types | The &lt;code&gt;union&lt;/code&gt; keyword declares a value that is one of several case types, with exhaustive switch checking | Some proposal features not yet implemented |&lt;/p&gt;

&lt;p&gt;| Closed hierarchies | A &lt;code&gt;closed&lt;/code&gt; class can only be derived in its own assembly, so switches over it need no default arm | Listed under C# 15 |&lt;/p&gt;

&lt;p&gt;| Extension indexers | Declare an indexer inside an &lt;code&gt;extension&lt;/code&gt; block | Listed under C# 15 |&lt;/p&gt;

&lt;p&gt;| Labeled break and continue | Name a loop or switch to exit or continue, instead of a flag or goto | Listed under C# 15 |&lt;/p&gt;

&lt;p&gt;| Memory safety | Pointer relaxations and an &lt;code&gt;unsafe(expression)&lt;/code&gt; form | Needs the preview language version |&lt;/p&gt;

&lt;p&gt;Union types are the headline. The docs example declares &lt;code&gt;public union Pet(Cat, Dog, Bird);&lt;/code&gt; and the compiler then checks that a switch expression covers all three cases.[4] The docs also say the runtime has included &lt;code&gt;UnionAttribute&lt;/code&gt; and &lt;code&gt;IUnion&lt;/code&gt; since .NET 11 Preview 5. Closed hierarchies solve the same exhaustiveness problem for class trees you control.&lt;/p&gt;

&lt;p&gt;Labeled &lt;code&gt;break&lt;/code&gt; and &lt;code&gt;continue&lt;/code&gt; is the one you will use the first day. The docs show &lt;code&gt;continue outer;&lt;/code&gt; and &lt;code&gt;break outer;&lt;/code&gt; against a labeled outer &lt;code&gt;for&lt;/code&gt; loop, replacing the Boolean flag pattern. A new style rule, IDE0410, flags the flag and goto patterns it replaces.[4]&lt;/p&gt;

&lt;h2&gt;
  
  
  Support windows for .NET 8, 9, 10 and 11
&lt;/h2&gt;

&lt;p&gt;The support policy page states that LTS releases get three years of free support and patches, and STS releases get two years.[3] Here are the dates from the policy page and the .NET 11 release notes README.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Release type&lt;/th&gt;
&lt;th&gt;Original release&lt;/th&gt;
&lt;th&gt;End of support&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| .NET 8 | LTS | 14 Nov 2023 | 10 Nov 2026 |&lt;/p&gt;

&lt;p&gt;| .NET 9 | STS | 12 Nov 2024 | 10 Nov 2026 |&lt;/p&gt;

&lt;p&gt;| .NET 10 | LTS | 11 Nov 2025 | 14 Nov 2028 |&lt;/p&gt;

&lt;p&gt;| .NET 11 | STS | Support starts 10 Nov 2026 (README) | 9 Nov 2028 (README) |&lt;/p&gt;

&lt;p&gt;Two details to read carefully. First, .NET 11 does not appear in the policy page support table yet; the dates for it come from the release notes README, which says it will be supported from 10 November 2026 to 9 November 2028.[2] Second, .NET 8 loses support in the same week .NET 11 is expected to ship, so the 8 to 10 move is a deadline, not a preference.&lt;/p&gt;

&lt;p&gt;On GA timing: the .NET Conf 2026 page lists the conference for 10 to 13 November and says it will celebrate the launch of .NET 11, but it gives no release date.[5] The README support start of 10 November lines up with day one of the conference. Treat GA at .NET Conf as expected, not announced.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrade path: what to change in the repo
&lt;/h2&gt;

&lt;p&gt;The mechanics are the same for every move. Pin the SDK, retarget, build with warnings visible, then read the breaking-changes list for the areas you use.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sdk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"11.0.100-rc.2.26504.105"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"rollForward"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"latestFeature"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowPrerelease"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the RC2 SDK build listed in the dotnet/core release notes (runtime 11.0.0-rc.2).[2] Install it from get.dot.net/11 and confirm with &lt;code&gt;dotnet --list-sdks&lt;/code&gt;. Then change the project file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
  net11.0
  false

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

&lt;/div&gt;



&lt;p&gt;Leave warnings-as-errors off for the first build so you can see the full list, then turn it back on once the list is clean. To check that global.json is valid JSON before CI does, paste it into the &lt;a href="https://dev.to/tools/json-formatter"&gt;JSON formatter&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the breaking-changes page lists
&lt;/h3&gt;

&lt;p&gt;Microsoft's .NET 11 breaking-changes page groups entries by area and tags each as binary incompatible, source incompatible or a behavioral change. It carries a note that it is a work in progress and not a complete list.[6] The areas that most apps touch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Core libraries: CborReader and CborWriter enforce a default maximum nesting depth; TAR-reading APIs verify header checksums; CRC32 validation is added when reading ZIP archive entries; Math.Round and MathF.Round return correctly rounded results; DateOnly and TimeOnly TryParse methods throw for invalid input.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extensions: IHost.RunAsync and IHost.StopAsync throw when a BackgroundService fails; synchronous access to async-validated options throws.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;JIT: floating-point conversions to small integral types are saturating, and minimum hardware requirements are updated.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Networking: SslStream server-side AIA certificate downloads are disabled by default.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SDK and MSBuild: dnx scripts bypass global.json SDK selection; the template engine packages no longer support netstandard2.0; VSTest drops its Newtonsoft.Json dependency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;.NET MAUI: the minimum Android API level is raised to 24.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cryptography: DSA is removed from macOS.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of these, the BackgroundService change is the one most likely to bite a service: a worker that used to fail quietly now surfaces the failure through the host. That is arguably better behavior, but it will change how your process exits and how your orchestrator restarts it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ship on RC2 or wait for GA
&lt;/h2&gt;

&lt;p&gt;The go-live license answers the legal question. It does not answer the engineering one. Use this decision table.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You run&lt;/th&gt;
&lt;th&gt;Deadline&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| .NET 8 in production | 10 Nov 2026 | Move to .NET 10 now. It is LTS to Nov 2028 and has a year of fixes behind it. Do not jump to an STS preview to beat a deadline. |&lt;/p&gt;

&lt;p&gt;| .NET 9 in production | 10 Nov 2026 | Move to .NET 10 if you want the longest runway, or to .NET 11 GA if you need a C# 15 feature. Either way, plan for November. |&lt;/p&gt;

&lt;p&gt;| .NET 10 in production | 14 Nov 2028 | Stay. Add a CI job that builds against RC2 so the breaking-changes list becomes a known quantity before GA. |&lt;/p&gt;

&lt;p&gt;| New internal service, short lifespan | None | RC2 is acceptable if you accept moving to GA the week it lands. |&lt;/p&gt;

&lt;p&gt;The case against shipping RC2 to customers is simple: an RC build is a moving target until GA, and the policy page gives RC2 the same end-of-support day as .NET 8. The case for it is also real. If you are building something that needs union types and exhaustive switches today, the compiler support is there, with the caveat that parts of the union proposal are unimplemented and the language is still labeled preview.[4]&lt;/p&gt;

&lt;p&gt;For teams on .NET 10 the better move is cheap: build against net11.0 in a side branch, count the warnings, and read only the breaking-changes entries for APIs you call. If you also run Node or Python services, the same deadline thinking applies there; see our &lt;a href="https://dev.to/blogs/node-26-lts-28-october-2026-upgrade-guide-from-node-24-22"&gt;Node 26 LTS upgrade guide&lt;/a&gt; and the &lt;a href="https://dev.to/blogs/python-3-15-release-october-1-2026-lazy-imports-utf8-default-migration-checklist"&gt;Python 3.15 migration checklist&lt;/a&gt; for how those release trains compare. The &lt;a href="https://dev.to/blogs/mcp-2026-07-28-breaking-changes-migration-guide-stateless-protocol"&gt;MCP breaking-changes migration guide&lt;/a&gt; is a reminder that protocol-level breaks hit harder than language ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can I use .NET 11 RC2 in production?
&lt;/h3&gt;

&lt;p&gt;Yes. The RC2 announcement says it includes a go-live support license and can be used in production.[1] The policy page lists RC2 support ending 10 November 2026, so you need to update to the GA build.&lt;/p&gt;

&lt;h3&gt;
  
  
  When is .NET 11 GA?
&lt;/h3&gt;

&lt;p&gt;No date is stated on the RC2 post. The .NET Conf 2026 page, 10 to 13 November, says it will celebrate the launch of .NET 11, and the release notes README starts support on 10 November. GA at the conference is expected, not confirmed.[5]&lt;/p&gt;

&lt;h3&gt;
  
  
  Is .NET 11 LTS?
&lt;/h3&gt;

&lt;p&gt;No. The README calls it a Standard Term Support release, supported for two years, to 9 November 2028.[2] .NET 10 is the current LTS.&lt;/p&gt;

&lt;h3&gt;
  
  
  When does .NET 8 support end?
&lt;/h3&gt;

&lt;p&gt;10 November 2026, per the support policy page. .NET 9 ends the same day.[3]&lt;/p&gt;

&lt;h3&gt;
  
  
  Is C# 15 final in RC2?
&lt;/h3&gt;

&lt;p&gt;The Microsoft Learn page still calls C# 15 the latest preview release, and some union proposal features are not implemented. Check the page again before relying on a feature.[4]&lt;/p&gt;

&lt;h3&gt;
  
  
  Where is the full list of breaking changes?
&lt;/h3&gt;

&lt;p&gt;learn.microsoft.com/dotnet/core/compatibility/11. Microsoft notes the list is incomplete and still growing.[6]&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://devblogs.microsoft.com/dotnet/dotnet-11-rc-2/" rel="noopener noreferrer"&gt;.NET 11 RC 2, .NET Blog, 13 October 2026 (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/dotnet/core/tree/main/release-notes/11.0" rel="noopener noreferrer"&gt;dotnet/core: .NET 11.0 release notes README (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dotnet.microsoft.com/platform/support/policy/dotnet-core" rel="noopener noreferrer"&gt;.NET and .NET Core official support policy (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/dotnet/csharp/whats-new/csharp-15" rel="noopener noreferrer"&gt;What is new in C# 15, Microsoft Learn (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.dotnetconf.net/" rel="noopener noreferrer"&gt;.NET Conf 2026 (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://learn.microsoft.com/dotnet/core/compatibility/11" rel="noopener noreferrer"&gt;Breaking changes in .NET 11, Microsoft Learn (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  7. &lt;a href="https://github.com/dotnet/core/tree/main/release-notes" rel="noopener noreferrer"&gt;dotnet/core release notes: releases.json for 8.0, 9.0 and 10.0 (October 2026 servicing, accessed 20 October 2026)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/dotnet-11-rc2-whats-new-upgrade-from-dotnet-8-10" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dotnet11</category>
      <category>net11</category>
      <category>upgradefrom</category>
      <category>net8</category>
    </item>
    <item>
      <title>Google Replaces pytype With Pyrefly: Which Type Checker in 2026</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Tue, 20 Oct 2026 19:15:05 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/google-replaces-pytype-with-pyrefly-which-type-checker-in-2026-484o</link>
      <guid>https://dev.to/akaranjkar08/google-replaces-pytype-with-pyrefly-which-type-checker-in-2026-484o</guid>
      <description>&lt;p&gt;&lt;strong&gt;Google has made Pyrefly, Meta's Rust-based Python type checker, its type checker across the company and is dropping pytype, and if your CI still runs pytype you are on a tool whose own README says Python 3.12 is the last supported version.&lt;/strong&gt; Google's announcement dated 6 October 2026 reports Pyrefly as "an order of magnitude faster than Pytype" on its internal benchmarks and scoring roughly 97% on the official typing conformance suite[1]. The pytype repository was archived on 3 September 2026[2]. Below: what Google actually said, a four-way comparison of mypy, Pyright, Pyrefly and ty, a bug that a sound checker catches and a lenient one lets through, and a migration path you can run this week.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;pytype is finished: its README names 3.12 as the last supported Python version and the repo is archived. Plan a move now, not when your next Python upgrade breaks it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pyrefly is the closest drop-in for pytype and mypy users who want speed: it ships &lt;code&gt;pyrefly init&lt;/code&gt; to convert mypy or Pyright config, and runs next to your old checker while you review.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ty from Astral is fast too, but its own README calls it beta with no stable API yet, so treat it as something to trial rather than gate releases on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stay on mypy or Pyright if your team already has clean runs, plugins or editor setup you rely on. Speed alone is a weak reason to churn a green pipeline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Migrate in this order: install, init, check locally, suppress the flood, add to CI beside the old checker, then remove the old one.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Google announced, and what it did not
&lt;/h2&gt;

&lt;p&gt;The post, "Adopting Pyrefly as the Python type checker at Google", was published on 6 October 2026 by the Google Python team[1]. It says Google used pytype internally for more than a decade, and gives its reasons for the switch. The reasons, summarised:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Speed. Pyrefly is written in Rust, and Google's internal benchmarks found it "an order of magnitude faster than Pytype". The post also reports incremental rebuilds up to 98% faster with a warm daemon, and a drop of more than 80% in daily peak compute used for Python type checking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spec conformance. Pyrefly tracks new Python versions and typing PEPs, which matters because pytype analysed compiled bytecode, and bytecode changes between Python releases. That design made new typing features hard to add.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Diagnostics. Pyrefly's errors point at the offending code with inline annotations and sometimes suggest a fix.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Soundness. Google's example is a function that wants an &lt;code&gt;int&lt;/code&gt; being called with a value typed &lt;code&gt;int | None&lt;/code&gt;. Pytype accepted it because one member of the union fit. Pyrefly rejects it and suggests narrowing with an &lt;code&gt;is not None&lt;/code&gt; check.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pytype side is stated just as plainly. The README says the team is making 3.12 the last supported Python version, attributes this to a bytecode-based design that has made new features hard, and encourages users to "investigate the mature and excellent alternative solutions for Python typing"[2]. It does not name a replacement. Google naming Pyrefly is a statement about Google's monorepo, not a recommendation for yours.&lt;/p&gt;

&lt;p&gt;What the announcement does not give you is a deadline. There is no date after which pytype stops working on your code. The practical clock is your Python version: the day you move to 3.13 or later, pytype has nothing to say. If you are planning that upgrade, see our &lt;a href="https://dev.to/blogs/python-3-15-release-october-1-2026-lazy-imports-utf8-default-migration-checklist"&gt;Python 3.15 migration checklist&lt;/a&gt; and put the type checker on the same list.&lt;/p&gt;

&lt;h2&gt;
  
  
  mypy, Pyright, Pyrefly and ty side by side
&lt;/h2&gt;

&lt;p&gt;Every cell below comes from the project's own pages or its release metadata.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Checker&lt;/th&gt;
&lt;th&gt;Written in&lt;/th&gt;
&lt;th&gt;Maintainer&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Conformance&lt;/th&gt;
&lt;th&gt;Config file&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| mypy | Python, compiled with mypyc[12] | The Python project (python/mypy on GitHub)[12] | stable; 2.4.0 on PyPI, 1 October 2026 | not published | &lt;code&gt;mypy.ini&lt;/code&gt;, &lt;code&gt;.mypy.ini&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt; ([tool.mypy]), &lt;code&gt;setup.cfg&lt;/code&gt;, read in that order[6] |&lt;/p&gt;

&lt;p&gt;| Pyright | TypeScript, runs on Node.js[13] | Microsoft[7] | stable; 1.1.414, 9 September 2026 | not published | &lt;code&gt;pyrightconfig.json&lt;/code&gt;, or &lt;code&gt;[tool.pyright]&lt;/code&gt; in &lt;code&gt;pyproject.toml&lt;/code&gt;; the JSON file wins if both exist[13] |&lt;/p&gt;

&lt;p&gt;| Pyrefly | Rust[1] | Meta (default checker for Instagram's codebase, now also Google's)[1][8] | README: "current development status is stable"; latest release v1.4.0, 15 October 2026[8][9] | roughly 97% on the typing conformance suite, per Google[1] | &lt;code&gt;pyrefly.toml&lt;/code&gt; or &lt;code&gt;[tool.pyrefly]&lt;/code&gt; in &lt;code&gt;pyproject.toml&lt;/code&gt;[4] |&lt;/p&gt;

&lt;p&gt;| ty | Rust[10] | Astral[11] | README: "currently in beta", 0.0.x versions, no stable API yet[11] | not published | &lt;code&gt;ty.toml&lt;/code&gt;, or &lt;code&gt;[tool.ty]&lt;/code&gt; in &lt;code&gt;pyproject.toml&lt;/code&gt;[14] |&lt;/p&gt;

&lt;p&gt;Editor support: Pyrefly lists extensions for VS Code, Neovim and Zed[8]. ty ships a language server with completions, code actions and inlay hints, with integrations for VS Code, PyCharm and Neovim[10]. Pyright's README describes a command-line tool plus a Visual Studio Code extension[7].&lt;/p&gt;

&lt;p&gt;Two readings of this table. First, only one tool in it has a published conformance number and it comes from Google, a user with an obvious interest in the result. Run the conformance suite yourself if the number decides your pick. Second, "stable" and "beta" are the projects' own labels; they say nothing about how many errors each will raise on your code.&lt;/p&gt;

&lt;h2&gt;
  
  
  The class of bug a sound checker catches
&lt;/h2&gt;

&lt;p&gt;The example below is ours, not Google's, but it has the shape their post describes: a value that might be &lt;code&gt;None&lt;/code&gt; flows into a function that needs a real number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;discount_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;65&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;checkout_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# int | None
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;discount_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# flagged: None is not an int
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;name&lt;/code&gt; is missing from the dict, &lt;code&gt;ages.get&lt;/code&gt; returns &lt;code&gt;None&lt;/code&gt;, and &lt;code&gt;age &amp;gt;= 65&lt;/code&gt; raises a &lt;code&gt;TypeError&lt;/code&gt; at runtime. It only fires for unknown customers, so tests with seeded data never hit it. A checker that treats &lt;code&gt;int | None&lt;/code&gt; as acceptable because one half of the union fits will pass this file. A sound union check will not. The fix is to narrow before the call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;checkout_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;discount_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expect the first run on a mature codebase to turn up dozens of these. Most are real latent bugs; some are places where an invariant you know about is invisible to the checker. That split is the whole migration problem, and the next section is about handling it without freezing the team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating from pytype or mypy to Pyrefly
&lt;/h2&gt;

&lt;p&gt;The steps below follow Pyrefly's migration page[3]. Pyrefly documents conversion from mypy and Pyright configs; it does not document a pytype importer, so a pytype project starts from a fresh config.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install beside your current checker
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv add &lt;span class="nt"&gt;--dev&lt;/span&gt; pyrefly
&lt;span class="c"&gt;# or&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;pyrefly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Generate a config
&lt;/h3&gt;

&lt;p&gt;If you have a mypy or Pyright config, run &lt;code&gt;pyrefly init&lt;/code&gt; to convert it. The migration page warns that unrecognised settings are skipped without a warning, so diff the generated file against your old one before committing[3]. Pyrefly reads &lt;code&gt;pyrefly.toml&lt;/code&gt; at the project root, or a &lt;code&gt;[tool.pyrefly]&lt;/code&gt; section in &lt;code&gt;pyproject.toml&lt;/code&gt;. Without an explicit &lt;code&gt;-c&lt;/code&gt; flag it searches upward for &lt;code&gt;pyrefly.toml&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;setup.py&lt;/code&gt;, &lt;code&gt;mypy.ini&lt;/code&gt; and &lt;code&gt;pyrightconfig.json&lt;/code&gt;, and if it finds no Pyrefly config it may migrate a nearby mypy or Pyright config in memory[4]. A minimal pytype-era start looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# pyrefly.toml&lt;/span&gt;
&lt;span class="py"&gt;project-includes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;python-version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"3.12"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those two keys are the ones the configuration docs use in their own example. If you do not set &lt;code&gt;python-version&lt;/code&gt;, Pyrefly queries your interpreter and falls back to 3.13.0 when that fails[4], which is worth pinning explicitly in CI.&lt;/p&gt;

&lt;p&gt;Create the config before your first check. With no &lt;code&gt;pyrefly.toml&lt;/code&gt; or &lt;code&gt;[tool.pyrefly]&lt;/code&gt; section and no mypy or Pyright config nearby, Pyrefly falls back to its basic preset, which only reports high-confidence error kinds and stays silent on the None-to-int mismatch above. A pytype project has nothing to migrate, so run &lt;code&gt;pyrefly init&lt;/code&gt; (it writes a &lt;code&gt;pyrefly.toml&lt;/code&gt;, or a &lt;code&gt;[tool.pyrefly]&lt;/code&gt; entry if you point it at &lt;code&gt;pyproject.toml&lt;/code&gt;) or write the file by hand[4]. We ran Pyrefly 1.4.0 on the example from this post: 0 errors under the basic preset, then one bad-argument-type error once a &lt;code&gt;pyrefly.toml&lt;/code&gt; with &lt;code&gt;project-includes&lt;/code&gt; existed.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Run it
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;p&gt;Your old config stays in place, so both checkers can run while you review[3].&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Handle the error flood
&lt;/h3&gt;

&lt;p&gt;Pyrefly documents two routes[5]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Suppression comments. Add &lt;code&gt;# pyrefly: ignore&lt;/code&gt; on a line, or target one error kind with &lt;code&gt;# pyrefly: ignore[bad-return]&lt;/code&gt;. For a whole file, &lt;code&gt;# pyrefly: ignore-errors&lt;/code&gt; at the top. To add them in bulk, run &lt;code&gt;pyrefly suppress&lt;/code&gt; (equivalent to &lt;code&gt;pyrefly check --suppress-errors&lt;/code&gt;), and add &lt;code&gt;--comment-location=same-line&lt;/code&gt; if you want comments on the error line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A baseline file. This records current errors so CI reports only new ones, with no edits to source. Generate it with &lt;code&gt;pyrefly check --baseline="baseline.json" --update-baseline&lt;/code&gt; and check against it with &lt;code&gt;pyrefly check --baseline="baseline.json"&lt;/code&gt;. The docs label this feature experimental, so read the current page before you depend on it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bulk suppression is the fast route and it leaves a visible to-do list in the diff. The baseline keeps the diff clean but hides the debt. Pick one per repo; mixing them makes it hard to say what is left. Later, &lt;code&gt;pyrefly suppress --remove-unused&lt;/code&gt; clears suppressions that no longer match an error[5].&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Put it in CI, then retire the old checker
&lt;/h3&gt;

&lt;p&gt;Run &lt;code&gt;pyrefly check&lt;/code&gt; as a second job beside pytype or mypy for a sprint. The migration page says you can keep both in CI, and its last step is removing the old checker and any ignore comments it left behind once you are ready[3]. It gives no CI snippets, so wire it into whatever job runner you already use. If you also manage AI-assisted Python work, a pinned checker command in your agent instructions stops an assistant from "fixing" errors by adding ignores; our &lt;a href="https://dev.to/product/claude-code-configuration-pack-for-python-backends"&gt;Claude Code configuration pack for Python backends&lt;/a&gt; is one place to put that rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to stay on mypy or Pyright
&lt;/h2&gt;

&lt;p&gt;Google's move solves Google's problem: a monorepo, a bytecode-based tool that could not keep up, and a compute bill measured in thousands of cores. Few teams have that problem. Stay put when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your mypy or Pyright run is green, fast enough, and trusted. A migration that produces 400 suppressions and no new bugs found is a cost with no return.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You depend on a mypy plugin for a framework or library. Whether a plugin has a Pyrefly equivalent is something to check against your own dependency list before you start; this post does not claim parity for any specific plugin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your editor experience is built on Pylance or Pyright and the team likes it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need a stable-labelled tool today and ty's beta status rules it out, while your goal is just speed. Pyrefly's README calls it stable; ty's calls itself beta.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reverse case is real too. If your type-check step is the slowest thing in the pre-commit loop, or you are still on pytype, trialling Pyrefly costs an afternoon: install it, run &lt;code&gt;pyrefly check&lt;/code&gt;, and count the errors. That number tells you more than any benchmark. If it is a handful, switch. If it is thousands, suppress, baseline, and schedule the fix-up work. Related reading for a typed Python service: &lt;a href="https://dev.to/blogs/python-fastapi-production-api-best-practices-2026"&gt;FastAPI production API best practices&lt;/a&gt;. For quick diffs of config files while you migrate, the &lt;a href="https://dev.to/tools/diff-checker"&gt;diff checker&lt;/a&gt; and &lt;a href="https://dev.to/tools/json-formatter"&gt;JSON formatter&lt;/a&gt; run in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is pytype still usable?
&lt;/h3&gt;

&lt;p&gt;Yes, on Python 3.12 and earlier. Its README says 3.12 is the last supported version, and the repository is archived and read-only[2]. It will not gain support for newer typing features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Pyrefly import my mypy config?
&lt;/h3&gt;

&lt;p&gt;It converts mypy and Pyright configs with &lt;code&gt;pyrefly init&lt;/code&gt;, but unrecognised settings are skipped without a warning, so review the output[3]. It does not document a pytype config importer.&lt;/p&gt;

&lt;h3&gt;
  
  
  What version is Pyrefly at, and is it stable?
&lt;/h3&gt;

&lt;p&gt;The newest release is v1.4.0, published 15 October 2026. Pyrefly 1.0.0 was tagged on 12 May 2026[9]. The README says its development status is stable[8].&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use ty instead?
&lt;/h3&gt;

&lt;p&gt;ty is a Rust checker and language server from Astral and is worth trialling, but its README says it is in beta and does not yet have a stable API[11]. Try it locally; do not make it a release gate yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I stop CI from failing on hundreds of old errors?
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;pyrefly suppress&lt;/code&gt; for one-time bulk comments, or the experimental baseline file so CI reports only new errors[5].&lt;/p&gt;

&lt;h3&gt;
  
  
  Is the 97% conformance figure independent?
&lt;/h3&gt;

&lt;p&gt;No. It is the figure Google reports in its own announcement[1]. Run the typing conformance suite on the versions you plan to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://opensource.googleblog.com/2026/10/adopting-pyrefly-as-the-python-type-checker-at-google.html" rel="noopener noreferrer"&gt;Google Open Source Blog: Adopting Pyrefly as the Python type checker at Google (6 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/google/pytype" rel="noopener noreferrer"&gt;google/pytype README (archived 3 September 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pyrefly.org/en/docs/migrating-to-pyrefly/" rel="noopener noreferrer"&gt;Pyrefly docs: migrating to Pyrefly&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pyrefly.org/en/docs/configuration/" rel="noopener noreferrer"&gt;Pyrefly docs: configuration&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pyrefly.org/en/docs/error-suppressions/" rel="noopener noreferrer"&gt;Pyrefly docs: error suppressions and baseline files&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://mypy.readthedocs.io/en/stable/config_file.html" rel="noopener noreferrer"&gt;mypy docs: the mypy configuration file&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/microsoft/pyright" rel="noopener noreferrer"&gt;microsoft/pyright README&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/facebook/pyrefly" rel="noopener noreferrer"&gt;facebook/pyrefly README&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/facebook/pyrefly/releases" rel="noopener noreferrer"&gt;facebook/pyrefly releases (v1.4.0)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.astral.sh/ty/" rel="noopener noreferrer"&gt;Astral ty documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/astral-sh/ty" rel="noopener noreferrer"&gt;astral-sh/ty README&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/python/mypy" rel="noopener noreferrer"&gt;python/mypy on GitHub (README: mypyc-compiled mypy)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/microsoft/pyright/blob/main/docs/configuration.md" rel="noopener noreferrer"&gt;Pyright configuration docs (and packages/pyright-internal, a TypeScript package)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  14. &lt;a href="https://docs.astral.sh/ty/configuration/" rel="noopener noreferrer"&gt;ty configuration docs&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/google-pyrefly-replaces-pytype-python-type-checker-2026" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>pyrefly</category>
      <category>pytypealternative</category>
      <category>pythontype</category>
      <category>pyreflyvs</category>
    </item>
    <item>
      <title>OVHcloud CLI Release Hijack: Verify Downloads, Lock Releases</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Tue, 20 Oct 2026 19:00:32 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/ovhcloud-cli-release-hijack-verify-downloads-lock-releases-2b5b</link>
      <guid>https://dev.to/akaranjkar08/ovhcloud-cli-release-hijack-verify-downloads-lock-releases-2b5b</guid>
      <description>&lt;p&gt;&lt;strong&gt;If you installed or updated the OVHcloud CLI (ovhcloud) between 12:47 and 14:21 UTC on 19 October 2026 and ended up on v0.11.0 through v0.15.0, treat every secret readable from that machine as stolen.&lt;/strong&gt; An attacker used a hijacked developer account to replace the release archives, and OVHcloud's own advisory says the build was meant to harvest secrets from disk[1]. The fix for maintainers is one checkbox: GitHub immutable releases lock a published release's assets and tag[7]. Below: who is affected, what to do tonight, why mutable release assets made this possible, a table of defences, how to switch immutability on, and how to verify a CLI before you run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Affected: ovhcloud-cli v0.11.0 to v0.15.0 downloaded 12:47 to 14:21 UTC on 19 Oct 2026 (macOS, Linux, Windows x86_64 archives). v0.10.0 and v0.16.0 are listed as clean[1].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do not run the binary to check it. Hash it and compare against the five MD5 values in OVHcloud's advisory, or look for an envchecker- folder in your temp directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you are affected: rotate cloud, SSH, Git, Docker, Kubernetes and AI tooling credentials from a different machine, delete the binary, then install v0.16.0.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Root cause: release immutability was off, so a privileged account could overwrite assets on old releases without touching CI[5].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintainers: Settings, Releases, Enable release immutability. It only applies to future releases[8].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Users: pin a hash in CI and run gh release verify-asset. A checksums file inside a mutable release proves nothing, because it was swapped too[6].&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What happened on 19 October 2026
&lt;/h2&gt;

&lt;p&gt;The advisory (GHSA-862f-55f5-vmvw, severity High, no CVE) says a compromised OVHcloud developer GitHub account was used to replace release binaries with malicious builds. Source code and the build chain were not affected, and no other repositories were touched[1]. The Hacker News adds a detail that matters for defenders: the bad build was a plain &lt;code&gt;go build&lt;/code&gt; from a later commit, uploaded on top of existing releases, so the release workflow never ran during the window[5].&lt;/p&gt;

&lt;p&gt;A downstream user caught it. Their CI pinned the SHA-256 of the Linux arm64 tarball, the pin started failing, and they opened issue #300 on the repository at about 13:50 UTC[2][6]. A maintainer replied that all binaries involved were deleted at 16:21 GMT+2 (14:21 UTC), and v0.16.0 followed as an immutable release with a signed tag[2][3].&lt;/p&gt;

&lt;h3&gt;
  
  
  Versions, platforms and the time window
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Affected releases | v0.11.0, v0.12.0, v0.13.0, v0.14.0, v0.15.0 | OVHcloud advisory[1] |&lt;/p&gt;

&lt;p&gt;| Clean releases | v0.10.0 and earlier, v0.16.0 and later | OVHcloud advisory[1] |&lt;/p&gt;

&lt;p&gt;| Affected platforms | Darwin arm64, Darwin x86_64, Linux arm64, Linux x86_64, Windows x86_64 | OVHcloud advisory[1] |&lt;/p&gt;

&lt;p&gt;| Not replaced | Linux i386, Windows i386, Windows arm64, WASM build | OpenSourceMalware[6] |&lt;/p&gt;

&lt;p&gt;| Exposure window | 12:47 to 14:21 UTC (14:47 to 16:21 UTC+2) on 19 Oct | OVHcloud advisory[1] |&lt;/p&gt;

&lt;p&gt;Press coverage disagrees on timing, so here is how to read it. BleepingComputer reports the compromised release appearing at 14:47 and being blocked at 16:21 with no timezone stated[4]. Those are Paris times. The Hacker News gives 12:47 to 14:21 UTC[5]. OpenSourceMalware's 12:47 to about 13:12 is the span in which the five releases were overwritten, not how long the files stayed up[6]. The advisory's UTC window of 12:47 to 14:21 is the one to use. Anything downloaded from those five releases before 12:47 UTC is outside it, per the advisory.&lt;/p&gt;

&lt;h3&gt;
  
  
  How people actually got hit
&lt;/h3&gt;

&lt;p&gt;According to The Hacker News, the exposed paths were the official install script (which does not check a hash), manual downloads from the five release pages, CI jobs fetching without a pinned hash, and the CLI's own upgrade command from v0.12.0 to v0.14.0 on macOS and Linux. The same report lists Homebrew (the cask pinned the original SHA-256), &lt;code&gt;go install&lt;/code&gt; and source builds, and the Docker image as not exposed[5]. Sources disagree on Homebrew: OpenSourceMalware lists the cask as an exposed path[6], while The Hacker News says it checked the tap history and the pinned hash would have made brew refuse the swapped file. OVHcloud's advisory does not mention Homebrew. That split is the whole story of this post: every path that verified a hash held up, and every path that trusted the release URL did not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is it GlassWorm?
&lt;/h3&gt;

&lt;p&gt;OpenSourceMalware links the compromised account to the GlassWorm malware family. The evidence: a Solana wallet in the account's earlier force-pushed repositories that appears in public GlassWorm indicator lists. The researchers themselves call the link to the October swap their inference, and no October binary has been tied to GlassWorm because no copy was preserved[6]. Treat the attribution as tentative. It does not change what you do.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do tonight if you may be affected
&lt;/h2&gt;

&lt;p&gt;Work through this in order. Rotation comes before the upgrade, because installing v0.16.0 does nothing about keys that were already copied.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Find the binary and hash it without running it.&lt;/strong&gt; The advisory lists MD5 values for the malicious binaries: Darwin arm64 &lt;code&gt;6f2f086239f3d88eb2750e871901927d&lt;/code&gt;, Darwin x86_64 &lt;code&gt;347e65eb7f2d78d1c6872690272a6cc3&lt;/code&gt;, Linux arm64 &lt;code&gt;01f57206d37c28cf711677f612052913&lt;/code&gt;, Linux x86_64 &lt;code&gt;301bff0b51980b9e76c93633e7cfd3bd&lt;/code&gt;, and Windows &lt;code&gt;6a3cf153338c416169cda2fe704c8848&lt;/code&gt;[1].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Look for the dropped folder.&lt;/strong&gt; A directory named envchecker- followed by random digits in your temp directory means the malware ran[1].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rotate from a different machine.&lt;/strong&gt; The advisory names cloud, SSH, Git, Docker, Kubernetes and AI assistant tooling credentials[1]. OpenSourceMalware's list adds package-manager tokens and &lt;code&gt;.env&lt;/code&gt; files[6]. OVHcloud's CEO told affected users to change every secret on disk, per BleepingComputer[4].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Delete the binary, then install v0.16.0.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check CI.&lt;/strong&gt; Any pipeline that downloaded the CLI in the window without a pinned hash ran the swapped build on a runner that holds deploy credentials.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hashing a binary is the easy part. Knowing what was on disk is the hard part. If you need an inventory, the &lt;a href="https://dev.to/product/ai-provider-key-hygiene-kit"&gt;AI Provider Key Hygiene Kit&lt;/a&gt; scans files and git history for AI provider keys and ships a rotation runbook. The same rotate-what-was-on-disk logic applied in the &lt;a href="https://dev.to/blogs/opencode-console-breach-rotate-openai-anthropic-keys-checklist-2026"&gt;OpenCode console breach checklist&lt;/a&gt;, and the order of operations is identical: revoke first, investigate second.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it worked: release assets were mutable
&lt;/h2&gt;

&lt;p&gt;A GitHub release is a page with files attached. Unless the repository opts in to immutability, anyone with write access can delete an attached file and upload a different one under the same name. The tag keeps pointing at the same commit, the source archive looks fine, and the release date does not change. OVHcloud's CEO said the cause was the immutability option being disabled, which let a sufficiently privileged account modify existing releases directly, bypassing the CI/CD checks, per BleepingComputer[4]. The advisory's own scope line fits: the pipelines were not the weak point[1].&lt;/p&gt;

&lt;p&gt;OpenSourceMalware lists the contributing weaknesses beyond mutability: releases published under personal accounts, a peripheral contributor holding release-asset write permission, an install script that skips checksum verification, no provenance or signing before v0.16.0, and no private vulnerability reporting channel, so disclosure happened in a public issue[6]. The checksum file was no help either. The same report says &lt;code&gt;checksums.txt&lt;/code&gt; was one of the six files replaced on each affected release[5][6]. A hash that lives next to the file it vouches for is only a typo check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defences compared: what each stops and who has to act
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Defence&lt;/th&gt;
&lt;th&gt;What it stops&lt;/th&gt;
&lt;th&gt;What it does not stop&lt;/th&gt;
&lt;th&gt;Who acts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| GitHub immutable releases | Replacing or deleting assets, and moving or deleting the tag, on a published release[7] | Releases published before it was switched on[8]. A compromised account cutting a brand-new release, which is a new, separately visible event | Maintainer |&lt;/p&gt;

&lt;p&gt;| Release attestation (generated automatically for immutable releases) | Lets anyone confirm a local file matches an asset on the release[7] | Malicious code that was in the release when it was published | Maintainer publishes, user verifies |&lt;/p&gt;

&lt;p&gt;| Checksums file inside the same release | Corrupted downloads | A swapped release, because the attacker replaces the checksums too[6] | Both, and low value |&lt;/p&gt;

&lt;p&gt;| Checksum or signature published somewhere the uploader cannot edit | A swap by anyone who can only touch the release page | A compromised maintainer machine or signing key | Maintainer publishes, user checks |&lt;/p&gt;

&lt;p&gt;| Hash pinned in your CI or install script | Any swap after you recorded the hash. This is what exposed the incident[2] | A release that was already bad when you pinned it | User |&lt;/p&gt;

&lt;p&gt;| Package manager with pinned hashes (Homebrew cask) | Same swap, because the cask held the original SHA-256, per The Hacker News[5] | A maintainer who updates the pin to a bad file | Packager |&lt;/p&gt;

&lt;p&gt;| Install script that downloads and runs with no hash check | Nothing | Everything above | Maintainer should fix; user should avoid |&lt;/p&gt;

&lt;p&gt;Two rows deserve a sentence each. Immutability is not a malware filter: it freezes whatever you published, good or bad, and it cannot stop an attacker from publishing a new release under a new tag. What it removes is the quiet rewrite of a trusted old release, which is exactly what let a v0.11.0 download from April turn hostile in October. And the signed-checksums row is a general pattern, not something OVHcloud shipped. Where a signature key lives matters more than the format.&lt;/p&gt;

&lt;h2&gt;
  
  
  For maintainers: turn on immutable releases
&lt;/h2&gt;

&lt;p&gt;GitHub's documentation gives the steps[8].&lt;/p&gt;

&lt;h3&gt;
  
  
  One repository
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open the repository, then Settings (under the &lt;strong&gt;⋯&lt;/strong&gt; menu if it is hidden).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scroll to the Releases section and select &lt;strong&gt;Enable release immutability&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  A whole organization
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open the organization, then Settings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the sidebar, under Code, planning, and automation, open Repository and click General.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Releases section, change the No policy dropdown to All repositories or Selected repositories.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For Selected repositories, click the gear icon, pick the repositories, and click Select repositories.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Read the caveat before you celebrate: the docs say immutability applies only to future releases[8]. Enabling it today does not retroactively lock last year's releases. The docs say nothing more about releases published before the switch, so for anything you must stand behind, cut a fresh release and point people at it. That is what OVHcloud did with v0.16.0, which its release page labels as an immutable release where only the title and notes can be edited[3].&lt;/p&gt;

&lt;p&gt;The docs also describe a publishing order that fits immutability: create the release as a draft, attach every asset, then publish, so nothing is missing at the moment it locks[7]. Creating an immutable release automatically generates a release attestation that records the tag, the commit SHA and the assets[7].&lt;/p&gt;

&lt;h3&gt;
  
  
  What else to change on the same afternoon
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Audit who holds write access on release-publishing repositories. In this incident the account was a contributor, not a core maintainer[6].&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish releases from a bot or organization-owned identity driven by your workflow, not from a person's account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Turn on private vulnerability reporting. OVHcloud enabled it after the incident[2], and the reporter here had to use a public issue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make your install script check a hash, or delete it and point people to a package manager that pins one.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sign tags. The v0.16.0 tag is signed, though its page flags the signing key as expired[3]. A signature you cannot trust the key for is weaker than it looks, so keep keys current.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  For users: verify a CLI before you run it
&lt;/h2&gt;

&lt;p&gt;You have three checks, from cheapest to strongest. None requires running the download.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Hash it
&lt;/h3&gt;

&lt;p&gt;On Linux, &lt;code&gt;sha256sum ovhcloud-cli_Linux_arm64.tar.gz&lt;/code&gt;. On macOS, &lt;code&gt;shasum -a 256 ovhcloud-cli_Linux_arm64.tar.gz&lt;/code&gt;. Compare against a value you got from somewhere other than the release page you downloaded from: the maintainer's docs, a package manager, or the value you recorded last time. If you only have a browser, the &lt;a href="https://dev.to/tools/hash-generator"&gt;hash generator&lt;/a&gt; has a file mode that computes MD5, SHA-1, SHA-256 and SHA-512 for a file you drop in, which is handy for matching the advisory's MD5 list. For the incident here, OpenSourceMalware published SHA-256 values for the v0.15.0 Linux arm64 archive: the swapped file ended in &lt;code&gt;...28933cb&lt;/code&gt; and the original in &lt;code&gt;...b80e0&lt;/code&gt;[6].&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Verify against the release itself
&lt;/h3&gt;

&lt;p&gt;GitHub's documentation shows two commands for releases that are immutable[9]:&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;# confirm the release exists and is immutable&lt;/span&gt;
gh release verify v0.16.0 &lt;span class="nt"&gt;--repo&lt;/span&gt; ovh/ovhcloud-cli

&lt;span class="c"&gt;# confirm a local file is an exact match for an asset on the release&lt;/span&gt;
gh release verify-asset v0.16.0 ./ovhcloud-cli_Linux_arm64.tar.gz &lt;span class="nt"&gt;--repo&lt;/span&gt; ovh/ovhcloud-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run them inside a clone of the repository, or add gh's repository flag. The first command answers whether the release can still change under you. The second answers whether your file is the one attached to it. The docs add that source zip and tarball downloads cannot be checked this way, because GitHub generates them on request[9]. In the web interface, an immutable release shows an Immutable label below its title[9]. OpenSourceMalware also recommends &lt;code&gt;gh attestation verify&lt;/code&gt; for v0.16.0[6]. We ran &lt;code&gt;gh attestation verify ovhcloud-cli_Linux_arm64.tar.gz --repo ovh/ovhcloud-cli&lt;/code&gt; on 20 October and got an HTTP 404: v0.16.0 has no build-provenance attestation, only the release attestation that GitHub creates for immutable releases. &lt;code&gt;gh release verify-asset&lt;/code&gt; checks that one, and it passed on the same file. So use verify-asset for this CLI, and do not read a failed &lt;code&gt;gh attestation verify&lt;/code&gt; as proof of tampering.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Pin it where an attacker cannot edit it
&lt;/h3&gt;

&lt;p&gt;The reporter of issue #300 never ran a verify command. They had a SHA-256 in CI, and the build broke when the file changed[2]. Pin the hash in your repository, in a Dockerfile, in a bootstrap script. Update it by pull request, with a person reading the diff. A failing pin is the cheapest intrusion detector most teams will ever deploy.&lt;/p&gt;

&lt;p&gt;Pipelines deserve extra attention because they hold the most valuable secrets and the least human supervision. If your CI downloads tools with curl and pipes to a shell, you have the exposure OVHcloud users had. The &lt;a href="https://dev.to/product/secretssafe-cicd-secrets-audit-pack"&gt;SecretsSafe CI/CD secrets audit pack&lt;/a&gt; is a checklist for finding which jobs hold which credentials, which tells you the blast radius before an incident does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Am I affected if I installed the CLI with Homebrew?
&lt;/h3&gt;

&lt;p&gt;Sources disagree. The Hacker News reports the Homebrew cask pinned the original SHA-256 and was not exposed, along with &lt;code&gt;go install&lt;/code&gt;, source builds and the Docker image[5]. OpenSourceMalware lists the cask as exposed[6], and the advisory does not mention Homebrew. The advisory's own scope is anyone who downloaded the five releases in the 12:47 to 14:21 UTC window[1]. If you cannot say which route your machine used, hash the binary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does updating to v0.16.0 fix it?
&lt;/h3&gt;

&lt;p&gt;It replaces the binary. It does not revoke credentials that a malicious build already read. Rotate first, from a clean machine, then upgrade.&lt;/p&gt;

&lt;h3&gt;
  
  
  Would immutable releases have prevented this?
&lt;/h3&gt;

&lt;p&gt;The CEO's stated cause is that the setting was off and a privileged account could edit existing releases[4]. With it on for those releases, overwriting their assets would not have been possible, per GitHub's description of what is locked[7]. It would not stop a hijacked account from publishing a new release, which is why verification on the user side still matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not trust the checksums.txt on the release page?
&lt;/h3&gt;

&lt;p&gt;Because in this incident it was swapped along with the archives, per The Hacker News and OpenSourceMalware[5][6]. A checksum is only evidence if the attacker could not have edited it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is the GlassWorm link confirmed?
&lt;/h3&gt;

&lt;p&gt;No. The researchers call it inference from shared account identity, and no copy of the October binary has been analyzed publicly[6]. OVHcloud's advisory does not attribute the attack to any named group[1].&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the advisory say what the malware sent out?
&lt;/h3&gt;

&lt;p&gt;The advisory calls the builds malicious and tells affected users to treat secrets as compromised[1]. The Hacker News notes OVHcloud has not said which files the binary read or where it sent data[5]. Assume the worst for anything on the disk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/ovh/ovhcloud-cli/security/advisories/GHSA-862f-55f5-vmvw" rel="noopener noreferrer"&gt;OVHcloud: GHSA-862f-55f5-vmvw, ovhcloud-cli security incident (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/ovh/ovhcloud-cli/issues/300" rel="noopener noreferrer"&gt;ovh/ovhcloud-cli issue #300 (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/ovh/ovhcloud-cli/releases/tag/v0.16.0" rel="noopener noreferrer"&gt;ovh/ovhcloud-cli release v0.16.0 (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.bleepingcomputer.com/news/security/ovhcloud-cli-releases-backdoored-on-github-to-steal-developer-secrets/" rel="noopener noreferrer"&gt;BleepingComputer: OVHcloud CLI releases backdoored on GitHub to steal developer secrets (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://thehackernews.com/2026/10/hackers-hijack-five-ovhcloud-cli.html" rel="noopener noreferrer"&gt;The Hacker News: hackers hijack five OVHcloud CLI releases (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://opensourcemalware.com/blog/glassworm-hacks-ovh-clouds-cli-tool" rel="noopener noreferrer"&gt;OpenSourceMalware: GlassWorm hacks OVH Cloud's CLI tool (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases" rel="noopener noreferrer"&gt;GitHub Docs: immutable releases (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/establish-provenance-and-integrity/preventing-changes-to-your-releases" rel="noopener noreferrer"&gt;GitHub Docs: preventing changes to your releases (accessed 20 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  9. &lt;a href="https://docs.github.com/en/code-security/how-tos/secure-your-supply-chain/secure-your-dependencies/verify-release-integrity" rel="noopener noreferrer"&gt;GitHub Docs: verifying the integrity of a release (accessed 20 October 2026)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/ovhcloud-cli-release-hijack-github-immutable-releases" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ovhcloudcli</category>
      <category>githubimmutable</category>
      <category>ghrelease</category>
      <category>verifycli</category>
    </item>
    <item>
      <title>TaxGst.in Free Income Tax Calculator, Free GST Tools &amp; Finance Guides India</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Tue, 20 Oct 2026 09:47:17 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/taxgstin-free-income-tax-calculator-free-gst-tools-finance-guides-india-2nbp</link>
      <guid>https://dev.to/akaranjkar08/taxgstin-free-income-tax-calculator-free-gst-tools-finance-guides-india-2nbp</guid>
      <description>&lt;h2&gt;
  
  
  Why TaxGst.in is the Go‑to Free Income Tax Calculator for Indian Developers
&lt;/h2&gt;

&lt;p&gt;Developers building payroll, finance, or fintech applications need a reliable, zero‑cost &lt;strong&gt;income tax calculator&lt;/strong&gt; that reflects the latest Indian tax slabs, cess, and deductions. TaxGst.in offers a web‑based calculator that instantly computes federal tax liability, handles HRA, home‑loan interest, and even capital‑gains nuances. Because it’s free, you can embed its logic, call its API, or simply direct users to &lt;a href="https://dev.to/tools/income-tax-calculator"&gt;the Income Tax Calculator&lt;/a&gt; page without worrying about licensing fees. This article walks you through the tool’s core features, integration patterns, and complementary GST utilities that keep your codebase tax‑compliant.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Features of the Free Income Tax Calculator
&lt;/h2&gt;

&lt;p&gt;TaxGst.in’s calculator is built on the same rules the Indian Income Tax Department publishes each FY. The engine supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;All individual tax slabs for FY 2024‑25 (including the new 30 % top rate).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Standard deduction, professional tax, and Section 80C‑80U deductions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HRA exemption calculation based on rent paid, city tier, and basic salary.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Home‑loan interest deduction under Section 24(b).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Capital gains from equity, debt, and real‑estate assets.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatic inclusion of health and education cess (4 %).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: Calculating Tax for a Bangalore Engineer
&lt;/h3&gt;

&lt;p&gt;Assume a software engineer in Bangalore earns ₹15,00,000 per annum, receives ₹1,80,000 HRA, pays ₹2,40,000 annual rent, and has a home‑loan interest of ₹1,20,000. The following JavaScript snippet demonstrates how to call TaxGst.in’s public endpoint (hypothetical) to fetch the tax liability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;financialYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2024-25&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;grossSalary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;hraReceived&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;rentPaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;240000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cityTier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;II&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;homeLoanInterest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;deductions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;section80C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;section80D&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25000&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.taxgst.in/v1/income-tax&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Tax payable:&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;taxPayable&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API returns a JSON object with &lt;code&gt;taxPayable&lt;/code&gt;, &lt;code&gt;taxBreakup&lt;/code&gt;, and &lt;code&gt;effectiveRate&lt;/code&gt;. You can then store the result, display it in a UI, or feed it into downstream payroll processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating the Calculator into a Payroll Service
&lt;/h2&gt;

&lt;p&gt;For a SaaS payroll product, you’ll need to run the tax computation for hundreds of employees each month. Below is a Node.js micro‑service outline that pulls employee data from a MongoDB collection, runs the calculation, and writes the result back.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MongoClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mongodb&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;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;computeTaxes&lt;/span&gt;&lt;span class="p"&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;client&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;MongoClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MONGO_URI&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;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;payroll&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;employees&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;employees&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({}).&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;for &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;emp&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;employees&lt;/span&gt;&lt;span class="p"&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;response&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.taxgst.in/v1/income-tax&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;financialYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2024-25&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;grossSalary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;annualCtc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;hraReceived&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hra&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;rentPaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;cityTier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cityTier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;homeLoanInterest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;homeLoanInterest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;deductions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deductions&lt;/span&gt;
      &lt;span class="p"&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;result&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;taxes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;updateOne&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;employeeId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;emp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;taxPayable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taxPayable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;computedAt&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;span class="p"&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;upsert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;computeTaxes&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern scales horizontally; you can spin up multiple instances behind a queue (e.g., RabbitMQ) to handle spikes during year‑end processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond Income Tax: Free GST Tools for Developers
&lt;/h2&gt;

&lt;p&gt;When you build e‑commerce or B2B platforms, GST compliance is equally critical. TaxGst.in hosts a suite of free GST utilities that you can call directly from your backend:&lt;/p&gt;

&lt;h3&gt;
  
  
  GST Calculator
&lt;/h3&gt;

&lt;p&gt;Use &lt;a href="https://dev.to/tools/gst-calculator"&gt;the GST Calculator&lt;/a&gt; to compute tax on invoice amounts, handle CGST, SGST, and IGST splits based on the buyer’s state, and round off to the nearest rupee. Here’s a quick Python example:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_gst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seller_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buyer_state&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invoiceAmount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sellerState&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;seller_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;buyerState&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;buyer_state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gstRate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;  &lt;span class="c1"&gt;# default GST rate for most goods
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://api.taxgst.in/v1/gst&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;calculate_gst&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Karnataka&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Maharashtra&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GST Late Fee &amp;amp; Interest Calculator
&lt;/h3&gt;

&lt;p&gt;If you need to display penalties for delayed filing, the &lt;a href="https://dev.to/tools/gst-late-fee-interest-calculator"&gt;GST Late Fee &amp;amp; Interest Calculator&lt;/a&gt; provides the exact interest amount based on the number of delayed days. The endpoint expects &lt;code&gt;principalAmount&lt;/code&gt; and &lt;code&gt;delayDays&lt;/code&gt; as inputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Capital Gains Tax Calculator
&lt;/h3&gt;

&lt;p&gt;For asset‑management apps, the &lt;a href="https://dev.to/tools/india-capital-gains-tax-calculator"&gt;India Capital Gains Tax Calculator&lt;/a&gt; computes short‑term and long‑term gains on equities, mutual funds, and property. Example request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.taxgst.in/v1/capital-gains &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
        "assetType": "Equity",
        "purchaseDate": "2021-04-10",
        "saleDate": "2024-03-15",
        "purchasePrice": 250000,
        "salePrice": 400000,
        "indexationBenefit": false
      }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Choosing the Right Tool for Your Product Roadmap
&lt;/h2&gt;

&lt;p&gt;TaxGst.in’s free suite covers most tax scenarios, but you may need additional modules for specific use‑cases. Browse the &lt;a href="https://dev.to/browse"&gt;product recommendations&lt;/a&gt; page to see premium APIs, bulk upload utilities, and compliance dashboards that integrate with the free calculators.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best Practices for Accuracy and Performance
&lt;/h2&gt;

&lt;p&gt;Tax rules change every budget. To keep your application up‑to‑date:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cache the tax‑rate JSON payload for 24 hours, then refresh.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate user inputs on the client side to avoid unnecessary API calls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log every calculation request with a correlation ID for audit trails.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run integration tests against the sandbox endpoint before production releases.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s a Node.js middleware that enforces these practices:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rateCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;expires&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;taxRateMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;next&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="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;rateCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expires&lt;/span&gt;&lt;span class="p"&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;r&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.taxgst.in/v1/rates&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;rateCache&lt;/span&gt;&lt;span class="p"&gt;.&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;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;rateCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expires&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 24h&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taxRates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rateCache&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="nf"&gt;next&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;h2&gt;
  
  
  Real‑World Use Cases from the Developer Community
&lt;/h2&gt;

&lt;p&gt;Below are three short case studies that show how teams incorporated TaxGst.in tools:&lt;/p&gt;

&lt;h3&gt;
  
  
  FinTech Startup “PayBuddy”
&lt;/h3&gt;

&lt;p&gt;PayBuddy needed to show users their projected tax liability when they created a savings goal. By embedding the &lt;a href="https://dev.to/tools/income-tax-calculator"&gt;Income Tax Calculator&lt;/a&gt; in a React component, they reduced manual calculations by 90 % and cut support tickets related to tax queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  E‑Commerce Platform “CartKart”
&lt;/h3&gt;

&lt;p&gt;CartKart integrated the &lt;a href="https://dev.to/tools/gst-calculator"&gt;GST Calculator&lt;/a&gt; into its checkout service. The API handled state‑wise IGST/CGST splits automatically, eliminating errors that previously caused order cancellations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Estate Investment App “PropGain”
&lt;/h3&gt;

&lt;p&gt;PropGain used the &lt;a href="https://dev.to/tools/india-capital-gains-tax-calculator"&gt;Capital Gains Tax Calculator&lt;/a&gt; to provide investors with a “post‑sale net profit” figure, accounting for indexation benefits. The feature boosted user engagement by 35 %.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Tax Logic with Unit Tests
&lt;/h2&gt;

&lt;p&gt;Because tax calculations are deterministic, you can write straightforward unit tests. Here’s a Jest test for the Bangalore engineer example:&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="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calculates tax for Bangalore engineer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;financialYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2024-25&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;grossSalary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;hraReceived&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;rentPaid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;240000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cityTier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;II&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;homeLoanInterest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;120000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;deductions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;section80C&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;section80D&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25000&lt;/span&gt;
    &lt;span class="p"&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;response&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;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/tax&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="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;taxPayable&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeCloseTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;158700&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The expected tax payable (₹158,700) matches the manual calculation using the Income Tax Calculator UI, confirming that the integration behaves correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Future Enhancements You Might Want to Track
&lt;/h2&gt;

&lt;p&gt;While the current free tools cover most statutory requirements, keep an eye on upcoming features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Support for the new optional tax regime introduced in FY 2025‑26.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Batch processing endpoints for large payroll runs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GraphQL wrapper for selective field retrieval, reducing payload size.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Subscribe to TaxGst.in’s developer newsletter to receive release notes and migration guides.&lt;/p&gt;

&lt;h2&gt;
  
  
  People Also Ask
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How accurate is the TaxGst.in income tax calculator?
&lt;/h3&gt;

&lt;p&gt;The calculator uses the latest Finance Act data published by the Indian Income Tax Department. It applies the correct slabs, cess, and standard deductions for the selected financial year, delivering results that match manual calculations performed by certified accountants.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use the GST calculator in a production environment?
&lt;/h3&gt;

&lt;p&gt;Yes. The free GST calculator API is rate‑limited to 200 calls per minute, which is sufficient for most midsize applications. For higher throughput, the premium plan offers unlimited calls and SLA guarantees.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is there an API for the capital gains tax calculator?
&lt;/h3&gt;

&lt;p&gt;TaxGst.in provides a REST endpoint that accepts asset type, purchase and sale dates, and prices. The response includes short‑term or long‑term classification, applicable tax rate, and the final tax amount.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need to handle GST interest calculations myself?
&lt;/h3&gt;

&lt;h2&gt;
  
  
  The &lt;a href="https://dev.to/tools/gst-late-fee-interest-calculator"&gt;GST Late Fee &amp;amp; Interest Calculator&lt;/a&gt; returns the exact interest based on the principal amount and days of delay, so you can display the penalty directly without custom logic.
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/taxgstin-free-income-tax-calculator-free-gst-tools-finance-guides-indi-2026" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>incometax</category>
    </item>
    <item>
      <title>Node 26 Becomes LTS on 28 October: Upgrade Guide from 24 and 22</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Mon, 19 Oct 2026 13:15:05 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/node-26-becomes-lts-on-28-october-upgrade-guide-from-24-and-22-m6i</link>
      <guid>https://dev.to/akaranjkar08/node-26-becomes-lts-on-28-october-upgrade-guide-from-24-and-22-m6i</guid>
      <description>&lt;p&gt;&lt;strong&gt;Node.js 26 is scheduled to enter Long Term Support on 28 October 2026, eight days after Node 24 drops from Active LTS to Maintenance on 20 October, and it is supported through 30 April 2029.&lt;/strong&gt;[1] Node 22 stays in Maintenance until 30 April 2027, and Node 20 has been end-of-life since 30 April 2026. As of 19 October the latest 26.x release is 26.12.0, shipped 14 October with V8 14.6 and npm 11.20.0[2]. This post gives you the full schedule table from the official file, the changes in Node 26 that can actually break an upgrade, the exact commands for nvm, fnm, Volta, GitHub Actions and Docker, and a plain answer to whether you should move now or wait. Nothing here is true until the release team flips the switch, so every date below is the planned one.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Node 26 becomes LTS on 28 October 2026 (planned). The schedule file lists no codename yet, so none is stated here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node 24 enters Maintenance on 20 October 2026 and reaches end-of-life on 30 April 2028. Staying on 24 is safe for production.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node 22 is already in Maintenance and ends on 30 April 2027. It is the line that needs a plan first.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node 20 is end-of-life since 30 April 2026 and gets no security fixes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What bites in 26: removed &lt;code&gt;http.Server.prototype.writeHeader()&lt;/code&gt;, removed legacy &lt;code&gt;_stream_*&lt;/code&gt; modules, runtime deprecations for &lt;code&gt;module.register()&lt;/code&gt;, and the removal of &lt;code&gt;--experimental-transform-types&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run your tests on 26 with &lt;code&gt;--trace-deprecation&lt;/code&gt; this week; switch production after 28 October, not before.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Node.js release schedule as of 19 October 2026
&lt;/h2&gt;

&lt;p&gt;The Node.js Release working group publishes its schedule as a JSON file, and the README table in the same repository is generated from the same dates[1][3]. The table below is copied from that file. The README adds the caveat that dates are subject to change, and that the exact date of an LTS move is chosen no later than the first day of the month it happens in.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Line&lt;/th&gt;
&lt;th&gt;Status on 19 Oct 2026&lt;/th&gt;
&lt;th&gt;First release&lt;/th&gt;
&lt;th&gt;LTS start&lt;/th&gt;
&lt;th&gt;Maintenance start&lt;/th&gt;
&lt;th&gt;End-of-life&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Node 20 (Iron) | End-of-life | 2023-04-18 | 2023-10-24 | 2024-10-22 | 2026-04-30 |&lt;/p&gt;

&lt;p&gt;| Node 22 (Jod) | Maintenance LTS | 2024-04-24 | 2024-10-29 | 2025-10-21 | 2027-04-30 |&lt;/p&gt;

&lt;p&gt;| Node 24 (Krypton) | Active LTS until 20 Oct | 2025-05-06 | 2025-10-28 | 2026-10-20 | 2028-04-30 |&lt;/p&gt;

&lt;p&gt;| Node 25 | End-of-life | 2025-10-15 | none (odd line) | none | 2026-06-01 |&lt;/p&gt;

&lt;p&gt;| Node 26 | Current | 2026-05-05 | 2026-10-28 | 2027-10-20 | 2029-04-30 |&lt;/p&gt;

&lt;p&gt;| Node 27 | Not released | alpha 2026-10-28, start 2027-04-22 | not listed | 2027-10-20 | 2030-04-30 |&lt;/p&gt;

&lt;p&gt;Two readings of that table matter. First, the working group says an even-numbered line stays in Active LTS for 12 months and then spends 18 months in Maintenance[3]. Node 24 and 26 both fit that pattern: 28 October to 20 October is the 12 months, 20 October to 30 April the 18. Second, the Node 27 row carries no LTS date and no codename in the schedule file. The file does not say what that means for the odd/even rule, so check the file again before you plan anything around 27.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Maintenance means for Node 24
&lt;/h3&gt;

&lt;p&gt;The README defines Maintenance as critical bug fixes and security updates, with new features added only at the release team's discretion, typically when they help migration to a later line[3]. It does not mean abandoned. Node 24 will keep getting security releases for another 18 months. The practical difference is that you should stop expecting backports of new APIs, and you should treat the line as a place you are leaving, not a place you are settling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Node 22 is the line that needs a decision
&lt;/h3&gt;

&lt;p&gt;Node 22 has about six months of life left (30 April 2027). If you run it, the question is not whether to move but whether to go to 24 or straight to 26. Going to 24 buys you until April 2028. Going to 26 buys you until April 2029 and one fewer migration. The catch is that 26 has been out for five months as a Current release, and the changes in the next section apply to you in full.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed in Node 26 that matters when you upgrade
&lt;/h2&gt;

&lt;p&gt;The 26.0.0 release notes, dated 5 May 2026, list the headline items as the Temporal API enabled by default, V8 updated to 14.6 and Undici updated to 8.0[4]. Version numbers from the release feed: 26.12.0 ships V8 14.6.202.34 and npm 11.20.0, while Node 24.22.0 ships V8 13.6 and npm 11.19.1, and Node 22.23.3 ships V8 12.4 and npm 10.9.9[2]. The npm major jump matters if you move from 22, because npm 10 to 11 is a separate set of changes to read.&lt;/p&gt;

&lt;h3&gt;
  
  
  New in 26.0.0
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporal API on by default.&lt;/strong&gt; The modern date and time API is available without a flag, contributed by Richard Lau in PR 61806[4]. Your &lt;code&gt;Date&lt;/code&gt; code keeps working. Nothing forces you to migrate, but libraries that feature-detect &lt;code&gt;Temporal&lt;/code&gt; may change behavior once it exists.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;V8 14.6.&lt;/strong&gt; The notes call out &lt;code&gt;Map.prototype.getOrInsert()&lt;/code&gt; and &lt;code&gt;getOrInsertComputed()&lt;/code&gt; (also on &lt;code&gt;WeakMap&lt;/code&gt;) plus &lt;code&gt;Iterator.concat()&lt;/code&gt;[4]. Both are small, but &lt;code&gt;getOrInsertComputed&lt;/code&gt; removes the common get-check-set pattern in caches.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Undici 8.0.2&lt;/strong&gt; in the 26.0.0 release, which backs &lt;code&gt;fetch&lt;/code&gt;. If you pin a custom &lt;code&gt;undici&lt;/code&gt; dispatcher or agent, retest it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Removed and deprecated in 26.0.0
&lt;/h3&gt;

&lt;p&gt;These are the entries that break builds, taken from the Deprecations and Removals section of the changelog[4]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;http.Server.prototype.writeHeader()&lt;/code&gt; is gone. Use &lt;code&gt;writeHead()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The legacy &lt;code&gt;_stream_wrap&lt;/code&gt;, &lt;code&gt;_stream_readable&lt;/code&gt;, &lt;code&gt;_stream_writable&lt;/code&gt;, &lt;code&gt;_stream_duplex&lt;/code&gt;, &lt;code&gt;_stream_transform&lt;/code&gt; and &lt;code&gt;_stream_passthrough&lt;/code&gt; modules are removed. Old packages that &lt;code&gt;require('_stream_readable')&lt;/code&gt; will throw. Import from &lt;code&gt;node:stream&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;--experimental-transform-types&lt;/code&gt; is removed, which hits anyone running TypeScript files through that flag.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;module.register()&lt;/code&gt; is now runtime-deprecated, so loader setups built on it print a warning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DEP0182 moved to end-of-life, DEP0203 and DEP0204 became runtime deprecations in &lt;code&gt;crypto&lt;/code&gt;, and DEP0201 in &lt;code&gt;stream&lt;/code&gt; became a runtime deprecation. I did not look up what each DEP number covers in the deprecations page, so grep your warnings for those codes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Platform floor: the build now needs GCC 13.2 and drops Python 3.9[4]. That matters if you compile Node yourself or build native addons on old CI images.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One more change that is easy to miss: &lt;code&gt;localStorage&lt;/code&gt; now returns &lt;code&gt;undefined&lt;/code&gt; when no storage file is configured, per the semver-major list in the same release[4]. Code that assumed an object will fail at the first property access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Useful additions since 26.0.0
&lt;/h3&gt;

&lt;p&gt;Node 26 already has twelve minor releases (26.1.0 to 26.12.0), so some features you may want are not in 24. These are the ones listed under Notable Changes, with the release that added them[4]:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Addition&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| 26.1.0 | 2026-05-07 | Experimental &lt;code&gt;node:ffi&lt;/code&gt; module, behind &lt;code&gt;--experimental-ffi&lt;/code&gt; |&lt;/p&gt;

&lt;p&gt;| 26.2.0 | 2026-05-20 | &lt;code&gt;stream.compose&lt;/code&gt; marked stable; &lt;code&gt;writeInformation&lt;/code&gt; for 1xx responses |&lt;/p&gt;

&lt;p&gt;| 26.8.0 | 2026-08-26 | &lt;code&gt;TracingChannel&lt;/code&gt; in &lt;code&gt;diagnostics_channel&lt;/code&gt; marked stable |&lt;/p&gt;

&lt;p&gt;| 26.9.0 | 2026-09-16 | &lt;code&gt;node:ffi&lt;/code&gt; enabled by default |&lt;/p&gt;

&lt;p&gt;| 26.11.0 | 2026-10-07 | &lt;code&gt;Buffer.stringLength()&lt;/code&gt;, &lt;code&gt;isLatin1&lt;/code&gt;, Alpine Linux promoted to tier 2 support |&lt;/p&gt;

&lt;p&gt;| 26.12.0 | 2026-10-14 | &lt;code&gt;http.websocketMask()&lt;/code&gt; and &lt;code&gt;websocketUnmask()&lt;/code&gt; |&lt;/p&gt;

&lt;p&gt;The ffi row deserves a second look. The 26.1.0 notes say the API is inherently unsafe, since bad pointers or wrong signatures can crash the process or corrupt memory[4]. Being on by default in 26.9.0 does not make it safe. Treat it as something you do not use in production code until it has a track record. Also from the notes: the 26.3.0 release flags a risk that macOS Universal Binaries may not be maintained for the full life of Node 26, though the stated intention is to keep shipping them as long as practical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrade checklist: Node 24 or 22 to Node 26
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Install 26 beside your current version
&lt;/h3&gt;

&lt;p&gt;Do not replace anything yet. Install 26 next to what you run, so you can switch per shell.&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;# nvm: install, then carry global packages over from 24&lt;/span&gt;
nvm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--reinstall-packages-from&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;24 26
nvm use 26

&lt;span class="c"&gt;# fnm&lt;/span&gt;
fnm &lt;span class="nb"&gt;install &lt;/span&gt;26
fnm use 26

&lt;span class="c"&gt;# Volta (pins the version in package.json)&lt;/span&gt;
volta &lt;span class="nb"&gt;install &lt;/span&gt;node@26
volta pin node@26
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--reinstall-packages-from&lt;/code&gt; flag is documented in the nvm README[5], and &lt;code&gt;fnm install [VERSION]&lt;/code&gt; and &lt;code&gt;fnm use [VERSION]&lt;/code&gt; are in the fnm command reference[6]. The Volta commands are from memory of its docs and I did not re-verify them today, so run &lt;code&gt;volta --help&lt;/code&gt; if one fails. After 28 October, &lt;code&gt;nvm install --lts&lt;/code&gt; should resolve to 26, but check &lt;code&gt;node -v&lt;/code&gt; rather than trusting it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Declare what you support in package.json
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=24 &amp;lt;27"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Widening &lt;code&gt;engines&lt;/code&gt; to cover both 24 and 26 lets you run both in CI during the transition without npm complaining. Add &lt;code&gt;"engine-strict=true"&lt;/code&gt; to &lt;code&gt;.npmrc&lt;/code&gt; if you want npm to enforce it. Also drop a &lt;code&gt;.nvmrc&lt;/code&gt; or &lt;code&gt;.node-version&lt;/code&gt; file: the &lt;code&gt;actions/setup-node&lt;/code&gt; action reads either through its &lt;code&gt;node-version-file&lt;/code&gt; input[7]. If you use Corepack for package managers, run &lt;code&gt;corepack --version&lt;/code&gt; after installing 26 to confirm it is present, because Corepack distribution has changed across recent Node releases and I did not trace the details.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Run a CI matrix on both lines
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;node&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;24&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;26&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v7&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.node }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current major of &lt;code&gt;actions/setup-node&lt;/code&gt; is v7; its latest release, v7.1.0, was published on 8 October 2026[7]. The README also notes that automatic package-manager caching is on by default and can be turned off with &lt;code&gt;package-manager-cache: false&lt;/code&gt; for workflows that handle sensitive data. For a full pipeline around this step, see our &lt;a href="https://dev.to/blogs/github-actions-ci-cd-nodejs-complete-pipeline-2026"&gt;GitHub Actions CI/CD pipeline for Node.js&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Update Docker base images
&lt;/h3&gt;

&lt;p&gt;Docker Hub already carries the 26 tags: &lt;code&gt;node:26&lt;/code&gt;, &lt;code&gt;node:26-slim&lt;/code&gt;, &lt;code&gt;node:26-alpine&lt;/code&gt;, &lt;code&gt;node:26-bookworm-slim&lt;/code&gt; and &lt;code&gt;node:26-trixie-slim&lt;/code&gt;, plus pinned forms like &lt;code&gt;node:26.12.0&lt;/code&gt;[8]. Pin a major (&lt;code&gt;node:26-slim&lt;/code&gt;) in production, and pin the full version if you need byte-identical rebuilds. I could not confirm from a primary source whether Docker will add an &lt;code&gt;lts&lt;/code&gt; alias pointing at 26 on 28 October, so do not depend on one. If your image builds native addons on Alpine, remember that 26.11.0 promoted Alpine to tier 2 support[4], which is good news but not a reason to skip a test build. Our &lt;a href="https://dev.to/blogs/docker-compose-production-nodejs-redis-postgres-2026"&gt;production Docker Compose guide for Node.js&lt;/a&gt; covers the rest of the stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to test before you switch
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run the full suite on 26.&lt;/strong&gt; Start with unit tests, then integration tests against real databases and queues. Failures from removed APIs show up as thrown errors, so they are loud.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Surface deprecations.&lt;/strong&gt; Run &lt;code&gt;node --trace-deprecation your-entry.js&lt;/code&gt; or set &lt;code&gt;NODE_OPTIONS=--trace-deprecation&lt;/code&gt; in CI. Runtime deprecations print a warning with a stack, and the stack usually points at a dependency, not your code. To make the suite fail on them, use &lt;code&gt;--throw-deprecation&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Grep for the removed names.&lt;/strong&gt; Search your source and &lt;code&gt;node_modules&lt;/code&gt; for &lt;code&gt;writeHeader(&lt;/code&gt;, &lt;code&gt;_stream_&lt;/code&gt;, &lt;code&gt;module.register&lt;/code&gt; and &lt;code&gt;experimental-transform-types&lt;/code&gt;. Dependencies are the usual source of old stream imports.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rebuild native addons.&lt;/strong&gt; Delete &lt;code&gt;node_modules&lt;/code&gt; and run &lt;code&gt;npm ci&lt;/code&gt; on 26 so every addon compiles against the new V8. Anything built with node-gyp needs a toolchain that supports GCC 13.2 on Linux; addons that ship prebuilt binaries need a release that targets Node 26's ABI. If a package has no 26 build, that is your blocker, not Node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Diff your fixtures and configs.&lt;/strong&gt; When a test fails on a data shape, normalize the sample before comparing. Paste it into the &lt;a href="https://dev.to/tools/json-formatter"&gt;JSON formatter&lt;/a&gt; to normalize them before comparing, or run YAML configs through the &lt;a href="https://dev.to/tools/yaml-to-json-converter"&gt;YAML to JSON converter&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Soak in staging.&lt;/strong&gt; Run 26 under real traffic in staging for a week and watch memory and latency. A new V8 changes garbage collection behavior in ways unit tests do not show.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your project is a command-line tool, our &lt;a href="https://dev.to/blogs/build-cli-tool-nodejs-typescript-complete-guide-2026"&gt;Node.js and TypeScript CLI guide&lt;/a&gt; has patterns for testing across several runtime versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to upgrade now, and when to wait
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your situation&lt;/th&gt;
&lt;th&gt;Recommendation&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Production on Node 20 | Move now, to 24 at minimum | End-of-life since 30 April 2026; no security fixes |&lt;/p&gt;

&lt;p&gt;| Production on Node 22 | Plan the move before spring 2027; test on 26 now | Ends 30 April 2027 |&lt;/p&gt;

&lt;p&gt;| Production on Node 24 | Wait. Test on 26, switch in 2027 | Supported until 30 April 2028 |&lt;/p&gt;

&lt;p&gt;| New project | Start on 24 today, or 26 after 28 October | 26 is the longer runway (to April 2029) |&lt;/p&gt;

&lt;p&gt;| Library author | Add 26 to your CI matrix now | Users will adopt 26 as soon as it is LTS |&lt;/p&gt;

&lt;p&gt;The reason to wait on 24 is boring and sound: LTS lines get fixes that have been audited by the release team, and a Current line that has just changed status has had less production exposure than the fifth month of a stable one. Node 26 has had five months of Current releases, and the 26.3.1 and 26.5.1 releases each shipped a list of CVE fixes[4]. Active patching counts in its favor, though it also shows the line has had real security work to do.&lt;/p&gt;

&lt;p&gt;If you do move before the LTS date, treat it as a normal Current-line adoption: pin an exact version, watch the changelog for each minor, and be ready to roll back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What date does Node 26 become LTS?
&lt;/h3&gt;

&lt;p&gt;The official schedule file lists 28 October 2026 as the LTS start for Node 26[1]. The README says dates are subject to change, so confirm on the day. This post was written on 19 October, before that date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Node 24 still safe to use after 20 October?
&lt;/h3&gt;

&lt;p&gt;Yes. From 20 October 2026 it is in Maintenance, which means critical bug fixes and security updates, until 30 April 2028[1]. You lose new-feature backports, not security fixes.&lt;/p&gt;

&lt;h3&gt;
  
  
  When does Node 22 reach end-of-life?
&lt;/h3&gt;

&lt;p&gt;30 April 2027, according to the schedule file[1]. It has been in Maintenance since 21 October 2025.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Node 20 end-of-life already?
&lt;/h3&gt;

&lt;p&gt;Yes. The schedule lists 30 April 2026 as its end date[1]. If you still run it, upgrade to 24 or 26 rather than hunting for patched builds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does Node 26 have a codename?
&lt;/h3&gt;

&lt;p&gt;Not in the schedule file as of 19 October 2026, where the codename field for v26 is empty[1]. Earlier LTS lines got element names such as Jod and Krypton, but I will not guess one for 26.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I skip Node 24 and go from 22 straight to 26?
&lt;/h3&gt;

&lt;p&gt;Yes, and many teams will. You inherit every removal and deprecation between the two lines, plus the npm 10 to 11 change, so read the changelogs for 24 and 26 and run the test steps above. I only reviewed the 26 changelog for this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/nodejs/Release/main/schedule.json" rel="noopener noreferrer"&gt;nodejs/Release: schedule.json (read 19 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nodejs.org/dist/index.json" rel="noopener noreferrer"&gt;Node.js release feed, nodejs.org/dist/index.json (read 19 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/nodejs/Release" rel="noopener noreferrer"&gt;nodejs/Release README: release schedule and phases (read 19 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V26.md" rel="noopener noreferrer"&gt;Node.js 26 changelog, CHANGELOG_V26.md (read 19 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/nvm-sh/nvm#readme" rel="noopener noreferrer"&gt;nvm README: installing and --reinstall-packages-from&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/Schniz/fnm/blob/master/docs/commands.md" rel="noopener noreferrer"&gt;fnm command reference&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/actions/setup-node" rel="noopener noreferrer"&gt;actions/setup-node README and releases (v7.1.0, 8 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  8. &lt;a href="https://hub.docker.com/_/node" rel="noopener noreferrer"&gt;Docker Hub: official node image tags (read 19 October 2026)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/node-26-lts-28-october-2026-upgrade-guide-from-node-24-22" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node26</category>
      <category>nodejs26</category>
      <category>upgradenode</category>
      <category>node24</category>
    </item>
    <item>
      <title>UPI MDR Deferred Past Diwali: What Merchants Should Check Now</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Mon, 19 Oct 2026 13:08:39 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/upi-mdr-deferred-past-diwali-what-merchants-should-check-now-12hk</link>
      <guid>https://dev.to/akaranjkar08/upi-mdr-deferred-past-diwali-what-merchants-should-check-now-12hk</guid>
      <description>&lt;p&gt;&lt;strong&gt;UPI MDR on larger merchant payments is deferred, not cancelled: NPCI said on 13 October 2026 that it will start "immediately post Diwali at a date to be notified separately", and as of 19 October 2026 no date has been notified.&lt;/strong&gt;[1] The rule that was due on 15 October was a Merchant Discount Rate of up to 0.4% on UPI person-to-merchant (P2M) payments above ₹2,000, paid by the merchant, never the customer.[2] Diwali Laxmi Pujan is on Sunday 8 November 2026,[6] and a date straight after the festival is consistent with NPCI's wording, but none has been notified. This guide separates what two primary documents confirm from what only news outlets have reported, then walks a freelancer, online seller or shop through what to check before the date lands.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is general information, not tax, legal or financial advice. Nothing here is a statement of what will be charged on any date, because no effective date is notified. Rates, caps and exemptions marked "as reported" come from news summaries, not from an NPCI circular I could open. Confirm against your bank, payment gateway agreement or a qualified professional before changing prices or contracts.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Status: deferred. NPCI's steering committee postponed MDR on "select" P2M UPI transactions to "immediately post Diwali"; no new date is notified as of 19 October 2026.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Described in Paytm's stock-exchange filing, which cites the circular: NPCI circular OC-No.237/2026-27 of 15 September 2026 set an MDR of up to 0.4% on P2M UPI payments above ₹2,000, and customers pay nothing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reported only (not read in the original): a ₹300 cap per transaction, flat ₹5 for some categories, 0.02% for capital markets, and an exemption for small merchants collecting up to ₹1 lakh a month on a UPI QR.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your job this week: tag every receipt as P2P, P2M via QR, or P2M via gateway; add up your monthly UPI QR total; read your gateway agreement for UPI fees.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do not reprice yet. Model the cost with the examples below and wait for the notified date and the final rate card.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is actually decided, and what is not
&lt;/h2&gt;

&lt;p&gt;Only two things in this story rest on documents anyone can open. The first is NPCI's press release dated Mumbai, 13 October 2026. Its operative sentence reads: "UPI and Services Steering Committee today decided that, keeping in mind the festive season, Merchant Discount Rate (MDR) on select Person-to-Merchant (P2M) UPI transactions, shall be implemented immediately post Diwali at a date to be notified separately."[1] It contains no rate, no threshold and no date. I opened it through a text mirror because the NPCI site refused a direct download.&lt;/p&gt;

&lt;p&gt;The second is a disclosure that One 97 Communications (Paytm) filed with BSE and NSE on 15 September 2026. It says NPCI, through circular no. NPCI/UPI/OC-No.237/2026-27 dated 15 September 2026, "introduced a Merchant Discount Rate of upto 0.4% on UPI Person-to-Merchant (P2M) transactions exceeding ₹2,000", that the circular "shall be effective from October 15, 2026", and that "no charge is levied on customers for UPI payments, which shall continue to remain free of charge for them."[2] The 15 October date has since been overtaken by the deferral. I could not open the circular itself, so everything beyond the Paytm filing's description is second-hand.&lt;/p&gt;

&lt;p&gt;That second-hand layer is large. Law-and-business outlets summarised an NPCI FAQ and a government notification, and their summaries are where the ₹300 cap and the ₹1 lakh exemption come from. They are plausible and they agree with each other on most points, but a summary of a FAQ is not the FAQ. The table keeps the source visible for every line.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;What is stated&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Deferral | MDR on select P2M UPI payments to start "immediately post Diwali", date to be notified | NPCI press release, 13 Oct 2026[1] | Primary |&lt;/p&gt;

&lt;p&gt;| Base rate | Up to 0.4% on P2M above ₹2,000 | Paytm exchange filing, 15 Sep 2026[2] | Primary (company filing quoting NPCI circular) |&lt;/p&gt;

&lt;p&gt;| Customer charge | None; UPI stays free for customers | Paytm exchange filing[2] | Primary |&lt;/p&gt;

&lt;p&gt;| Cap | ₹300 per transaction, reported to bite from ₹75,000 | SCC Online[3], Outlook India[4] | Reported |&lt;/p&gt;

&lt;p&gt;| Flat fee categories | ₹5 per transaction above ₹2,000 for railways, telecom, insurance, fuel and some utilities | SCC Online, Outlook India | Reported |&lt;/p&gt;

&lt;p&gt;| Capital markets | 0.02%, capped at ₹300 | SCC Online, Outlook India | Reported |&lt;/p&gt;

&lt;p&gt;| Exempt | P2P transfers; P2M up to ₹2,000; small P2PM merchants collecting up to ₹1 lakh a month on UPI QR | SCC Online, Outlook India | Reported |&lt;/p&gt;

&lt;p&gt;| No pass-through | Merchants may not recover MDR from customers; UPI apps may not add platform fees | SCC Online, Outlook India | Reported |&lt;/p&gt;

&lt;p&gt;| Government notification | 14 Sep 2026 notice under section 10A of the Payment and Settlement Systems Act, 2007 on charges up to ₹2,000 | LiveLaw[5] | Reported, not read |&lt;/p&gt;

&lt;h2&gt;
  
  
  How the timeline reads
&lt;/h2&gt;

&lt;p&gt;The sequence matters because search results still show the old date. Anyone who read "from 15 October" in mid-September is now out of date.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;14 September 2026: a Department of Financial Services notification is reported, covering charges on UPI and RuPay debit card payments up to ₹2,000.[5]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;15 September 2026: NPCI circular OC-No.237/2026-27, effective 15 October according to Paytm's filing; NPCI FAQs follow, as summarised by SCC Online.[2][3]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;13 October 2026: NPCI defers the start to immediately after Diwali, date to be notified separately.[1]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;19 October 2026: no new date is notified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;8 November 2026: Diwali Laxmi Pujan; NSE also lists 10 November as a trading holiday for Diwali Bali Pratipada.[6]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"Immediately post Diwali" does not map to a single calendar day. Diwali is a multi-day festival, so the first working day after the last festival holiday, the first of the next month, or a mid-month date are all consistent with the wording. Plan for the earliest case: assume the charge could apply within days of 10 November and make your preparations in October.&lt;/p&gt;

&lt;h2&gt;
  
  
  The government notification covers payments up to ₹2,000
&lt;/h2&gt;

&lt;p&gt;The reported section 10A notification is the part to treat most carefully. LiveLaw's headline says the Centre prohibits charges on UPI transactions up to ₹2,000 and on RuPay debit cards.[5] That is consistent with the NPCI framework leaving payments up to ₹2,000 free. Only LiveLaw reports the notification, and it covers charges up to ₹2,000; no source cited here says what it means for payments above ₹2,000, and I have not read the gazette text. So this guide does not say that MDR above ₹2,000 is legally settled in any direction. The only fact that is safe to build on is the NPCI circular as described in Paytm's filing, plus NPCI's own statement that the start is deferred.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: sort your receipts into P2P, P2M by QR and P2M by gateway
&lt;/h2&gt;

&lt;p&gt;MDR, as described in every source above, sits on person-to-merchant payments. Whether you owe anything therefore depends on how the money reached you, not on what you sell.&lt;/p&gt;

&lt;h3&gt;
  
  
  The three buckets
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;P2P receipts.&lt;/strong&gt; A friend or relative sends you money to your personal UPI ID. Reported as exempt whatever the amount.[3] This bucket does not become business income just because you also freelance; it simply is not the target of the rule.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P2M by QR or merchant VPA.&lt;/strong&gt; A customer scans a merchant QR registered to your shop or business, or pays to a merchant handle. This is where the reported ₹1 lakh a month exemption for small P2PM merchants applies, if it stands.[4]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P2M through a payment gateway or aggregator.&lt;/strong&gt; Your website checkout, payment link or invoice link opens UPI inside Razorpay, Cashfree, PhonePe PG, PayU or similar. Your contract is with the gateway, not directly with a bank, so the question of who bears NPCI's MDR is a matter of your agreement with them.&lt;/p&gt;

&lt;h3&gt;
  
  
  A five-minute audit
&lt;/h3&gt;

&lt;p&gt;Export three months of settlement or bank statements and tag each credit. A spreadsheet with four columns is enough: date, amount, bucket, and payer type (individual or business). Then total the P2M QR column per calendar month. The result tells you two things: whether you sit near the reported ₹1 lakh threshold, and how many payments land above ₹2,000.&lt;/p&gt;

&lt;p&gt;If you take client payments to a personal handle because it is convenient, flag it. Collecting business payments on a personal VPA is a question about your bank's terms and about clean bookkeeping, and I am not offering an interpretation of how the MDR framework would treat it. Ask your bank. Separately, keeping business and personal money apart is what &lt;a href="https://dev.to/blogs/freelancer-accounting-in-india-gst-itr-bookkeeping-2026"&gt;the freelancer accounting guide&lt;/a&gt; recommends for GST and ITR reasons that have nothing to do with MDR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: do you count as a small P2PM merchant?
&lt;/h2&gt;

&lt;p&gt;As reported, NPCI's FAQ defines the small-merchant tier as vendors who receive up to ₹1 lakh a month through UPI QR codes directly into their accounts, with GST registration not required to qualify[3], and with the exemption holding even when a single payment is above ₹2,000.[4] SCC Online adds a qualifier: MDR applicability depends on the merchant's overall categorisation and monthly collections.[3]&lt;/p&gt;

&lt;p&gt;Practical reading, flagged as unconfirmed: a tea stall, tutor or home baker taking ₹300 to ₹1,500 per sale on a QR will probably never see a charge. A freelancer who gets a handful of ₹25,000 payments, or a shop with a busy month above ₹1 lakh in QR collections, is the person the rule can reach. What is not known is how the monthly total is measured (calendar month, which accounts, whether gateway settlements count) and what happens in a month you cross the line. Those are details for the final circular.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worked examples (illustrative only)
&lt;/h2&gt;

&lt;p&gt;The arithmetic below applies the reported structure to round numbers. None of it is a quote of a notified rate card. The reported cap of ₹300 is applied to payments of ₹75,000 and above, which is where 0.4% reaches ₹300.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Payment&lt;/th&gt;
&lt;th&gt;Calculation (reported rules)&lt;/th&gt;
&lt;th&gt;Merchant pays&lt;/th&gt;
&lt;th&gt;Net received&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| ₹1,500 | Up to ₹2,000, outside MDR | ₹0 | ₹1,500 |&lt;/p&gt;

&lt;p&gt;| ₹2,000 | Not above ₹2,000 | ₹0 | ₹2,000 |&lt;/p&gt;

&lt;p&gt;| ₹3,000 | 0.4% x 3,000 | ₹12 | ₹2,988 |&lt;/p&gt;

&lt;p&gt;| ₹5,000 | 0.4% x 5,000 | ₹20 | ₹4,980 |&lt;/p&gt;

&lt;p&gt;| ₹50,000 | 0.4% x 50,000 | ₹200 | ₹49,800 |&lt;/p&gt;

&lt;p&gt;| ₹75,000 | 0.4% x 75,000 = 300, equals the cap | ₹300 | ₹74,700 |&lt;/p&gt;

&lt;p&gt;| ₹1,00,000 | 0.4% = ₹400, capped at ₹300 | ₹300 | ₹99,700 |&lt;/p&gt;

&lt;p&gt;| ₹3,000 fuel or insurance premium | Flat ₹5 (reported) | ₹5 | ₹2,995 |&lt;/p&gt;

&lt;p&gt;| ₹1,00,000 mutual fund purchase | 0.02% x 1,00,000 (reported) | ₹20 | ₹99,980 |&lt;/p&gt;

&lt;p&gt;Two things stand out. The ₹3,000, ₹50,000 and ₹75,000 and above rows match the NPCI FAQ examples as SCC Online reproduced them (₹12, ₹200 and ₹300).[3] And the percentage drops as tickets grow: ₹300 on ₹1,00,000 is 0.3%, and ₹300 on ₹3,00,000 is 0.1%.&lt;/p&gt;

&lt;h3&gt;
  
  
  Three business scenarios
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The freelance designer.&lt;/strong&gt; Ten client payments of ₹25,000 in a month, ₹2,50,000 in total. At 0.4% each costs ₹100, so ₹1,000 across the month. If those payments arrive as P2M on a merchant QR and the account is not in the small-merchant tier, that is the exposure. If the same ten payments are bank transfers, the exposure is zero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The online seller.&lt;/strong&gt; A store taking 200 orders a month at ₹1,500 pays nothing, because every order is at or below ₹2,000. The same store selling 40 orders at ₹3,000 (₹1,20,000 in total) would pay 40 x ₹12 = ₹480, about 0.4% of revenue, if its UPI payments count as standard P2M. The reported ₹1 lakh a month small-merchant tier is described for UPI QR collections, so it may not apply to gateway checkout at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The shop with a counter QR.&lt;/strong&gt; Most baskets are below ₹2,000, which NPCI says covers over 95% of merchant UPI volume (reported by SCC Online and Outlook India).[3] The risk is concentrated in a few large baskets: an electronics shop with ten ₹20,000 sales pays up to ₹80 each, ₹800 total. To run your own numbers, multiply each payment above ₹2,000 by 0.004 and cap the result at ₹300 if the reported cap holds. To compare card and international gateway fees, the &lt;a href="https://dev.to/tools/payment-fee-calculator"&gt;payment fee calculator&lt;/a&gt; covers those providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The gateway angle
&lt;/h2&gt;

&lt;p&gt;If you sell through a checkout page or send payment links, you are probably not paying NPCI directly. Your gateway collects from the customer's bank and settles to you. Whether and how a gateway passes a new MDR on to you is set by its agreement and pricing page. I did not verify any gateway's current UPI pricing in preparing this guide, and gateway fees change, so I am not quoting numbers. What to look for in your agreement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Does the plan list a UPI rate today, or does it say "0% on UPI" for a promotional period that may end?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is there a clause allowing the gateway to pass on "regulatory or network charges"?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is there notice period before a pricing change, and do you have to accept it to keep processing?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Does the fee apply to the gross amount or the net after GST?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do refunds return the fee?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last question is not trivial. If a ₹5,000 payment is refunded, whether the ₹20 comes back depends on the processor. Ask support in writing and keep the answer.&lt;/p&gt;

&lt;p&gt;If you receive payments through a link rather than a gateway, the &lt;a href="https://dev.to/tools/upi-payment-link-maker"&gt;UPI payment link maker&lt;/a&gt; generates a link and QR for a given amount and note. Ask your bank whether it classifies your VPA as personal or merchant.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about GST on the fee?
&lt;/h2&gt;

&lt;p&gt;MDR is a charge for a service. Check whether your gateway or bank invoice shows GST on its fees today. I did not open a CBIC notification for the treatment of MDR on UPI specifically, so I am not stating a rate or a rule. Check the GST line on your gateway or bank statement for the current treatment, and use the &lt;a href="https://dev.to/tools/gst-calculator"&gt;GST calculator&lt;/a&gt; to split an invoice into base and tax once you know what applies to you. If you claim input tax credit on payment-processing fees, your accountant will want fee invoices rather than bank narrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing and passing the cost on
&lt;/h2&gt;

&lt;p&gt;Reported rule: merchants cannot recover MDR from customers, and UPI apps cannot add platform fees.[3][4] So a "UPI surcharge" line on an invoice is exactly what the reports say is not permitted. If the fee matters to your margin, the clean way to recover it is a base-price change, not a visible add-on. At 0.4% the fee is small for most sellers: a 5% margin product gives up 8% of its margin on a payment above ₹2,000 (0.4 divided by 5). A 40% margin service barely notices.&lt;/p&gt;

&lt;p&gt;There is also a payment-mix option. For large invoices to businesses, bank transfer (NEFT, RTGS or IMPS) avoids the UPI path entirely. Whether bank-transfer fees are lower for your amounts depends on your bank; look at your fee schedule rather than assuming. UPI is popular with customers for convenience, and pushing large payments elsewhere can cost you sales.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is still unknown
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The effective date. NPCI says "at a date to be notified separately."[1]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whether the final rate remains "up to 0.4%", and who sets the rate within "up to" when a gateway or bank is in the chain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whether the ₹300 cap, the ₹5 flat fee categories and the 0.02% capital-markets rate survive unchanged into the notified rate card.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whether the small-merchant ₹1 lakh a month tier is unchanged, and how monthly collections are counted.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How the government notification reported by LiveLaw interacts with MDR on payments above ₹2,000.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What the "select" in "select P2M transactions" covers beyond the categories already described.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Checklist before the date is notified
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Export the last three months of UPI credits and tag each as P2P, P2M QR, or P2M gateway.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Total the P2M QR receipts per month and compare with ₹1 lakh.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Count the payments above ₹2,000 and multiply by 0.4% to get a worst-case monthly fee; apply the ₹300 cap to any payment of ₹75,000 and above.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read your gateway pricing page and agreement for UPI fees, pass-through clauses and notice periods.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decide a payment mix for invoices over, say, ₹50,000: UPI, bank transfer or both.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ask your bank how it classifies your VPA and whether your QR is on the small-merchant tier.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set a reminder to check NPCI's website for the notified date, and re-read this post's status line before acting.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want a companion read on a different UPI change affecting merchants and freelancers this autumn, &lt;a href="https://dev.to/blogs/upi-privacy-rules-september-2026-masked-mobile-numbers-username-upi-id-guide"&gt;the UPI privacy rules guide&lt;/a&gt; covers masked mobile numbers and username-based UPI IDs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is UPI MDR cancelled?
&lt;/h3&gt;

&lt;p&gt;No. NPCI's 13 October 2026 release says MDR on select P2M UPI transactions "shall be implemented immediately post Diwali at a date to be notified separately." It is postponed, with no new date as of 19 October 2026.[1]&lt;/p&gt;

&lt;h3&gt;
  
  
  Will customers be charged for UPI payments above ₹2,000?
&lt;/h3&gt;

&lt;p&gt;According to the Paytm filing quoting NPCI's circular, no. The charge is on the merchant side and UPI stays free for customers.[2]&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the 0.4% apply to money from friends and family?
&lt;/h3&gt;

&lt;p&gt;The sources describe MDR as applying to P2M, not P2P. SCC Online reports P2P transfers as exempt regardless of amount.[3]&lt;/p&gt;

&lt;h3&gt;
  
  
  I get under ₹1 lakh a month by QR. Do I pay?
&lt;/h3&gt;

&lt;p&gt;Reported as exempt if you fall in the small-merchant P2PM tier, even for single payments above ₹2,000.[4] That detail comes from news summaries of the NPCI FAQ and should be confirmed once the notified framework is published.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I add a UPI surcharge to my invoices?
&lt;/h3&gt;

&lt;p&gt;Outlets report that merchants cannot pass MDR on to customers.[3] Treat a visible surcharge as risky and adjust base prices instead if you need to recover cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  When should I expect the new date?
&lt;/h3&gt;

&lt;p&gt;Nobody has published one. Diwali Laxmi Pujan falls on 8 November 2026,[6] and NPCI's wording points to the period straight after the festival, but treat any specific date you see in a social post as unverified until it appears on NPCI's website.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.npci.org.in/uploads/UPI_MDR_on_Select_Merchant_Transactions_Shall_be_Implemented_Post_Diwali_4c9cdd77d5.pdf" rel="noopener noreferrer"&gt;NPCI press release: UPI MDR on Select Merchant Transactions Shall be Implemented Post Diwali, Mumbai, 13 October 2026&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nsearchives.nseindia.com/corporate/PAYTM_15092026234600_SEDisclosureNPCICircularsd.pdf" rel="noopener noreferrer"&gt;One 97 Communications Ltd (Paytm), Regulation 30 disclosure to BSE and NSE, 15 September 2026, citing NPCI circular NPCI/UPI/OC-No.237/2026-27&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.scconline.com/blog/post/2026/09/16/npci-released-upi-mdr-faqs-explained/" rel="noopener noreferrer"&gt;SCC Online: UPI MDR explained, 16 September 2026 (summary of NPCI FAQ; secondary source)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.outlookindia.com/national/upi-payments-above-2000-what-changes-from-october-15" rel="noopener noreferrer"&gt;Outlook India: UPI payments above ₹2,000, what changes from October 15, 15 September 2026 (secondary source)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.livelaw.in/top-stories/centre-prohibits-charges-on-upi-transactions-up-to-rs-2000-rupay-debit-card-550015" rel="noopener noreferrer"&gt;LiveLaw: Centre prohibits charges on UPI transactions up to Rs 2,000 and RuPay debit card, 15 September 2026 (secondary source; notification text not read)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  6. &lt;a href="https://www.nseindia.com/resources/exchange-communication-holidays" rel="noopener noreferrer"&gt;NSE: trading holidays 2026, Diwali Laxmi Pujan 8 November 2026 and Diwali Bali Pratipada 10 November 2026&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/upi-mdr-deferred-after-diwali-merchant-charges-explained-2026" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>upimdr</category>
      <category>upicharges</category>
      <category>upi04</category>
      <category>npcimdr</category>
    </item>
    <item>
      <title>How the Claude Code Team Reviews Code: A Small-Team Version</title>
      <dc:creator>Anup Karanjkar</dc:creator>
      <pubDate>Sun, 18 Oct 2026 19:15:06 +0000</pubDate>
      <link>https://dev.to/akaranjkar08/how-the-claude-code-team-reviews-code-a-small-team-version-2lb</link>
      <guid>https://dev.to/akaranjkar08/how-the-claude-code-team-reviews-code-a-small-team-version-2lb</guid>
      <description>&lt;p&gt;&lt;strong&gt;Anthropic reviews Claude Code with seven stacked layers, and a team of one to ten people can copy five of them this week with GitHub branch protection, a short REVIEW.md and one CI workflow.&lt;/strong&gt; In the post Anthropic published on 15 October 2026, the share of internal PRs that passed after a single review-and-fix round rose from 65% to 78%, PRs needing five or more rounds fell from 8.9% to 1.5%, and the mean number of reviews to pass dropped from 2.08 to 1.32[1]. Claude wrote about 90 percent of Claude Code's own code, so the review system is what keeps that volume safe. The two layers you cannot copy are the risk classifier and the staged release channels at Anthropic's volume. Below: the seven layers, a mapping table, a starter REVIEW.md, a risk-tier rule of thumb, the exact GitHub settings, and the trade-offs.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Anthropic's layers: self-verification, AI review on every PR, blocking security review, blocking checks, risk-tiered human approval, merge queue plus flags plus staged release, fast rollback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reported results are internal and come without sample sizes: 65% to 78% one-round passes, 8.9% to 1.5% for five-plus rounds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A small team can get most of the value from branch protection, a risk-tier rule by path and size, a REVIEW.md, and a rollback switch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The hosted Code Review product is for Team and Enterprise plans, and Anthropic's docs say it never approves or blocks a PR by itself. Your CI has to do the blocking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Everything labelled "Anthropic reported" below comes from their post. Everything labelled "my recommendation" is mine and untested at Anthropic's scale.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Anthropic actually reported
&lt;/h2&gt;

&lt;p&gt;The post describes a goal and a guardrail. The goal is that most PRs merge with at most one human in the loop. The guardrail is that reverts and incidents must not rise. Anthropic reports that from June to September, merged PRs to the Claude Code codebase more than doubled while the share that had to be reverted fell by more than 40 percent[1]. In the wider monorepo, daily landed changes went from about 2,500 in May to more than 30,000 in September.&lt;/p&gt;

&lt;p&gt;Those are the company's own numbers. The post gives no sample sizes and nobody outside Anthropic has checked them, so treat them as a direction, not a benchmark. The useful part is the structure, which is seven layers where each one catches what the previous one missed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The seven layers in Anthropic's words
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verify before anyone looks.&lt;/strong&gt; Claude runs tests, builds or screenshot comparisons, and a subagent with fresh context reviews the diff.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;AI review on every PR.&lt;/strong&gt; Several agents hunt for bugs in parallel, verifiers vote on each finding, and only findings enough verifiers agree on get posted, tagged Important, Nit or Pre-existing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security review that can block.&lt;/strong&gt; A PR cannot merge while any finding from the bug review or the security review is still open.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automated checks that block.&lt;/strong&gt; Lint, type checks, tests on every platform and a build. A typical CLI PR may run dozens of checks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Human approval scaled by risk.&lt;/strong&gt; More on this below.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Merge queue, flags and gradual release.&lt;/strong&gt; The queue re-runs checks against main, new behavior ships behind flags to employees first, and public releases go to the &lt;code&gt;latest&lt;/code&gt; channel before &lt;code&gt;stable&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast detection and rollback.&lt;/strong&gt; Flags turn off without a deploy, and there is a weekly on-call rotation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How the human approvals are tiered
&lt;/h3&gt;

&lt;p&gt;A classifier reads the change and picks the risk tier, so the tier follows what the change touches and not who wrote it. Low-risk changes (docs, copy, internal-only features, additive changes behind a flag) need no human once automated review and security checks are green. Medium risk (ordinary product changes plus sensitive areas such as caching, the auto-updater or system prompts) needs one person. High risk needs two. A second classifier can force a person in even when the tier would not[1].&lt;/p&gt;

&lt;p&gt;Three rules in the post are worth copying word for word in spirit. An agent's approval never counts as a person's. On agent-written PRs, the person directing the agent counts as one of the required reviewers. And an approval covers one specific commit, so a push after approval should reset it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer-by-layer: what a small team does instead
&lt;/h2&gt;

&lt;p&gt;This table is my recommendation. The first two columns are Anthropic's design as reported[1]; the last three are what I think a one-to-ten person team can do and when to skip it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Anthropic's version&lt;/th&gt;
&lt;th&gt;Small-team version&lt;/th&gt;
&lt;th&gt;Effort&lt;/th&gt;
&lt;th&gt;Skip it if&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| 1. Self-verification | Claude runs tests and a fresh-context subagent reviews the diff | Put "run the test command and a diff-review subagent before opening a PR" in CLAUDE.md or a custom subagent | 30 minutes | You do not use an agent to write code |&lt;/p&gt;

&lt;p&gt;| 2. AI review on every PR | Multi-agent review with verifier voting | On Team or Enterprise, the hosted Code Review. Otherwise run &lt;code&gt;/code-review&lt;/code&gt; locally or Claude in your own CI | 1 hour, plus usage cost | PRs are under about 20 lines and you read every one |&lt;/p&gt;

&lt;p&gt;| 3. Blocking security review | Open findings block merge | Run &lt;code&gt;/security-review&lt;/code&gt; or a security job in CI, and make that job a required status check | 1 to 2 hours | No auth, payments, file upload or secrets handling in the repo |&lt;/p&gt;

&lt;p&gt;| 4. Blocking checks | Dozens of checks per CLI PR | Lint, type check, unit tests, build as required status checks | Half a day if missing | Never. This is the cheapest layer |&lt;/p&gt;

&lt;p&gt;| 5. Risk-tiered approval | Classifier picks 0, 1 or 2 humans | A path-and-size rule picks 0, 1 or 2 humans (see below) | 2 hours | You are a solo developer: tier controls how careful you are, not who approves |&lt;/p&gt;

&lt;p&gt;| 6. Merge queue, flags, staged release | Queue plus employee flags plus latest then stable | Merge queue if main breaks often; one feature flag for risky work; deploy to staging or a canary first | 1 day | You deploy rarely and can redeploy in minutes |&lt;/p&gt;

&lt;p&gt;| 7. Detection and rollback | Flags off without deploy, weekly on-call | Error alerts, a one-command rollback you have actually run, a named person on call this week | 2 hours | Never |&lt;/p&gt;

&lt;p&gt;If you only do three things, do layers 4, 5 and 7. Required checks, a risk rule and a practiced rollback prevent more damage than any AI reviewer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The small-team setup, step by step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Write a short REVIEW.md
&lt;/h3&gt;

&lt;p&gt;Anthropic says REVIEW.md is written by code owners and tells the reviewer what matters in their part of the code. The post recommends keeping it short, stating what failure looks like in your repo, capping nits, listing paths to skip, and asking for a file and line as evidence instead of a guess from a name[1]. Per the Claude Code docs, the hosted review reads REVIEW.md from the base or default branch, never from the PR's own changes[2]. That matters: a PR cannot rewrite its own reviewer's instructions.&lt;/p&gt;

&lt;p&gt;Here is a starter I wrote for a typical web app. Edit the first section to match what breaks in your repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# REVIEW.md&lt;/span&gt;

&lt;span class="gu"&gt;## What failure looks like here&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Charging or refunding the wrong amount, or charging twice
&lt;span class="p"&gt;-&lt;/span&gt; A route that returns data for a user who does not own it
&lt;span class="p"&gt;-&lt;/span&gt; A migration that locks a large table or cannot be rolled back
&lt;span class="p"&gt;-&lt;/span&gt; A background job that retries a non-idempotent action

&lt;span class="gu"&gt;## How to report&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Cite the file and line for every finding. If you cannot, drop it.
&lt;span class="p"&gt;-&lt;/span&gt; Report at most 3 nits per PR. Prefer zero.
&lt;span class="p"&gt;-&lt;/span&gt; Label each finding: Important, Nit, or Pre-existing.
&lt;span class="p"&gt;-&lt;/span&gt; Do not comment on formatting. The linter owns that.

&lt;span class="gu"&gt;## Skip&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; generated/&lt;span class="gs"&gt;**, **&lt;/span&gt;/&lt;span class="ge"&gt;*.snap, package-lock.json, docs/*&lt;/span&gt;&lt;span class="err"&gt;*&lt;/span&gt;

&lt;span class="gu"&gt;## Always flag&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Any change under auth/, billing/, migrations/ or .github/workflows/
&lt;span class="p"&gt;-&lt;/span&gt; New environment variables or secrets read at runtime
&lt;span class="p"&gt;-&lt;/span&gt; Any removed test without a replacement
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pair it with a CLAUDE.md that covers how code should be written. I covered what survives in production in &lt;a href="https://dev.to/blogs/claude-md-rules-that-survive-production-2026"&gt;CLAUDE.md rules that survive production&lt;/a&gt;. REVIEW.md is the reviewer's brief; CLAUDE.md is the author's.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Add a risk-tier rule you can compute
&lt;/h3&gt;

&lt;p&gt;Anthropic uses a classifier. You can get a decent first version from file paths and diff size. This is my recommendation, not Anthropic's rule, and you should tune the numbers after a month of data.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Rule of thumb&lt;/th&gt;
&lt;th&gt;Approvals&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;| Low | Only docs, copy, tests or config comments; or under 30 changed lines in non-sensitive paths; checks green | 0, after green checks and a clean AI review |&lt;/p&gt;

&lt;p&gt;| Medium | Everything else, up to about 400 changed lines | 1 person |&lt;/p&gt;

&lt;p&gt;| High | Touches auth, billing, migrations, deploy workflows, secrets handling, or exceeds about 400 lines | 2 people, or 1 person plus the author walking through it live |&lt;/p&gt;

&lt;p&gt;On a team of three, "2 people" may mean the author is one of the two. That is fine if you keep Anthropic's rule that the person directing an agent counts as a required reviewer, and the AI never counts as a person.&lt;/p&gt;

&lt;p&gt;If you would rather not hand-build the tier script, the WOWHOW &lt;a href="https://dev.to/product/ai-code-review-pipeline-kit"&gt;AI Code Review Pipeline Kit&lt;/a&gt; packages a REVIEW.md template, a path-and-size risk-tier classifier, a GitHub Actions approval gate and a findings parser. Everything in this post works without it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Set the GitHub branch protection that makes it real
&lt;/h3&gt;

&lt;p&gt;A rule nobody enforces is a suggestion. In GitHub's protected-branch settings, these are the options that map to the layers[3]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Require pull request reviews before merging&lt;/strong&gt;, with the number of required approvals set to 1 on your default branch. GitHub's current UI may label this "Require a pull request before merging"; the page I checked uses the first wording.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Require status checks before merging&lt;/strong&gt;, with the checkbox "Require status checks to pass before merging". Add lint, types, tests, build and your security job by name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Require branches to be up to date before merging&lt;/strong&gt;, so checks run against current main.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dismiss stale pull request approvals when new commits are pushed&lt;/strong&gt;. This is the setting that gives you Anthropic's "an approval covers one specific commit".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Require merge queue&lt;/strong&gt;, if main breaks often enough to justify it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code owner review through a CODEOWNERS file for your high-risk paths, so those need a named owner.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub treats rulesets as a separate feature from classic branch protection. Either route works; use one, not both, to avoid conflicting rules.&lt;/p&gt;

&lt;p&gt;The two-approval rule for high-risk paths does not exist as a single checkbox. Branch protection applies one approval count to the whole branch. To get tiers, use CODEOWNERS for the sensitive paths, or run a small workflow that reads the changed files, computes the tier, and fails a required check until enough approvals exist. That workflow is the only custom code in this whole setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Decide where the AI review runs
&lt;/h3&gt;

&lt;p&gt;You have four options, and the docs list them side by side[2]:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The hosted Code Review, for organizations on Team or Enterprise plans with GitHub repositories, turned on by an Owner. Reviews run on Anthropic infrastructure and come in Quick, Standard and Deep levels.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/code-review&lt;/code&gt; in your own Claude Code session, on any plan.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Claude in your own CI through GitHub Actions or GitLab CI/CD, using an API key.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your own reviewer as a subagent or skill.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One detail trips people up. Anthropic's post says its internal setup blocks merge on open findings. The public docs say the hosted review never approves or blocks a PR, and its check run does not conclude as a failure[2]. So if you want blocking findings, you build it: run a security job in CI that fails on findings, and make it a required status check. The post does not give pricing, and I am not quoting any; check the Code Review costs page before turning it on across many repos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Make rollback boring
&lt;/h3&gt;

&lt;p&gt;Layer 7 is the one small teams skip, and the one that saves a Friday evening. Pick a rollback you can run in one command, run it once against staging this week, and write down who is on call. If you ship behind a flag, test that flipping it off actually removes the behavior. Pair this with a regression check on the model itself; WOWHOW built one for that in &lt;a href="https://dev.to/blogs/is-claude-nerfed-build-20-task-eval-canary-nightly-github-action-2026"&gt;the 20-task eval canary&lt;/a&gt;, and the &lt;a href="https://dev.to/product/model-regression-canary"&gt;Model Regression Canary&lt;/a&gt; packages it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Honest trade-offs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AI review is noisy until you tune it.&lt;/strong&gt; Anthropic's own fix is verifier voting and a nit cap, which is why the REVIEW.md above caps nits at 3. Without a cap, people learn to ignore the bot within a week.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A clean review is not a safe PR.&lt;/strong&gt; The Claude Code docs say it directly: Code Review uses AI and may miss bugs and vulnerabilities, and a review with no findings does not mean the code is error-free or secure[2]. The docs also note that a review reads the diff and surrounding code without building or running it. Your tests are still the thing that runs the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero-human tiers carry real risk.&lt;/strong&gt; The post itself says Anthropic lacks circuit breakers that tighten approval when its numbers move. If you allow zero-approval merges for low-risk changes, keep the definition narrow and review the list of auto-merged PRs weekly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost scales with PR volume.&lt;/strong&gt; A deeper review level costs more per PR. Use Quick on routine repos and Deep only where a bug is expensive, as the docs suggest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your failure modes are not Anthropic's.&lt;/strong&gt; Agent-written code fails in recognizable ways. The &lt;a href="https://dev.to/blogs/ai-coding-agent-failure-mode-taxonomy-14-2026"&gt;14-item failure mode taxonomy&lt;/a&gt; is a good source for filling in the "what failure looks like here" section of your REVIEW.md.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Code Review for Claude Code available on every plan?
&lt;/h3&gt;

&lt;p&gt;No. The hosted Code Review is generally available on Team and Enterprise plans and works with GitHub repositories[1][2]. The local &lt;code&gt;/code-review&lt;/code&gt; command runs in your Claude Code session on any plan.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the AI reviewer block merges?
&lt;/h3&gt;

&lt;p&gt;The public docs say the hosted review never approves or blocks a pull request, and its check run does not conclude as a failure[2]. Anthropic's post describes its own internal setup, where open findings do block merge. To get that behavior, make your own CI job a required status check.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a solo developer use this?
&lt;/h3&gt;

&lt;p&gt;Yes, with a smaller version. Keep required checks, a REVIEW.md, an AI review pass and a tested rollback. Skip human tiers, since you are the only human. Use the risk tier to decide how long you read the diff yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where does REVIEW.md go and who can edit it?
&lt;/h3&gt;

&lt;p&gt;It lives in the repository. The hosted review reads it from the base or default branch and never from the PR under review, so a PR cannot loosen its own review rules[2].&lt;/p&gt;

&lt;h3&gt;
  
  
  What does it cost?
&lt;/h3&gt;

&lt;p&gt;Anthropic's post gives no pricing. The docs have a separate page on Code Review costs and usage, and a deeper review level costs more than a lighter one[2]. Check that page for current numbers before enabling it widely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://claude.dev/blog/solving-code-review-at-anthropic/" rel="noopener noreferrer"&gt;Anthropic: how the Claude Code team does code review (published 15 October 2026, accessed 18 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/code-review" rel="noopener noreferrer"&gt;Claude Code docs: Code Review (accessed 18 October 2026)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches" rel="noopener noreferrer"&gt;GitHub docs: about protected branches (accessed 18 October 2026)&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://wowhow.cloud/blogs/claude-code-team-seven-layer-code-review-small-team-version-2026" rel="noopener noreferrer"&gt;wowhow.cloud&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>aicode</category>
      <category>howanthropic</category>
      <category>reviewmd</category>
    </item>
  </channel>
</rss>
