From dotnet-skills
Using artifacts output layout. UseArtifactsOutput, ArtifactsPath, impact on CI and Docker.
How this skill is triggered — by the user, by Claude, or both
Slash command
/dotnet-skills:dotnet-artifacts-outputThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Reference guide for the .NET SDK artifacts output layout, which centralizes build outputs (`bin/`, `obj/`, `publish/`, `package/`) into a single `artifacts/` directory at the repo root. Available since .NET 8 as an opt-in feature. Recommended for new projects; evaluate tradeoffs before migrating existing projects.
Reference guide for the .NET SDK artifacts output layout, which centralizes build outputs (bin/, obj/, publish/, package/) into a single artifacts/ directory at the repo root. Available since .NET 8 as an opt-in feature. Recommended for new projects; evaluate tradeoffs before migrating existing projects.
Prerequisites: Run [skill:dotnet-version-detection] first to confirm .NET 8+ SDK -- artifacts output layout is not available in earlier SDK versions.
Scope boundary: [skill:dotnet-project-structure] covers source tree organization (.sln, .csproj, src/, tests/). This skill covers build output organization (artifacts/bin/, artifacts/obj/, artifacts/publish/). Source tree vs output tree.
Cross-references: [skill:dotnet-project-structure] for solution layout, [skill:dotnet-containers] for Dockerfile path adjustments, [skill:dotnet-gha-build-test] for CI artifact upload paths, [skill:dotnet-scaffold-project] for generating new projects with artifacts output enabled.
Traditional .NET build output scatters bin/ and obj/ directories throughout the source tree, one per project. The artifacts output layout consolidates all build outputs under a single artifacts/ directory next to Directory.Build.props.
Benefits:
.gitignore -- one artifacts/ entry replaces per-project bin/ and obj/ entriesbin//obj/ foldersTradeoffs:
bin/Debug/net10.0/ paths must be updatedAdd UseArtifactsOutput to your Directory.Build.props at the repo root:
<Project>
<PropertyGroup>
<UseArtifactsOutput>true</UseArtifactsOutput>
</PropertyGroup>
</Project>
Alternatively, generate a new Directory.Build.props with artifacts output pre-configured:
dotnet new buildprops --use-artifacts
This creates:
<Project>
<PropertyGroup>
<ArtifactsPath>$(MSBuildThisFileDirectory)artifacts</ArtifactsPath>
</PropertyGroup>
</Project>
Setting ArtifactsPath directly is equivalent to UseArtifactsOutput=true and additionally lets you customize the root directory location.
All build outputs are organized under artifacts/ with three levels: output type, project name, and pivot (configuration/TFM/RID).
artifacts/
bin/
MyApp/
debug/ # Single-targeted project
debug_net10.0/ # Multi-targeted project
release_linux-x64/ # RID-specific build
MyApp.Core/
debug/
obj/
MyApp/
debug/
publish/
MyApp/
release/ # dotnet publish output
release_linux-x64/ # RID-specific publish
package/
release/ # NuGet .nupkg files (no project subfolder)
| Directory | Contents | Traditional equivalent |
|---|---|---|
artifacts/bin/ | Compiled assemblies and dependencies | <project>/bin/ |
artifacts/obj/ | Intermediate build files, generated code | <project>/obj/ |
artifacts/publish/ | Published application output | <project>/bin/<config>/<tfm>/publish/ |
artifacts/package/ | NuGet packages (.nupkg, .snupkg) | <project>/bin/<config>/ |
The pivot subfolder combines configuration, TFM, and RID joined by underscores. Components that are not present are omitted:
| Scenario | Pivot | Full path example |
|---|---|---|
| Single-targeted, debug | debug | artifacts/bin/MyApp/debug/ |
| Multi-targeted, debug | debug_net10.0 | artifacts/bin/MyApp/debug_net10.0/ |
| Release, RID-specific | release_linux-x64 | artifacts/bin/MyApp/release_linux-x64/ |
| Package output | release | artifacts/package/release/ |
Note: artifacts/package/ omits the project name subfolder. The pivot includes only the configuration.
Set ArtifactsPath to change the root location:
<PropertyGroup>
<ArtifactsPath>$(MSBuildThisFileDirectory).output</ArtifactsPath>
</PropertyGroup>
This places all build outputs under .output/ instead of artifacts/.
Customize the pivot subfolder naming with ArtifactsPivots:
<PropertyGroup>
<ArtifactsPivots>$(ArtifactsPivots)_MyCustomPivot</ArtifactsPivots>
</PropertyGroup>
With artifacts output enabled, simplify .gitignore:
# Artifacts output layout (replaces per-project bin/ and obj/ entries)
artifacts/
This single entry replaces the traditional pattern:
# Traditional layout (no longer needed with artifacts output)
[Bb]in/
[Oo]bj/
If using a custom ArtifactsPath, update the .gitignore entry to match.
Multi-stage Dockerfiles that copy build output must reference the new path structure. See [skill:dotnet-containers] for full Dockerfile patterns.
Traditional paths:
COPY --from=build /app/src/MyApp/bin/Release/net10.0/publish/ .
Artifacts output paths:
COPY --from=build /app/artifacts/publish/MyApp/release/ .
Key differences in Dockerfile paths:
artifacts/publish/ not bin/Release/<tfm>/publish/release not Release)CI workflows that upload build artifacts or reference output paths must be updated. See [skill:dotnet-gha-build-test] for full CI workflow patterns.
GitHub Actions -- upload build output:
- name: Publish
run: dotnet publish src/MyApp/MyApp.csproj -c Release
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: app
path: artifacts/publish/MyApp/release/
GitHub Actions -- upload NuGet packages:
- name: Pack
run: dotnet pack -c Release
- name: Upload packages
uses: actions/upload-artifact@v4
with:
name: packages
path: artifacts/package/release/*.nupkg
Azure DevOps -- publish artifacts:
- script: dotnet publish src/MyApp/MyApp.csproj -c Release
displayName: 'Publish'
- task: PublishPipelineArtifact@1
inputs:
targetPath: 'artifacts/publish/MyApp/release/'
artifact: 'app'
When enabling artifacts output on an existing project:
UseArtifactsOutput to Directory.Build.props.gitignore -- replace [Bb]in/ and [Oo]bj/ with artifacts/COPY --from=build paths to use artifacts/ structurebin/ or obj/ pathsbin/ and obj/ directories from all projectsdotnet build and dotnet publish to confirm output appears under artifacts/dotnet test to confirm test execution with new pathsdebug), not debug_net10.0. Multi-targeted projects include the TFM in the pivot.debug, release), not the traditional capitalized names (Debug, Release).artifacts/package/ has a project name subfolder. Unlike bin/, obj/, and publish/, the package/ output type omits the project name level. Packages appear directly under artifacts/package/<config>/.COPY --from=build directives and artifact upload steps that reference traditional bin/ paths.npx claudepluginhub wshaddix/dotnet-skillsPublishing .NET artifacts from Azure DevOps. NuGet push, containers to ACR, pipeline artifacts.
Containerizes .NET 10 apps using the SDK's built-in container publishing feature — no Dockerfile needed. Handles MSBuild properties, chiseled images, multi-arch builds, and registry publishing.
Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.