Running PowerShell in NORA: The Complete Guide

Running PowerShell in NORA: The Complete Guide

PowerShell is a first-class citizen in NORA. You can run any PowerShell command — pipelines, API calls, registry operations, file manipulation, anything — directly inside a workflow node. But there are a few behaviors that are unconventional compared to running PowerShell directly in a terminal. This guide explains how it actually works, what to expect, and how to avoid the most common frustrations.


How NORA Executes Commands

When you run a Command Node in NORA, the command string goes through two layers before it executes:

  1. Shell detection — NORA analyzes the command text to determine which shell to use (CMD, PowerShell, Bash, or a fallback)
  2. Shell wrapping — The command is wrapped in powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "..." (or equivalent for other shells) and passed to Node.js’s exec()

That second step — the wrapping — is where most PowerShell quirks come from. The command is passed through cmd.exe as an intermediate layer before PowerShell receives it, which affects how quotes are interpreted.


The Shell Dropdown (Most Important Setting)

Every Command Node has a Shell dropdown. The options are:

Setting Behavior
Auto NORA guesses the shell from your command text
PowerShell Always uses powershell.exe (Windows PowerShell 5.1)
pwsh Always uses pwsh.exe (PowerShell 7+, if installed)
CMD Always uses cmd.exe
Bash Always uses bash (WSL or Git Bash)

Always set this to PowerShell when writing PowerShell commands. Do not rely on Auto for anything beyond simple cmdlets.

Why Auto-Detection Can Fail

Auto-detection works by scanning your command for known PowerShell patterns: Get-, Set-, $env:, Where-Object, $_. If your command doesn’t contain one of those patterns, NORA defaults to CMD — even if the rest of the command is entirely PowerShell syntax.

Example that fails with Auto:

$token = 'abc123'; Invoke-RestMethod -Uri 'https://api.example.com' -Method GET

This contains $token (a plain variable) and Invoke-RestMethod — neither of which are in NORA’s auto-detection list. NORA routes it to CMD. CMD does not understand $token and throws:

'$token' is not recognized as an internal or external command

Fix: Set Shell to PowerShell explicitly. Auto-detection is a convenience, not a guarantee.


The Quoting Rule: Use Single Quotes for Values

This is the most important behavioral difference between running PowerShell in NORA vs. running it directly in a terminal.

What Happens Internally

When Shell is set to PowerShell and you run a command, NORA wraps it like this:

powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "<your command here>"

That outer "..." is passed through cmd.exe. CMD interprets \" as a literal backslash+quote — not as an escaped double quote. This means any double-quoted strings inside your command get mangled before PowerShell ever sees them.

The Problem in Practice

This will fail (double quotes inside):

$token = "ghp_abc123"; Invoke-RestMethod -Uri "https://api.github.com/repos/..." -Method GET

What cmd.exe actually sees:

powershell.exe -NoProfile -Command "$token = "ghp_abc123"; Invoke-RestMethod -Uri "https://api.github.com/..."

The extra unescaped quotes break the command completely.

This works (single quotes for values):

$token = 'ghp_abc123'; Invoke-RestMethod -Uri 'https://api.github.com/repos/...' -Method GET

Single quotes pass through cmd.exe untouched. PowerShell treats single-quoted strings as literals (no variable expansion), which is exactly what you want for static values like tokens, file paths, and URLs.

When You Need Variable Expansion

There is one case where you still need double quotes: when you want PowerShell to expand a variable inside a string.

$token = 'ghp_abc123'; Invoke-RestMethod -Headers @{ Authorization = "Bearer $token" }

"Bearer $token" must be double-quoted so PowerShell expands $token. Everything else — the token value itself, the URL, file paths — stays single-quoted.

Summary: Quote Selection Rules

What you’re writing Use
Static string values (tokens, URLs, paths) Single quotes '...'
Variable expansion inside strings Double quotes "..."
PowerShell hashtable keys Single quotes 'Content-Type'
Authorization headers with $variable Double quotes "Bearer $token"

Write Commands on One Line

NORA Command Nodes accept a single command string. Multi-line PowerShell blocks do not work as-is — they need to be collapsed to one line using semicolons.

Multi-line (works in a terminal, not in NORA):

$token = 'abc123'
$body = @{ message = 'hello' } | ConvertTo-Json
Invoke-RestMethod -Uri 'https://...' -Method PUT -Body $body

One line (works in NORA):

$token = 'abc123'; $body = @{ message = 'hello' } | ConvertTo-Json; Invoke-RestMethod -Uri 'https://...' -Method PUT -Body $body

Semicolons work the same in PowerShell as newlines for statement separation. Collapse every line with ; and it runs identically.


Real Example: Pushing a File to GitHub via API

Here’s a complete working example that pushes a local file to a GitHub repository using the GitHub Contents API — no git required.

What it does: Reads a local file, base64-encodes it, and calls the GitHub API to create or update the file in a repo.

$token = 'YOUR_PAT_HERE'; $filePath = 'C:\Users\YourUser\Documents\NORA\automation\workflows\my-workflow.js'; $content = [Convert]::ToBase64String([IO.File]::ReadAllBytes($filePath)); $body = @{ message = 'Add workflow file'; content = $content } | ConvertTo-Json; Invoke-RestMethod -Uri 'https://api.github.com/repos/youruser/yourrepo/contents/folder/my-workflow.js' -Method PUT -Headers @{ Authorization = "Bearer $token"; 'Content-Type' = 'application/json' } -Body $body

Key points in this command:
$token = 'YOUR_PAT_HERE' — single quotes, no expansion needed
$filePath = 'C:\Users\...' — single quotes, backslashes safe inside single quotes in PowerShell
Authorization = "Bearer $token" — double quotes needed here because $token must expand
'Content-Type' = 'application/json' — single quotes for the key and value
– Everything on one line with ; separators

Updating an Existing File (SHA Required)

If the file already exists in the repo, GitHub returns a 422 error unless you include the file’s current SHA in the request body. Get the SHA first, then include it:

$token = 'YOUR_PAT_HERE'; $filePath = 'C:\Users\YourUser\Documents\NORA\automation\workflows\my-workflow.js'; $content = [Convert]::ToBase64String([IO.File]::ReadAllBytes($filePath)); $sha = (Invoke-RestMethod -Uri 'https://api.github.com/repos/youruser/yourrepo/contents/folder/my-workflow.js' -Headers @{ Authorization = "Bearer $token" }).sha; $body = @{ message = 'Update workflow file'; content = $content; sha = $sha } | ConvertTo-Json; Invoke-RestMethod -Uri 'https://api.github.com/repos/youruser/yourrepo/contents/folder/my-workflow.js' -Method PUT -Headers @{ Authorization = "Bearer $token"; 'Content-Type' = 'application/json' } -Body $body

Common Errors and What They Mean

'$token' is not recognized as an internal or external command

Cause: Shell is set to Auto and NORA routed to CMD because no auto-detection markers were found in the command.

Fix: Set the node’s Shell dropdown to PowerShell.


Variable reference is not valid. ':' was not followed by a valid variable name character

Cause: You wrote $env: "somevalue" — that’s not valid syntax. $env: must be followed directly by a variable name ($env:GITHUB_TOKEN), not a value.

Fix: Use $token = 'somevalue' for plain variable assignment. Use $env:VARNAME = 'value' only for setting environment variables.


Unexpected token '"somevalue"' or ParserError

Cause: Double quotes in your command are being stripped or mangled by the cmd.exe intermediary layer before PowerShell sees them.

Fix: Switch all static string values from double quotes to single quotes.


422 Unprocessable Entity from GitHub API

Cause: The file already exists at that path and you didn’t include the current SHA in the request body.

Fix: Fetch the SHA first and include it in $body (see the update example above).


401 Unauthorized from GitHub API

Cause: Token is invalid, expired, or was rotated.

Fix: Generate a new Personal Access Token at github.com/settings/tokens with repo scope. Do not hardcode tokens in workflow configs you export or share.


Using $env: for Tokens (Safer Pattern)

Instead of putting your token directly in the command string, you can set it as an environment variable in a prior step and reference it later:

$env:GH_TOKEN = 'YOUR_PAT_HERE'; $filePath = 'C:\path\to\file.js'; $content = [Convert]::ToBase64String([IO.File]::ReadAllBytes($filePath)); $body = @{ message = 'Add file'; content = $content } | ConvertTo-Json; Invoke-RestMethod -Uri 'https://api.github.com/repos/youruser/yourrepo/contents/file.js' -Method PUT -Headers @{ Authorization = "Bearer $env:GH_TOKEN"; 'Content-Type' = 'application/json' } -Body $body

Using $env:GH_TOKEN also has a side benefit: $env: is one of NORA’s auto-detection markers, so the node will route to PowerShell correctly even if Shell is set to Auto.


PowerShell Pipelines Work Normally

Complex pipelines, filtering, and object manipulation all work as expected once Shell is set correctly:

Get-Process | Where-Object { $_.CPU -gt 10 } | Select-Object Name, CPU | ConvertTo-Json
Get-ChildItem 'C:\Logs' -Filter '*.log' | Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } | Select-Object Name, LastWriteTime
Get-Volume | Where-Object { $_.SizeRemaining / $_.Size -lt 0.15 } | Select-Object DriveLetter, @{N='FreeGB';E={[math]::Round($_.SizeRemaining/1GB,2)}} | ConvertTo-Json

Quick Reference Card

Situation What to do
Any PowerShell command Set Shell dropdown to PowerShell
Multi-line script Collapse to one line with ; between statements
String values (tokens, paths, URLs) Use single quotes '...'
Variable expansion inside a string Use double quotes "Bearer $token"
File already exists on GitHub Include sha in request body
Auto-detection needed (Auto mode) Start command with $env:DUMMY='x'; to force PS detection

Get NORA

Download at software.reibuys.com/nora. Windows 10 or later. One-time purchase, no subscription.

Get NORA at software.reibuys.com/nora

Leave a Comment