NugetUtil is a small CLI that discovers packable .csproj files, builds them with dotnet build, regenerates .nuspec files, packs with dotnet pack, and optionally pushes packages with dotnet nuget push.
It also supports Dynamics 365 FO deployable package repacking mode via fopack.
fopack accepts either a deployable package ZIP or a prepared model directory.
Given a repo root, NugetUtil will:
- Discover
*.csprojrecursively - Identify package projects (
PackageId+Version+ notIsPackable=false) - Build each package project with
dotnet build -c <Configuration> - Regenerate
<PackageId>.nuspecin each package project folder - Pack with
dotnet pack(from nuspec) - Optionally push with
dotnet nuget push
By default, NugetUtil computes filesystem fingerprints and only regenerates/packs packages that changed.
Nuspec mode is the default behavior and is required when a package project directly references non-packable projects.
- .NET SDK installed (
dotneton PATH)
Recommended install location:
C:\nuget\
Suggested layout:
C:\nuget\nugetutil.exe
Add install folder to PATH:
- Open System Properties → Advanced → Environment Variables.
- Under User variables (or System variables), edit
Path. - Add:
C:\nuget\ - Open a new terminal and verify:
nugetutil --versionConfig file path:
%APPDATA%\NugetUtil\config.json- Example expanded path:
C:\Users\<you>\AppData\Roaming\NugetUtil\config.json
State file path:
%APPDATA%\NugetUtil\state.json
Notes:
- NugetUtil creates a starter
config.jsonon first run if missing. apiKeycan be set in config or provided at runtime with-api-key.
nugetutil ["<rootPath>"] [options]If <rootPath> is omitted, NugetUtil uses the current directory.
Current directory must contain .sln/.csproj (or subfolders containing .sln/.csproj).
Examples:
nugetutil "C:\Dev\sample-repo" -pushnugetutil "C:\Dev\sample-repo" -push -source "PrivateFeed"nugetutil "C:\Dev\sample-repo" -push -source "PrivateFeed" -api-key "YOUR_API_KEY"nugetutil "C:\Dev\sample-repo" -autobump -bumplevel patchnugetutil "C:\Dev\sample-repo" -forcenugetutil fopack "C:\Downloads\Contoso.Module.1.2.3.zip" -output "artifacts\\fo"nugetutil fopack "C:\Downloads\Contoso.Module.1.2.3.zip" -output "artifacts\\fo" -save-nuspecnugetutil fopack "C:\Temp\SampleModule" -output "artifacts\\fo" -save-nuspec-
-push- Push generated
.nupkgfiles after packing. - Default:
false. - If no packages were rebuilt, NugetUtil can push matching existing
.nupkgfiles from the output folder.
- Push generated
-
fopack "<zip>"- Dynamics 365 FO mode: accepts either a deployable package ZIP or a prepared model directory.
- For ZIP input, extracts payload from
AOSService\Packages\files\*.zipinside the deployable package. - For directory input, expects a root
*.xreffile and package folders such asbin,AdditionalFiles,Reports, andResources. - Package id is inferred from the root
*.xreffilename (for examplePackagename.xref->Packagename). - Package version is inferred from file version of
bin\Dynamics.AX.<PackageId>.dll. - Output package preserves package root layout and includes root
*.xrefplus only the source folders that actually existed, frombin,AdditionalFiles,Reports, andResources. - Empty included folders are materialized with
_nugetutil.keeponly when that folder existed in the original source.
-
-save-nuspec- With
fopackor-deployable-package, saves the generated nuspec to the output folder as<PackageId>.nuspec. - If the file exists, it is overwritten.
- With
-
-source "<name>"- NuGet source name configured on your machine (for
dotnet nuget push --source). - Must also exist in config
sourceswhen-api-keyis not provided. - Default:
defaultSourcefrom config.
- NuGet source name configured on your machine (for
-
-api-key "<key>"- Overrides
apiKeyfrom config for push operations. - Useful for passing a temporary key from command line.
- If omitted, key is loaded from config source entry.
- Overrides
-
-configuration Release|Debug- Build configuration for
dotnet build. - Default:
Release.
- Build configuration for
-
-output "<folder>"- Output folder for generated
.nupkgfiles. - Relative paths are resolved under
<rootPath>. - Default:
artifacts\nuget(or config override).
- Output folder for generated
-
-skip-duplicate- Adds
-SkipDuplicatewhen pushing. - Default behavior comes from config (
behavior.skipDuplicate, defaulttrue).
- Adds
-
-verbose-build- Prints full
dotnet buildoutput for each package. - Default: concise build output (
- Build: succeededor build errors).
- Prints full
-
-force- Processes all discovered packages, ignoring fingerprint change detection.
- Useful when you want to regenerate/repack everything.
-
-autobump- Uses filesystem fingerprints to detect which packages need a version bump.
- Bumps changed packages and dependent packages, then packs only bumped packages.
- Also updates matching internal
PackageReferenceversions across discovered projects.
-
-bumplevel patch|minor|major- Version bump level used with
-autobump. - Default:
patch.
- Version bump level used with
-
-dryrun- Dry-run mode. Commands are printed but not executed.
-
-yes- Non-interactive push confirmation.
-
-include "<glob>"- Repeatable include glob for project discovery.
- If omitted, all discovered projects are considered (subject to excludes).
-
-exclude "<glob>"- Repeatable exclude glob for project discovery.
- Combined with config
behavior.excludeGlobs.
-
-v,--version- Prints NugetUtil version and exits.
Location:
%APPDATA%\NugetUtil\config.json
Autobump state file:
%APPDATA%\NugetUtil\state.json
State is used for both default changed-package detection and -autobump.
Behavior summary:
- default: fingerprint-based changed packages only
-force: all discovered packages-autobump: bump changed packages and dependent packages, then pack bumped packages- with
-pushand no rebuilds: push existing output packages that match discovered package IDs
On first run, if missing, NugetUtil creates a starter config automatically.
Example:
{
"defaultSource": "PrivateFeed",
"sources": {
"PrivateFeed": {
"apiKey": "REPLACE_WITH_YOUR_API_KEY"
}
},
"behavior": {
"skipDuplicate": true,
"outputFolder": "artifacts\\nuget",
"excludeGlobs": [
"**\\bin\\**",
"**\\obj\\**",
"**\\**Tests**\\**"
]
}
}Notes:
- API keys are stored in plain text by design.
-source/defaultSourceuses the NuGet source name configured on your machine.- NugetUtil masks API keys in command logs/output.
- Generates
<projectFolder>\<PackageId>.nuspecfrom scratch every run. - Uses package metadata from the package
.csproj. - Includes dependencies from package and referenced non-packable project package references.
- Resolves
$(PropertyName)versions from project properties andDirectory.Build.propsup the directory tree. - For internal package dependencies discovered in the same run, NugetUtil uses the latest discovered package version.
- Embeds non-packable referenced project outputs into
lib\<packageTfm>via<files>entries.
- Tracks package input fingerprints in
%APPDATA%\NugetUtil\state.json. - Detects changes from filesystem content (no git integration required).
- Marks changed packages for bump.
- Propagates bumps to dependent packages.
- Updates
<Version>in.csproj, regenerates nuspec, and packs bumped packages.
0success2invalid arguments/config3build failed4pack failed5push failed
The CLI prints:
Job finished successfully.on successJob failed with exit code: <code>on failure
nugetutil -hnugetutil --helpnugetutil -vnugetutil --version
Help/version invocations exit with code 0.