Skip to content
Volume P · The TensorCore.si Library

PowerShell

Automation with objects, not text.

PowerShell is Microsoft's cross-platform shell and scripting language. Unlike traditional shells that pass text, PowerShell passes structured .NET objects through the pipeline. It is the standard tool for automating Windows, Microsoft 365 and Azure, and it runs on Linux and macOS too.

Prologue

Why learn PowerShell?

If you work with Windows, Azure or Microsoft 365, PowerShell is the fastest way to automate it, including AI services on Azure.

  • Objects in the pipeline: filter and sort by properties, no text parsing.
  • Microsoft ecosystem: manage Windows, Azure, Entra ID and Microsoft 365.
  • REST built in: Invoke-RestMethod turns JSON APIs into objects.
Prologue

Set up and run your first program

Windows includes Windows PowerShell 5.1; install PowerShell 7 (pwsh) for the modern cross-platform version.

terminal
winget install Microsoft.PowerShell   # Windows
brew install powershell              # macOS
pwsh ./hello.ps1
hello.ps1
$name = "Ada"
Write-Output "Hello, AI! Welcome to PowerShell, $name."
TipIf scripts are blocked on Windows, run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned once.
Chapter 1

Variables and types

Variables start with $. Double-quoted strings expand variables; $( ) evaluates expressions inside strings.

variables.ps1
$layers = 32
$model  = "llama3.1"
[double]$params = 8.03e9
$gb = $params * 2 / 1e9
Write-Output "$model has $layers layers"
Write-Output "FP16 size: $([math]::Round($gb, 1)) GB"
$layers.GetType().Name   # Int32
Chapter 2

Cmdlets and the object pipeline

Commands (cmdlets) use Verb-Noun names. Output is objects, so Where-Object, Sort-Object and Select-Object work on properties.

pipeline.ps1
# Five largest files in a folder
Get-ChildItem -Recurse -File |
  Sort-Object Length -Descending |
  Select-Object -First 5 Name, @{n='MB'; e={[math]::Round($_.Length / 1MB, 1)}}

# Processes using the most memory
Get-Process | Sort-Object WorkingSet64 -Descending | Select-Object -First 3 Name, Id
Chapter 3

Arrays, hashtables and objects

@( ) makes arrays and @{ } makes hashtables. [pscustomobject] creates objects you can pipe, sort and export.

collections.ps1
$gpus = @(
  [pscustomobject]@{ Name = "H100"; Vram = 80 }
  [pscustomobject]@{ Name = "H200"; Vram = 141 }
  [pscustomobject]@{ Name = "RTX 5090"; Vram = 32 }
)
$gpus | Where-Object Vram -ge 80 | ForEach-Object { "$($_.Name): $($_.Vram) GB" }
$prices = @{ H100 = 2.49; H200 = 3.29 }
$prices["H100"]
$gpus | Export-Csv gpus.csv -NoTypeInformation
Chapter 4

Functions and parameters

Functions declare parameters with types, defaults and validation. Advanced functions behave like built-in cmdlets.

functions.ps1
function Get-ModelParams {
  param(
    [Parameter(Mandatory)][int]$Layers,
    [int]$Width = 4096
  )
  12 * $Layers * [long]$Width * $Width
}

function Test-Fits {
  param([int]$ModelGB, [int]$VramGB)
  if ($ModelGB -le $VramGB) { "fits" } else { "too big" }
}

Get-ModelParams -Layers 32
Test-Fits -ModelGB 16 -VramGB 24
Chapter 5

Errors and REST APIs

try/catch handles errors (use -ErrorAction Stop to make cmdlet errors catchable). Invoke-RestMethod calls web APIs and converts JSON to objects.

rest.ps1
try {
  $models = Invoke-RestMethod -Uri "http://localhost:11434/api/tags" -ErrorAction Stop
  $models.models | Select-Object name, size
} catch {
  Write-Warning "Ollama is not running: $($_.Exception.Message)"
}
$repo = Invoke-RestMethod "https://api.github.com/repos/pytorch/pytorch"
"PyTorch stars: $($repo.stargazers_count)"
Part II · AI with PowerShell

AI with PowerShell

PowerShell automates the infrastructure around AI: creating Azure OpenAI and Azure AI Foundry resources, managing GPU virtual machines, checking nvidia-smi on Windows servers and calling model APIs. Microsoft also offers AI helpers for the shell, and any OpenAI-compatible endpoint can be called with Invoke-RestMethod.

The essential libraries

Az moduleManage Azure, including AI services and GPU VMs.
Invoke-RestMethodCall any LLM REST API.
PSOpenAI (community)Wrapper for OpenAI and Azure OpenAI.
Microsoft GraphAutomate Microsoft 365 data for AI workflows.

Summarise files with a local LLM

Send each text file in a folder to a local model and save the summaries to CSV.

summarise.ps1
$url = "http://localhost:11434/v1/chat/completions"
$results = foreach ($file in Get-ChildItem *.txt) {
  $text = Get-Content $file -Raw
  $body = @{
    model = "llama3.1"
    messages = @(@{ role = "user"; content = "Summarise in one sentence:`n$text" })
  } | ConvertTo-Json -Depth 5
  $res = Invoke-RestMethod -Uri $url -Method Post -Body $body -ContentType "application/json"
  [pscustomobject]@{ File = $file.Name; Summary = $res.choices[0].message.content }
}
$results | Export-Csv summaries.csv -NoTypeInformation
Part III · Build an AI agent

Build an AI agent in PowerShell

Because JSON becomes objects automatically, a tool-calling agent in PowerShell is short and readable.

Your goal→Model plans→Tool call→Your code runs the tool→Result back to model→Final answer
agent.ps1
$url = "http://localhost:11434/v1/chat/completions"
$tools = @(@{ type = "function"; function = @{ name = "get_disk_free"; description = "Free disk space in GB for a drive or mount"
  parameters = @{ type = "object"; properties = @{ path = @{ type = "string" } }; required = @("path") } } })

function get_disk_free($path) {
  $d = Get-PSDrive -PSProvider FileSystem | Where-Object { $path.StartsWith($_.Root) } | Select-Object -First 1
  "{0:N1} GB free on {1}" -f ($d.Free / 1GB), $d.Root
}

$messages = [System.Collections.ArrayList]@(@{ role = "user"; content = "How much space is free on C:\ ?" })
for ($round = 0; $round -lt 5; $round++) {
  $body = @{ model = "llama3.1"; messages = $messages; tools = $tools } | ConvertTo-Json -Depth 10
  $msg = (Invoke-RestMethod -Uri $url -Method Post -Body $body -ContentType "application/json").choices[0].message
  [void]$messages.Add($msg)
  if (-not $msg.tool_calls) { $msg.content; break }
  foreach ($call in $msg.tool_calls) {
    $fnArgs = $call.function.arguments | ConvertFrom-Json
    [void]$messages.Add(@{ role = "tool"; tool_call_id = $call.id; content = (get_disk_free $fnArgs.path) })
  }
}

Use -Depth 10 with ConvertTo-Json; the default depth truncates nested tool schemas.

Run it locallyInstall Ollama, run ollama pull llama3.1, and keep it running. The code talks to its OpenAI-compatible API at http://localhost:11434/v1, so the same program also works with vLLM, llama.cpp server or a cloud API by changing the URL, model name and adding an API key.
Part IV · Your path

PowerShell learning roadmap

Tick items off as you go. Your progress is saved in this browser.

Beginner

Intermediate

Advanced

Part IV · Your path

Projects to build

Disk reportEmail a weekly CSV of disk usage.
Azure GPU VMScript creating and stopping a GPU VM.
IT agentAn LLM agent that answers system questions with safe tools.
Reference

PowerShell cheat sheet

TaskSyntax
Variable$x = 5
HelpGet-Help Get-Process -Examples
Filter... | Where-Object Size -gt 100
Loopforeach ($f in $files) { }
Object[pscustomobject]@{ A = 1 }
RESTInvoke-RestMethod -Uri $u
Reference

Common mistakes

  • Comparison uses -eq, -gt, -lt, not == or > (> redirects output).
  • ConvertTo-Json only goes 2 levels deep by default.
  • Windows PowerShell 5.1 and PowerShell 7 differ; target pwsh 7 for new scripts.
Reference

Where to go next

On TensorCore.si: Bash volume, C# volume.

Keyboard: [ previous language · ] next language · / search the library