.NET Tools
|
This section documents MSBuild 18.9, the .NET SDK 10.0.402 (with its This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The C# Reference bibliography lists the reference material consulted while preparing these pages. |
A .NET tool is a console application distributed as a NuGet package and run through the dotnet CLI — dotnet-ef,
dotnet-format before it joined the SDK, the API-compatibility tool, Ledgerline's own ledgerline command. Tools
are installed globally for a user, into a tool path, or locally for a repository through a manifest; since
.NET 10 they can also be executed once without installing. This page does all four with .NET SDK 10.0.402
and the Ledgerline.Cli package from Ledgerline's local feed. The overview in the C# Reference is
Build and Tooling — Global and Local
Tools; distributing command-line tools in general is compared in
Packaging and Distribution — dotnet tool; building
the package is on
Tool and Template Packages.
Three ways to install
| Kind | Command | Installed to | Invoked as |
|---|---|---|---|
Global |
|
|
|
Tool path |
|
|
|
Local |
|
the NuGet global-packages folder; recorded in |
|
Source: .NET tools: Install a global tool in a custom location, Install a global tool, Install a local tool.
Global
dotnet tool install --global Ledgerline.Cli --add-source ~/ledgerline/artifacts/feed
~/.dotnet/tools/ledgerline check ~/ledgerline/samples/Ledgerline.Report/journal.ledger.csv
dotnet tool list --global
Tools directory '~/.dotnet/tools' is not currently on the PATH environment variable.
If you are using bash, you can add it to your profile by running the following command:
cat << \EOF >> ~/.bash_profile
# Add .NET Core SDK tools
export PATH="$PATH:~/.dotnet/tools"
EOF
You can add it to the current session by running the following command:
export PATH="$PATH:~/.dotnet/tools"
You can invoke the tool using the following command: ledgerline
Tool 'ledgerline.cli' (version '1.0.0') was successfully installed.
OK: 4 lines, every entry balances.
Package Id Version Commands
-------------------------------------------
ledgerline.cli 1.0.0 ledgerline
The package ID is matched case-insensitively and reported in lower case; the command name (ledgerline) comes from
the package’s ToolCommandName. ~/.dotnet/tools holds a small launcher per command and a hidden .store folder with
the package (.store/ledgerline.cli/1.0.0/). A global tool is per user, not per repository: two repositories cannot
use two versions of the same global tool.
--tool-path <dir> installs the same way into a chosen folder, which suits CI images and containers that should not
depend on a user profile.
Local
A local tool is pinned in a manifest. dotnet new tool-manifest creates one (on SDK 10 at the repository root as
dotnet-tools.json; older SDKs used .config/dotnet-tools.json, which is still found). Ledgerline already has one for
the API-compatibility tool:
dotnet tool install Ledgerline.Cli --local
cat dotnet-tools.json
dotnet tool list --local
dotnet ledgerline check samples/Ledgerline.Report/journal.ledger.csv
You can invoke the tool from this directory using the following commands: 'dotnet tool run ledgerline' or 'dotnet ledgerline'.
Tool 'ledgerline.cli' (version '1.0.0') was successfully installed. Entry is added to the manifest file ~/ledgerline/dotnet-tools.json.
{
"version": 1,
"isRoot": true,
"tools": {
"microsoft.dotnet.apicompat.tool": {
"version": "10.0.402",
"commands": [
"apicompat"
],
"rollForward": false
},
"ledgerline.cli": {
"version": "1.0.0",
"commands": [
"ledgerline"
],
"rollForward": false
}
}
}
Package Id Version Commands Manifest
--------------------------------------------------------------------------------------------------
microsoft.dotnet.apicompat.tool 10.0.402 apicompat ~/ledgerline/dotnet-tools.json
ledgerline.cli 1.0.0 ledgerline ~/ledgerline/dotnet-tools.json
OK: 4 lines, every entry balances.
The manifest is committed; the tool itself is not. A fresh clone runs dotnet tool restore, which downloads every
tool in the manifest:
Run "dotnet tool restore" to make the "ledgerline" command available.
Tool 'microsoft.dotnet.apicompat.tool' (version '10.0.402') was restored. Available commands: apicompat
Tool 'ledgerline.cli' (version '1.0.0') was restored. Available commands: ledgerline
Restore was successful.
The first line is what dotnet ledgerline printed on a machine with empty NuGet and CLI caches. On the original
machine, though, emptying only the NuGet global-packages folder (NUGET_PACKAGES) was not enough to reproduce it:
the CLI’s tool resolver cache (~/.dotnet/toolResolverCache) still pointed at the old package, and the tool ran. CI
should always run dotnet tool restore rather than infer from a missing-tool error. isRoot: true stops the CLI from
merging manifests found in parent folders.
Updating, removing, searching
dotnet pack src/Ledgerline.Cli -p:Version=1.1.0 -o ~/feed2
cd ~/ledgerline && dotnet tool update --global Ledgerline.Cli --add-source ~/feed2
cd /tmp && dotnet tool update --global Ledgerline.Cli --add-source ~/feed2
dotnet tool uninstall -g Ledgerline.Cli
Successfully created package '~/feed2/Ledgerline.Cli.1.1.0.nupkg'.
The --add-source option cannot be combined with package source mapping. To use an additional source, update your NuGet configuration file's source mapping settings. Learn more: https://aka.ms/nuget-package-source-mapping
Tool 'ledgerline.cli' was successfully updated from version '1.0.0' to version '1.1.0'.
Tool 'ledgerline.cli' (version '1.1.0') was successfully uninstalled.
Run inside the Ledgerline folder, the update was refused: its nuget.config uses package source mapping, and an
ad hoc --add-source would bypass the mapping. Run from a folder without that configuration it worked. For tools of a
repository with source mapping, publish the new version to a mapped feed (or map the extra source) instead
(Package Sources and Source Mapping).
dotnet tool search <text> queries nuget.org for packages of type DotnetTool:
Package ID Latest Version Authors Downloads Verified
---------------------------------------------------------------------------------------------------------------
dotnet-outdated-tool 4.8.1 dotnet-outdated Team & Contributors 7897378
dotnet-tools-outdated 0.8.0 Mojmir Rychly 1793791
One-shot execution: dotnet tool exec and dnx
dotnet tool exec <id> downloads the package to the cache (in aninteractive terminal it asks for confirmation first; --yes skips that), runs it and leaves nothing on PATH or in a manifest. dnx is a short script shipped
next to dotnet that does the same:
dotnet tool exec Ledgerline.Cli --add-source ~/ledgerline/artifacts/feed -- check ~/ledgerline/samples/Ledgerline.Report/journal.ledger.csv
dnx Ledgerline.Cli --yes --add-source ~/ledgerline/artifacts/feed -- balance ~/ledgerline/samples/Ledgerline.Report/journal.ledger.csv
OK: 4 lines, every entry balances.
[
{
"Account": "1000-Cash",
"Debit": 500.00,
"Credit": 120.00,
"Balance": 380.00
…
The dnx script on Linux ends with:
SDK_VERSION=$("$DOTNET" --list-sdks | tail -n 1 | cut -d' ' -f1)
…
exec "$DOTNET" exec "$SDK_PATH" dnx "$@"
It always runs the highest installed SDK, ignoring global.json. Inside a repository that pins an SDK, dotnet
tool exec respects the pin; dnx does not.
| Command | Installs | Scope |
|---|---|---|
|
nothing (package cached) |
one run |
|
global shim |
the user |
|
a folder |
that folder |
|
manifest entry |
the repository |
Source: dotnet tool exec: Comparison with other commands, What’s new in the .NET 10 SDK: One-shot tool execution, The new dnx tool execution script.
|
A tool is code that runs with your permissions, and |
RID-specific and Native AOT tools
From .NET 10 a tool package can contain RID-specific, self-contained or Native AOT builds of the tool; the CLI
picks the package for the current platform at install time, falling back to a framework-dependent any build when the
author published one. Installing needs nothing special — dotnet tool install -g <id> chooses — but the tool then
starts without the JIT and needs no installed runtime. Authoring such packages
(ToolPackageRuntimeIdentifiers, PublishAot) is covered on
Tool and Template Packages.
Common mistakes
-
Global tools for repository builds — versions drift between machines; use a manifest.
-
Skipping
dotnet tool restorein CI — the resolver cache can hide a missing restore locally. -
--add-sourcein a repository with source mapping — refused; map the source. -
dnxin a pinned repository — it uses the newest SDK. -
Forgetting
PATHfor global tools — the install message prints the line to add.