Nothing. It ships with Murage, which is open source. Your bots run on the AI plan you already have.
Can I change it?+
Yes. Open it in Settings → Skills to read, edit or duplicate it. Skill Guard scans it again after every edit.
Give your first job to Murage.
Download the app, connect the AI you already pay for, and tell your Chief of Staff what needs doing. Plan on about ten minutes from install to a working team.
User asks about Directory.Build.props, Directory.Build.targets, or Directory.Packages.props for centralized configuration
User asks about NuGet configuration -- NuGet.Config, nuget.config, Central Package Management (CPM), or package source mapping
User asks how to configure SDK-style .csproj files, target framework monikers, or multi-targeting
User asks about .NET 8 or .NET 9 project templates, implicit usings, nullable reference types, or global.json
User asks about global.json SDK pinning, build properties, or repository-level MSBuild conventions
User asks how to configure a project for NuGet package publishing, SourceLink, deterministic builds, or package metadata
Do NOT use this skill when:
User asks about C# language features, pattern matching, records, or modern idioms -- use csharp-modern-idioms
User asks about writing unit tests, test project setup, xUnit, NUnit, or Moq -- use csharp-testing-patterns
User asks about ASP.NET Core Minimal API, controllers, middleware, or Blazor -- use csharp-aspnet-patterns
User asks about Docker or Kubernetes deployment of a .NET app -- use a container deployment skill
User asks about GitHub Actions, Azure Pipelines, or CI/CD pipeline configuration specifically -- use a CI/CD skill
User asks about Entity Framework Core migrations or database modeling -- use a data-access skill
User asks about .NET MAUI, Xamarin, or mobile project setup -- outside scope of this skill
Process
1. Assess Project Context and Choose the Right Template
Before generating any configuration, gather these critical dimensions:
Project type: Library (classlib), console app (console), worker service (worker), web API (webapi), gRPC service (grpc) -- each has different <OutputType> and SDK values
Deployment target: Is this a NuGet package, a self-contained executable, a framework-dependent app, or an AOT-compiled binary?
Mono-repo vs. standalone: A monorepo with 3+ projects warrants Directory.Build.props; a single project does not need it
Target framework: Default to net8.0 for LTS, net9.0 for current. Use net8.0;net9.0 only when the library must support both. Never use netstandard2.0 for new libraries unless targeting legacy consumers requiring .NET Framework compatibility
Team size: Solo projects can use loose conventions; team projects must encode conventions in MSBuild properties and .editorconfig
SDK version pinning: Always determine whether the repo needs a global.json -- required when CI must reproduce builds exactly or when multiple SDK versions coexist on developer machines
Run dotnet --version to confirm the installed SDK. Use dotnet new list to see all available templates.
2. Initialize the Solution and Project Structure
Follow this canonical layout for any project beyond a single file:
Create the solution file first: dotnet new sln -n MyRepo
Create projects: dotnet new classlib -n MyRepo.Core -o src/MyRepo.Core
Add projects to solution: dotnet sln MyRepo.sln add src/MyRepo.Core/MyRepo.Core.csproj
Repeat for all projects. Never add test projects to the src/ directory -- keep them in tests/
The solution file is a human-readable grouping file; all real configuration lives in .csproj and Directory.Build.props
Use solution folders (dotnet sln add --solution-folder) to visually group src, tests, and samples in Visual Studio and Rider
3. Author the SDK-Style .csproj File
An SDK-style .csproj is declarative and minimal. Avoid the verbose legacy format:
xml
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AnalysisLevel>latest-recommended</AnalysisLevel>
</PropertyGroup>
<ItemGroup>
<!-- Project references use relative paths -->
<ProjectReference Include="..\..\src\MyRepo.Core\MyRepo.Core.csproj" />
</ItemGroup>
<ItemGroup>
<!-- Package versions come from Directory.Packages.props if using CPM -->
<PackageReference Include="Serilog" Version="3.1.1" />
</ItemGroup>
</Project>
Key property decisions:
<Nullable>enable</Nullable> -- mandatory for all new projects. Nullable reference types eliminate entire classes of null-dereference bugs
<ImplicitUsings>enable</ImplicitUsings> -- adds a generated GlobalUsings.g.cs with System, System.Collections.Generic, System.Linq, etc. Do not fight this feature; add additional global usings in a GlobalUsings.cs file
<LangVersion>latest</LangVersion> -- tracks the latest stable C# version for the SDK. Use preview only for experimental work
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> -- critical for team projects; forces nullable warnings and analyzer warnings to be resolved
<AnalysisLevel>latest-recommended</AnalysisLevel> -- enables Roslyn analyzers without requiring a separate analyzer package. Options: none, default, latest, latest-recommended, latest-all
<OutputType>Exe</OutputType> -- only required for console apps and workers. Libraries omit this; it defaults to Library
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> -- only in projects that explicitly require unsafe pointer operations
4. Configure Directory.Build.props for Centralized Properties
Directory.Build.props is evaluated by MSBuild before any .csproj file in the same directory or any subdirectory. Place it at the repository root to apply properties globally:
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> -- causes .editorconfig style rules (IDE diagnostics) to fire as build errors, not just IDE squiggles
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild> -- required for SourceLink to embed correct paths into PDB files; set conditionally on the CI environment variable
Use a <PropertyGroup Condition="..."> to vary behavior for src/ vs. tests/ projects by checking $(MSBuildProjectFullPath.Contains('tests'))
Directory.Build.props is not recursive-override -- a project-level .csproj can override any property defined here. This is by design
Directory.Build.targets is evaluated after .csproj, making it appropriate for targets that enforce post-build checks or file manipulation
5. Configure NuGet and Central Package Management
For repositories with 3 or more projects, Central Package Management (CPM) eliminates version drift across projects:
Directory.Packages.props (repository root):
xml
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<!-- DisableCentralPackageVersions can be set per-project to opt out -->
</PropertyGroup>
<ItemGroup>
<!-- Versions declared once, referenced without version in .csproj -->
<PackageVersion Include="Serilog" Version="3.1.1" />
<PackageVersion Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageVersion Include="FluentValidation" Version="11.9.0" />
<PackageVersion Include="Polly" Version="8.3.0" />
</ItemGroup>
<!-- Test-only packages kept separate for clarity -->
<ItemGroup Label="Test">
<PackageVersion Include="xunit" Version="2.8.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
<PackageVersion Include="NSubstitute" Version="5.1.0" />
</ItemGroup>
</Project>
In each .csproj with CPM enabled, omit Version from <PackageReference>:
xml
<PackageReference Include="Serilog" /> <!-- version resolved from Directory.Packages.props -->
NuGet.Config -- required when using a private feed or package source mapping:
rollForward: "latestMinor" means the SDK will roll forward to the latest patch and minor within the major version. Use "patch" for maximum reproducibility, "latestMinor" for a balance of flexibility and stability
allowPrerelease: false prevents accidental use of preview SDKs in production builds
Run dotnet --list-sdks to enumerate installed versions. Update global.json intentionally when upgrading the SDK
In CI, explicitly install the exact SDK version matching global.json using the setup-dotnet action or UseDotNet task
7. Configure .editorconfig for Code Style and Roslyn Analyzers
.editorconfig is the single source of truth for both formatting and code-style diagnostic severity. Place it at the repository root:
Never use <PackageReference> with floating versions (*, 1.2.*, [1.0,2.0)). Pin exact versions in Directory.Packages.props or in the .csproj. Floating versions cause non-reproducible builds and can pull in breaking changes silently.
Never target netstandard2.0 for new libraries unless the library must be consumed by .NET Framework 4.6.1+ projects. For libraries targeting only modern .NET, use net8.0 or multi-target net8.0;net9.0. netstandard2.0 loses access to 5+ years of API surface and forces polyfills.
Never place <Version> in Directory.Build.props for libraries intended for NuGet publication. Version must be set by CI using dotnet pack -p:Version=$(GitVersion) or a MinVer/GitVersion integration. A hardcoded version in shared props means every package publishes the same version.
Always set <Nullable>enable</Nullable> from the first commit. Retrofitting nullable annotations onto an existing codebase with thousands of #nullable disable suppressions is a multi-week project. Starting clean costs nothing.
Always use <TreatWarningsAsErrors>true</TreatWarningsAsErrors> in Directory.Build.props. Teams that leave warnings as warnings accumulate hundreds of unaddressed warnings within months, rendering the warning system useless. If a rule produces false positives, suppress it explicitly in .editorconfig with a comment justifying the suppression.
Never commit bin/, obj/, or the NuGet cache to source control. These directories contain binary outputs and machine-specific paths. The project.assets.json inside obj/ contains absolute paths that will break other developers' builds.
Always use file-scoped namespaces for all new C# 10+ code.namespace MyRepo.Core; instead of namespace MyRepo.Core { ... } reduces indentation by one level for the entire file. Enforce this via .editorconfig: csharp_style_namespace_declarations = file_scoped:error.
Never add <GenerateAssemblyInfo>false</GenerateAssemblyInfo> as a blanket workaround. This property disables auto-generation of AssemblyInfo.cs attributes. It is sometimes used to fix conflicts with a legacy AssemblyInfo.cs file -- but the correct fix is to delete the legacy file, not to disable generation.
Always use <ArtifactsPath> or an explicit output directory in CI rather than relying on per-project bin/ directories. This makes artifact collection in CI trivial and avoids hunting for outputs across subdirectories.
Never mix SDK styles in the same solution. A solution should not combine legacy non-SDK .csproj files (the verbose format from before .NET Core) with SDK-style projects. The two formats differ fundamentally in how they handle wildcards, transitive references, and implicit items. If a legacy project must remain, isolate it or migrate it.
Edge Cases
Multi-targeting for Library Compatibility
When a library must support both net8.0 and netstandard2.0 (for legacy consumers), use conditional compilation:
#if NET8_0_OR_GREATER
// Use System.Text.Json source generation
#elif NETSTANDARD2_0
// Use Newtonsoft.Json fallback
#endif
Be aware that multi-targeting multiplies build time. A project with 3 target frameworks builds 3 times. In a solution with 10 such projects, build time is 30x the single-framework cost. Only multi-target when the library is genuinely consumed by diverse consumers.
Projects That Must Opt Out of Global Properties
Some projects -- particularly generated code projects, scaffolded EF Core migration projects, or vendored third-party code -- cannot satisfy global constraints like TreatWarningsAsErrors. Override at the project level:
xml
<PropertyGroup>
<!-- This is generated code; global warning-as-error policy does not apply -->
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);CS1591;CS8618</NoWarn>
</PropertyGroup>
Alternatively, use a second Directory.Build.props placed inside the subdirectory containing these projects. MSBuild walks up the directory tree and stops at the first Directory.Build.props it finds -- so a nested file in src/Generated/Directory.Build.props can override the root file for only those projects.
Native AOT and Trimming
When the target is a Native AOT executable (.NET 8+), the project must enable trimming-compatible code patterns:
AOT imposes significant constraints: no runtime reflection, no dynamic, no Assembly.Load. Dependencies must be AOT-compatible. Run dotnet publish -r linux-x64 -c Release early and often to catch trimming warnings before they accumulate.
Enterprise Private NuGet Feed Without Internet Access
In air-gapped or enterprise environments where nuget.org is unreachable:
Also, set NUGET_PACKAGES environment variable in CI to a shared cache directory to avoid redundant downloads across agents. Use dotnet restore --locked-mode after an initial dotnet restore that generates packages.lock.json to guarantee package identity in CI.
Incremental Migration from Legacy .csproj Format
When migrating a Visual Studio 2015-era .csproj file to SDK style:
Create a new SDK-style .csproj alongside the old one in a branch
Remove all <Compile Include="..."> entries -- SDK style includes all *.cs files by default
Remove all <Reference> entries to BCL assemblies (System, System.Core, etc.) -- SDK style handles these via the target framework
Retain <Reference> entries for COM interop and non-NuGet assemblies
Migrate packages.config to <PackageReference> using dotnet migrate or the Visual Studio migration wizard
Delete packages.config and the packages/ directory from the repository
Verify that no AssemblyInfo.cs attributes conflict with SDK-generated ones ([assembly: AssemblyVersion], [assembly: AssemblyTitle], etc.) -- either delete the file or set <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
NuGet Package Publishing Configuration
When a library project will be published to NuGet.org or a private feed, the .csproj must include package metadata:
xml
<PropertyGroup>
<IsPackable>true</IsPackable>
<PackageId>Acme.MyRepo.Core</PackageId>
<!-- Version set by CI, not here: dotnet pack -p:Version=1.2.3 -->
<Description>Core abstractions for the MyRepo library.</Description>
<PackageTags>acme;myrepo;core</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageProjectUrl>https://github.com/acme/myrepo</PackageProjectUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<!-- SourceLink: embed source in symbols for debugger step-through -->
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
</PropertyGroup>
<ItemGroup>
<None Include="../../README.md" Pack="true" PackagePath="/" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>
Set <IsPackable>false</IsPackable> explicitly on all test projects and sample projects to prevent accidental packaging.
Example
Input: "I'm starting a new .NET 8 open-source library called Conduit that will be published to NuGet.org. It has a core abstractions project, an implementation project, and tests. I want strict nullable checking, centralized package management, and a clean project structure."
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>true</IsPackable>
<PackageId>Conduit.Abstractions</PackageId>
<!-- Version is set by CI: dotnet pack -p:Version=$(VERSION) -->
<Description>Core interfaces and abstractions for the Conduit pipeline library.</Description>
<PackageTags>conduit;pipeline;abstractions;mediator</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageProjectUrl>https://github.com/acme/conduit</PackageProjectUrl>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
</PropertyGroup>
<ItemGroup>
<None Include="..\..\README.md" Pack="true" PackagePath="/" />
<!-- PrivateAssets=All: SourceLink is a build-time tool, not a runtime dep -->
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
</ItemGroup>
</Project>
// Global usings for Conduit.Abstractions
// System.* usings are provided by ImplicitUsings; add domain-specific usings here.
global using System.Threading;
global using System.Threading.Tasks;
Decisions Log
Decision
Choice
Rationale
Target framework
net8.0 only
LTS release; no .NET Framework consumers identified; avoids multi-target
Nullable reference types
enabled (error severity)
OSS library must have airtight null safety before consumers depend on it
Central Package Management
enabled
3 projects sharing test dependencies; prevents version drift
TreatWarningsAsErrors
true
Enforces nullable and analyzer compliance; required for quality OSS
SourceLink
GitHub / snupkg
Enables debugger step-through for library consumers without source access
File-scoped namespaces
enforced via .editorconfig
C# 10+ standard; reduces indentation; consistent with modern OSS projects
Version location
CI-injected (-p:Version=...)
Prevents accidental publish of hardcoded version; enables GitVersion/MinVer
NuGet.Config with <clear />
yes
Prevents implicit machine-level feed injection in CI environments
EnforceCodeStyleInBuild
true
.editorconfig violations become build errors, not silent IDE suggestions
GenerateDocumentationFile
true
Produces XML docs for IntelliSense in downstream consumers