Generated banner for Item Management
Generated logo for Item Management

Item Management

.NET (Microsoft)OfficialPublished by .NET (Microsoft)

  • Skill
  • Tool integration
  • Software development
  • MIT
  • No issues found

From the author

Own concrete MSBuild ItemGroup and item-expression questions. USE FOR: Include, Remove, Update, item identity and metadata, transforms, filtering, batching, duplicate or overlapping items, and reviews that verify whether those operations are correct. Generated items stay in scope when the central defect is item identity, metadata, batching, duplicate declarations, or glob/Remove/Update semantics. For a generated artifact missing from compilation or output, wrong target timing/path, or FileWrites clean tracking without a broader item-semantics defect, use including-generated-files. The item operation may be broken, suspected, or already correct. Exclude property-only issues, general incrementality with no item question, broad reviews with no concrete item concern, and non-MSBuild systems.
— the description by .NET (Microsoft)

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a structured reference for working with MSBuild items. It covers the core operations of Include, Remove, and Update, explains the mechanics of item batching using metadata, and details how to use item transforms. It also addresses common pitfalls such as cross-product batching and proper file management within the build lifecycle to ensure clean builds and maintainable project files.

What it does

  • Explains the distinct roles of Include, Remove, and Update operations in ItemGroups.
  • Demonstrates how to use metadata batching for target-level and task-level execution.
  • Provides patterns for item transforms to manipulate file paths and display lists.
  • Outlines best practices for conditional item inclusion and package asset management.
  • Identifies common pitfalls like cross-product batching and source tree pollution.
  • Highlights the necessity of tracking generated files in FileWrites for clean builds.

When to use it

  • When defining or modifying file collections in MSBuild project files.
  • When you need to perform operations on items based on specific metadata values.
  • When troubleshooting duplicate items or incorrect file inclusion/exclusion logic.
  • When optimizing build targets to run per-item or per-metadata group.
  • When ensuring generated files are correctly tracked for cleanup.

Advantages

  • Standardizes MSBuild item management to reduce build errors.
  • Provides clear examples for complex operations like set subtraction and metadata batching.
  • Helps prevent common performance issues like unintended cross-product batching.
  • Promotes clean build practices by emphasizing proper output directory usage.

Usage examples

“How do I modify metadata for existing items in an ItemGroup without re-adding them?”
Use the Update operation, which allows you to target existing items by their group name and apply metadata changes conditionally.
“Why is my build task running multiple times for every file?”
You are likely using metadata batching in a task parameter. The task will execute once for every unique value of the metadata specified.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/dotnet/item-management/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip item-management.zip -d .agents/skills

Documentation by .NET (Microsoft)

MSBuild Item Management Patterns

Canonical patterns for working with item groups, from Microsoft.Common.CurrentVersion.targets.

Include / Remove / Update — Three Operations

OperationPurposeWhen to use
IncludeAdd new items to the groupCreating items with identity + metadata
RemoveRemove items matching a patternExcluding files or clearing a group
UpdateModify metadata on existing itemsAdding/changing metadata without re-adding
Include — Add Items
<ItemGroup>
  <Compile Include="Generated\*.cs">
    <AutoGen>true</AutoGen>
  </Compile>
</ItemGroup>
Remove — Subtract Items
<ItemGroup>
  <!-- Remove specific items -->
  <Reference Remove="$(AdditionalExplicitAssemblyReferences)" />

  <!-- Set subtraction: prior minus current -->
  <_CleanOrphanFileWrites Include="@(_CleanPriorFileWrites)"
      Exclude="@(_CleanCurrentFileWrites)" />

  <!-- Clear an entire group -->
  <_Temporary Remove="@(_Temporary)" />
</ItemGroup>
Update — Modify Existing Items
<ItemGroup>
  <EmbeddedResource Update="@(EmbeddedResource)"
      Condition="'%(NuGetPackageId)' == 'Microsoft.CodeAnalysis.Collections'">
    <GenerateSource>true</GenerateSource>
    <ClassName>Microsoft.CodeAnalysis.Collections.SR</ClassName>
  </EmbeddedResource>
</ItemGroup>

Update does not add items — it only modifies items already in the group.

Item Batching — %(Metadata)

When %(Metadata) appears in target attributes or task parameters, MSBuild batches execution per unique metadata value.

Target-level batching (Outputs)
<Target Name="GenerateSatelliteAssemblies"
    Inputs="$(MSBuildAllProjects);@(_SatelliteAssemblyResourceInputs)"
    Outputs="$(IntermediateOutputPath)%(Culture)\$(TargetName).resources.dll">
  <!-- Runs once per unique Culture value -->
</Target>
Task-level batching
<Copy SourceFiles="@(_SourceItems)"
    DestinationFiles="@(_SourceItems->'$(OutDir)%(TargetPath)')">
</Copy>
Per-item filtering with Condition
<ItemGroup>
  <_ResxOutput Include="@(EmbeddedResource->'%(OutputResource)')"
      Condition="'%(EmbeddedResource.WithCulture)' == 'false'" />
</ItemGroup>
Batching rules
  • %(Metadata) in Condition or Outputs → target batches per unique value.

  • %(Metadata) in task parameters → task batches per unique value.

  • Do not mix %() from different item groups in the same expression — this causes a cross-product (see Common Pitfalls).

Item Transforms — @(Item->'expression')

Transforms create new item lists by applying an expression to each item:

<!-- Transform file paths to destinations -->
<Copy SourceFiles="@(IntermediateAssembly)"
    DestinationFiles="@(IntermediateAssembly->'$(OutDir)%(Filename)%(Extension)')"/>

<!-- Transform with separator for display -->
<Message Text="Files: @(Compile->'%(Filename)', ', ')" />

Exclude Pattern — Set Subtraction on Include

<ItemGroup>
  <Compile Include="**\*.cs" Exclude="Generated\**;Tests\**" />
</ItemGroup>

Exclude only works on Include — it cannot be used with Update or Remove.

Conditional Item Inclusion

<!-- Condition on ItemGroup — all or nothing -->
<ItemGroup Condition="'$(NetCoreBuild)' == 'true'">
  <PackageReference Include="System.IO.Pipelines" />
</ItemGroup>

<!-- Condition on individual items -->
<ItemGroup>
  <PackageReference Include="System.IO.Pipelines"
      Condition="'$(NetCoreBuild)' == 'true'" />
</ItemGroup>

PrivateAssets on Tool/Analyzer Packages

<ItemGroup>
  <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" PrivateAssets="all" />
  <PackageReference Include="StyleCop.Analyzers" PrivateAssets="all" />
</ItemGroup>

Common Pitfalls

Cross-product batching

Referencing %(Metadata) from two different item groups creates O(N×M) executions:

<!-- BAD: Cross-product of @(Source) × @(Config) -->
<Exec Command="process %(Source.Identity) with %(Config.Identity)" />

<!-- GOOD: Reference one group via batching, the other via property -->
<Exec Command="process %(Source.Identity) with $(ConfigFile)" />
Generated files in source tree

Write to $(IntermediateOutputPath) (obj/), not the source directory. Source-tree generation pollutes version control and can cause duplicate compilation via globs.

Missing FileWrites

Every file created during a target must be added to @(FileWrites) for dotnet clean support.

Files

LICENSE

The MIT License (MIT)

Copyright (c) .NET Foundation and Contributors

All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
.NET (Microsoft)
Publisher
.NET (Microsoft) (Official)
Source
dotnet/skills · plugins/dotnet-msbuild/skills/item-management · commit 96c3d68
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by .NET (Microsoft).

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download item-management.zip