psake 5.0.0 Is Here: Declarative Tasks, Caching, and Structured Output
After years of steady iteration on the v4 line, we're thrilled to announce the release of psake 5.0.0—the biggest update to the PowerShell build automation framework since its inception. This release introduces a declarative task syntax, two-phase compilation, local file-based caching, structured output, and first-class CI integration. Here's everything that's new.
Declarative Task Syntax
The flagship feature of psake 5 is a new hashtable-based syntax for defining tasks. Rather than relying on positional parameters, you can now describe tasks as structured data with named, validated keys:
Task 'Build' @{
DependsOn = 'Clean'
Action = { dotnet build -c $Configuration }
}
Every key is validated at compile time—typos like DependsOn or Action are caught before a single task runs. The original parameter-based syntax still works, so your existing build scripts don't need to change.
Two-Phase Compilation
psake 5 separates build file loading from task execution. When you call Invoke-psake, the dependency graph is built first via a topological sort, and circular dependencies are caught at compile time rather than halfway through a run. This means faster, clearer feedback—and no more builds that silently fail mid-execution.
You can also use the new -CompileOnly parameter to inspect the build plan without running anything:
Invoke-psake -CompileOnly
This is especially useful in code review and CI pre-flight checks.
Local File-Based Caching
For tasks that process files—compilation, transpilation, packaging—psake 5 introduces content-addressed caching. Declare Inputs and Outputs on a task, and psake will SHA256-hash the inputs to determine whether the task actually needs to run:
Task 'Build' @{
Inputs = 'src/**/*.cs', 'src/**/*.csproj'
Outputs = 'bin/**/*.dll'
Action = { dotnet build -c $Configuration }
}
Cache state is stored in .psake/cache/. If nothing changed, the task is skipped and the build report marks it as Cached. To bypass caching for a single run, pass -NoCache:
Invoke-psake -NoCache
And to clear the cache entirely, use the new Clear-PsakeCache function.
Structured Build Results
Invoke-psake now returns a PsakeBuildResult object containing per-task metrics, success status, duration, and error information. Scripting against build output no longer requires parsing console text:
$result = Invoke-psake
$result.Tasks | Where-Object Cached | Select-Object Name, Duration
The $psake.build_success variable is still set after every run, so existing CI scripts that check build status continue to work without modification.
CI-Native Output Formats
Building for GitHub Actions? Pass -OutputFormat GitHubActions and psake will emit workflow annotations—warnings and errors that surface directly in pull request diffs. For pipelines that consume build data programmatically, -OutputFormat JSON outputs the full PsakeBuildResult as structured JSON.
The output format can also be set via the PSAKE_OUTPUT_FORMAT environment variable, making it easy to configure in CI without changing your build scripts.
Quiet Mode
The new -Quiet parameter suppresses all console output while still returning the full PsakeBuildResult object—including complete error records for any failed tasks. No output is swallowed; it's simply not printed.
This is particularly valuable when psake is invoked by an LLM agent or AI coding tool. Console build logs are noisy: progress messages, separator lines, and timing output all burn through context that the model could spend on the actual problem. With -Quiet, the agent gets silence on stdout and a precise, structured result it can inspect programmatically:
$result = Invoke-psake -Quiet
if (-not $result.Success) {
# Full error records are available—no log scraping needed
$result.Tasks | Where-Object { $_.Error } | ForEach-Object {
Write-Host "Task '$($_.Name)' failed: $($_.Error.Message)"
}
}
Rather than parsing wall-of-text build output, the agent can check $result.Success, iterate $result.Tasks, and read $_.Error directly—structured data that maps cleanly to a tool call response. Pair this with -OutputFormat JSON if you need to pass the result across a process boundary or into a prompt.
The psake Agent Skill has been updated for 5.0 and is available through the LLM tools marketplace. Install it into Claude, GitHub Copilot, or any Agent Skills–compatible client to give your assistant first-class knowledge of the new declarative syntax, caching, structured output, and migration patterns covered in this post.
New Testing APIs
Two new functions let you inspect and test your build scripts without running a full build:
Get-PsakeBuildPlan— Returns the full execution plan for a build file without running it. Inspect task order, dependencies, and caching configuration in tests.Test-PsakeTask— Executes a single named task with custom variable overrides. Great for unit-testing individual task logic in isolation.
Version Declaration
Build files can now declare the minimum psake major version they require:
Version 5
If someone runs your build script on an older psake installation, they get a clear error instead of a confusing failure deep inside a task.
Hashtable Properties
The Properties block gains a more concise hashtable syntax alongside the original scriptblock form:
Properties @{
Configuration = 'Release'
OutputDir = './artifacts'
}
Both styles are supported and can be mixed within the same build file.
NO_COLOR Support
psake 5 respects the $env:NO_COLOR convention for suppressing colored output. Set it in environments where ANSI escape codes cause issues—terminals without color support, log aggregators, or accessibility tools.
Breaking Changes
psake 5 is a major version, and it includes a few breaking changes. Most build scripts will work without modification, but there are three things to check:
- Rename
default.ps1topsakefile.ps1— Thedefault.ps1fallback file name is no longer auto-detected. - Replace the wrapper scripts —
psake.ps1andpsake.cmdare removed. UseImport-Module psake; Invoke-psakeinstead. - Update Framework calls — .NET Framework versions below 4.0 are no longer supported, and the default is now 4.7.2. The
$frameworkglobal variable is removed; useFramework '4.7.2'instead.
Additionally, the minimum required PowerShell version is now 5.1 (raised from 3.0), and the output handler configuration properties have been removed in favor of the new -OutputFormat and -Quiet parameters.
Full details are in the migration guide.
Upgrading
# Install from the PowerShell Gallery
Install-Module -Name psake -MinimumVersion 5.0.0 -Force
# Verify the version
Get-Module psake -ListAvailable | Select-Object Version
Then run your existing build to check for any breaking changes. For most projects, it'll just work.
psake 5 is the result of years of community feedback, and we're excited to see what you build with it. If you run into anything unexpected, open an issue. And if you're using the new features in interesting ways, we'd love to hear about it.
