Extend NuGet Command Line

Yesterday I started a discussion about adding a new command to nuget.exe. It ended in creating an extension to the command line that behaves in the same way without having to dive into the nuget code base or add more complexity to it.

I haven’t seen any blog posts or documentation surrounding this new concept (new in nuget 1.4) of extending the command line except for Matt Hamilton’s posts on using NuGet for plug-ins and NuGet with MEF (which are not quite this concept).

Here is my experience. I found looking at the commands in nuget.exe (NuGet.Commands) to make it easy to create my own command and extend NuGet.  Some of this information may not be exactly what you should do, but it worked for me.

The Code

  1. Create a new Visual Studio Solution and add a Class Library (full .NET 4.0 framework).
  2. Add A NuGet Reference to Nuget.CommandLine.
  3. Now manually add a reference to nuget.exe. Yes, you can add references to .NET executables.
  4. Adding a reference to nuget.exe gives you access to Command and the CommandAttribute. These are what I see as necessary to extending NuGet.
  5. Add a reference to System.ComponentModel.Composition (MEF).
  6. Now you provide a class and resource file per command.

The resource file contains the command descriptions:


The class is attributed with CommandAttribute and inherits from Command.

[Command(typeof (CopyResources), "copy", "Description", MinArgs = 1, MaxArgs = 5, UsageSummaryResourceName = "UsageSummary",UsageDescriptionResourceName = "UsageDescription")]
public class Copy : Command {}

The Command Attribute asks for a few things:

  1. typeof (CopyResources)ResourceClass - What is the resx file that the command will draw its help information from?
  2. “copy”CommandName - what is the name of the command?
  3. “Description”Description - resource name in the resource file that gives the description on the command line.
    Description - Copies a package from one source to another source
  4. MinArgs=1Minimum Arguments - what are the minimum number of arguments that can be passed to this command and satisfy its needs?
  5. MaxArgs = 5Maximum Arguments - what are the maximum number of arguments that can be passed to this command?
  6. UsageSummaryResourceName = “UsageSummary”UsageSummary - a very short amount of information that explains the usage of the command.
  7. UsageDescription = “Usage Description”UsageDescription - more detailed information about how to use the command.

Here is what the command looks like when run with help. Notice where from the CopyResources.resx these items match up to the screen.

The help command showing the items from the resx file.

Now that we have the command attribute finished, let’s work on the command itself.

private readonly IPackageRepositoryFactory _repositoryFactory;
private readonly IPackageSourceProvider _sourceProvider;

public Copy(IPackageRepositoryFactory repositoryFactory, IPackageSourceProvider sourceProvider)
    _repositoryFactory = repositoryFactory;
    _sourceProvider = sourceProvider;

[Option(typeof (CopyResources), "SourceDescription", AltName = "src")]
public string Source { get; set; }

[Option(typeof (CopyResources), "DestinationDescription", AltName = "dest")]
public string Destination { get; set; }

[Option(typeof (CopyResources), "VersionDescription")]
public string Version { get; set; }

[Option(typeof (CopyResources), "ApiKeyDescription")]
public string ApiKey { get; set; }

public override void ExecuteCommand()
    string packageId = base.Arguments[0];

    Console.WriteLine("Copying {0} from {1} to {2}.", string.IsNullOrEmpty(Version) ? packageId : packageId + " " + Version,
                      string.IsNullOrEmpty(Source) ? "any source" : Source, Destination);

    //do work son

Important things to note:

  1. [ImportingConstructor] is the constructor that will be called. Notice I am having it get passed an IPackageRepositoryFactory and an IPackageSourceProvider. Most of my work is already done for me setting these up in the command line application.
  2. Each command line option has [Option(typeof (CopyResources), "DestinationDescription", AltName = "dest")] .
  3. Notice again with the options we specify the Resource File with an Option Description (“DestinationDescription”) and an optional short parameter for the Option (AltName). Notice how that translates into options on the help command.
    options available with the custom command
  4. I am overriding ExecuteCommand and pulling the packageId as the first item from base.Arguments. 

From here I can do all the work necessary for my custom command.

Get NuGet to Recognize It

Nuget looks for custom commands in %LocalAppData%\NuGet\Commands. Drop your DLL in there and then call nuget. See if it registers your command. This will allow you to continue to tweak your package prior to releasing it in the wild.

Use AddExtension to Add New Commands

NuGet Extend (AddConsoleExtension) makes installing new commands to the console from NuGet packages super easy. You install it by typing the following:

NuGet.exe Install /ExcludeVersion /OutputDir %LocalAppData%\NuGet\Commands AddConsoleExtension

From then on, adding a new extension is as easy as

nuget.exe addExtension packageName
nuget addExtension nuget.copy.extension

Distribute Your Extension as a NuGet Package And Enjoy Your New Custom Command

When I created my package, I noted in the nuspec description that Nuget Extend should be installed first.  I also added the tag ConsoleExtension since that is what NuGet Extend used. All I package up is the DLL. The nuspec has ZERO dependencies specified (I do not include that I have a dependency on NuGet.CommandLine). I don’t need to include the nuget dependency since that will be resolved when the extension is run with nuget.exe.

Now that you have your custom command, enjoy life a little easier. And tell others about it.

nuget copy castle.windsor -destination awesome

NuGet Copy Extension is the extension I wrote that pulls packages from one source and pushes them to another. If you are a company that wants to house packages in a company feed and perhaps shut off the official feed for the rest of your developers, then this command may come in very handy.

Have Fun!

Posted 07-15-2011 3:00 AM by Rob Reynolds
Filed under: , ,



Maarten Balliauw {blog} wrote Copy packages from one NuGet feed to another
on 07-15-2011 5:27 AM

Copy packages from one NuGet feed to another

Scott Hanselman wrote re: Extend NuGet Command Line
on 07-18-2011 6:10 PM

EPIC WIN. Maybe this can be at docs.nuget.org?

Rob Reynolds wrote re: Extend NuGet Command Line
on 07-19-2011 1:03 AM

@Scott: I think Phil is already working on this?

Rob Reynolds wrote re: Extend NuGet Command Line
on 07-26-2011 8:46 AM

The next post will show more about automated testing nuget extensions.

MyGet Blog wrote Copy packages from one NuGet feed to another
on 02-28-2012 12:31 PM

Copy packages from one NuGet feed to another

Daniel Hegner wrote re: Extend NuGet Command Line
on 05-09-2012 7:28 AM

Great addin! However, since %LocalAppData% didn't exist on my old Windows XP box the %LocalAppData%\NuGet\Commands  does not work. nuget doesn't find the commands.

To make it work set %LocalAppData%=C:\Documents and Settings\userName\Local Settings\Application Data\

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET


SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
NHibernate Profiler
Balsamiq Mockups
JetBrains - ReSharper
Web Sequence Diagrams
Ducksboard<-- NEW Friend!


Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers


Community Server (Commercial Edition)