Depos

Dependency notes for .NET

A PackageReference records a package ID and a version. It does not say why the package is there, which framework upgrade it is waiting for, or which packages have to move with it. An XML comment has room for a phrase, and it stays in the one project file that has it.

Depos keeps a note for each package in .depos/nuget/DEPENDENCY-NOTES.md and shows it on the package's line. C#, F# and Visual Basic projects are read alike, and under central package management the versions in Directory.Packages.props are read too, keyed by the same package ID.

What Depos reads

  • Manifest: *.csproj, *.fsproj, *.vbproj, Directory.Packages.props
  • Notes file: .depos/nuget/DEPENDENCY-NOTES.md
  • Section heading: the case-insensitive package ID as written: ## Newtonsoft.Json

Depos reads literal PackageReference Include items in C#, F# and VB project files; and PackageVersion Include/Update plus GlobalPackageReference Include items in Directory.Packages.props. Package IDs are matched case-insensitively. Imports, MSBuild expressions, project/framework references, downloads and transitive packages are not evaluated.

Depos never runs .NET, MSBuild or NuGet, so it needs no SDK and restores nothing.

Example

<ItemGroup>
  <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
  <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
  <PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
</ItemGroup>

.depos/nuget/DEPENDENCY-NOTES.md:

## Microsoft.EntityFrameworkCore

Stay on 8 until the API moves to .NET 9 (PLAT-212).

### Agent notes

- purpose: ORM for the orders database
- constraint: keep the major equal to the target framework (net8.0)
- bump-with: Npgsql.EntityFrameworkCore.PostgreSQL
- verify: `dotnet test` and `dotnet ef database update` on an empty database
- verified: 8.0.11

The heading is the package ID as the project file writes it; IDs are matched without regard to case.

Comments in .csproj files

<ItemGroup>
  <!-- EF Core: keep the major equal to the target framework -->
  <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
  <PackageReference Include="Serilog.AspNetCore" Version="8.0.3" /> <!-- structured request logs -->
</ItemGroup>

A project file is XML, so a comment is <!-- … -->, and MSBuild ignores what is inside it: a PackageReference in a comment is not restored. A comment cannot contain --. With <!-- CI restores with --locked-mode --> in it, dotnet restore fails with MSB4025: … An XML comment cannot contain '--'.

dotnet add package keeps the comments, but not where they belong: it inserts a new reference in name order, which can put it between a comment and the reference below it. dotnet remove package leaves the removed reference's comment behind, and when dotnet add package changes a version in place, the comment beside it stays word for word. .NET 10 introduced the names dotnet package add and dotnet package remove for the same commands.

Pinning a version

Version="8.0.11" means 8.0.11 or higher, and NuGet restores the lowest version that satisfies the requirements: 8.0.11, even when a newer one is on the feed. Version="[8.0.11]" accepts that version only.

Under central package management, the versions sit in Directory.Packages.props as <PackageVersion Include="…" Version="…" /> and take the same ranges; a project can still override one with VersionOverride, and a floating version such as 8.0.* is not allowed there. With <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>, restore writes packages.lock.json, and dotnet restore --locked-mode fails once a reference no longer matches it.

None of these says why a version is held. The constraint: line in the example above does: it keeps EF Core's major equal to the target framework.

Editors

The notes file is the same in all three, so one team can mix them: Visual Studio 2022 and newer on Windows, Rider and other JetBrains IDEs, and VS Code. In Visual Studio the note shows in Quick Info on the package ID, the Depos mark beside it opens the note, and Tools → Options → Depos holds the settings.

For AI coding agents

An agent reads a package's section before it adds, upgrades or removes the package. bump-with: lists the packages that have to move with it, and verify: the tests to run afterwards. See the rules agents follow.