<?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: Calvin A. Allen</title>
    <description>The latest articles on DEV Community by Calvin A. Allen (@calvinallen).</description>
    <link>https://dev.to/calvinallen</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F354384%2F2cf133cc-26bd-47af-a235-168da894508d.png</url>
      <title>DEV Community: Calvin A. Allen</title>
      <link>https://dev.to/calvinallen</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/calvinallen"/>
    <language>en</language>
    <item>
      <title>Introducing the 'Debugalizers' Visual Studio extension!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Tue, 27 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-the-debugalizers-visual-studio-extension-55gl</link>
      <guid>https://dev.to/calvinallen/introducing-the-debugalizers-visual-studio-extension-55gl</guid>
      <description>&lt;p&gt;If you've ever found yourself debugging an application and hovering over a string variable that contains a massive blob of minified JSON, XML, or some other structured data - you know the pain. You squint at the DataTip, try to make sense of the wall of text, maybe copy it out to a separate tool to format it, and by then you've lost your debugging flow entirely.&lt;/p&gt;

&lt;p&gt;I decided to fix that problem for myself, and now I'm sharing it with you!&lt;/p&gt;

&lt;p&gt;Introducing "&lt;a href="https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.Debugalizers" rel="noopener noreferrer"&gt;Debugalizers&lt;/a&gt;", a Visual Studio extension that provides beautiful, formatted debug visualizers for over 30 different data formats.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does It Do?
&lt;/h2&gt;

&lt;p&gt;When you're debugging and hover over a string variable, you'll see that little magnifying glass icon in the DataTip. Click it, select your Debugalizer of choice, and boom - a proper window pops up with your content beautifully formatted, syntax highlighted, and ready to explore.&lt;/p&gt;

&lt;p&gt;The extension supports a wide variety of formats across five categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Formats&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON, XML, HTML, YAML, TOML (with formatted, tree, and raw views)&lt;/li&gt;
&lt;li&gt;CSV, TSV, INI (table and raw views)&lt;/li&gt;
&lt;li&gt;Markdown (rendered and raw)&lt;/li&gt;
&lt;li&gt;SQL, GraphQL (syntax highlighted)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Encoded Data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base64 (decoded, hex, and raw views)&lt;/li&gt;
&lt;li&gt;Base64 Images (actual image preview!)&lt;/li&gt;
&lt;li&gt;URL Encoded, HTML Entities, Unicode Escape&lt;/li&gt;
&lt;li&gt;Hex Strings, GZip, and Deflate (decompressed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security &amp;amp; Authentication&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JWT tokens (claims table with token breakdown)&lt;/li&gt;
&lt;li&gt;SAML (XML tree with claim parsing)&lt;/li&gt;
&lt;li&gt;X.509 Certificates (detailed information table)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Structured Strings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connection Strings (parsed key-value table)&lt;/li&gt;
&lt;li&gt;URIs/URLs (parsed components and query parameters)&lt;/li&gt;
&lt;li&gt;Query Strings, Regex patterns&lt;/li&gt;
&lt;li&gt;Cron expressions (human-readable schedules)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Binary &amp;amp; Low-Level&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hex Dump (with ASCII sidebar)&lt;/li&gt;
&lt;li&gt;GUID/UUID (format and version info)&lt;/li&gt;
&lt;li&gt;Unix Timestamps (human-readable conversion)&lt;/li&gt;
&lt;li&gt;IP Addresses (IPv4/IPv6 with CIDR info)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Interactive Features
&lt;/h2&gt;

&lt;p&gt;It's not just about formatting, though. Each visualizer window gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Search&lt;/strong&gt; - Hit Ctrl+F to find content within your data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy&lt;/strong&gt; - Grab the raw content or the formatted version&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export&lt;/strong&gt; - Save to a file for later analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Word Wrap&lt;/strong&gt; - Toggle it on or off as needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation&lt;/strong&gt; - Visual feedback showing whether your content is valid&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Statistics&lt;/strong&gt; - Line count, character count, byte count at a glance&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How To Use It
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install the extension from the &lt;a href="https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.Debugalizers" rel="noopener noreferrer"&gt;Visual Studio Marketplace&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Start debugging your application&lt;/li&gt;
&lt;li&gt;Hover over any string variable&lt;/li&gt;
&lt;li&gt;Click the magnifying glass icon in the DataTip&lt;/li&gt;
&lt;li&gt;Select the appropriate Debugalizer from the list&lt;/li&gt;
&lt;li&gt;Enjoy actually being able to read your data!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The extension supports Visual Studio 2022 (version 17.8 or later), and it's completely zero-configuration - just install and go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;I got tired of the dance: hover, squint, copy, paste into an online formatter, lose context, go back to Visual Studio, repeat. Every. Single. Time. With Debugalizers, everything stays right there in Visual Studio where you need it. Your debugging flow stays intact, and you can actually understand what you're looking at without leaving the IDE.&lt;/p&gt;

&lt;p&gt;Feel free to check it out, and let me know if you have any suggestions for it - I know there are probably more formats people would love to see visualizers for! PRs accepted, too, if you're into that sort of thing.&lt;/p&gt;

&lt;p&gt;And, of course, &lt;a href="https://github.com/CodingWithCalvin/VS-Debugalizers" rel="noopener noreferrer"&gt;it's open source&lt;/a&gt;, so feel free to peruse the source code, create issues, and have discussions on ways we can make this tool even better!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>extensibility</category>
      <category>visualstudio</category>
    </item>
    <item>
      <title>Introducing the 'Couchbase Explorer' Visual Studio extension!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Mon, 19 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-the-couchbase-explorer-visual-studio-extension-453b</link>
      <guid>https://dev.to/calvinallen/introducing-the-couchbase-explorer-visual-studio-extension-453b</guid>
      <description>&lt;p&gt;Introducing "&lt;a href="https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.CouchbaseExplorer" rel="noopener noreferrer"&gt;Couchbase Explorer&lt;/a&gt;", an extension for Visual Studio 2022 (and 2026!) that brings Couchbase database browsing and management directly into your IDE. If you've ever found yourself constantly switching between Visual Studio and Couchbase's web console while developing, this extension is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vision
&lt;/h2&gt;

&lt;p&gt;Couchbase Explorer is designed to be your Couchbase companion inside Visual Studio. The goal is to let you browse your clusters, explore your data, and work with documents without breaking your development flow or switching context to another application.&lt;/p&gt;

&lt;p&gt;Note that this extension is currently in &lt;strong&gt;BETA&lt;/strong&gt; - it's functional, but there's still plenty of work to do. It's also worth mentioning that this is an independent, community-driven project and is not affiliated with, endorsed by, or sponsored by Couchbase, Inc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Features
&lt;/h2&gt;

&lt;p&gt;The initial release focuses on connection management and data browsing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Connections&lt;/strong&gt; - Save and manage connections to multiple Couchbase Server clusters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Credential Storage&lt;/strong&gt; - Passwords are stored securely using Windows Credential Manager&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL/TLS Support&lt;/strong&gt; - Connect securely to clusters with SSL encryption enabled&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hierarchical Tree View&lt;/strong&gt; - Intuitive navigation: Connections → Buckets → Scopes → Collections → Documents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Viewer&lt;/strong&gt; - Double-click any document to open it in a dedicated editor with formatted JSON and syntax highlighting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy Loading&lt;/strong&gt; - Efficient handling of large collections with batched document retrieval&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy Functionality&lt;/strong&gt; - Quickly copy document contents or document IDs to your clipboard&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refresh Support&lt;/strong&gt; - Refresh at any level to see the latest data from your cluster&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Theme Support&lt;/strong&gt; - Adapts to Visual Studio's light and dark themes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Once installed, you can access the Couchbase Explorer from the &lt;strong&gt;View&lt;/strong&gt; menu. Right-click in the explorer to add your first connection - you'll need your cluster's connection string, username, and password. The extension will securely store your credentials and connect to your cluster.&lt;/p&gt;

&lt;p&gt;From there, you can expand the connection to see your buckets, then scopes, then collections. Expand a collection to browse its documents. Double-click any document to view its contents in a formatted JSON editor.&lt;/p&gt;

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

&lt;p&gt;The roadmap is packed with planned features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Couchbase Capella Support&lt;/strong&gt; - Connect to Couchbase's cloud offering&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;N1QL Query Editor&lt;/strong&gt; - Write and execute SQL++ queries directly in Visual Studio&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document Editing&lt;/strong&gt; - Create, update, and delete documents&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Index Management&lt;/strong&gt; - View and manage your cluster indexes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-Text Search Integration&lt;/strong&gt; - Work with FTS indexes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bulk Import/Export&lt;/strong&gt; - Move data in and out of your collections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query Results Panel&lt;/strong&gt; - View query results in a dedicated tool window&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output/Log Window&lt;/strong&gt; - Track operations and debug connection issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check out the full &lt;a href="https://github.com/CodingWithCalvin/VS-CouchbaseExplorer/issues" rel="noopener noreferrer"&gt;issue list on GitHub&lt;/a&gt; to see everything that's planned and track progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get It Now
&lt;/h2&gt;

&lt;p&gt;Feel free to check it out on the &lt;a href="https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.CouchbaseExplorer" rel="noopener noreferrer"&gt;Visual Studio Marketplace&lt;/a&gt;, and let me know if you have any suggestions! It's &lt;a href="https://github.com/CodingWithCalvin/VS-CouchbaseExplorer" rel="noopener noreferrer"&gt;open source on GitHub&lt;/a&gt;, so issues and PRs are happily accepted if you're into that sort of thing.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>extensibility</category>
      <category>visualstudio</category>
    </item>
    <item>
      <title>Introducing the 'Git Ranger' Visual Studio extension!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Fri, 16 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-the-git-ranger-visual-studio-extension-1a3j</link>
      <guid>https://dev.to/calvinallen/introducing-the-git-ranger-visual-studio-extension-1a3j</guid>
      <description>&lt;p&gt;Introducing "&lt;a href="https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.VS-GitRanger" rel="noopener noreferrer"&gt;Git Ranger&lt;/a&gt;", an extension for Visual Studio 2022 (and 2026!) that brings enhanced Git tooling directly into your editor. If you've ever used GitLens in VS Code, this extension draws inspiration from that experience and aims to bring similar capabilities to Visual Studio.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vision
&lt;/h2&gt;

&lt;p&gt;Git Ranger is designed to be a comprehensive Git companion for Visual Studio developers. The goal is to surface Git information where you need it, when you need it - without breaking your flow or switching context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Features
&lt;/h2&gt;

&lt;p&gt;The initial release focuses on inline Git information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inline Annotations&lt;/strong&gt; - See who last modified each line, when, and why - right in your editor&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gutter Margin&lt;/strong&gt; - A visual indicator in the left margin showing commit history at a glance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Theme-Adaptive Colors&lt;/strong&gt; - 12 vibrant colors that automatically adjust for dark and light themes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Author Color Coding&lt;/strong&gt; - Each contributor gets their own distinctive color&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Age Heat Map Mode&lt;/strong&gt; - Optional visualization showing relative age of changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Tooltips&lt;/strong&gt; - Hover to see full commit details&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy Commit SHA&lt;/strong&gt; - Quick access to commit hashes via click or menu command&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Customization
&lt;/h2&gt;

&lt;p&gt;Git Ranger is highly configurable. Head to &lt;strong&gt;Tools → Options → Git Ranger&lt;/strong&gt; where you can adjust display options, color modes, date formats, caching behavior, and more.&lt;/p&gt;

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

&lt;p&gt;The roadmap is packed with planned features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Git CodeLens&lt;/strong&gt; for methods and classes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File History&lt;/strong&gt; and &lt;strong&gt;Line History&lt;/strong&gt; tool windows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual Git Graph&lt;/strong&gt; with styling and interactions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Status bar indicator&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branch and Tag management&lt;/strong&gt; tool windows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit Details&lt;/strong&gt; and &lt;strong&gt;Contributors&lt;/strong&gt; views&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Diff integration&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remote provider integrations&lt;/strong&gt; (GitHub, GitLab, etc.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git Command Palette&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stash management&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interactive rebase editor&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI-powered commit message generation&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check out the full &lt;a href="https://github.com/CodingWithCalvin/VS-GitRanger/issues" rel="noopener noreferrer"&gt;issue list on GitHub&lt;/a&gt; to see everything that's planned and track progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get It Now
&lt;/h2&gt;

&lt;p&gt;Feel free to check it out on the &lt;a href="https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.VS-GitRanger" rel="noopener noreferrer"&gt;Visual Studio Marketplace&lt;/a&gt;, and let me know if you have any suggestions! It's &lt;a href="https://github.com/CodingWithCalvin/VS-GitRanger" rel="noopener noreferrer"&gt;open source on GitHub&lt;/a&gt;, so issues and PRs are happily accepted if you're into that sort of thing.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>extensibility</category>
      <category>visualstudio</category>
    </item>
    <item>
      <title>Introducing the Visual Studio Code MCP Server!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Thu, 15 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-the-visual-studio-code-mcp-server-3a9g</link>
      <guid>https://dev.to/calvinallen/introducing-the-visual-studio-code-mcp-server-3a9g</guid>
      <description>&lt;p&gt;Yesterday I &lt;a href="https://dev.to/calvinallen/introducing-the-visual-studio-mcp-server-2k80-temp-slug-4208678"&gt;introduced the Visual Studio MCP Server&lt;/a&gt;. Today, it's VS Code's turn.&lt;/p&gt;

&lt;h2&gt;
  
  
  VSC MCP Server
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;VSC MCP Server&lt;/strong&gt; exposes VS Code's language intelligence features as &lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;MCP&lt;/a&gt; tools. Once connected, an AI assistant can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get symbols from documents and workspaces&lt;/li&gt;
&lt;li&gt;Navigate to definitions and find references&lt;/li&gt;
&lt;li&gt;Get IntelliSense completions and signature help&lt;/li&gt;
&lt;li&gt;Run diagnostics, format code, and rename symbols&lt;/li&gt;
&lt;li&gt;Search files and text across the entire workspace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the things you take for granted when coding in VS Code — now available to your AI tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Under the Hood
&lt;/h2&gt;

&lt;p&gt;VS Code has incredibly powerful language features built in. IntelliSense, Go to Definition, Find All References, hover info, call hierarchies — these aren't just UI conveniences. They're backed by language servers that deeply understand your code.&lt;/p&gt;

&lt;p&gt;The problem is that this intelligence is locked inside VS Code. An AI tool running alongside the IDE can't tap into any of it. It has to rely on its own understanding of your codebase, which means re-parsing files, guessing at types, and missing context that VS Code already has.&lt;/p&gt;

&lt;p&gt;This extension bridges that gap. It wraps VS Code's language server commands and exposes them through MCP, giving AI assistants access to the same semantic understanding that powers your daily coding experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tools
&lt;/h2&gt;

&lt;p&gt;The extension exposes 30 MCP tools organized into categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code Navigation &amp;amp; Analysis&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;document_symbols&lt;/code&gt; — Get all symbols in a file (functions, classes, variables)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;workspace_symbols&lt;/code&gt; — Search symbols across the entire workspace&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;go_to_definition&lt;/code&gt; — Find where a symbol is defined&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;find_references&lt;/code&gt; — Find all usages of a symbol&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hover_info&lt;/code&gt; — Get type information and documentation at a position&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;call_hierarchy&lt;/code&gt; — Get incoming and outgoing function calls&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type_hierarchy&lt;/code&gt; — Get type inheritance chains&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Completions &amp;amp; Suggestions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;get_completions&lt;/code&gt; — Get IntelliSense code completions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_signature_help&lt;/code&gt; — Get function signature and parameter info&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_code_actions&lt;/code&gt; — Get available quick fixes and refactorings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Formatting &amp;amp; Refactoring&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;format_document&lt;/code&gt; — Format an entire document&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;format_range&lt;/code&gt; — Format a specific range&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;organize_imports&lt;/code&gt; — Sort and organize imports&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rename_symbol&lt;/code&gt; — Rename a symbol across all references&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Diagnostics &amp;amp; Workspace&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;diagnostics&lt;/code&gt; — Get errors and warnings for files or the workspace&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search_workspace_files&lt;/code&gt; — Search for files using glob patterns&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;search_workspace_text&lt;/code&gt; — Search text across the entire workspace&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write operations support dry-run mode, so the AI can preview changes before applying them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Install the extension from the &lt;a href="https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.VSC-MCPServer" rel="noopener noreferrer"&gt;Visual Studio Marketplace&lt;/a&gt;, or search for "VSC as MCP" in the Extensions view.&lt;/p&gt;

&lt;p&gt;The MCP server starts automatically when VS Code launches. By default, it listens on port 4000. Configure your MCP client to connect to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "mcpServers": {
    "vscode": {
      "url": "http://localhost:4000/mcp"
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;That's it. Your AI assistant can now query VS Code's language intelligence directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;

&lt;p&gt;If you need to change the defaults, head to &lt;strong&gt;Settings&lt;/strong&gt; and search for &lt;code&gt;codingwithcalvin.mcp&lt;/code&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;autoStart&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start the server when VS Code launches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;port&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Port for the MCP server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bindAddress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;127.0.0.1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bind address (localhost only for security)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can also control the server from the Command Palette:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP Server: Start&lt;/strong&gt; — Start the server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Server: Stop&lt;/strong&gt; — Stop the server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Server: Restart&lt;/strong&gt; — Restart the server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Server: Show Available Tools&lt;/strong&gt; — View all available tools&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;The server only binds to localhost by default. It validates the Host header to prevent DNS rebinding attacks and restricts CORS to localhost origins. No authentication is required since it assumes same-machine local access is trusted.&lt;/p&gt;

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

&lt;p&gt;This is v0.1.0. The tool coverage is solid, but there's always room for more. I'm looking at exposing debugging capabilities, terminal integration, and task execution. If there's something you'd find useful, let me know.&lt;/p&gt;

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

&lt;p&gt;The source is on &lt;a href="https://github.com/CodingWithCalvin/VSC-MCPServer" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. If you run into issues or have ideas for additional tools, open an issue or send a PR.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>extensibility</category>
      <category>vscode</category>
      <category>ai</category>
    </item>
    <item>
      <title>Introducing the Visual Studio MCP Server!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Wed, 14 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-the-visual-studio-mcp-server-36mm</link>
      <guid>https://dev.to/calvinallen/introducing-the-visual-studio-mcp-server-36mm</guid>
      <description>&lt;p&gt;JetBrains is shipping MCP servers for their IDEs. Visual Studio isn't.&lt;/p&gt;

&lt;p&gt;So I wrote one.&lt;/p&gt;

&lt;h2&gt;
  
  
  VS MCP Server
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;VS MCP Server&lt;/strong&gt; exposes Visual Studio features as &lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;MCP&lt;/a&gt; tools. Once connected, an AI assistant can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get information about your currently open solution and projects&lt;/li&gt;
&lt;li&gt;Open, close, read, and write documents&lt;/li&gt;
&lt;li&gt;Work with text selections and navigate the editor&lt;/li&gt;
&lt;li&gt;Trigger builds and check build status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All through the MCP protocol. It doesn't matter if you're using Claude Desktop, Cursor, Windsurf, or any other MCP-compatible client - they all speak the same language.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;Visual Studio extensions run on the UI thread, and blocking that is a recipe for a sluggish IDE. An MCP server needs to handle HTTP connections and process requests, so doing all that on the main thread wasn't going to work.&lt;/p&gt;

&lt;p&gt;The solution was to split things up. The extension spawns a separate process to handle HTTP/SSE communication with MCP clients. That process talks back to the Visual Studio extension via named pipes using JSON-RPC. Visual Studio stays responsive, the MCP server handles requests without blocking anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[MCP Client&amp;lt;br/&amp;gt;Any AI Tool] &amp;lt;--&amp;gt;|HTTP/SSE&amp;lt;br/&amp;gt;:5050| B[MCPServer.Server&amp;lt;br/&amp;gt;Out of process]
    B &amp;lt;--&amp;gt;|Named Pipes&amp;lt;br/&amp;gt;JSON-RPC| C[VS Extension&amp;lt;br/&amp;gt;VS Integration]

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The extension is available on the &lt;a href="https://marketplace.visualstudio.com/items?itemName=CodingWithCalvin.VS-MCPServer" rel="noopener noreferrer"&gt;Visual Studio Marketplace&lt;/a&gt;. Install it, configure settings at &lt;strong&gt;Tools &amp;gt; Options &amp;gt; MCP Server&lt;/strong&gt; if needed, then start the server via &lt;strong&gt;Tools &amp;gt; MCP Server &amp;gt; Start Server&lt;/strong&gt; (or enable auto-start).&lt;/p&gt;

&lt;p&gt;From there, configure your MCP client to connect to &lt;code&gt;http://localhost:5050/sse&lt;/code&gt;. The extension supports Visual Studio 2022 and 2026, on both ARM64 and AMD64.&lt;/p&gt;

&lt;p&gt;For the full list of available tools and configuration options, check out the &lt;a href="https://github.com/CodingWithCalvin/VS-MCPServer" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The current toolset covers the basics - solutions, documents, editor operations, and builds. But there's a lot more potential here. I'm planning to integrate Roslyn to enable deeper code exploration capabilities. Imagine asking your AI assistant to find all usages of a method, or get the signature of a class, or navigate through the semantic model of your code. That's where things get really interesting.&lt;/p&gt;

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

&lt;p&gt;This is a new project, and I'm still finding the rough edges. If you run into issues or have ideas for additional tools, let me know. The source is on &lt;a href="https://github.com/CodingWithCalvin/VS-MCPServer" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, and as always, I'm open to feedback and contributions.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>extensibility</category>
      <category>visualstudio</category>
    </item>
    <item>
      <title>Introducing rnr - A Zero-Dependency Task Runner</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Mon, 12 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-rnr-a-zero-dependency-task-runner-586m</link>
      <guid>https://dev.to/calvinallen/introducing-rnr-a-zero-dependency-task-runner-586m</guid>
      <description>&lt;p&gt;Have you ever cloned a repository, ready to contribute, only to discover you need to install Node.js, Python, Make, or some other global dependency just to run the build? I have. Many times. And honestly, it's frustrating.&lt;/p&gt;

&lt;p&gt;I wanted something simpler. Something where contributors could clone a repo and immediately run tasks without any setup. No "first, install this runtime" steps. No version mismatches. Just clone and go.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;rnr&lt;/strong&gt; (pronounced "runner").&lt;/p&gt;

&lt;h2&gt;
  
  
  What is rnr?
&lt;/h2&gt;

&lt;p&gt;rnr is a cross-platform task runner with one key differentiator: &lt;strong&gt;the binaries live inside your repository&lt;/strong&gt;. When a contributor clones your project, they already have everything they need to run your build tasks. Zero friction.&lt;/p&gt;

&lt;p&gt;It's written in Rust, compiles to native binaries for all major platforms, and uses a simple YAML configuration file to define your tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Most task runners require contributors to have something installed globally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;npm scripts&lt;/strong&gt; require Node.js&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Makefiles&lt;/strong&gt; require Make (and good luck on Windows)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Just&lt;/strong&gt; requires installing just&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task&lt;/strong&gt; requires installing task&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For maintainers, this is fine. But for contributors—especially those making quick documentation fixes or small improvements—asking them to install a runtime just to run a build is a barrier.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;With rnr, you initialize once as a maintainer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Linux
curl -fsSL https://github.com/CodingWithCalvin/rnr.cli/releases/latest/download/rnr-linux-amd64 -o rnr
chmod +x rnr
./rnr init

# macOS (Apple Silicon)
curl -fsSL https://github.com/CodingWithCalvin/rnr.cli/releases/latest/download/rnr-macos-arm64 -o rnr
chmod +x rnr
./rnr init

# Windows (PowerShell)
Invoke-WebRequest -Uri "https://github.com/CodingWithCalvin/rnr.cli/releases/latest/download/rnr-windows-amd64.exe" -OutFile "rnr.exe"
.\rnr.exe init

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; command presents an interactive selector where you choose which platforms your contributors might use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Which platforms should this project support?

  [x] linux-amd64 (760 KB)
  [] macos-amd64 (662 KB)
  [x] macos-arm64 (608 KB) &amp;lt;- current
  [x] windows-amd64 (584 KB)
  [] windows-arm64 (528 KB)

  Selected: 1.95 MB total

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

&lt;/div&gt;



&lt;p&gt;Once you confirm, rnr downloads the appropriate binaries and sets up wrapper scripts. Here's what gets created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;your-repo/
├── .rnr/
│ ├── config.yaml # Tracks configured platforms
│ └── bin/ # Platform binaries (only selected ones)
├── rnr # Unix wrapper script (auto-detects platform)
├── rnr.cmd # Windows wrapper script
└── rnr.yaml # Your task definitions

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

&lt;/div&gt;



&lt;p&gt;The wrapper scripts automatically detect the current platform and architecture, then run the correct binary from &lt;code&gt;.rnr/bin/&lt;/code&gt;. Commit all of this to your repo.&lt;/p&gt;

&lt;p&gt;After that, contributors simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./rnr build # Run your build task
./rnr test # Run your tests
./rnr --list # See all available tasks

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

&lt;/div&gt;



&lt;p&gt;That's it. No installation required on their end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining Tasks
&lt;/h2&gt;

&lt;p&gt;Tasks are defined in an &lt;code&gt;rnr.yaml&lt;/code&gt; file at the root of your repository. The syntax is intentionally simple.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple one-liners:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build: cargo build --release
test: cargo test
lint: cargo clippy

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Full task definitions&lt;/strong&gt; with descriptions, working directories, and environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build:
  description: Build for production
  dir: src/backend
  env:
    NODE_ENV: production
  cmd: npm run build

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sequential steps&lt;/strong&gt; that reference other tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ci:
  description: Run CI pipeline
  steps:
    - task: lint
    - task: test
    - task: build

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Parallel execution&lt;/strong&gt; for speeding up independent operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;build-all:
  description: Build all services
  steps:
    - cmd: echo "Starting builds..."
    - parallel:
        - task: build-api
        - task: build-web
    - cmd: echo "All done!"

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nested task files&lt;/strong&gt; for monorepos—subdirectories can have their own &lt;code&gt;rnr.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Root rnr.yaml
api:build:
  dir: services/api
  task: build # Runs 'build' from services/api/rnr.yaml

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Built-in Commands
&lt;/h2&gt;

&lt;p&gt;rnr ships with a few built-in commands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rnr &amp;lt;task&amp;gt;&lt;/code&gt; — Execute a task from your &lt;code&gt;rnr.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rnr init&lt;/code&gt; — Initialize rnr in the current directory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rnr upgrade&lt;/code&gt; — Update to the latest rnr binaries&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rnr --list&lt;/code&gt; — View all available tasks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rnr --version&lt;/code&gt; — Display the current version&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rnr --help&lt;/code&gt; — Show help information&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Rust?
&lt;/h2&gt;

&lt;p&gt;I chose Rust for a few reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Single binary&lt;/strong&gt; — No runtime dependencies, just a native executable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform&lt;/strong&gt; — Compiles cleanly to Windows, macOS, and Linux&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt; — Fast startup, minimal overhead&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I wanted to learn more Rust&lt;/strong&gt; — Let's be honest, this was a big motivator&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;If you maintain an open source project and want to reduce friction for contributors, give rnr a try:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the binary for your platform from the &lt;a href="https://github.com/CodingWithCalvin/rnr.cli/releases" rel="noopener noreferrer"&gt;releases page&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;./rnr init&lt;/code&gt; and select your target platforms&lt;/li&gt;
&lt;li&gt;Create your &lt;code&gt;rnr.yaml&lt;/code&gt; with your tasks&lt;/li&gt;
&lt;li&gt;Commit the binaries and config to your repo&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your contributors will thank you.&lt;/p&gt;

&lt;p&gt;I'm already using rnr on a couple of my own projects—&lt;a href="https://github.com/CodingWithCalvin/dtvem.cli" rel="noopener noreferrer"&gt;dtvem.cli&lt;/a&gt; and &lt;a href="https://github.com/CodingWithCalvin/rnr.cli" rel="noopener noreferrer"&gt;rnr.cli itself&lt;/a&gt;. Yes, rnr builds rnr. Dogfooding at its finest.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;This is v0.1.0, so there's plenty more I want to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Task dependencies (&lt;code&gt;depends: [build, test]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Conditional execution (&lt;code&gt;if: ${{ env.CI }}&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Watch mode (&lt;code&gt;watch: [src/**/*.rs]&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Variable interpolation (&lt;code&gt;${{ vars.version }}&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Caching and incremental builds&lt;/li&gt;
&lt;li&gt;Interactive task picker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of these would be useful for your workflow, let me know—or better yet, open an issue on GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's Open Source
&lt;/h2&gt;

&lt;p&gt;rnr is MIT licensed and available on GitHub at &lt;a href="https://github.com/CodingWithCalvin/rnr.cli" rel="noopener noreferrer"&gt;CodingWithCalvin/rnr.cli&lt;/a&gt;. If you find bugs, have feature requests, or want to contribute, PRs are absolutely welcome.&lt;/p&gt;

&lt;p&gt;I'd love to hear what you think. Let me know if you try it out!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>opensource</category>
      <category>cli</category>
    </item>
    <item>
      <title>Introducing vscwhere!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Thu, 08 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-vscwhere-bj2</link>
      <guid>https://dev.to/calvinallen/introducing-vscwhere-bj2</guid>
      <description>&lt;p&gt;If you've ever used Microsoft's &lt;a href="https://github.com/microsoft/vswhere" rel="noopener noreferrer"&gt;vswhere&lt;/a&gt;, you know how handy it is. Need to find where Visual Studio is installed? Run &lt;code&gt;vswhere&lt;/code&gt;. Need the path for a CI/CD script? &lt;code&gt;vswhere -latest -property installationPath&lt;/code&gt;. It just works.&lt;/p&gt;

&lt;p&gt;But what if you need to find Visual Studio &lt;em&gt;Code&lt;/em&gt; instead?&lt;/p&gt;

&lt;p&gt;So I built it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing vscwhere
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;vscwhere&lt;/strong&gt; is a CLI tool that locates Visual Studio Code installations on Windows. Think of it as vswhere's little sibling — same idea, same familiar interface, just for VS Code instead of Visual Studio.&lt;/p&gt;

&lt;p&gt;Need to find all your VS Code installations? Just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vscwhere

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

&lt;/div&gt;



&lt;p&gt;That's it. You'll get a list of all the VS Code installations on your machine — Stable and Insiders builds alike.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Options
&lt;/h2&gt;

&lt;p&gt;If you're familiar with vswhere, you'll feel right at home:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Options:
  -all Find all instances (default)
  -prerelease Include prerelease (Insiders) builds
  -latest Return only the latest version
  -format &amp;lt;type&amp;gt; Output format: text (default), json
  -property &amp;lt;name&amp;gt; Return value of specified property
  -nologo Suppress version banner
  -sort Sort instances by version (descending)
  -help, -? Display this help message

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

&lt;/div&gt;



&lt;p&gt;Need JSON for your build scripts? &lt;code&gt;-format json&lt;/code&gt;. Just want the latest stable version's path? &lt;code&gt;-latest -property installationPath&lt;/code&gt;. Need to include Insiders builds? &lt;code&gt;-prerelease&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example Output
&lt;/h2&gt;

&lt;p&gt;Here's what it looks like in action. Running &lt;code&gt;vscwhere&lt;/code&gt; with no arguments:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; vscwhere
VSCWhere version 0.1.0

installationPath: C:\Users\calvin.allen\AppData\Local\Programs\Microsoft VS Code\
installationVersion: 1.107.1
productPath: C:\Users\calvin.allen\AppData\Local\Programs\Microsoft VS Code\Code.exe
productId: stable
isPrerelease: false
displayName: Visual Studio Code
extensionsPath: C:\Users\calvin.allen\.vscode\extensions
userDataPath: C:\Users\calvin.allen\AppData\Roaming\Code

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

&lt;/div&gt;



&lt;p&gt;And with &lt;code&gt;-format json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; vscwhere -format json
VSCWhere version 0.1.0

[
  {
    "installationPath": "C:\\Users\\calvin.allen\\AppData\\Local\\Programs\\Microsoft VS Code\\",
    "installationVersion": "1.107.1",
    "productPath": "C:\\Users\\calvin.allen\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe",
    "productId": "stable",
    "isPrerelease": false,
    "displayName": "Visual Studio Code",
    "extensionsPath": "C:\\Users\\calvin.allen\\.vscode\\extensions",
    "userDataPath": "C:\\Users\\calvin.allen\\AppData\\Roaming\\Code"
  }
]

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

&lt;/div&gt;



&lt;p&gt;Also, the most important for workflows, &lt;code&gt;-nologo&lt;/code&gt; (and combine it with JSON output):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; vscwhere -nologo -format json
[
  {
    "installationPath": "C:\\Users\\calvin.allen\\AppData\\Local\\Programs\\Microsoft VS Code\\",
    "installationVersion": "1.107.1",
    "productPath": "C:\\Users\\calvin.allen\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe",
    "productId": "stable",
    "isPrerelease": false,
    "displayName": "Visual Studio Code",
    "extensionsPath": "C:\\Users\\calvin.allen\\.vscode\\extensions",
    "userDataPath": "C:\\Users\\calvin.allen\\AppData\\Roaming\\Code"
  }
]

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  How Does It Work?
&lt;/h2&gt;

&lt;p&gt;Here's where it gets a little unusual. VS Code doesn't write any special registry keys when it's installed — there's no convenient "here's where I live" entry to read. The &lt;em&gt;only&lt;/em&gt; registry presence VS Code has is its uninstall entries.&lt;/p&gt;

&lt;p&gt;So that's what vscwhere uses. It finds the uninstall entries in the Windows Registry and works backwards to determine the actual installation directory. It's a reliable way to find installations regardless of where the user chose to install them — and really, it's the only way without resorting to scanning the entire filesystem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Rust?
&lt;/h2&gt;

&lt;p&gt;Executable size. That's it. A .NET trimmed, single-file binary clocked in at 12MB. The Rust version? Under 1MB. For a simple CLI tool that finds VS Code installations, 12MB felt absurd. Rust gives me a tiny, dependency-free binary that's fast and easy to distribute. No runtime dependencies, no installers — just download the executable and run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Limitations
&lt;/h2&gt;

&lt;p&gt;A few things to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows only&lt;/strong&gt; — macOS and Linux support may come later, but for now it's Windows-focused&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No portable installations&lt;/strong&gt; — it finds Stable and Insiders builds installed the normal way, but won't detect portable VS Code installations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Get It
&lt;/h2&gt;

&lt;p&gt;vscwhere is available from GitHub releases. Grab the latest binary and drop it somewhere in your PATH:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/CodingWithCalvin/vscwhere" rel="noopener noreferrer"&gt;github.com/CodingWithCalvin/vscwhere&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an early release — version 0.1.0 — so there's plenty of room for improvement. If you've got ideas or run into issues, let me know!&lt;/p&gt;

&lt;p&gt;As always, I accept pull requests :)&lt;/p&gt;

</description>
      <category>rust</category>
      <category>cli</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Introducing the Developer Tools Virtual Environment Manager!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Mon, 05 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-the-developer-tools-virtual-environment-manager-463g</link>
      <guid>https://dev.to/calvinallen/introducing-the-developer-tools-virtual-environment-manager-463g</guid>
      <description>&lt;p&gt;If you've ever tried to manage multiple versions of Python, Node.js, or Ruby on Windows, you know the pain. Tools like &lt;code&gt;nvm&lt;/code&gt;, &lt;code&gt;pyenv&lt;/code&gt;, and &lt;code&gt;rbenv&lt;/code&gt; work great on macOS and Linux, but Windows support ranges from "hacky workarounds" to "just use WSL." And even on Unix systems, you're juggling three different tools with three different configurations.&lt;/p&gt;

&lt;p&gt;So I built something better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing dtvem
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;dtvem&lt;/strong&gt; (Developer Tools Virtual Environment Manager) is a unified, cross-platform runtime version manager written in Go. One tool to manage Python, Node.js, and Ruby — and it works identically on Windows, macOS, and Linux.&lt;/p&gt;

&lt;p&gt;No shell hooks. No &lt;code&gt;.bashrc&lt;/code&gt; modifications. No WSL required. Just install it and go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Another Version Manager?
&lt;/h2&gt;

&lt;p&gt;The existing tools are great, but they all have the same problem: Windows is an afterthought. And if you work across multiple runtimes, you're maintaining separate tools with separate configurations.&lt;/p&gt;

&lt;p&gt;dtvem takes a different approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows is a first-class citizen&lt;/strong&gt; — not an afterthought or "community port"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shim-based architecture&lt;/strong&gt; — works in cmd.exe, PowerShell, bash, zsh, fish, whatever&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One tool for multiple runtimes&lt;/strong&gt; — Python, Node.js, and Ruby today, with Go, Rust, and Java on the roadmap&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project-local versions&lt;/strong&gt; — drop a config file in your project and the right versions activate automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;dtvem uses shims instead of shell integration. When you run &lt;code&gt;python&lt;/code&gt; or &lt;code&gt;node&lt;/code&gt;, it intercepts the command and routes it to the correct version based on your configuration.&lt;/p&gt;

&lt;p&gt;The resolution order is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Local config&lt;/strong&gt; — &lt;code&gt;.dtvem/runtimes.json&lt;/code&gt; in your project (or any parent directory)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global config&lt;/strong&gt; — &lt;code&gt;~/.dtvem/config/runtimes.json&lt;/code&gt; for system-wide defaults&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System PATH&lt;/strong&gt; — falls back to whatever's installed on your system&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No magic. No shell hooks. It just works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Installation is a one-liner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows (PowerShell):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irm dtvem.io/install.ps1 | iex

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -fsSL dtvem.io/install.sh | bash

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

&lt;/div&gt;



&lt;p&gt;Once installed, the workflow is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install a runtime version
dtvem install python 3.12.0
dtvem install node 22.0.0

# Set global defaults
dtvem global python 3.12.0
dtvem global node 22.0.0

# Set project-specific versions
cd my-project
dtvem local python 3.10.0
dtvem local node 18.20.0

# Check what's active
dtvem current

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

&lt;/div&gt;



&lt;p&gt;That's it. Navigate into &lt;code&gt;my-project&lt;/code&gt; and Python 3.10.0 and Node 18.20.0 are automatically active. Navigate out and your global versions take over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating from Existing Tools
&lt;/h2&gt;

&lt;p&gt;Already using nvm, pyenv, or rbenv? dtvem can import your existing installations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dtvem migrate node # Import from nvm or fnm
dtvem migrate python # Import from pyenv
dtvem migrate ruby # Import from rbenv, rvm, chruby, or uru

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

&lt;/div&gt;



&lt;p&gt;It detects your existing version managers, copies the installed versions, preserves your globally installed packages, and optionally cleans up the old installations. You can run both tools side-by-side during the transition if you want a gradual migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Website
&lt;/h2&gt;

&lt;p&gt;All the details live at &lt;a href="https://dtvem.io" rel="noopener noreferrer"&gt;dtvem.io&lt;/a&gt;. You'll find:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Getting Started guide&lt;/strong&gt; — installation and basic workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command reference&lt;/strong&gt; — all 18 commands documented&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime guides&lt;/strong&gt; — specifics for Python, Node.js, and Ruby&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration guide&lt;/strong&gt; — step-by-step for switching from other tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comparison page&lt;/strong&gt; — how dtvem stacks up against nvm, pyenv, rbenv, asdf, and mise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The install scripts are served directly from the domain, so the one-liner installations just work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get It / Contribute
&lt;/h2&gt;

&lt;p&gt;dtvem is pre-1.0 but fully functional. The core runtimes are stable, and I'm working on adding Go, Rust, and Java.&lt;/p&gt;

&lt;p&gt;Both projects are open source under the MIT license:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLI: &lt;a href="https://github.com/CodingWithCalvin/dtvem.cli" rel="noopener noreferrer"&gt;github.com/CodingWithCalvin/dtvem.cli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Website: &lt;a href="https://github.com/CodingWithCalvin/dtvem.io" rel="noopener noreferrer"&gt;github.com/CodingWithCalvin/dtvem.io&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're tired of juggling multiple version managers — or you've been stuck on Windows without good options — give dtvem a try.&lt;/p&gt;

&lt;p&gt;As always, I accept pull requests :)&lt;/p&gt;

</description>
      <category>go</category>
      <category>cli</category>
      <category>python</category>
      <category>node</category>
    </item>
    <item>
      <title>Introducing the Visual Studio Toolbox!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Fri, 02 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/introducing-the-visual-studio-toolbox-fef</link>
      <guid>https://dev.to/calvinallen/introducing-the-visual-studio-toolbox-fef</guid>
      <description>&lt;p&gt;If you've ever used JetBrains Toolbox, you know how convenient it is. It's the central hub for all your JetBrains IDEs — install new tools, manage updates, launch any version with a single click. Everything in one place, tucked away in the system tray.&lt;/p&gt;

&lt;p&gt;The other day I was clicking around in JetBrains Toolbox and it hit me — why doesn't Visual Studio have something like this? I've got multiple versions installed, experimental hives for extension development, and I'm constantly hunting through the Start menu to find the right one. Turns out this was exactly what I needed but didn't know I wanted.&lt;/p&gt;

&lt;p&gt;So I built it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Visual Studio Toolbox
&lt;/h2&gt;

&lt;p&gt;Visual Studio Toolbox is a Windows system tray application that serves as mission control for Visual Studio. It automatically detects all your Visual Studio installations — 2019, 2022, 2026, experimental hives, the whole lot — and puts them one click away.&lt;/p&gt;

&lt;p&gt;No more hunting through the Start menu. No more trying to remember which version you need for that legacy project. Just click the tray icon and pick the one you want.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codingwithcalvin.net%2Fintroducing-the-visual-studio-toolbox%2Finstance-list.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codingwithcalvin.net%2Fintroducing-the-visual-studio-toolbox%2Finstance-list.png" alt="Instance List" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can It Do?
&lt;/h2&gt;

&lt;p&gt;Here's the quick rundown of features:&lt;/p&gt;

&lt;h3&gt;
  
  
  One-Click Launch
&lt;/h3&gt;

&lt;p&gt;Each Visual Studio instance in the list has a play button right there — click it and that version launches. That's it. That's the whole thing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codingwithcalvin.net%2Fintroducing-the-visual-studio-toolbox%2Finstance-list-hover.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codingwithcalvin.net%2Fintroducing-the-visual-studio-toolbox%2Finstance-list-hover.png" alt="Instance List Hover" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer Tools at Your Fingertips
&lt;/h3&gt;

&lt;p&gt;Click the gear icon on any instance and you get quick access to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developer Command Prompt&lt;/strong&gt; — because sometimes you just need that environment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer PowerShell&lt;/strong&gt; — same deal, but PowerShell flavored&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Installation Folder&lt;/strong&gt; — jump straight to where VS lives on disk&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open AppData Folder&lt;/strong&gt; — for when you need to poke around in settings and extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The list of command prompt and PowerShell options is driven by your Windows Terminal profiles. If you've got custom profiles set up, they'll show up here. If you don't have Windows Terminal installed or don't have any profiles, it falls back to a single Developer Command Prompt and single Developer PowerShell option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codingwithcalvin.net%2Fintroducing-the-visual-studio-toolbox%2Finstance-list-menu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codingwithcalvin.net%2Fintroducing-the-visual-studio-toolbox%2Finstance-list-menu.png" alt="Instance List Context Menu" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Stays Out of Your Way
&lt;/h3&gt;

&lt;p&gt;The app lives in your system tray. You can configure it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch on Windows startup&lt;/li&gt;
&lt;li&gt;Start minimized&lt;/li&gt;
&lt;li&gt;Minimize to tray instead of taskbar&lt;/li&gt;
&lt;li&gt;Close to tray (so it's always ready when you need it)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codingwithcalvin.net%2Fintroducing-the-visual-studio-toolbox%2Fsettings.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.codingwithcalvin.net%2Fintroducing-the-visual-studio-toolbox%2Fsettings.png" alt="Settings" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tech Stack
&lt;/h2&gt;

&lt;p&gt;For those curious about what's under the hood:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C# 13&lt;/strong&gt; and &lt;strong&gt;.NET 10&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WinUI 3&lt;/strong&gt; with &lt;strong&gt;Windows App SDK 1.8&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;H.NotifyIcon.WinUI&lt;/strong&gt; for the system tray functionality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MVVM Community Toolkit&lt;/strong&gt; for keeping things clean and testable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted to build this with modern Windows development tech, and WinUI 3 gave me exactly what I needed — a native Windows look and feel with proper light/dark theme support (complete with that sweet Visual Studio purple accent color).&lt;/p&gt;

&lt;p&gt;Getting the window styled the way I wanted took some effort though. I was going for a specific look — no traditional Windows chrome, square borders, a flat aesthetic. WinUI 3 doesn't make that trivial out of the box, but after some wrestling with window customization APIs, I got it where I wanted it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get It / Contribute
&lt;/h2&gt;

&lt;p&gt;Visual Studio Toolbox is open source under the MIT license. Grab a portable executable from the GitHub releases, or check out the source:&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/CodingWithCalvin/VSToolbox" rel="noopener noreferrer"&gt;github.com/CodingWithCalvin/VSToolbox&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eventually there will be an MSIX package on the Microsoft Store — when I have time to figure that whole process out.&lt;/p&gt;

&lt;p&gt;This is still early days — version 0.1.1 just shipped — so there's plenty of room for new features and improvements. If you've got ideas or run into issues, let me know!&lt;/p&gt;

&lt;p&gt;As always, I accept pull requests :)&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>visualstudio</category>
      <category>winui</category>
    </item>
    <item>
      <title>SDK-style Projects for your Visual Studio Extensions!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Thu, 01 Jan 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/sdk-style-projects-for-your-visual-studio-extensions-1ie4</link>
      <guid>https://dev.to/calvinallen/sdk-style-projects-for-your-visual-studio-extensions-1ie4</guid>
      <description>&lt;p&gt;Remember &lt;a href="https://www.codingwithcalvin.net/creating-your-own-msbuild-sdk-it-s-easier-than-you-think" rel="noopener noreferrer"&gt;that post I wrote last week&lt;/a&gt; about creating MSBuild SDKs? Well, I wasn't just writing that for fun - I was actually building something with all that knowledge.&lt;/p&gt;

&lt;p&gt;I've released &lt;a href="https://www.nuget.org/packages/CodingWithCalvin.VsixSdk/" rel="noopener noreferrer"&gt;CodingWithCalvin.VsixSdk&lt;/a&gt;, an MSBuild SDK that brings modern SDK-style &lt;code&gt;.csproj&lt;/code&gt; files to Visual Studio extension development. No more XML soup!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;If you've ever created a Visual Studio extension, you know the pain. The &lt;code&gt;.csproj&lt;/code&gt; file looks like it was written in 2008 (because it basically was). Hundreds of lines of XML, explicit file includes for everything, and don't even get me started on trying to understand what half of those properties do.&lt;/p&gt;

&lt;p&gt;Sure, you could migrate from &lt;code&gt;packages.config&lt;/code&gt; to &lt;code&gt;PackageReference&lt;/code&gt; in the old format - Visual Studio has supported that for years - but you'd still be stuck with all that verbose XML and manual file management.&lt;/p&gt;

&lt;p&gt;And here's the kicker - without an SDK-style project, you can't use &lt;code&gt;dotnet build&lt;/code&gt; from the command line. You're stuck invoking MSBuild directly, like some kind of caveman. Meanwhile, every other .NET project gets to use the nice, clean SDK-style format and the dotnet CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project Sdk="Microsoft.NET.Sdk"&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;TargetFramework&amp;gt;net8.0&amp;lt;/TargetFramework&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Why should VSIX projects be stuck in the past?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;With my new SDK, your VSIX project can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project Sdk="CodingWithCalvin.VsixSdk/0.3.0"&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;TargetFramework&amp;gt;net48&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;RootNamespace&amp;gt;MyAwesomeExtension&amp;lt;/RootNamespace&amp;gt;
    &amp;lt;AssemblyName&amp;gt;MyAwesomeExtension&amp;lt;/AssemblyName&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.*" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;That's it. That's the whole thing. The SDK handles all the VSSDK build tools, the manifest processing, the VSCT compilation - everything that used to require dozens of lines of cryptic XML. And yes, you can now just run &lt;code&gt;dotnet build&lt;/code&gt; like everybody else!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;The easiest way to get started is with the dotnet template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install the template
dotnet new install CodingWithCalvin.VsixSdk.Templates

# Create a new extension
dotnet new vsix -n MyExtension --publisher "Your Name" --description "My awesome extension"

# Build it
cd MyExtension
dotnet build

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

&lt;/div&gt;



&lt;p&gt;The template sets up everything you need - the project file, the manifest, the whole nine yards.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Get
&lt;/h2&gt;

&lt;p&gt;Beyond the clean project file, the SDK includes some features I'm pretty proud of:&lt;/p&gt;

&lt;h3&gt;
  
  
  Source Generators
&lt;/h3&gt;

&lt;p&gt;The SDK automatically generates a &lt;code&gt;VsixInfo&lt;/code&gt; class from your manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Auto-generated - use these anywhere in your code
public static class VsixInfo
{
  public const string Id = "MyExtension.a1b2c3d4-...";
  public const string Version = "1.0.0";
  public const string Publisher = "Your Name";
  public const string DisplayName = "My Extension";
  // ... and more
}

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

&lt;/div&gt;



&lt;p&gt;No more hardcoding strings that get out of sync with your manifest. Just use &lt;code&gt;VsixInfo.Version&lt;/code&gt; and you're done.&lt;/p&gt;

&lt;p&gt;If you have &lt;code&gt;.vsct&lt;/code&gt; files, you get generated constants for those too - GUIDs, command IDs, menu groups, all as strongly-typed constants.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version Override at Build Time
&lt;/h3&gt;

&lt;p&gt;If you've ever tried to automate versioning a VSIX in CI/CD, you know how painful it is. You'd typically have to run some kind of &lt;code&gt;sed&lt;/code&gt; or PowerShell regex to find and replace the version in the manifest XML, then trigger a separate build step, and hope you didn't break the XML formatting in the process. It's fragile and annoying.&lt;/p&gt;

&lt;p&gt;With this SDK, it's just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet build -p:SetVsixVersion=2.0.0

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

&lt;/div&gt;



&lt;p&gt;One command. The SDK updates the manifest, regenerates the constants, and builds the VSIX with the correct version everywhere. Perfect for GitHub Actions where you want to version based on tags or run numbers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- name: Build Release
  run: dotnet build -c Release -p:SetVsixVersion=${{ github.ref_name }}

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

&lt;/div&gt;



&lt;p&gt;No more grep/sed gymnastics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auto-Inclusion
&lt;/h3&gt;

&lt;p&gt;The SDK automatically includes common VSIX files like &lt;code&gt;.vsct&lt;/code&gt; files and &lt;code&gt;VSPackage.resx&lt;/code&gt;. You don't have to explicitly list them anymore - they just work.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Real-World Example
&lt;/h2&gt;

&lt;p&gt;I've already migrated my &lt;a href="https://github.com/CodingWithCalvin/VS-OpenInNotepadPlusPlus" rel="noopener noreferrer"&gt;Open in Notepad++&lt;/a&gt; extension to use this SDK. Here's what the project file looks like now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project Sdk="CodingWithCalvin.VsixSdk/0.3.0"&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;TargetFramework&amp;gt;net48&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;RootNamespace&amp;gt;CodingWithCalvin.OpenInNotepadPlusPlus&amp;lt;/RootNamespace&amp;gt;
    &amp;lt;AssemblyName&amp;gt;CodingWithCalvin.OpenInNotepadPlusPlus&amp;lt;/AssemblyName&amp;gt;
    &amp;lt;LangVersion&amp;gt;latest&amp;lt;/LangVersion&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;PropertyGroup Condition="'$(Configuration)' == 'Debug'"&amp;gt;
    &amp;lt;DeployExtension&amp;gt;True&amp;lt;/DeployExtension&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;PackageReference Include="Microsoft.VisualStudio.SDK" Version="17.14.40265" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;Content Include="..\..\resources\icon.png" Link="resources\icon.png"&amp;gt;
      &amp;lt;IncludeInVSIX&amp;gt;true&amp;lt;/IncludeInVSIX&amp;gt;
    &amp;lt;/Content&amp;gt;
    &amp;lt;Content Include="..\..\LICENSE" Link="resources\LICENSE"&amp;gt;
      &amp;lt;IncludeInVSIX&amp;gt;true&amp;lt;/IncludeInVSIX&amp;gt;
    &amp;lt;/Content&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Compare that to the hundreds of lines it used to be. F5 debugging works, the VSIX builds correctly, deploys to the experimental instance - everything just works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating an Existing Project
&lt;/h2&gt;

&lt;p&gt;If you have an existing extension you want to migrate, the process is pretty straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Back up your project&lt;/strong&gt; - Always a good idea before major changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replace the &lt;code&gt;.csproj&lt;/code&gt; content&lt;/strong&gt; - Swap out all that legacy XML for the SDK-style format&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update the manifest&lt;/strong&gt; - Remove support for versions prior to VS 2022, and add support for VS 2026 (version range &lt;code&gt;[17.0, 19.0)&lt;/code&gt;). While you're in there, it's a good time to add arm64 support too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add your PackageReferences&lt;/strong&gt; - If you were already using PackageReference, just move them over. If not, convert your package references now.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete the cruft&lt;/strong&gt; - Remove &lt;code&gt;packages.config&lt;/code&gt; (since you've migrated to PackageReference in the previous step), &lt;code&gt;Properties/AssemblyInfo.cs&lt;/code&gt;, and any explicit file includes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build and test&lt;/strong&gt; - Run &lt;code&gt;dotnet build&lt;/code&gt; and fix any issues&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href="https://github.com/CodingWithCalvin/VsixSdk" rel="noopener noreferrer"&gt;README on GitHub&lt;/a&gt; has a detailed migration guide with before/after examples and a checklist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Visual Studio 2022 or later&lt;/li&gt;
&lt;li&gt;.NET Framework 4.7.2+ target framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The SDK is specifically for VS 2022+ extensions. If you're still supporting older versions of Visual Studio, you'll need to stick with the legacy project format for now.&lt;/p&gt;

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

&lt;p&gt;I built this SDK because I got tired of fighting with legacy project files every time I wanted to create or update an extension. If you're building Visual Studio extensions and want a cleaner development experience, give it a try.&lt;/p&gt;

&lt;p&gt;The SDK is &lt;a href="https://www.nuget.org/packages/CodingWithCalvin.VsixSdk/" rel="noopener noreferrer"&gt;available on NuGet&lt;/a&gt; and the source is &lt;a href="https://github.com/CodingWithCalvin/VsixSdk" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt;. If you run into issues or have ideas for improvements, let me know - I'm always looking to make this thing better.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>vsix</category>
    </item>
    <item>
      <title>Creating Your Own MSBuild SDK - It's Easier Than You Think!</title>
      <dc:creator>Calvin A. Allen</dc:creator>
      <pubDate>Thu, 25 Dec 2025 12:00:00 +0000</pubDate>
      <link>https://dev.to/calvinallen/creating-your-own-msbuild-sdk-its-easier-than-you-think-17n3</link>
      <guid>https://dev.to/calvinallen/creating-your-own-msbuild-sdk-its-easier-than-you-think-17n3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This post is part of the 2025 C# Advent Calendar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://csadvent.christmas" rel="noopener noreferrer"&gt;Check it out here, for other AWESOME posts.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'll be honest - I put off learning how MSBuild SDKs work for way too long. Every time I saw that &lt;code&gt;Sdk="Microsoft.NET.Sdk"&lt;/code&gt; attribute at the top of a &lt;code&gt;.csproj&lt;/code&gt; file, I just accepted it as magic and moved on. But recently I needed to create a custom SDK, and after banging my head against the wall for a bit, I finally figured it out.&lt;/p&gt;

&lt;p&gt;Spoiler: it's not nearly as scary as I thought.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Even Is an MSBuild SDK?
&lt;/h2&gt;

&lt;p&gt;Before we dive in, let's clear up what we're actually talking about. An MSBuild SDK is basically a NuGet package that automatically imports &lt;code&gt;.props&lt;/code&gt; and &lt;code&gt;.targets&lt;/code&gt; files into your project. That's it. That's the whole thing.&lt;/p&gt;

&lt;p&gt;When you write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project Sdk="MyAwesome.Sdk/1.0.0"&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;MSBuild goes "oh, you want that SDK?" and then imports &lt;code&gt;Sdk.props&lt;/code&gt; at the very beginning and &lt;code&gt;Sdk.targets&lt;/code&gt; at the very end of your project. Everything in between is your actual project content.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Folder Structure
&lt;/h2&gt;

&lt;p&gt;Here's what your SDK package needs to look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MyAwesome.Sdk/
├── Sdk/
│ ├── Sdk.props ← Imported first
│ └── Sdk.targets ← Imported last
└── MyAwesome.Sdk.csproj

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Sdk/&lt;/code&gt; folder is the magic folder. MSBuild looks there specifically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Props File
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;.props&lt;/code&gt; file runs before anything else in the project. This is where you set up defaults:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;!-- Set defaults that users can override --&amp;gt;
    &amp;lt;TargetFramework Condition="'$(TargetFramework)' == ''"&amp;gt;net8.0&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;ImplicitUsings Condition="'$(ImplicitUsings)' == ''"&amp;gt;enable&amp;lt;/ImplicitUsings&amp;gt;

    &amp;lt;!-- Properties you always want set --&amp;gt;
    &amp;lt;MyCustomProperty&amp;gt;true&amp;lt;/MyCustomProperty&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;See those &lt;code&gt;Condition&lt;/code&gt; attributes? That's the key pattern. You're saying "only set this if the user hasn't already set it." This lets your SDK provide sensible defaults while still allowing customization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Targets File
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;.targets&lt;/code&gt; file runs after the project content. This is where you do the real work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project&amp;gt;
  &amp;lt;!-- Auto-include certain files --&amp;gt;
  &amp;lt;ItemGroup Condition="'$(EnableDefaultMyItems)' != 'false'"&amp;gt;
    &amp;lt;None Include="**/*.config" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

  &amp;lt;!-- Add custom build targets --&amp;gt;
  &amp;lt;Target Name="MyCustomTarget" BeforeTargets="Build"&amp;gt;
    &amp;lt;Message Importance="high" Text="Look ma, I'm in a custom SDK!" /&amp;gt;
  &amp;lt;/Target&amp;gt;

  &amp;lt;!-- Validate configuration --&amp;gt;
  &amp;lt;Target Name="ValidateStuff" BeforeTargets="BeforeBuild"&amp;gt;
    &amp;lt;Warning Condition="'$(SomeProperty)' == ''"
             Text="Hey, you probably want to set SomeProperty." /&amp;gt;
  &amp;lt;/Target&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping Other SDKs
&lt;/h2&gt;

&lt;p&gt;Here's where it gets interesting. You probably don't want to recreate everything from scratch - you want to build &lt;em&gt;on top of&lt;/em&gt; the existing .NET SDK. The pattern looks like this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sdk.props:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project&amp;gt;
  &amp;lt;!-- Import the base SDK props first --&amp;gt;
  &amp;lt;Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" /&amp;gt;

  &amp;lt;!-- Then add your customizations --&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;MyCustomDefault&amp;gt;true&amp;lt;/MyCustomDefault&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sdk.targets:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project&amp;gt;
  &amp;lt;!-- Your custom logic first --&amp;gt;
  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;None Include="**/*.special" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

  &amp;lt;!-- Then import base SDK targets --&amp;gt;
  &amp;lt;Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" /&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;The order matters here. Props imports happen outside-in (base first, then yours), and targets happen inside-out (yours first, then base). At least, that's what made sense for my use case - your mileage may vary.&lt;/p&gt;

&lt;h2&gt;
  
  
  The .csproj for Your SDK Package
&lt;/h2&gt;

&lt;p&gt;Your SDK project itself is pretty minimal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project Sdk="Microsoft.NET.Sdk"&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;TargetFramework&amp;gt;netstandard2.0&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;PackageId&amp;gt;MyAwesome.Sdk&amp;lt;/PackageId&amp;gt;
    &amp;lt;Version&amp;gt;1.0.0&amp;lt;/Version&amp;gt;
    &amp;lt;PackageType&amp;gt;MSBuildSdk&amp;lt;/PackageType&amp;gt;
    &amp;lt;IncludeBuildOutput&amp;gt;false&amp;lt;/IncludeBuildOutput&amp;gt;
    &amp;lt;SuppressDependenciesWhenPacking&amp;gt;true&amp;lt;/SuppressDependenciesWhenPacking&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;None Include="Sdk\**" Pack="true" PackagePath="Sdk" /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;The important bits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;PackageType&amp;gt;MSBuildSdk&lt;/code&gt; - tells NuGet this is an SDK package&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IncludeBuildOutput&amp;gt;false&lt;/code&gt; - you're not shipping a DLL, just the props/targets&lt;/li&gt;
&lt;li&gt;That &lt;code&gt;ItemGroup&lt;/code&gt; makes sure your &lt;code&gt;Sdk/&lt;/code&gt; folder ends up in the right place in the package&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing Locally (The Part I Struggled With)
&lt;/h2&gt;

&lt;p&gt;This is where I wasted the most time. You can't just &lt;code&gt;dotnet build&lt;/code&gt; and expect Visual Studio to find your SDK. Here's what actually works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build your SDK package: &lt;code&gt;dotnet pack -c Release&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add your output folder as a local NuGet source&lt;/li&gt;
&lt;li&gt;Reference the exact version in your test project&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Or, the sneaky way - during development, just use &lt;code&gt;Microsoft.NET.Sdk&lt;/code&gt; in your test project and manually import your props/targets:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Directory.Build.props:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project&amp;gt;
  &amp;lt;Import Project="../src/MyAwesome.Sdk/Sdk/Sdk.props" /&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Directory.Build.targets:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Project&amp;gt;
  &amp;lt;Import Project="../src/MyAwesome.Sdk/Sdk/Sdk.targets" /&amp;gt;
&amp;lt;/Project&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;This way you can iterate without constantly rebuilding packages. Just switch to the real &lt;code&gt;Sdk="..."&lt;/code&gt; reference when you're ready to ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Gotchas
&lt;/h2&gt;

&lt;p&gt;A few things that tripped me up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Props vs Targets confusion&lt;/strong&gt; - If your defaults aren't working, you probably put them in targets instead of props. Properties need to be set before the project content, not after.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Condition syntax&lt;/strong&gt; - It's &lt;code&gt;Condition="'$(Prop)' == ''"&lt;/code&gt; with single quotes inside double quotes. I mess this up constantly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Import order matters&lt;/strong&gt; - Some properties from other SDKs or build tools need to be set super early in props, before they get evaluated. If something isn't working, try moving it earlier in the import chain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The casing matters&lt;/strong&gt; - The folder must be &lt;code&gt;Sdk/&lt;/code&gt; with a capital S. Lowercase won't work on case-sensitive file systems.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;NuGet caching will drive you insane&lt;/strong&gt; - When testing locally, NuGet aggressively caches packages. Either bump your version number every time, or clear the cache with &lt;code&gt;dotnet nuget locals all --clear&lt;/code&gt;. Trust me on this one.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Creating an MSBuild SDK isn't rocket science - it's really just packaging up props and targets files in a specific folder structure. The hardest part is figuring out which properties go where and what order to import things.&lt;/p&gt;

&lt;p&gt;If you're building something that needs consistent project configuration across multiple projects, or you're wrapping complex build tooling behind a simpler interface, an SDK is a great way to go.&lt;/p&gt;

&lt;p&gt;If you have questions or run into issues I didn't cover, let me know - I'm still learning this stuff myself and always happy to compare notes.&lt;/p&gt;

</description>
      <category>msbuild</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
