A package stack manager and safe update engine for .NET.
Dotkiln helps .NET developers define, reuse, apply, check, and safely update curated NuGet package stacks. Instead of remembering the same set of packages for every new project, you describe that set once in a .dotkiln.yaml file and let Dotkiln apply it consistently.
Starting a new .NET project often means repeating the same setup:
- add logging
- add validation
- add Entity Framework Core
- add API documentation
- add test packages
- remember which package versions work together
That is tedious when creating a new project, and it becomes worse later when packages need updates. Standard dependency bots usually open one pull request per package, even when several packages should move together. Entity Framework Core packages, for example, are much safer to update as one group than as separate, unrelated changes.
Dotkiln treats a dependency baseline as a versioned stack: a small, readable file that says which packages belong together and which groups must be updated together.
Dotkiln can:
- validate stack files before they are used
- apply a stack to a new or existing
.NETproject - show drift between a project and a stack
- report extra packages separately as informational output
- suppress project-specific extra packages with
.dotkilnignore - group related packages during update planning
- run updates in isolation so failed updates do not touch the real project
- search and publish stack files through a local/registry-style workflow
- output human-readable text or JSON for CI automation
A stack is a .dotkiln.yaml file:
schemaVersion: "0.1"
name: aspnet-webapi-standard
description: Opinionated baseline for a production ASP.NET Core minimal API
targetFramework: net8.0
packages:
- id: Serilog.AspNetCore
version: "8.0.*"
group: logging
- id: Serilog.Sinks.Console
version: "6.*"
group: logging
- id: Microsoft.EntityFrameworkCore.SqlServer
version: "8.0.*"
group: ef-core
- id: Microsoft.EntityFrameworkCore.Tools
version: "8.0.*"
group: ef-coreThe group field matters. Packages in the same group are treated as one update unit, so related dependencies move together.
Install Dotkiln from NuGet:
dotnet tool install --global Elehko.Dotkiln.CliThe examples below use stack files and sample projects from this repository. Run them from the repository root:
cd C:\path\to\DotkilnValidate one of the built-in stacks:
dotkiln validate stacks/aspnet-webapi-standard.dotkiln.yamlCheck whether a project matches a stack:
dotkiln status stacks/aspnet-webapi-standard.dotkiln.yaml samples/TestApp/TestApp.csprojPreview applying a stack:
dotkiln apply stacks/aspnet-webapi-standard.dotkiln.yaml samples/TestApp/TestApp.csproj --dry-runRun grouped update planning in dry-run mode:
dotkiln update stacks/aspnet-webapi-standard.dotkiln.yaml samples/TestApp/TestApp.csproj --group ef-core --dry-runStart with a normal project that has one package from the stack and one project-specific package:
<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.3" />
<PackageReference Include="AutoMapper" Version="13.0.1" />
</ItemGroup>Run status:
dotkiln status stacks/aspnet-webapi-standard.dotkiln.yaml MyApp.csprojDotkiln separates real stack drift from informational extras:
Stack: aspnet-webapi-standard
api-docs drift detected
missing Swashbuckle.AspNetCore (missing) -> 6.*
ef-core drift detected
missing Microsoft.EntityFrameworkCore.SqlServer (missing) -> 8.0.*
missing Microsoft.EntityFrameworkCore.Tools (missing) -> 8.0.*
logging drift detected
missing Serilog.Sinks.Console (missing) -> 6.*
validation drift detected
missing FluentValidation.AspNetCore (missing) -> 11.*
Extra packages not in stack (informational):
AutoMapper 13.0.1
Drift detected. 1 extra packages found (not flagged).
The missing stack packages are drift. AutoMapper is visible, but it is not treated as a failure because it is outside the stack's promise.
Preview the fix:
dotkiln apply stacks/aspnet-webapi-standard.dotkiln.yaml MyApp.csproj --dry-runExample preview:
Would run: dotnet add "C:\repo\MyApp\MyApp.csproj" package Serilog.Sinks.Console --version 6.*
Would run: dotnet add "C:\repo\MyApp\MyApp.csproj" package FluentValidation.AspNetCore --version 11.*
Would run: dotnet add "C:\repo\MyApp\MyApp.csproj" package Microsoft.EntityFrameworkCore.SqlServer --version 8.0.*
Would run: dotnet add "C:\repo\MyApp\MyApp.csproj" package Microsoft.EntityFrameworkCore.Tools --version 8.0.*
Would run: dotnet add "C:\repo\MyApp\MyApp.csproj" package Swashbuckle.AspNetCore --version 6.*
Run without --dry-run when ready. Dotkiln uses dotnet add package, so the project file is modified by the .NET SDK rather than by custom XML editing.
For projects using Central Package Management, Dotkiln keeps project references versionless and writes resolved versions to the nearest Directory.Packages.props file instead.
To hide project-specific extra packages from the informational report, add a .dotkilnignore file next to the project:
# .dotkilnignore
AutoMapper
After that, AutoMapper will no longer appear in the extra-package section.
Dotkiln is published as a .NET global tool on NuGet:
dotnet tool install --global Elehko.Dotkiln.CliPackage page:
After installation, run commands with:
dotkiln <command>To update an existing global-tool install:
dotnet tool update --global Elehko.Dotkiln.CliDuring local development, you can still run the CLI from source:
dotnet run --project src/Elehko.Dotkiln.Cli -- <command>Stack paths are resolved relative to your current directory. For example, stacks/aspnet-webapi-standard.dotkiln.yaml works when you run it from this repository root. In another project, pass the path to a stack file in that project or use an absolute path.
| Command | Purpose |
|---|---|
validate <stack> |
Parse and validate a stack file. |
new <stack> <project-name> |
Create a new .NET project and apply a stack. |
apply <stack> [project.csproj] |
Add or update direct package references from a stack. Uses Directory.Packages.props when Central Package Management is present. |
status <stack> [project.csproj] |
Show drift between the project and the stack. |
update <stack> [project.csproj] [--group name] |
Apply grouped updates in an isolated workspace and verify them. |
registry search <term> |
Search local/registry stack definitions. |
registry publish <stack-file> |
Publish a validated stack file into a registry directory. |
Every mutating command supports:
--dry-runMutating apply and update commands require a clean git working tree by default. Use --force to override this guard.
Every command supports:
--jsonDotkiln is designed around a conservative update workflow.
When running update, Dotkiln:
- groups packages by the stack's
groupfield - creates an isolated workspace
- applies package updates inside that workspace
- runs
dotnet build - runs discovered test projects when present
- reports success or writes a failure log
If verification fails, the real project branch is not modified by the update workflow.
For mutating commands, Dotkiln also checks git first. If the working tree has uncommitted changes, apply and update stop before making changes:
The git working tree has uncommitted changes.
Dotkiln relies on git for rollback safety and will not modify files
while uncommitted changes are present.
Commit or stash your changes, or re-run with --force to proceed anyway
(not recommended).
This keeps rollback simple: commit or stash first, run Dotkiln, inspect git diff, and use normal git commands if you want to undo the result.
Dotkiln supports:
- exact versions, such as
8.0.30 - wildcard versions, such as
8.0.*or6.* - basic NuGet-style ranges, such as
[8.0.0,9.0.0)
Prerelease versions are excluded by default for wildcard and range expressions. A stack must explicitly request a prerelease version to allow one.
| Path | Purpose |
|---|---|
src/Elehko.Dotkiln.Core |
Stack models, parsing, validation, and version matching. |
src/Elehko.Dotkiln.Engine |
Project inspection, status calculation, NuGet resolution, and apply execution. |
src/Elehko.Dotkiln.Updates |
Grouped update planning, isolation, and verification. |
src/Elehko.Dotkiln.Cli |
Command-line entry point. |
src/Elehko.Dotkiln.Registry.Api |
Optional lightweight stack registry API. |
tests/Elehko.Dotkiln.Core.Tests |
Unit tests for core behavior and update planning. |
stacks |
Built-in example stack definitions. |
samples |
Sample projects used for local testing and demos. |
docs |
Guides and architecture decision records. |
- Getting started
- Stack schema
- Writing a stack
- Versioning rules
- Drift detection
- Apply behavior
- Update behavior
- Package groups
- CLI reference
- JSON output
- Dry-run output
- Ignore and exclusion rules
- Safety and recovery
- URL stack sources and caching
- Registry workflows
- CI/CD examples
- Migration guide
- FAQ
Dotkiln is early-stage software. The local stack workflow is implemented, including validation, apply, status, grouped update planning, isolation, and build/test verification.
Still planned:
- production registry authentication and storage
- GitHub pull request creation for verified updates
- broader integration and end-to-end test coverage
- migration from custom CLI parsing to
System.CommandLine
Build everything:
dotnet build Dotkiln.slnRun tests:
dotnet test Dotkiln.slnRun the CLI from source:
dotnet run --project src/Elehko.Dotkiln.Cli -- --helpContributions are welcome. Start with CONTRIBUTING.md, and check the docs in docs for stack authoring and architecture notes.
Dotkiln is licensed under the MIT License.