Plaster for PowerShell: one manifest turns into a whole module skeleton
Plaster is a template-based file and project generator written in PowerShell.
At a glance
- What is it?
- Plaster is a template-based file and project generator written in PowerShell, built to scaffold module projects, Pester tests and DSC configurations from a manifest that lists parameters and content actions. It earns a place in a PowerShell team workflow, with gaps around rollback, custom output and multi-language scaffolding.
- Who is it for?
- Plaster fits PowerShell platform teams that generate module skeletons repeatedly and can afford to keep a template directory under version control, but it does not fit teams that need non-PowerShell scaffolds, a hosted template catalogue, or a rollback story, since the documentation describes neither.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 34 days ago.
- What is it written in?
- Mainly PowerShell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Plaster answers one narrow question: what should a new PowerShell project look like
Plaster is a template-based file and project generator written in PowerShell. Its stated purpose is the creation of PowerShell module projects, Pester tests, DSC configurations, and more, and the README frames it around crafted templates that let a user fill in details and choose from options to reach a desired output. That is a narrower job than most scaffolding tools take on, and the narrowness is the point.
If your team ships one PowerShell module after another and every new repository repeats the same folder layout, the same boilerplate module manifest, the same Pester stub and the same optional Git folder, then the value of Plaster is that the repeating part lives in a template directory once and every later project is generated from it. The reader who benefits is a PowerShell developer or platform engineer who already writes scaffolding scripts by hand and is tired of copying. The README does not describe support for any language other than PowerShell, so a template that needs to scaffold a Python package, a Node service or a container has no documented path here. It also does not describe a hosted catalogue of community templates. Discovery happens on your own machine, through Get-PlasterTemplate.
A template is a directory holding a manifest, source files and delimiter-tagged files
The unit of work in Plaster is a template directory. Inside it sit three kinds of thing: a manifest file, which is either plasterManifest.xml or plasterManifest.json or both; source files and directories that get copied or processed; and template files, whose content is expanded using <%= and %> delimiters. The manifest is what makes the directory a template rather than a folder of examples.
The manifest describes parameters the user fills in and content actions the generator performs. The action list is short and fixed. A file action copies files or directories. A templateFile action copies and expands a template file. A modify action rewrites existing files with search and replace. A newModuleManifest action generates a PowerShell module manifest, a requireModule action verifies that required modules are installed, and a message action displays text to the user. Because content is expressed as data, the same template behaves the same whether it is driven interactively or through named parameters, and the same action vocabulary works for a module project, a test folder or a DSC configuration.
Installing from the PowerShell Gallery and generating the first module
Installation is a single module install, or a clone plus an import if you prefer to work from source. The gallery route is the one the README marks as recommended.
Install-Module -Name Plaster -Scope CurrentUserThe source route leaves the module manifest to be imported by path:
git clone https://github.com/PowerShellOrg/Plaster.git
Import-Module .\Plaster\Plaster\Plaster.psd1Once the module is loaded, Get-PlasterTemplate lists what is available, and the pipeline filters that list down to one template. Running it without parameters walks the user through the prompts interactively:
# Discover available templates
Get-PlasterTemplate
# Create a new PowerShell module (interactive)
$template = Get-PlasterTemplate | Where-Object Name -eq NewPowerShellScriptModule
Invoke-Plaster -TemplatePath $template.TemplatePath -DestinationPath .\MyNewModuleThe same invocation with named parameters produces the output without any prompting at all, which is the form you want in CI or in a bootstrap script:
# Non-interactive with parameters
Invoke-Plaster -TemplatePath $template.TemplatePath -DestinationPath .\MyModule `
-ModuleName 'MyModule' -ModuleDesc 'My awesome module' -Version '1.0.0' `
-FullName 'Your Name' -License MIT -Options Git,Pester,PSScriptAnalyzerNote the split between the two paths. Template discovery is by template path, not by template name, so anything not returned by Get-PlasterTemplate has to be addressed with its own path.
Parameter types decide what a template is allowed to ask
Prompts in a manifest come from a fixed set of parameter types. A text parameter takes free-form input. A choice parameter takes a single selection. A multichoice parameter takes several. Two further types read identity from git configuration: user-fullname and user-email. The type matters beyond the prompt, because it shapes what a non-interactive invocation can pass on the command line and what the generator can do with the value afterwards.
The value of a parameter also drives conditional content. A content entry can carry a condition expression, so an item is only emitted when the answer matches:
{
"type": "file",
"source": "tests.ps1",
"destination": "Tests/${ProjectName}.Tests.ps1",
"condition": "${Features} -contains 'Tests'"
}That is how a single template offers optional pieces such as a test folder without producing empty directories for people who do not want them. The same parameters can be constrained, since a parameter accepts a pattern that the answer must satisfy:
{
"name": "ModuleName",
"type": "text",
"pattern": "^[A-Za-z][A-Za-z0-9_]*$",
"prompt": "Enter a valid module name"
}A pattern is a guard rail, not a validator with a report. The README does not say what happens when a value fails the pattern, so treat the pattern as a way to keep obviously wrong names out, not as a guarantee that every downstream name is legal for PowerShell.
XML and JSON manifests differ in variable syntax, escaping and default values
The alternative approach inside Plaster is the older XML manifest, and the two formats are genuinely different rather than cosmetic variations of one another. JSON arrived with Plaster 2.0 and the README frames it as the format for new templates, with XML still supported in full.
The differences are concrete. In XML, a destination path refers to a parameter as ${PLASTER_PARAM_ModuleName}. In JSON, it is simply ${ModuleName}. Multichoice defaults are a comma-separated string in XML and a real array in JSON. Special characters need XML entity escaping, so an ampersand is written & in XML and stays & in JSON. Schema validation also differs, with XSD for XML and a JSON Schema for JSON. A JSON manifest points at that schema through its own $schema field, with a schemaVersion and a metadata block carrying the name, title, description, version and templateType.
Because both formats can sit in the same template directory and Plaster detects them automatically, migration is a per-template decision rather than a cutover. Converting an existing XML manifest is a two-command pipeline:
# Or pipe directly
Test-PlasterManifest -Path .\plasterManifest.xml | ConvertTo-JsonManifest | Set-Content .\plasterManifest.jsonA JSON template starts the same way, and the scaffolded manifest is designed to be opened in an editor with schema support:
# Create a new JSON manifest
New-PlasterManifest -TemplateName MyTemplate -TemplateType Project -Format JSON
# Edit the generated plasterManifest.json with VS Code for full IntelliSense
code plasterManifest.jsonVariable references inside copied files need the same attention during conversion. A file action written for XML looks like this:
<file source="template.ps1" destination="${PLASTER_PARAM_ModuleName}.ps1"/>and its JSON equivalent drops the PLASTER_PARAM prefix.
Where Plaster leaves gaps: rollback, custom output and shared templates
Plaster is good at the narrow job, and it stops at the edges of that job in ways worth knowing before you rely on it.
There is no rollback story. The README does not document a dry run, a preview mode, or a way to undo a completed generation. Generation writes into a destination path, so the safe pattern is to point it at an empty directory and treat the result as disposable. If you need a partially applied change, the documentation offers no procedure.
Custom output is similarly bounded. The action list is fixed at file, templateFile, modify, newModuleManifest, requireModule and message. Anything outside that vocabulary, such as generating a service registration or a CI pipeline definition from a template of your own design, has to be expressed through the template file machinery rather than through a first-class action.
Sharing is local. Templates can be embedded in a PowerShell module so that module consumers find them, but there is no documented online gallery, versioning story for shared templates, or way to update a template already installed on a machine. Localization exists only as culture-specific manifest files such as plasterManifest_fr-FR.json and plasterManifest_de-DE.json, so a translated template is a separate file rather than a runtime switch.
Release pace and what the MIT licence means in practice
The repository is not archived, and the last push was on 2026-09-19. Three recent releases sit close together: 2.1.5 on 2026-09-19, 2.1.4 on 2026-09-13, and 2.1.3 on 2026-06-19. That gives a picture of a project that ships small increments, with a gap of about three months before the 2.1.3 release.
Licensing is MIT, so the code carries a permissive licence with no restriction on commercial use, modification or redistribution beyond keeping the copyright notice and licence text. That is a statement about the licence terms and not legal advice, and anyone with specific obligations should read the LICENSE file in the repository.
The upgrade cost for a consumer is low but not zero. Templates written against the XML format keep working, since the README describes the JSON support as introducing no breaking changes. A team that adopts JSON will want its templates to reference the version 2 schema, and a module that embeds templates declares a minimum Plaster version, so raising that floor is a deliberate edit to the module manifest rather than a free upgrade.
Editorial conclusion
Plaster fits PowerShell platform teams that generate module skeletons repeatedly and can afford to keep a template directory under version control, but it does not fit teams that need non-PowerShell scaffolds, a hosted template catalogue, or a rollback story, since the documentation describes neither. Before adopting it, run Invoke-Plaster once against a throwaway destination path and diff the output against the project layout your team actually wants, because the choices you get are only the parameters you declared.
Frequently asked questions
How do I install Plaster for the current user?
Run Install-Module -Name Plaster -Scope CurrentUser, which the README marks as the recommended route. You can also clone the repository and import the module manifest directly with Import-Module .\Plaster\Plaster\Plaster.psd1.
What is the difference between a JSON manifest and an XML manifest in Plaster?
JSON manifests, introduced in 2.0, use ${Name} for parameters while XML uses ${PLASTER_PARAM_Name}, and they store multichoice defaults as real arrays rather than comma-separated strings. JSON also avoids XML entity escaping and is validated by a JSON Schema instead of XSD, while existing XML templates keep working unchanged.
Can a Plaster template require certain PowerShell modules to be present?
Yes, the manifest has a requireModule content action that verifies required modules are installed before the template continues. The README does not list a fixed prerequisite set for Plaster itself beyond the install commands.
Does Plaster support localized or translated templates?
Templates can be localized by shipping culture-specific manifest files, such as plasterManifest_fr-FR.json for French and plasterManifest_de-DE.json for German, alongside the default plasterManifest.json. Localisation is done by file selection rather than by a runtime setting.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/powershellorg-plaster)Was this useful?