How-to Guides

Use the normal Nova loop: scaffold → copilot guidance → build → test → import → reload

Most of your time with NovaModuleTools should stay in this loop. Once you are comfortable here, packaging, upload, publish, and release become much easier to reason about.

Create the project

Nova supports two scaffold styles:

  • minimal scaffold for a clean new module
  • example scaffold for a working sample you can inspect and adapt

Create either scaffold style

Showing: PowerShell

PS> Initialize-NovaModule -Path ~/Work
PS> Initialize-NovaModule -Example -Path ~/Work

Both scaffold styles ask the same core project questions, and both now offer an optional Agentic Copilot starter package after the Git prompt.

The starting version prompt now defaults to 0.1.0-preview, so new projects begin on Nova's prerelease-friendly starter line unless you choose a different version. Before the first question, Nova also checks whether a newer NovaModuleTools release is available and warns without blocking the scaffold flow. When you enable Git in either scaffold style, Nova also creates or updates a default .gitignore in the generated project root so common local and CI artifact paths are ignored without overwriting existing rules.

The Agentic prompt defaults to No, and the package follows Nova's maintained agentic guidance through a filtered starter mirror, including Nova build/test/package expectations, project.json Manifest.PowerShellHostVersion compatibility guidance, strict ScriptAnalyzer guidance without excluded rules, generated dist module files, command-help ownership, source-mirrored test guidance, instructions to fix ScriptAnalyzer findings reported by run.ps1 before handoff, explicit public/private PowerShell file ownership guidance, a best-effort source/helper-script maintainability guidance plus separate test-design guidance delivered through Agentic Copilot guidance files, explicit PSScriptAnalyzer workflow guidance for ./scripts/build/Invoke-ScriptAnalyzerCI.ps1, ./run.ps1, and focused Invoke-ScriptAnalyzer usage, separate Invoke-NovaTest unit-test and Test-NovaBuild build-validation guidance that forbids direct Invoke-Pester, explicit valid-PlatyPS help guidance for docs/<ProjectName>/en-US/*.md using New-MarkdownCommandHelp, Update-MarkdownCommandHelp, and Test-MarkdownCommandHelp, with a matching help file required for every new public entry point, and a strict file-ending rule for changed or generated text files.

The generated project.json also starts with Nova's standard Pester defaults, including explicit source coverage paths for src/public/, nested src/private/ helper folders, and src/classes/. The minimal scaffold keeps CodeCoverage disabled until you opt in, while the packaged example scaffold enables it by default so Test-NovaBuild can measure src/**/*.ps1 without requiring a prior build.

When you answer Yes, Nova also asks for a short project name used in generated guidance placeholders such as Invoke-<ShortName>*. For NovaModuleTools the short name is Nova, but it could also have been NMT.

Use the example scaffold when you want the shortest path to understanding a real project layout, test suite, and package configuration. Use the minimal scaffold when you already know the structure you want.

Apply the copilot workflow to an existing project

Use this workflow when the project already exists and you want Nova to add or refresh its managed Agentic Copilot guidance without recreating the module scaffold.

Apply or refresh the managed scaffold

Showing: PowerShell

PS> Invoke-NovaAgenticCopilotScaffold -ShortName NMT
PS> Invoke-NovaAgenticCopilotScaffold -Path ~/Work/MyModule -ShortName NMT -OverrideWarning

The target directory must contain a valid project.json. Nova reads ProjectName and Description from that file and requires an explicit short name on every run for generated placeholders such as Invoke-<ShortName>*.

Nova refreshes only the managed Agentic guidance paths under .github/ together with AGENTS.md and CONTRIBUTING.md. Existing README.md, CHANGELOG.md, and RELEASE_NOTE.md are preserved and are created only when they are missing.

By default Nova prompts before it overwrites the managed scaffold paths.

Use -OverrideWarning only when you intentionally want a non-interactive apply, and use -WhatIf when you want to preview the changes first.

Build the module

Build the current project

Showing: PowerShell

PS> Invoke-NovaBuild
PS> Invoke-NovaBuild -ContinuousIntegration

The build step turns your project into a real PowerShell module under dist/<ProjectName>.

Use the continuous-integration form when the same CI/self-hosting session must keep using the freshly built module after the build completes. Nova then re-imports the new dist/ output before returning.

What build includes

  • generated .psm1 output
  • generated manifest
  • external help generation from the command-help markdown
  • resource copying
  • duplicate function validation when enabled

If SetSourcePath is enabled, the generated module includes # Source: markers before each source block. If Preamble is configured, those lines are written at the top of the generated module before the rest of the content.

Run the tests

Run the Nova test workflow

Showing: PowerShell

PS> Invoke-NovaTest
PS> Test-NovaBuild
PS> Invoke-NovaTest -TagFilter unit,fast
PS> Test-NovaBuild -ExcludeTagFilter slow
PS> Invoke-NovaTest -OutputVerbosity Detailed -OutputRenderMode Ansi
PS> $credential = Get-Credential
PS> $container = New-PesterContainer -Path 'tests/public/PublishNovaModule.Tests.ps1' -Data @{ Credential = $credential }
PS> Invoke-NovaTest -PesterConfigurationOverride @{ Run = @{ Container = @($container) } }

Invoke-NovaTest reads the Pester configuration from project.json, runs the unit-test flow, and writes results to artifacts/UnitTestResults.xml. Test-NovaBuild runs the build-validation integration flow and writes results to artifacts/TestResults.xml.

Starter projects already include the matching Pester.CodeCoverage block in project.json, but keep it disabled until you opt in. When you set Pester.CodeCoverage.Enabled to true, Invoke-NovaTest also writes JaCoCo coverage to artifacts/coverage.xml and stops if the measured coverage percentage is lower than the configured CoveragePercentTarget.

Use -Build, --build, or -b when you want Nova to rebuild the project before the test workflow starts.

Important behavior: when BuildRecursiveFolders is true, nested test files are discovered. When it is false, Nova stays closer to top-level Pester-style discovery.

Invoke-NovaTest also supports a guarded -PesterConfigurationOverride hook for runtime-only unit-test data. In v1 Nova accepts only Run.Container, so you can inject values such as PSCredential with file-backed New-PesterContainer -Path objects while Nova still owns discovery, coverage, result files, and the rest of the test workflow.

Use -WhatIf if you want to preview the test run and output path without creating the results directory or invoking Pester.

Import the built output

This is the recommended way to work with Nova-built modules during development:

Import the built module from dist

Showing: PowerShell

PS> $project = Get-NovaProjectInfo
PS> Import-Module $project.OutputModuleDir -Force

Importing from dist/ keeps your runtime behavior aligned with what Nova will package and publish later.

Reload safely after changes

When you edit source files, rebuild and reload the module instead of trusting the module already loaded in memory:

Refresh the module after source changes

Showing: PowerShell

PS> $project = Get-NovaProjectInfo
PS> Remove-Module $project.ProjectName -ErrorAction SilentlyContinue
PS> Invoke-NovaBuild
PS> Import-Module $project.OutputModuleDir -Force

This avoids stale function definitions and stale resource loading.

When local publish changes the story.

Publish-NovaModule -Local reloads the published module from the local install path after a successful publish. That is different from the normal build/import loop, which works from dist/.

CI/self-hosting note.

When a later command in the same session must switch back to the built dist/ module, use Invoke-NovaBuild -ContinuousIntegration so Nova restores the built module state automatically.

Move into packaging and release when you are ready

Once the build/test/import loop feels natural, the next question is usually one of these:

If you want to… Go here next
create package artifacts Packaging & Delivery → Create package artifacts
upload package files to a raw endpoint Packaging & Delivery → Upload package artifacts
publish the module locally or to PowerShell Gallery Packaging & Delivery → Publish to a PowerShell repository
run a full release workflow with version bumping Packaging & Delivery → Run the release workflow
tune the project configuration project.json Reference