Levitate.Generator
1.0.1
dotnet add package Levitate.Generator --version 1.0.1
NuGet\Install-Package Levitate.Generator -Version 1.0.1
<PackageReference Include="Levitate.Generator" Version="1.0.1"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="Levitate.Generator" Version="1.0.1" />
<PackageReference Include="Levitate.Generator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add Levitate.Generator --version 1.0.1
#r "nuget: Levitate.Generator, 1.0.1"
#:package Levitate.Generator@1.0.1
#addin nuget:?package=Levitate.Generator&version=1.0.1
#tool nuget:?package=Levitate.Generator&version=1.0.1

Levitate
Compile C# automation methods into production-grade PowerShell at build time.
Levitate is a Roslyn source generator and automation toolkit for teams that want C# ergonomics with PowerShell output they can inspect, validate, save, execute, and ship. Mark a static C# method with [PowerShellScript]; Levitate translates the supported method body into PowerShell during compilation and generates a strongly named C# accessor for the script.
It is built for infrastructure automation, internal ops tools, admin portals, LLM-assisted runbooks, and deployment workflows where string-built scripts are too fragile.
What Levitate Gives You
| Area | Capability |
|---|---|
| Compile-time generator | Translate [PowerShellScript] methods into PowerShell while the project builds. |
| Runtime execution | Run generated scripts from C# and capture exit code, stdout, stderr, duration, lines, JSON, and key-value output. |
| Fluent builder | Build PowerShell scripts manually with Levitate.Core when source generation is not the right fit. |
| BCL mappings | Map common .NET APIs to PowerShell cmdlets for files, directories, paths, console output, services, registry, certificates, processes, environment variables, and more. |
| Pipelines and LINQ | Compose object pipelines with PS.Command(...) and translate a useful LINQ preview surface. |
| Ops modules | Use marker APIs for IIS, Active Directory, Azure, X509, registry, and service automation. |
| Safety diagnostics | Get diagnostics for unsupported constructs, raw PowerShell injection risk, Windows-only commands, and portability issues. |
| Generated artifacts | Emit generated .ps1 files under obj/Levitate/generated/ or copy them to a configured review folder. |
Install
For compile-time generation:
<ItemGroup>
<PackageReference Include="Levitate.Attributes" Version="1.0.1" />
<PackageReference Include="Levitate.Runtime" Version="1.0.1" />
<PackageReference Include="Levitate.Generator" Version="1.0.1"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false"
PrivateAssets="all" />
<PackageReference Include="Levitate.Build" Version="1.0.1" PrivateAssets="all" />
</ItemGroup>
For fluent script building without the source generator:
dotnet add package Levitate.Core --version 1.0.1
dotnet add package Levitate.Runtime --version 1.0.1
For starter projects:
dotnet new install Levitate.Templates::1.0.1
dotnet new levitate-console
dotnet new levitate-ops-tool
First Script
using Levitate;
using System;
using System.IO;
namespace Company.Automation;
public partial class MaintenanceScripts
{
[PowerShellScript]
public static void CleanTempFiles(string tempPath, int olderThanDays)
{
if (!Directory.Exists(tempPath))
{
Console.Error.WriteLine($"Missing path: {tempPath}");
return;
}
Console.WriteLine($"Cleaning {tempPath}");
PS.Raw("Get-ChildItem -Path $tempPath -File | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$olderThanDays) } | Remove-Item -Force");
}
}
Levitate generates a PowerShell script and a C# accessor:
var script = MaintenanceScripts.CleanTempFilesScript.PowerShell;
await MaintenanceScripts.CleanTempFilesScript.ExecuteAsync(
tempPath: @"C:\Temp",
olderThanDays: 14);
MaintenanceScripts.CleanTempFilesScript.SaveTo("clean-temp.ps1");
Generated PowerShell is ordinary, reviewable text:
param(
[Parameter(Mandatory=$true)]
[string]$tempPath,
[Parameter(Mandatory=$true)]
[int]$olderThanDays
)
if (-not (Test-Path $tempPath -PathType Container)) {
Write-Error "Missing path: $tempPath"
return
}
Write-Host "Cleaning $tempPath"
Get-ChildItem -Path $tempPath -File | Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-$olderThanDays) } | Remove-Item -Force
Package Map
| Package | Purpose |
|---|---|
Levitate.Attributes |
Public marker attributes and compile-time marker APIs: [PowerShellScript], PS.Raw, PS.Command, IIS, AD, Azure, RequiresModule, RequiresPowerShell, TargetPlatform. |
Levitate.Generator |
Roslyn source generator that emits script accessors and .ps1 artifacts. |
Levitate.Analyzers |
IDE/build diagnostics for the Levitate automation profile. |
Levitate.Build |
MSBuild props and targets for generated script output, validation, strict mode, and clean behavior. |
Levitate.Runtime |
Executes scripts through PowerShell and returns structured ExecutionResult data. |
Levitate.Core |
Fluent script builder, AST nodes, emitters, condition helpers, and cmdlet helpers. |
Levitate.Templates |
dotnet new templates for console and ops automation projects. |
Supported C# Translation
Levitate intentionally supports a clear automation profile instead of trying to become a full C# runtime inside PowerShell.
| C# surface | Generated PowerShell |
|---|---|
| Method parameters | param() block with typed, mandatory parameters |
string, int, long, double, bool, object |
PowerShell type annotations |
| Arrays and collections | T[] parameter typing for arrays, List<T>, IEnumerable<T>, and related collection interfaces |
Dictionary<TKey,TValue> |
hashtable |
DateTime, TimeSpan, Guid, Uri |
datetime, timespan, guid, string |
| Nullable value types | Unwrapped to the underlying PowerShell type |
| Variables and assignments | $name = value |
if, else if, else |
if, elseif, else |
foreach, for, while, do while |
PowerShell loop forms |
try, catch, finally |
PowerShell error handling with $ErrorActionPreference = "Stop" where needed |
switch |
PowerShell switch |
return, break, continue |
Native PowerShell keywords |
==, !=, <, <=, >, >= |
-eq, -ne, -lt, -le, -gt, -ge |
&&, ||, ! |
-and, -or, -not |
| Interpolated strings | PowerShell interpolation with subexpressions when needed |
Enums, const, booleans, null |
Folded into typed PowerShell literals |
| Nested namespaces and classes | Correct generated namespace and nested partial class wrappers |
BCL To PowerShell Mappings
Levitate maps common .NET automation calls to idiomatic PowerShell:
| C# call family | Example generated command |
|---|---|
Console.WriteLine, Console.Error.WriteLine |
Write-Host, Write-Error |
Directory.Exists, CreateDirectory, Delete, Copy |
Test-Path, New-Item, Remove-Item, Copy-Item |
File.Exists, ReadAllText, WriteAllText, AppendAllText, Copy, Delete |
Test-Path, Get-Content, Set-Content, Add-Content, Copy-Item, Remove-Item |
Path.Combine, GetFileName, GetDirectoryName |
Join-Path and path expressions |
ServiceController.Get, GetAll, Start, Stop, Restart, Suspend, Resume, WaitForStatus |
Get-Service, Start-Service, Stop-Service, Restart-Service, and related cmdlets |
Process.Start, process helpers |
Start-Process and process cmdlets |
Environment.GetEnvironmentVariable, SetEnvironmentVariable |
$env: reads and writes |
Registry, RegistryKey helpers |
registry provider commands such as Get-ItemProperty, Set-ItemProperty, Remove-ItemProperty, New-Item |
X509Store, X509Certificate2 |
certificate provider and certificate import/export commands |
DateTime.Now, conversion helpers, sleeps |
Get-Date, casts, Start-Sleep |
See docs/bcl-mappings.md for the detailed table.
Pipelines And LINQ Preview
Use PS.Command(...) when the intent is a PowerShell object pipeline:
[PowerShellScript]
public static void RunningServices()
{
PS.Command("Get-Service")
.Where("Status", PsOperator.Eq, "Running")
.Select("Name", "Status")
.SortBy("Name")
.FormatTable();
}
Generated pipeline:
Get-Service | Where-Object { $_.Status -eq "Running" } | Select-Object Name, Status | Sort-Object Name | Format-Table -AutoSize
Supported pipeline stages include:
| API | PowerShell |
|---|---|
Where(prop, op, value) and Where(prop, value) |
Where-Object |
Select("Name", "Status") |
Select-Object Name, Status |
SortBy("Name"), SortBy("Name", descending: true) |
Sort-Object Name, Sort-Object Name -Descending |
GroupBy("Status") |
Group-Object Status |
First(), First(5), Skip(10) |
Select-Object -First, Select-Object -Skip |
FormatTable(), OutFile(path, append) |
Format-Table -AutoSize, Out-File |
The LINQ preview translates common object-pipeline forms including Where, Select, Any, All, Count, First, FirstOrDefault, Last, LastOrDefault, OrderBy, ThenBy, descending variants, GroupBy, Skip, Take, Distinct, ToList, and ToArray.
Module-Aware Ops APIs
Levitate includes marker APIs that compile to module-specific PowerShell commands. They are compile-time markers and intentionally throw if executed directly as normal C#.
| Area | Marker APIs |
|---|---|
| IIS | IIS.GetSite, GetAllSites, StartSite, StopSite, RestartSite, NewSite, RemoveSite, GetAppPool, StartAppPool, StopAppPool, RecycleAppPool |
| Active Directory | AD.GetUser, GetUsers, NewUser, SetUser, RemoveUser, EnableUser, DisableUser, GetGroup, GetGroupMembers, AddGroupMember, RemoveGroupMember, ResetPassword, UnlockAccount |
| Azure | Azure.GetVM, StartVM, StopVM, RestartVM, GetResourceGroups, GetResourceGroup, GetStorageAccount, GetContext, Connect, SetSubscription |
| Certificate store | X509Store and X509Certificate2 mappings for common local machine certificate operations |
Example:
using Levitate;
public partial class CloudScripts
{
[RequiresPowerShell("7.4")]
[RequiresModule("Az")]
[PowerShellScript]
public static void StopDevVm(string name, string resourceGroup)
{
Azure.StopVM(name, resourceGroup);
}
}
Generated prefix and command:
#Requires -Version 7.4
#Requires -Modules Az
param(
[Parameter(Mandatory=$true)]
[string]$name,
[Parameter(Mandatory=$true)]
[string]$resourceGroup
)
Stop-AzVM -Name $name -ResourceGroupName $resourceGroup -Force
Manifest, Platform, And Safety Features
| Feature | C# or MSBuild input | Generated behavior |
|---|---|---|
| PowerShell version requirement | [RequiresPowerShell("7.4")] |
Adds #Requires -Version 7.4 |
| Module requirement | [RequiresModule("ActiveDirectory")] |
Adds #Requires -Modules ActiveDirectory |
| Multiple modules | Repeated [RequiresModule(...)] |
Emits one #Requires -Modules line per attribute |
| Platform intent | [TargetPlatform(PowerShellPlatform.Windows)] |
Documents Windows-only scripts and suppresses Windows-only command warnings |
| Strict mode | <LevitateStrictMode>true</LevitateStrictMode> |
Emits Set-StrictMode -Version Latest after param() |
| Error behavior | <LevitateErrorActionPreference>Stop</LevitateErrorActionPreference> |
Emits $ErrorActionPreference = "Stop" near the top of the script |
| Raw PowerShell guardrail | PS.Raw(...) with non-constant input |
Reports SS401 injection-risk warning |
| Windows-only guardrail | IIS, AD, registry, certificate, or other Windows-specific commands in cross-platform scripts | Reports SS501 unless the method targets Windows |
Generated Artifacts
Levitate can emit scripts as build artifacts so reviewers and CI can inspect the exact PowerShell that will run.
<PropertyGroup>
<LevitateEmitPs1>true</LevitateEmitPs1>
<LevitatePs1OutputPath>Scripts/Generated</LevitatePs1OutputPath>
<LevitateValidateGeneratedScripts>true</LevitateValidateGeneratedScripts>
<LevitateStrictMode>true</LevitateStrictMode>
<LevitateErrorActionPreference>Stop</LevitateErrorActionPreference>
</PropertyGroup>
Default generated location:
obj/Levitate/generated/
Accessor helpers generated for every script method:
| Helper | Purpose |
|---|---|
PowerShell |
Embedded generated script text |
ExecuteAsync(...) |
Execute the script through Levitate.Runtime |
SaveTo(string path) |
Save script to a file path |
SaveTo(FileInfo file) |
Save script to a FileInfo target |
Diagnostics
Levitate diagnostics are designed to be actionable. v1.0 messages include rewrite suggestions for the most common blockers.
| Code | Severity | Meaning |
|---|---|---|
SS001 |
Error | [PowerShellScript] method must be static. |
SS002 |
Error | Containing class must be partial. |
SS003 |
Error | Unsupported C# construct. Suggestion: use PS.Raw("...") for PowerShell-native constructs. |
SS004 |
Error | Unsupported BCL method. Suggestion: use PS.Raw("...") or check docs/bcl-mappings.md. |
SS201 |
Warning | Unsupported automation expression. Suggestion: rewrite with PS.Command(...) or PS.Raw(...). |
SS230 |
Warning | Object construction inside LINQ Select is not supported. |
SS401 |
Warning | PS.Raw() argument is not a compile-time constant. Suggestion: use a named param() variable or a compile-time string. |
SS501 |
Warning | Windows-only command in a cross-platform script. Suggestion: add [TargetPlatform(PowerShellPlatform.Windows)]. |
LLM-Safe Automation Workflow
Levitate works well as a compiler layer between AI-generated C# and executable PowerShell:
- Ask an LLM for Levitate-profile C# instead of raw shell commands.
- Build the project so normal C# compilation, analyzers, and Levitate diagnostics run.
- Inspect generated
.ps1artifacts. - Parse-validate generated PowerShell in tests.
- Execute through
Levitate.Runtimeonly after review.
The recommended LLM profile is documented in docs/llm-guide.md.
Runtime Execution
var result = await MaintenanceScripts.CleanTempFilesScript.ExecuteAsync(
tempPath: @"C:\Temp",
olderThanDays: 14);
if (!result.Success)
{
Console.Error.WriteLine(result.ErrorOutput);
}
foreach (var line in result.AsLines())
{
Console.WriteLine(line);
}
ExecutionResult includes:
| Property or method | Description |
|---|---|
RawOutput |
Captured standard output |
ErrorOutput |
Captured standard error |
ExitCode |
PowerShell process exit code |
Duration |
Runtime duration |
Success, HasError |
Convenience status flags |
AsLines() |
Output split into non-empty lines |
AsJson() and As<T>() |
JSON parsing helpers |
AsKeyValue() |
Parse key: value style output |
Fluent Builder
When you want to generate PowerShell without source generation, use Levitate.Core directly:
using Levitate.Core;
using Levitate.Core.Conditions;
var ps = Shell.New()
.Echo("Levitate works")
.If(new FileExistsCondition("$profile"), thenBlock => thenBlock
.Raw("Write-Host \"Profile exists\""))
.Build();
The builder layer includes AST nodes for commands, pipelines, functions, script blocks, variables, conditionals, loops, switch statements, try/catch blocks, here-strings, JSON/XML operations, jobs, sessions, scheduled tasks, certificates, services, registry, networking, storage, and more.
Cross-Platform Guidance
Levitate targets PowerShell 7 where possible and can fall back to Windows PowerShell on Windows through the runtime. Cross-platform scripts should prefer file/path/process/environment APIs, portable pwsh cmdlets, and explicit module requirements.
Windows-specific automation is supported, but should be marked clearly:
[RequiresModule("WebAdministration")]
[TargetPlatform(PowerShellPlatform.Windows)]
[PowerShellScript]
public static void RestartSite(string siteName)
{
IIS.RestartSite(siteName);
}
Build And Test
dotnet restore Levitate.slnx
dotnet build Levitate.slnx --configuration Release
dotnet test Levitate.slnx --configuration Release --no-build
dotnet pack Levitate.slnx --configuration Release --no-build --output nupkgs/Levitate/v1.0.1
The v1.0 tree validates generator output with golden tests and PowerShell parser checks.
Documentation
- Getting started
- How it works
- API reference
- Supported constructs
- BCL mappings
- Raw PowerShell guide
- Cross-platform guide
- Library guide
- LLM guide
Release
Levitate v1.0.1 is the Trustworthy Automation Compiler release:
- Stable public package identities under
Levitate.*. - Compile-time source generation with reviewable PowerShell artifacts.
- Runtime execution support for generated scripts.
- BCL, pipeline, LINQ preview, IIS, AD, Azure, registry, service, and certificate mappings.
- Strict mode, manifest attributes, platform diagnostics, and raw PowerShell injection-risk warnings.
Learn more about Target Frameworks and .NET Standard.
This package has no dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.0.1 - NuGet gallery README and package icon compatibility fix.