Creating Chocolatey Packages


See What are Chocolatey Packages? first.

Note: When you host internal packages, those packages can embed software and/or point to internal shares. You are not subject to software distribution rights like the packages on the community feed, so you can create packages that are more reliable and secure.

First you should determine if you are making a self-contained package or (also) using automation scripts. You should also consider creating automatic packages for the best maintainability over time.

  1. Run choco new -h to get a feel for what you can pass e.g choco new bob (to create a package named bob)
  2. Note all the rules below. This will help you, especially in publishing to the community feed (


If you have a self-contained package, you can remove the automation scripts
entirely and just include the runtime executables, they will automatically get shimmed,
which puts them on the path. Ensure you have the legal right to distribute
the application though. You should read up on the Shim Generation section
below though to familiarize yourself on what to do with GUI applications
and/or ignoring shims (also known as batch redirects).

Including the Software Installer in the Package

Sometimes called embedding the binaries, there are functions in the automation scripts you can call that will use the installers directly from the package instead of downloading first. This makes for the most reliable and deterministic packages, but ensure you have the legal right to distribute the software first if publishing to a public location (like the community package repository).

Automation Scripts

You have a powerful use of Chocolatey, as you are using PowerShell. So you
can do just about anything you need. Choco has some very handy built-in functions that you can use, these are sometimes called

Table of Contents

  1. Rules
  2. Encoding
  3. Learning about NuGet (and Chocolatey) Packages in general - Information and Nuspec
  4. Description/Release Notes Recommendations
  5. Limit Windows Versions
  6. Install paths
  7. Upgrading and Uninstalling
  8. Naming your package
  9. Versioning (and package fix version notation)
  10. Icons
  11. Exclude executables from shims
  12. Make shim for GUI application
  13. Localization
  14. Building / Testing / Pushing
  15. Maintainer magic - automatically updating packaging
  16. Taking over existing package

Quick Start guide

If you think you got what it takes and just want to know the basic steps to get a package out, there is a special Quick Start Guide for you. NOTE: This doesn't exempt you from observing the rules, requirements and guidelines (noted below).

Rules to be observed before publishing packages

There are a few rules that you have to follow before pushing packages to

  1. Don't package illegal software. Packages of software that is illegal in most countries in the world are prohibited to publish on This applies in particular to software that violates the copyright, pirated software and activation cracks. Remember that this also affects software that is especially designed to accomplish software piracy.
  2. Do not include software in a package that you don't have the right to distribute. Please see Distribution Rights for more information. Any package found not in compliance with this will be removed immediately. Instead you can download binaries from official distribution locations at runtime.
  3. Packaging commercial or trial software? Clearly state this in the package description. Does it require an activation key? Is there a trial period if you don't have a key? How long is this trial period?
  4. Only post publicly relevant packages. You should consider whether this package is useful for others. If that is not the case, it shouldn't be published on Reasons for that can be if the package would require a very customized configuration. You can host your personal packages on MyGet and still be able to install them with Chocolatey using the -source parameter.
  5. Do not publish junk or malware packages.
  6. Don't package software containing malware. Packages of software that comes with bundled adware, spyware or other unrelated software that installs even in silent mode, are not allowed. But if you can figure out how to install the desired software without this unrelated software, it is allowed to publish the package. That can be accomplished for example with additional command line switches or by adding specific values to the registry. Examples of packages which make use of this are PDFCreator and CCleaner.
  7. Don't package software that is already packaged. Use the search function in the gallery and look if there is already a package for the desired software. If you would like to improve the already existing package or if you have suggestions, just contact the package maintainer or open a pull request at the maintainer's package repository.
  8. Don't include other required software if there's a package of it. If a package requires other software of which there is already a package, the already existing package should be used as dependency instead.
  9. Split dependencies into multiple packages. Try to split up packages as much as possible. If for example a program comes with additional modules/installers that are optional, make different packages for them instead of including all the things into one package. This idea is already widely applied for Linux packages, because it leads to a more lightweight system and reduces potential issues and conflicts.
  10. Use a simple intuitive lowercase name for the package. See the package naming guidelines for details. (If you are a reviewer/moderator, this is considered a guideline).

Is your package unqualified for the Chocolatey feed, but you like to be able to install it through Chocolatey? Don't worry, you can always host your package for free on MyGet. See Hosting Chocolatey Packages on MyGet.

Character encoding

Note: There is a lot of confusion in the world of character encodings: For example, ANSI is an incorrect term for the internal Windows character encodings, e.  g. Windows-1252. But you should not use this encoding family anyway.

What version of the software should I package?

The main release of a product versions are usually sufficient. If there are also beta versions available and you would rather have that, then please create both the official release and the beta (and set the beta as a prerelease when pushing the item to Regular users of packages may want to use official releases only and not betas. NOTE: Both of these have the SAME package id, just different versions.

Okay, how do I create packages?

There are three main elements to a Chocolatey package. Only the nuspec is required (#1 below).

  1. Nuspec
  2. chocolateyInstall.ps1 - check out the helper reference
  3. any application files to include (it is highly suggested that you are the author in this case or you have the right to distribute files). EXE files in the package/downloaded to package folder from chocolateyInstall.ps1 will get a link to the command line.
  4. chocolateyUninstall.ps1, for uninstalling your package. See helper reference for functions available in your script.

Note: Please maintain compatibility with Posh v2. Not every OS we support is on Posh v2 (nor comes OOB with Posh v3+). It's best to work with the widest compatibility of systems out there.

There is a video showing the creation of a package:
The video is a bit outdated in showing the contents of the chocolateyInstall.ps1. Have a look at what the chocolateyInstall.ps1 looks like now:

$packageName = 'windirstat'
$fileType = 'exe'
$url = ''
$silentArgs = '/S'

Install-ChocolateyPackage $packageName $fileType $silentArgs $url

During which scenarios will my custom scripts be triggered?

The table below shows which scripts are available, and which command(s) will cause them to be run.

Script Name Install Upgrade Uninstall
chocolateyBeforeModify.ps1 Yes Yes
chocolateyInstall.ps1 Yes Yes
chocolateyUninstall.ps1 Yes

Note: In the upgrade scenario, the chocolateyInstall.ps1 script will be the one included in the new package. The chocolateyBeforeModify.ps1 script will be the one from the previously installed package.

The chocolateyBeforeModify.ps1 script will only be executed if using choco version 0.9.10 or later.


The Chocolatey Windows package manager uses the same infrastructure as NuGet, the Visual Studio package manager by Outercurve Foundation (sponsored by Microsoft). Therefore packages are based on the same principles. One of those is a package description (specification) in xml format, known as the Nuspec.

The Nuspec contains basic information such as the version, license, maintainer, and package dependencies. Chocolatey includes additional optional functionality on top of NuGet's Nuspec format - the best way to determine currently supported features is to create a test package, and look at the generated nuspec file.

choco new testpackage

Note: If your package uses recently introduced functionality, you might want to include chocolatey as a dependency with the version being the lowest version that has the introduced functionality. Otherwise the installation could fail for users with an older version of Chocolatey installed.

You can indicate the Chocolatey dependency like any other dependency. E.g.:

      <dependency id="chocolatey" version="" />

Logically, the version is based on the lowest compatible version. But if you don't know and used a lot of sorcery in your package, depend on the version of Chocolatey that you succesfully tested your package on.

See also: NuGet Version Reference

But for real, how do I create a package?

Install Only On Some Versions of Windows

Right now if the software the package installs is only supported on particular versions of Windows, you should absolutely fail the package. An installed package indicates success. If you pass a warning message but don't also throw an error, that means the package installed successfully. Folks using the package are going to be confused because they will then expect that the underlying software is also installed. The software itself may throw a cryptic error, which will lead to questions from the community about why it is broken (when it is just unsupported). Do yourself a favor and check the version of Windows and throw an error if it is not a supported version. Under no circumstances should you bypass with a warning, because a warning is still a success.

There is at least one noted exception to this and that is low-level packages that are meant as dependencies that need to be present even if they do not install anything. These are things like KBs that only need to be installed on some versions of Windows. If the package failed and it was a dependency of a higher level package that installed software, it would cause issues attempting to install that software on different versions of Windows. Since about 5% of the packages apply to this exception, stick with the above thoughts for packages.

NOTE: We will ultimately enhance the nuspec and take care of this for you automatically. Until we get there, follow the above avenue.

Installation Paths

As the package maintainer, you decide where the packaged application is installed or extracted to. Depending on your type of application (see "What distinction does Chocolatey make between an installable and a portable application?" at the bottom of the FAQ) there are a couple of suitable locations (not listed in any particular order):

1. The default installation path of your .msi/.exe setup file

The original creator probably had a reason for choosing a specific default installation path.
If you think, the user should be able to customize this path and you, the package maintainer, know how to pass a custom path on to the installer, then you should use %ChocolateyBinRoot%.

2. The package directory in %ChocolateyInstall%\lib\mypackage

You can extract the application within the package directory itself (or even ship an extracted version with the package). This allows Chocolatey to automatically find executables and put those on %path%.

3. Path provided by the Get-BinRoot helper - will be deprecated later (closer to v1) but okay to use for now

The path returned by the helper Get-BinRoot can be used as the parent directory for the installation. Get-BinRoot will return the value of the environment variable %ChocolateyBinRoot%. If the value does not contain a drive reference, the system drive will be prepended. If the environment variable is not set, the default path (C:\Tools C:\Chocolatey\bin) will be returned.

As an example, MinGW uses %ChocolateyBinRoot%. If the environment variable is not set, it will be set to c:\tools and MinGW will install to C:\Tools\MinGW by default. If %ChocolateyBinRoot% is set to "C:\Common\bin", MinGW installs to C:\Common\bin\MinGW.

%ChocolateyBinRoot% gives the Chocolatey user a way of controlling where packages are installed. If you want to allow customizing the installation path, then this is currently the way to go.

Make it clear in the package description

No matter how you decide, you are advised to state the default installation directory in your package description. This prevents confusion about where the application will end up being installed.

If you allow customizing the installation path, then append instructions on how to do that, too.


Prior to choco version 0.9.10, there is no dedicated automation script for upgrade scenarios. Instead, your chocolateyInstall.ps1 script should support installing/upgrading on top of any previous versions of your package.

More recent versions of choco (0.9.10+) give you the option of supplying a chocolateyBeforeModify.ps1 script.
If applicable, the version of this script from the currently installed package will be run before subsequent
chocolateyInstall or chocolateyUninstall scripts.


Uninstalling is handled by a chocolateyUninstall.ps1 script, which should be in your package's tools directory, next to chocolateyInstall.ps1. All the usual helper reference are available. If your package doesn't uninstall cleanly, people will get grumpy because they'll have to manually clean up after you. Be a good human being and write an uninstaller.

Dependency Chaining

You can make packages that depend on other packages just by adding those dependencies to the nuspec. Take a look at ferventcoder.chocolatey.utilities nuspec.

Avoid folders named "content"

Do not use a folder named "content" in your package. NuGet attaches a special meaning to this folder and will not allow you to have dependencies on packages that have content folders without also having a content folder. It's turtles all the way down until we or NuGet removes this limitation.

Naming your package

The title of your package (<title> tag in the nuspec) should be the same as the name of the application. Follow the official spelling, use upper and lower case and don't forget the spaces. Examples of correct package titles are: Google  Chrome, CCleaner, PuTTY and FileZilla. The title will appear on the left side in the package list of the Chocolatey gallery, followed by the version.

There are some guidelines in terms of the package id (<id> tag in the nuspec):

These guidelines are already commonly applied on packages for all major Linux distributions, because they lead to a more consistent look of software repositories, easier to remember package id's and less considerations about the naming for package creators.

Note that a lot of packages in the Chocolatey Gallery don't follow these guidelines. The simple reason is that the affected packages were created before the introduction of these guidelines.

If you are going to offer a package that has both an installer and an archive (zip or executable only) version of the application, create three packages   - see Portable vs Installable and Install, Portable, and Meta/Virtual Packages

Package description and release notes

The <description> of the package should contain a short text or at least a few words about the software for which the package is made. Here are a few things that should be respected:

Versioning Recommendations

Versioning can be both simple and complicated. The best recommendation is to use the same versioning that the installable/portable application uses. With Chocolatey you get four version segments. If the application only uses 1, 2 or 3 version segments, follow suit.

If the 4th segment is used, some folks like to drop the segment altogether and use that as only the package fix notation using one of the notations in the next section. There is no recommendations at this time.

Package Fix Version Notation

Package fix version notation ONLY applies when you are making a fix to the package because the existing version of a package is incorrect in some way. So if the software is 1.1.0, in a normal scenario the package version should be 1.1.0. If you find that the 1.1.0 package has an issue and you need to fix the package but keep the same version of the software, that is where package fix version notation comes into play. You would end up with both a 1.1.0 package and a 1.1.0.YYYYMMDD version of the package.

NOTE: This doesn't apply to packages on the community feed (aka that are still under review (not yet approved). Please read the instructions given in email for resubmitting the same version.

If you need to fix an approved package for some reason, you can use the fourth version element (aka segment) for a package fix notation. There are two recommended methods of package fix version notation:

Date Package Fix Version Notation is recommended because one can ascertain what it is immediately upon seeing it, where sequential is not obvious on sight whether it is part of the software versioning or something special with the package.

Package fix version notation is only acceptable in the fourth segment. Do not use any of the other segments for package fix notation. If an application only uses 1 or 2 version segments, add zeros into the other segments until you get to the 4th segment (i.e.

When the fourth segment is already used, it is recommended to add two zeroes (00) to the end of the version. Then when you need to fix, you just increment that number. So if the package was ruby and the version was 2.0.0-p353, the package is (adding the two zeroes at the end). Then a fix would be and so on. WARNING: If you decide to add a secondary set of numbers to the fourth segment, you MUST ALWAYS include that secondary set of numbers while the other three version segments are the same. The reason - if you fix .1 to .100, then release .2, .100 is greater than .2 because versioning doesn't look at the ".", only the number in the element. So 100 is greater than 2.

Internationalization and localization of packages

For Chocolatey, internationalization and localization of packages is very important, because it has users from all over the world. Many applications support multiple languages, but they use several different methods to achieve that. Therefore, there is no standard how internationalization/localization has to be integrated into packages. However, here are a few examples of packages that use various techniques. You can use them as inspiration for new packages:

Package icon guidelines

If there is an icon which is suitable for your package, you can specify it in the <iconUrl> tag in the nuspec. But there are a few things you should consider:

The icon shown on the package page is saved, and served, locally to mitigate against cross scripting attacks and to prevent getting non HTTPS assets errors on the website. Sometimes the page loads faster than the image can be served and the default image gets cached and as a result the new package icon may not be shown until you clear the browser cache for and wait 3 hours before reloading the page.

How do I exclude executables from getting shims?

If you have executables in the package or brought into the package folder during PowerShell run and you want to exclude them you need to create an empty file named exactly like (case sensitive) the executable with .ignore suffixed on the end in the same directory where the executable is or will be.

Example: In the case of Bob.exe you would create a file named Bob.exe.ignore and that file would not get a redirect batch link. The Chocolatey package has an example of that. To further expand, bob.exe.ignore would not work because it doesn't have the correct casing.

Here's a great programmatic example:

$files = get-childitem $installDir -include *.exe -recurse

foreach ($file in $files) {
  #generate an ignore file
  New-Item "$file.ignore" -type file -force | Out-Null

How do I set up shims for applications that have a GUI?

If you don't want to see a hanging window when you open an application from the command line that was set up with Chocolatey, you want to create a file next to the executable that is named exactly the same (case sensitive) with .gui suffixed on the end.

Example: In the case of Bob.exe you would create a file named Bob.exe.gui and that file would be set up as a GUI application so the window will call it and then move on without waiting for it to finish. Again, bob.exe.gui would not work because it doesn't have the correct casing.

Build Your Package

Open a command line in the directory where the nuspec is and type choco pack. That's it.

Testing Your Package

NOTE: We strongly suggest the following should be performed in a VM and not on your machine.

NOTE: Testing your package can be done in the same way as the verifier - take a look at Chocolatey Verifier Testing.

To test the package you just built, open a command line shell and navigate to the directory where the *.nupkg file is located. Then type:

choco install packageName -dv -s .

This will install the package right out of your source. As you find things you may need to fix, using --force (-f) will remove and reinstall the package from the updated *.nupkg. If you are specifically testing chocolateyBeforeModify.ps1, you need to be testing upgrade and uninstall scenarios. You need to install a version of the package with this file first as before modify is like uninstall, it runs from the installed package, not the package you are installing (like chocolateyInstall.ps1 does).

NOTE: Using Force --force (-f) should only be done in subsequent testing where you are reinstalling the same package that you've changed and should NOT be used in regular use scenarios. It should definitely not be in scripts.

NOTE: If you are using a Semver dash in your package version (such as 1.0.0-beta), you will need to use the -pre switch or else you will get Unable to find package errors from choco install. You can also specify -version 1.0.0-beta to try to install that exact version.

. points to the current directory. You can specify multiple directories separated by a semicolon;

When your nuspec specifies dependencies that are not in your source, you should add their paths to the source directory. E.g. in the case of Chocolatey itself:

      <dependency id="chocolatey" version="" />

You'll need to append the API path like so:
-source "'.;'" (note the double quotes bookending the apostrophes here, use %cd% in cmd.exe or $pwd in Powershell.exe if . doesn't resolve). See passing options with quotes. Note: If you need to do this, please ensure you run choco pack first. This method of passing a source won't work calling a nuspec or nupkg directly as it will override the source passed to the local folder.

You can also use the -debug switch on choco install to provide more information.

NOTE: Do not call install with .nupkg - pointing to a file explicitly overrides source. You must call your install with the package name, not the nupkg file and location. You've already specified for choco to look in a local source with -s "'.;'". Call choco install dude -s "'.;'", not choco install .\dude.nupkg -s "'.;'".

Alternative testing strategy

You can also type choco install -fdv path/to/nuspec and choco will build the nupkg and attempt to install it.

NOTE: This is not recommended if you are passing install arguments or package parameters due to some weirdness, and definitely does not work with passed sources as it need to override that with the local folder once it builds the package. Most likely you will want to stick with the recommended strategy.

Push Your Package

To push your package after you have built and tested it, you type choco push packageName.nupkg -s sourceLocation where packageName.nupkg is the name of the nupkg that was built with a version number as part of the package name and sourceLocation is the location of the source you want to push to (e.g. -s for chocolatey's community feed). You must have an api key for set. Take a look at choco push

You can also log into and upload your package from there (not recommended for packages over 2MB).

Automatic packaging?

Yes - Automatic Packaging

Becoming a primary maintainer of an existing package

See Package Maintainer Handover