In NuGet 4.8+ support for cross platform plugins has been added. This was achieved with by building a new plugin extensibility model, that has to conform to a strict set of rules of operation. The plugins are self-contained executables (runnables in the .NET Core world), that the NuGet Clients launch in a separate process. This is a true write once, run everywhere plugin. It will work with all NuGet client tools. The plugins can be written in any programming language, but the easiest plugin development and installation experience will be with .NET. A versioned communication protocol between the NuGet Client and the plugin is defined. During the startup handshake, the 2 processes negotiate the protocol version.
How does it workThe high level workflow can be described as follows:
The current protocol version is 2.0.0. Under this version, the requirements are as follows:
Plugins discovered from the PATH environment variable (for example, installed via dotnet tool
) additionally must match the filename pattern nuget-plugin-*
. The nuget-plugin-
part must be written entirely in lowercase letters.
NuGet 6.12 (MSBuild 17.12, and .NET SDK 9.0.100) and earlier also required plugins to be Authenticode signed on Windows.
The technical specification is described in more detail in the following specs:
Client - Plugin interactionNuGet client tools and the plugins communicate with JSON over standard streams (stdin, stdout, stderr). All data must be UTF-8 encoded. The plugins are launched with the argument "-Plugin". In case a user directly launches a plugin executable without this argument, the plugin can give an informative message instead of waiting for a protocol handshake. The protocol handshake timeout is 5 seconds. The plugin should complete the setup in as short of an amount as possible. NuGet client tools will query a pluginâs supported operations by passing in the service index for a NuGet source. A plugin may use the service index to check for the presence of supported service types.
The communication between the NuGet client tools and the plugin is bidirectional. Each request has a timeout of 5 seconds. If operations are supposed to take longer the respective process should send out a progress message to prevent the request from timing out. After 1 minute of inactivity a plugin is considered idle and is shut down.
Plugin installation and discoveryNuGet searches for plugins from a convention based directory structure, and scanning the PATH environment variable.
Convention based discoveryCI/CD scenarios and power users can use environment variables to override the behavior. When using environment variables, only absolute paths are allowed. Note that NUGET_NETFX_PLUGIN_PATHS
and NUGET_NETCORE_PLUGIN_PATHS
are only available with 5.3+ version of the NuGet tooling and later.
NUGET_NETFX_PLUGIN_PATHS
- defines the plugins that will be used by the .NET Framework based tooling (NuGet.exe/MSBuild.exe/Visual Studio). Takes precedence over NUGET_PLUGIN_PATHS
. (NuGet version 5.3+ only)NUGET_NETCORE_PLUGIN_PATHS
- defines the plugins that will be used by the .NET Core based tooling (dotnet.exe). Takes precedence over NUGET_PLUGIN_PATHS
. (NuGet version 5.3+ only)NUGET_PLUGIN_PATHS
- defines the plugins that will be used for that NuGet process, priority preserved. If this environment variable is set, it overrides the convention based discovery. Ignored if either of the framework specific variables is specified.%UserProfile%/.nuget/plugins
. This location cannot be overridden. A different root directory will be used for .NET Core and .NET Framework plugins.%UserProfile%/.nuget/plugins/netcore
dotnet CLI .NET Framework %UserProfile%/.nuget/plugins/netfx
MSBuild, NuGet.exe, Visual Studio
Each plugin should be installed in its own folder. The plugin entry point will be the name of the installed folder, with the .dll extensions for .NET Core, and .exe extension for .NET Framework.
.nuget
plugins
netfx
myPlugin
myPlugin.exe
nuget.protocol.dll
...
netcore
myPlugin
myPlugin.dll
nuget.protocol.dll
...
PATH discovery
Starting from NuGet 6.13, NuGet will search each directory provided in the PATH environment variable for files matching the pattern nuget-plugin-*
. The pattern matching is case-sensitive, and nuget-plugin-
must be written entirely in lowercase letters. On Windows the file must have an .exe
or .bat
extension. On Linux and Mac the file must have the executable bit set.
This allows NuGet plugins to be installed via dotnet tool
commands, WinGet, a Linux distribution's package manager, or any other method that can put executables on the user's PATH. This also allows NuGet plugins to be written in any programming language (previously plugins for Linux and Mac must be written in .NET).
We recommend plugins are developed in .NET, so that you can use the NuGet.Protocol package to avoid needing to write the json RPC code, and to allow customers to discover your plugin via dotnet package search nuget-plugin
.
Two operations are supported under the new plugin protocol.
Operation name Minimum protocol version Minimum NuGet client version Download Package 1.0.0 4.3.0 Authentication 2.0.0 4.8.0 Running plugins under the correct runtimeFor the NuGet in dotnet.exe scenarios, plugins need to be able to execute under that specific runtime of the dotnet.exe. It's on the plugin provider and the consumer to make sure a compatible dotnet.exe/plugin combination is used. A potential issue could arise with the user-location plugins when for example, a dotnet.exe under the 2.0 runtime tries to use a plugin written for the 2.1 runtime.
Capabilities cachingThe security verification and instantiation of the plugins is costly. The download operation happens way more frequently than the authentication operation, however the average NuGet user is only likely to have an authentication plugin. To improve the experience, NuGet will cache the operation claims for the given request. This cache is per plugin with the plugin key being the plugin path, and the expiration for this capabilities cache is 30 days.
The cache is located in %LocalAppData%/NuGet/plugins-cache
and be overriden with the environment variable NUGET_PLUGINS_CACHE_PATH
. To clear this cache, one can run the locals command with the plugins-cache
option. The all
locals option will now also delete the plugins cache.
Protocol Version 1.0.0 messages:
Close
Copy files in package
Copy package file (.nupkg)
Get credentials
Get files in package
Get operation claims
Note
This message has been updated in version 2.0.0. It is on the client to preserve backward compatibility.
Get package hash
Get package versions
Get service index
Handshake
Initialize
Log
Monitor NuGet process exit
Prefetch package
Set credentials
Set log level
Protocol Version 2.0.0 messages
Request direction: NuGet -> plugin
If the service index and package source are null, then the plugin can answer with authentication.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4