| name | dotnet-tool-management |
| category | developer-experience |
| subcategory | tools |
| description | Installs and manages .NET tools. Global, local, manifests, restore, version pinning. |
| license | MIT |
| targets | ["*"] |
| tags | ["foundation","dotnet","skill"] |
| version | 0.0.1 |
| author | dotnet-agent-harness |
| invocable | true |
| claudecode | {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} |
| codexcli | {"short-description":".NET skill guidance for foundation tasks"} |
| opencode | {"allowed-tools":["Read","Grep","Glob","Bash","Write","Edit"]} |
| copilot | {} |
| geminicli | {} |
| antigravity | {} |
dotnet-tool-management
Consumer-side management of .NET CLI tools: installing global and local tools, creating and maintaining
.config/dotnet-tools.json manifests, version pinning for team reproducibility, dotnet tool restore in CI pipelines,
updating and uninstalling tools, and troubleshooting common tool issues.
Version assumptions: .NET 8.0+ baseline. Local tools and tool manifests available since .NET Core 3.0. RID-specific
tool packaging available since .NET 10.
Scope
- Global tool installation and management
- Local tool manifests (.config/dotnet-tools.json)
- Version pinning and team workflow reproducibility
- CI integration with dotnet tool restore
- RID-specific tool installation (.NET 10+)
- Troubleshooting common tool issues
Out of scope
- Tool authoring and packaging (PackAsTool, NuGet packaging) -- see [skill:dotnet-cli-packaging]
- Distribution strategy (AOT vs framework-dependent decision) -- see [skill:dotnet-cli-distribution]
- Release CI/CD pipeline -- see [skill:dotnet-cli-release-pipeline]
Cross-references: [skill:dotnet-cli-packaging] for tool authoring and NuGet packaging, [skill:dotnet-cli-distribution]
for distribution strategy and RID matrix, [skill:dotnet-cli-release-pipeline] for automated release workflows,
[skill:dotnet-project-analysis] for detecting existing tool manifests.
Global Tool Installation
Global tools are installed per-user and available from any directory. The tool binaries are added to a directory on the
user's PATH.
dotnet tool install -g <package-id>
dotnet tool install -g <package-id> --version 1.2.3
dotnet tool install -g <package-id> --version "*-rc*"
dotnet tool list -g
dotnet tool update -g <package-id>
dotnet tool uninstall -g <package-id>
```text
**Default install locations:**
| OS | Path |
|-----|------|
| Linux/macOS | `$HOME/.dotnet/tools` |
| Windows | `%USERPROFILE%\.dotnet\tools` |
Global tools are user-scoped, not machine-wide. Each user maintains their own tool installations independently.
Use `--tool-path` to install to a custom directory. The directory is not automatically added to PATH -- you must manage PATH yourself:
```bash
dotnet tool install <package-id> --tool-path ~/my-tools
```bash
---
Local tools are scoped to a directory tree and tracked a manifest file. Different directories can use different versions of the same tool.
The manifest file `.config/dotnet-tools.json` tracks tool versions. Create it at the repository root:
```bash
dotnet new tool-manifest
```bash
This produces:
```json
{
: 1,
: ,
: {}
}
```text
Commit this file to control so all team members share the same tool versions.
Omit the `-g` flag to install a tool locally. The tool is recorded the nearest manifest file:
```bash
dotnet tool install <package-id>
dotnet tool install <package-id> --version 2.0.1
dotnet tool list
dotnet tool update <package-id>
dotnet tool uninstall <package-id>
```text
After installing two tools, the manifest looks like:
```json
{
: 1,
: ,
: {
: {
: ,
: [
]
},
: {
: ,
: [
]
}
}
}
```text
```bash
dotnet tool run <command-name>
dotnet <command-name>
dotnet tool run dotnet-ef migrations add Init
dotnet ef migrations add Init
```text
---
The tool manifest enables reproducible tool versions across the team.
1. **One team member** creates the manifest and installs tools with specific versions
2. **Commit** `.config/dotnet-tools.json` to control
3. **All team members** run `dotnet tool restore` after cloning or pulling
4. **Updates** are explicit: one person runs `dotnet tool update <package-id>`, commits the updated manifest
Use the `--version` option with NuGet version ranges controlled flexibility:
```bash
dotnet tool install <package-id> --version 2.0.1
dotnet tool install <package-id> --version
dotnet tool install <package-id> --version
```text
The manifest always records the exact resolved version, ensuring all team members use identical versions after restore.
---
In CI pipelines, restore tools before any build step that depends on them. Tool restore is fast and idempotent.
**GitHub Actions:**
```yaml
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version:
- name: Restore tools
run: dotnet tool restore
- name: Build
run: dotnet build
- name: Run EF migrations check
run: dotnet ef migrations has-pending-changes
```text
**Azure DevOps Pipelines:**
```yaml
steps:
- task: UseDotNet@2
inputs:
packageType: sdk
version:
- script: dotnet tool restore
displayName:
- script: dotnet build
displayName:
```text
- **Always run `dotnet tool restore` before build** -- not rely on tools being pre-installed on CI agents
- **Commit `.config/dotnet-tools.json`** -- the manifest ensures CI uses the same tool versions as development
- **Do not install tools globally CI** -- use tool manifests reproducibility; global installs may conflict across concurrent
- **Cache NuGet packages** to speed up tool restore (`~/.nuget/packages` on Linux/macOS, `%USERPROFILE%\.nuget\packages` on Windows)
---
Starting with .NET 10, tool authors can publish RID-specific, self-contained, or Native AOT versions of their tools. From a consumer perspective, this is transparent -- the `dotnet tool install` automatically selects the best package your platform.
```bash
dotnet tool install -g <package-id>
```bash
The .NET CLI detects your platform and downloads the appropriate RID-specific package. If no RID-specific package matches your platform, the CLI falls back to a framework-dependent package ( the tool author provided one).
For details on authoring and packaging RID-specific tools, see [skill:dotnet-cli-packaging].
---
**** -- Uninstall first or use `dotnet tool update`:
```bash
dotnet tool update -g <package-id>
```bash
**** -- Run `dotnet new tool-manifest` to create one, or check that you are a directory at or below the manifest location.
**** -- For global tools, verify `~/.dotnet/tools` is on your PATH. For tools, ensure you are the directory tree containing the manifest.
**** -- Verify `.config/dotnet-tools.json` is committed and `dotnet tool restore` runs before any tool usage.
---
| Aspect | Global Tool | Local Tool |
|--------|------------|------------|
| Scope | System-wide (per user) | Per-project directory tree |
| Install location | `~/.dotnet/tools` | `.config/dotnet-tools.json` manifest |
| Version management | Manual `dotnet tool update -g` | Tracked control |
| CI/CD | Must install before use (not reproducible) | `dotnet tool restore` restores all (reproducible) |
| Team consistency | Each developer manages independently | Manifest ensures identical versions |
| Best | Personal productivity tools, one-off utilities | Project-specific build/dev tools |
**Prefer tools** anything used a projects pinned versions.
2. **Do not skip `dotnet tool restore` CI pipelines.** Tools are not pre-installed on CI agents. Always restore before any step that invokes a tool, or the build will fail with
3. **Do not omit `.config/dotnet-tools.json` from control.** The manifest is the single of truth tool versions. Without it, `dotnet tool restore` has nothing to restore and each developer gets different versions.
4. **Do not specify RID flags when installing tools as a consumer.** The .NET CLI automatically selects the correct RID-specific package your platform. Manual RID selection is unnecessary and may cause installation failures.
5. **Do not confuse tool names with package IDs.** The package ID (e.g., `dotnet-ef`) may differ from the name (e.g., `dotnet ef`). Use `dotnet tool list` to see the mapping between package IDs and commands.
---
- [.NET tools overview](https://learn.microsoft.com/en-us/dotnet/core/tools/global-tools)
- [How to manage .NET tools](https://learn.microsoft.com/en-us/dotnet/core/tools/local-tools-how-to-use)
- [dotnet tool install ](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-tool-install)
- [dotnet tool restore ](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-tool-restore)
- [RID-specific .NET tools](https://learn.microsoft.com/en-us/dotnet/core/tools/rid-specific-tools)
- [Troubleshoot .NET tool usage issues](https://learn.microsoft.com/en-us/dotnet/core/tools/troubleshoot-usage-issues)