Global and Local Tools
The .NET SDK includes a tool ecosystem for distributing and installing command-line utilities as NuGet packages. A global tool, installed with dotnet tool install --global dotnet-ef (or the shorthand -g), is placed in a per-user tool location and added to your PATH, making the tool's command available from any directory on the machine, in any project, without being tied to a specific repository. Popular examples include dotnet-ef for Entity Framework Core migrations and dotnet-format for code formatting.
Cricket analogy: A franchise like Mumbai Indians keeps a personal fitness trainer on permanent staff who travels with the team to every match regardless of venue, similar to a global .NET tool like dotnet-ef installed once to the user profile and available from any project directory via PATH.
Local Tools: Pinned Versions Per Repository
Local tools solve the problem of every team member needing the exact same tool version for a given repository. Running dotnet new tool-manifest creates a .config/dotnet-tools.json manifest file in the repo, and dotnet tool install dotnet-ef --local (without -g) adds an entry to that manifest pinning an exact version. Anyone who clones the repository runs dotnet tool restore to install precisely those pinned tool versions locally, ensuring the whole team, and CI, use identical tooling regardless of what's installed globally on each machine.
Cricket analogy: A specific match referee panel is appointed per series so every team in that series follows the identical set of officials and rules, similar to a dotnet-tools.json manifest pinning exact tool versions so every developer on a repo uses the identical toolchain.
# Create a local tool manifest for this repo
dotnet new tool-manifest
# Install a local tool, pinned in .config/dotnet-tools.json
dotnet tool install dotnet-ef --local
# Anyone who clones the repo restores the exact pinned versions
dotnet tool restore
# .config/dotnet-tools.json
# {
# "version": 1,
# "isRoot": true,
# "tools": {
# "dotnet-ef": {
# "version": "8.0.4",
# "commands": ["dotnet-ef"]
# }
# }
# }Building and Publishing Your Own Tool
You can package your own console application as an installable .NET tool by setting <PackAsTool>true</PackAsTool> in the project file, along with a <ToolCommandName> that defines the command users will type to invoke it. Running dotnet pack produces a NuGet package that, once pushed to NuGet.org or a private feed, others can install with dotnet tool install --global your-tool-name just like any first-party tool, immediately gaining a new CLI command without cloning or building source code themselves.
Cricket analogy: A retired player like Rahul Dravid packaging his batting expertise into a formal coaching certification that others can 'install' and use is like a developer wrapping a console app with <PackAsTool>true</PackAsTool> so others can install it as a reusable CLI command.
Keeping Tools Up to Date
Tool versions can drift over time as new releases ship, so dotnet tool list -g (or without -g for local tools) shows what's currently installed and its version, dotnet tool update -g dotnet-ef bumps a specific global tool to the latest compatible version, and dotnet tool uninstall -g <name> removes one that's no longer needed. For local tools tied to a manifest, updating still edits dotnet-tools.json, so the new pinned version is committed and shared with the rest of the team rather than silently diverging per machine.
Cricket analogy: A team periodically reviews and updates its playing eleven, dropping underperforming players and bringing in fresh talent ahead of a new series, similar to running dotnet tool update -g dotnet-ef to bring an aging tool up to the latest version.
Always commit .config/dotnet-tools.json to source control. It's a small, explicit manifest that lets every teammate and your CI pipeline run dotnet tool restore and get byte-for-byte identical tool versions, no more 'works on my machine' formatter or migration tool mismatches.
Global tools are versioned per user profile, not per project. If two repositories on the same machine expect different major versions of the same tool, a global install will silently work for one and break the other. Prefer local tools pinned via a manifest for anything version-sensitive in a team project.
- Global tools install once per user and are available from any directory via PATH.
- Local tools are pinned per repository in .config/dotnet-tools.json, created via dotnet new tool-manifest.
- dotnet tool restore installs the exact tool versions listed in the manifest for every team member and CI.
- You can package your own console app as a tool with PackAsTool and ToolCommandName, then publish it to NuGet.
- dotnet tool update keeps installed tools current; dotnet tool list shows what's installed and its version.
- Commit dotnet-tools.json to source control to guarantee consistent tooling across the team.
- Global tool versions aren't project-scoped, which can cause version drift across different repositories on the same machine.
Practice what you learned
1. What command creates the manifest file needed for local tools in a repository?
2. What is the main advantage of local tools over global tools for a team project?
3. Which csproj property marks a console application as packable into an installable .NET tool?
4. What does `dotnet tool restore` do?
5. Why is it risky to rely solely on global tools for a project with strict version requirements?
Was this page helpful?
You May Also Like
dotnet watch and Hot Reload
How dotnet watch automatically rebuilds your app on file changes, and how Hot Reload patches a running process live to speed up the edit-test loop.
Runtime Identifiers and Native AOT
How Runtime Identifiers (RIDs) target specific platforms and how Native AOT compiles .NET apps straight to native code for fast, lightweight startup.
.NET on Linux and macOS
How the .NET SDK and runtime install, behave, and get deployed across Linux and macOS, and the platform differences that matter for portable code.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics