United Kingdom: +44 (0)208 088 8978

Seven tips for using Paket effectively

We're hiring Software Developers

Click here to find out more

Paket is a powerful NuGet client for the .NET platform. As a project that was created nearly ten years ago, it is mature and stable. This post isn't going to explain the value proposition being Paket - the official docs and this series that I wrote on my personal blog several years ago do a decent enough job of that. Instead, this is about giving some simple instructions on how to efficiently and effectively perform some common tasks with it.

1. Installing paket

Paket is nowadays just a dotnet tool; you can install it from clean with the following:

dotnet new tool-manifest
dotnet tool install paket

If you already have a .NET tool manifest file in your repository, the first command is not required.

2. Adding and removing a single package to / from a project

Adding a package to a project is, obviously, a common task you'll be doing often. We made some changes to Paket a while back to optimise this: you no longer have to add the package to the dependencies file and then add to the project references. Instead, paket can now do it in a single command:

cd src/project-to-add-package-to
dotnet paket add <package>

Paket will add the package to the "parent" paket.dependencies file, update the associated paket.lock file with an updated dependency graph, add the entry to the paket.references in the current directory and ultimately to the project itself. Removing a package from a project is very similar:

cd src/project-to-remove-package-from
dotnet paket remove <package>

3. How to update a single dependency

If you want to update a single dependency, simply do the following:

dotnet paket update <package name>

This will also update all the transitive dependencies (child dependencies) of that package at the same time, but won't modify any packages that are not related in some way to the package you wanted to update.

4. How to update all your dependencies at once

If you want to update the entire graph to the latest versions of everything, simply run

dotnet paket update

This will calculate a brand new graph for the entire dependency chain.

There are often many valid solutions for a NuGet package dependency graph.

5. How to "conservatively" update a dependency

There are times when you want to update a dependency (or all dependencies) but don't want paket to be too aggressive in upgrading them. This is extremely useful if you want to update whilst minimising the risk of breaking changes e.g. the current version of a package has a bug - you just want "the next version" that fixed it rather than going to a brand new major version.

One option is to restrict paket to only upgrade to specific boundaries: major, minor or patch.

dotnet paket update Giraffe keep-major
dotnet paket update keep-minor
dotnet paket update keep-patch

These examples above behave as follows:

  • Updates Giraffe (and all transitives) but keeps the current major versions of all packages e.g. 1.5 -> 1.9
  • Updates all dependencies but keeps the current minor versions e.g. 1.5.1 -> 1.5.9
  • Updates all dependencies but keeps the current patch versions e.g. 1.5.9-alpha -> 1.5.9-rc

Another option is to specify a particular version to update a package to:

dotnet paket update Giraffe --version 5.0

You can also manually pin packages in the paket.dependencies file:

nuget Fsharp.Core ~> 6

This instructs paket to never upgrade FSharp.Core above version 6. If you ask to upgrade another package which has a dependency on FSharp.Core, it will never upgrade that package to a version that depends on version 7 or greater of FSharp.Core.

Lastly, you can also update the dependencies file to specify using a more conservative resolution strategy. Putting strategy:min in your paket.dependencies file instructs Paket to always seek out the "lowest" version of transitive dependencies, not the maximum. This is useful if package authors have not specified the "max" version of transitives - in this case Paket can download transitives that have breaking changes in them.

6. How to see why a package has been added.

It is sometimes useful to know the reason that a package has been added into your paket.lock file. For example, I might want to know why I have Newtonsoft.Json in my lock file:

dotnet paket why Newtonsoft.Json

NuGet Newtonsoft.Json - 13.0.1 is a transitive dependency.
It is part of following dependency chains:

-> Fable.Remoting.Giraffe - 5.9
  -> Fable.Remoting.Server - 5.29
    -> Fable.Remoting.Json - 2.21
      -> Newtonsoft.Json - 13.0.1

-> Saturn - 0.16.1
  -> Giraffe - 6.0
    -> Newtonsoft.Json - 13.0.1

This is occasionally a very useful tool to help diagnose issues with your dependency chain.

7. Use Install and Restore correctly.

My last tip is to know the differences between the three core commands of Paket: install, restore and update. I often see confusion around these and see them used incorrectly.

  • paket update I have covered above: use it when you want to update the version of packages that you already have.
  • You should never need to use paket restore directly since dotnet restore will call this command automatically. It is used to download NuGet packages to your physical machine after e.g. cloning a repository. It will never modify any paket files.
  • You should only need to use paket install if you have manually modified any paket files by hand. It essentially checks that they are all "in sync"; if they aren't, paket re-generates the sections of the lock file as required to bring it in-line with the dependencies file, and adds / removes any required packages as project references.

Summary

The official NuGet client has certainly improved over the last few years. However, it still lacks the flexibility and power of Paket, especially from a command line perspective. This article will hopefully enable you to be even more effective when using it!