CLI tool
dotnet/dotnet avatar
dotnet/dotnet

dotnet/dotnet and the virtual monorepo that builds the .NET SDK

Home of .NET's Virtual Monolithic Repository which includes all the code needed to build the .NET SDK.

1,300 stars348 forksC#MIT

At a glance

What is it?
The dotnet/dotnet repository is a Virtual Monolithic Repository that mirrors the source of every product repository under src/ so that the whole .NET SDK can be built from a single commit, while the real coding work stays in the repositories it mirrors. The payoff is a single identifiable commit for the product; the cost is a build environment that the project itself calls a work in progress.
Who is it for?
Adopt dotnet/dotnet if you are a distribution builder, a partner who needs to build, test and modify .NET with your own infrastructure, or a team debugging a bug that spans several product repositories, since a single commit that builds the SDK is exactly what those scenarios need. Do not adopt it as your everyday development repository, because the project asks contributors to keep working in dotnet/runtime, dotnet/sdk and dotnet/aspnetcore where the validation is best.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A monorepo that is a mirror rather than a merger

dotnet/dotnet is described as a Virtual Monolithic Repository, and the two words matter separately. Monolithic means it is a join of multiple repositories that make up the whole product, such as dotnet/runtime and dotnet/sdk. Virtual means it is a mirror, explicitly not a replacement, of the product repositories, where the sources are synchronized with.

What you find under src/ is the source of each product repository, mirrored into its own directory. Alongside that sit the tools that make it possible to build the whole .NET product from source on Linux, and, in future, end to end tests for the entire product. The top level of the tree shows how much of the repository is the product and how much is the machinery around it: there is src/ and test/ for the mirrored code and tests, eng/ for the pipeline, prereqs/ and repo-projects/ for build inputs, plus global.json, Directory.Packages.props, Directory.Build.props and NuGet.config for the central build configuration.

The central design decision is that active development stays where it happens today. ASP.NET features continue to be developed in dotnet/aspnetcore and CLR features in dotnet/runtime, because those repositories have their own communities and processes, and aggregating development into a true mono-repo would work against that. The VMR gives the simplicity of a mono-repo for building and servicing the product, while the day to day experience of a typical contributor does not change.

That is a deliberate trade. A real monorepo would give atomic cross-cutting commits, and this one gives you the buildable result without the political cost of moving everyone into one repository.

One commit that can build the .NET product

The stated main purpose is to have all the source code necessary to build the .NET product available in one repository and identified by a single commit. That is a narrower goal than contributing to .NET, and a more concrete one.

The second goal is to become the place from which future versions of .NET are released and serviced, reducing the complexity of the product construction process, with the intention that partners and third parties can build, test and modify .NET using their own infrastructure, and that the process becomes available to the community.

The list of problems the project wants the VMR to solve is the most useful part of the README. It is meant to enable the standard downstream and upstream open source model, so that a change can flow from a product repository into a distribution and back. It is meant to satisfy distribution builders such as Red Hat or Canonical who need to include .NET natively in their own repositories. It is meant to simplify client-run testing of bug fixes and improvements, with the build working in an offline environment for certain platforms. It is meant to let developers make and test changes that span several repositories. And it is meant to make the security fix pipeline more efficient during the CVE pre-disclosure process.

Read together, these are all the same problem seen from different angles. Distributed development is the right model for the people writing the code, and it is a bad model for the people shipping the product, because a release then depends on a set of repositories at a set of commits that nothing records. A single commit that produces the product removes that.

Code flow runs in both directions

The mechanism that keeps the mirror honest is code flow pull requests, and it works in two directions.

The forward flow is the path from the product repositories into the VMR. Individual repositories flow their source changes into the VMR when their local official builds are promoted. The VMR changes are then checked in, an official build happens in the VMR, and the source changes plus the packages flow backward into the constituent repositories in what the documentation calls the back flow.

The interesting property is that the VMR is the only place where the whole product is built. The product repositories build their own piece, but the combination, the thing that actually ships, is built once, centrally, from a known set of sources. That is what makes the single commit claim true rather than decorative.

The branch model follows from this. Just like the development repositories, the VMR has a release branch for every feature band, for example release/10.0.1xx, and the main branch follows the default branches of the product repositories, using a synchronisation based on declared dependencies. A declared dependency is a statement that one product repository cannot be built without a particular version of another, and the sync uses those statements to decide what has to move together.

The end to end tests for the whole product are listed as future work, so the VMR is not yet the place where the entire .NET test suite runs. That is the single largest piece of the stated plan that has not arrived.

Where to make a change, and the eng/common trap

The contribution guidance is unusually explicit, because the answer depends on which directory you are in.

Under src/ you are in constituent repository territory, with the exception of VMR pipeline changes. Everything outside src/ is changed directly in the VMR. The root pipeline logic lives in eng/* and belongs in the VMR, and that is where VMR pipeline changes are expected to go.

Then there is the Arcade complication, and it is worth reading carefully because it is the kind of detail that wastes a day. There are many copies of eng/common in the VMR. The root eng/common/* is used to bootstrap the VMR build, and those copies should not be updated manually, only through a re-bootstrap of the VMR. A VMR build uses src/arcade/eng/common/* for Arcade and for any repository that builds after Arcade, and changes there may be made directly and will flow back into Arcade and into any repository that takes its Arcade flow from the VMR. The recommendation, however, is that the VMR should be used to test eng/common changes while the actual change is made in the dotnet/arcade repository.

The overall policy is that contribution to .NET should mostly still happen in the constituent repositories, for two reasons. The project wants to ramp up direct VMR changes slowly to avoid surprises, and the individual repositories still have the best validation for most changes.

For a cross-cutting change, the guidance is to ask the Unified Build team, tagging @dotnet/product-construction in an issue or discussion in your repository. A CODEOWNERS file, an AGENTS.md and a .config directory at the root make the ownership of those paths explicit.

Building the VMR, and the dependency Source-Build adds

The repository is explicitly flagged as a work in progress with usability issues attached, and the README names them: some checked-in files getting modified by the build itself, and similar nuisances. That sentence is the most important thing in the dev instructions, because it tells you that a dirty working tree after a build is expected rather than a mistake.

The build entry points are build.sh, build.cmd and build.proj at the root, and there is a .devcontainer directory for working inside a container, along with a prep-source-build.sh script and a prereqs/ directory holding the build prerequisites.

The dependency story has two layers. The base dependencies for building are documented in the runtime repository, on the requirements page linked from the README, and if you cannot prepare an environment that meets them the recommendation is to use Docker instead. On top of that, building the VMR with Source-Build adds one more requirement to a Linux environment:

bash
brotli-dev

The distinction between a source build and a non-source build is the one to understand. A source build compiles the whole .NET product from the sources in the repository, which is what distro builders need so their package contains the code they can patch. A non-source build uses prebuilt artifacts, which is faster and is what most people want. The supported platform table shows the split: for 8.0 and 9.0 the configuration is source-build on Linux, and for 10.0 and later, which is marked as work in progress, there is both a source-build configuration on Linux and a non-source-build configuration on Linux, Mac and Windows.

A .devcontainer plus a Docker fallback plus a Linux specific source-build path plus a Mac and Windows non-source-build path is a fair amount of surface area for a build, and the WIP warning explains why.

Three feature bands patched on the same afternoon

The recent releases show the servicing model in action. v10.0.402, tracking .NET 10.0.13, was published on 2026-10-13, followed by v9.0.122 for .NET 9.0.21 and v8.0.132 for .NET 8.0.32 on the same day, with the timestamps within about two hours of each other.

Three bands, three separate tags, one afternoon. That is the VMR doing exactly what it was created to do, since servicing a release means rebuilding the product from a specific set of sources and a single commit identifies that set. A multi-repository setup would produce the same binaries through a more error-prone path, with the set of commits living in a build manifest rather than in a branch.

The version numbers carry two pieces of information each. The .NET 10.0.13 part is the runtime and SDK patch level, and the 10.0.402 part is the SDK feature band, which is the same number that names the release branch, release/10.0.1xx. The band changes every few months, and the patch within a band is the thing that gets security and bug fixes.

The repository is not archived and the last push was on 2026-10-15, two days after those three tags. For a project of this size, that is a good sign of an active servicing cycle rather than a one off consolidation effort, and the fact that the release branches exist per band means the same structure continues to be maintained for every supported line.

MIT for the code, and a repository that admits its own rough edges

The licence is MIT, with the text in LICENSE.TXT at the root, and there is a separate THIRD-PARTY-NOTICES.txt for the bundled third party components. The code itself belongs to the various product repositories it mirrors, and each of those has its own community, which is precisely the point of the virtual arrangement. The MIT grant in this repository covers the VMR's own infrastructure, the build machinery and the mirrored layout, not a relicense of the mirrored product code.

The documentation is unusually candid for a project of this scale. The repository is called a work in progress, the usability issues are named rather than hinted at, the end to end tests are described as future work, the supported platform table marks 10.0 and later as work in progress, and the contribution guidance asks people to ramp up direct VMR changes slowly. That combination, a repository that says what it is not yet, is worth more than a repository that oversells.

For an engineer the practical question is which door to use. If you are building.NET, testing a fix across repositories, or shipping a distribution, the VMR is the answer and dotnet/source-build is the documentation. If you are fixing a bug in the runtime, dotnet/runtime is still where the work happens, and the VMR will pick it up when the local official build is promoted. Both doors exist, and the project is explicit about which one to use for what.

Editorial conclusion

Adopt dotnet/dotnet if you are a distribution builder, a partner who needs to build, test and modify .NET with your own infrastructure, or a team debugging a bug that spans several product repositories, since a single commit that builds the SDK is exactly what those scenarios need. Do not adopt it as your everyday development repository, because the project asks contributors to keep working in dotnet/runtime, dotnet/sdk and dotnet/aspnetcore where the validation is best. Verify three things first: that your feature band has a release branch, that your environment meets the build requirements linked from the runtime repository, and that you can accept the extra brotli-dev dependency if you intend to build with Source-Build on Linux. The last push was on 2026-10-15 and the last push is part of a pattern, since three SDK bands were patched on 2026-10-13.

Frequently asked questions

What is the .NET Virtual Monolithic Repository?

dotnet/dotnet is a mirror of the .NET product repositories, with the sources of each product repository synchronised into their own directories under src/, plus the tooling to build the whole .NET product from source on Linux. It is a mirror rather than a replacement for the product repositories.

How does code flow work in the .NET VMR?

It is two-way. Repositories flow their changes into the VMR when their local official builds are promoted, the VMR is checked in and built, and then the source changes and packages flow back into the constituent repositories through code flow pull requests.

Where should I make a change to the .NET VMR?

Most .NET contributions still go to the constituent repositories, and within the VMR, src/* belongs to the product repositories, non-src directories are changed directly in the VMR, and VMR pipeline logic lives in eng/*. For eng/common, test in the VMR but make the real change in dotnet/arcade.

Which .NET versions can be built from the VMR?

For 8.0 and 9.0 there is a source-build configuration on Linux. For 10.0 and later, marked as work in progress, there is a source-build configuration on Linux and a non-source-build configuration on Linux, Mac and Windows.

What extra dependency does a Source-Build of the VMR need?

On Linux, building the VMR with Source-Build requires brotli-dev in addition to the base build requirements, which are documented in the runtime repository. If you cannot prepare that environment, the README points to using Docker instead.

How often are .NET SDK releases produced from the VMR?

The repository is not archived, the last push was on 2026-10-15, and three SDK bands were patched on 2026-10-13: v10.0.402 for .NET 10.0.13, v9.0.122 for .NET 9.0.21 and v8.0.132 for .NET 8.0.32.

Official sources

  1. dotnet/dotnet on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dotnet-dotnet.svg)](https://hysenlabs.com/projects/dotnet-dotnet)

Was this useful?