A saved PowerShell script and a live terminal do not provide the same execution context. The difference matters even when the visible code is identical.
A .ps1 file has a path, a script-level parameter binding step, and prerequisite handling tied to script invocation. Terminal input is assembled and submitted by a host and line editor. That changes how constructs such as param(), #Requires, script-path variables, scope, and multiline input should be handled.
PSRafScan makes the choice explicit: use Ps1File for a saved script and TerminalPaste for code that will be entered directly into a terminal.
The contexts at a glance
| Feature | Saved .ps1 script | Live terminal input |
|---|---|---|
| Invocation | The file is invoked by path | The host submits interactive input |
| Parameters | Top-level param() binds script arguments | A bare paste has no script-file invocation |
| Prerequisites | #Requires applies to the script | Use deliberate checks or keep the code as a script |
| Script path | $PSScriptRoot and $PSCommandPath describe the file | No executing .ps1 path exists |
| Scope | Script scope ends with the invocation | Definitions can remain in the session |
| Multiline input | The parser receives the file as one source unit | The host decides when input is complete |
Interactive behavior can vary with the terminal, PowerShell host, line editor, PowerShell and PSReadLine versions, edit mode, and paste method. Test the terminal workflow you actually plan to use.
Top-level param() belongs to script invocation
This is a normal saved script:
param(
[Parameter(Mandatory)]
[string] $Name
)
"Hello, $Name"Save it as Hello.ps1 and invoke it with a named argument:
./Hello.ps1 -Name AdaThe script invocation binds Ada to $Name. Pasting the same source into a running terminal does not create a file invocation with arguments.
For a short terminal task, assign the value explicitly:
$name = 'Ada'
"Hello, $name"For reusable terminal work, define a function and call it:
function Write-Greeting {
param(
[Parameter(Mandatory)]
[string] $Name
)
"Hello, $Name"
}
Write-Greeting -Name AdaPSRafScan's TopLevelParamInTerminalPaste rule calls attention to a top-level param() block when the intended use is TerminalPaste.
#Requires describes a script prerequisite
A saved script can declare requirements at the top of the file:
#Requires -Version 7.4
#Requires -Modules Microsoft.PowerShell.Management
Get-ChildItem -LiteralPath .Keeping prerequisite declarations with the script makes the dependency clear and lets PowerShell evaluate them as part of script startup.
For terminal input, check the prerequisite explicitly or leave the code as a script:
if ($PSVersionTable.PSVersion -lt [version]'7.4') {
throw 'PowerShell 7.4 or later is required.'
}
Get-ChildItem -LiteralPath .The RequiresInTerminalPaste rule helps identify #Requires lines that need this decision.
Script-path variables need an executing file
Saved scripts can build paths relative to their own location:
$configPath = Join-Path -Path $PSScriptRoot -ChildPath 'config.json'
Get-Content -LiteralPath $configPathThat is valuable when the caller's working directory can change. In direct terminal input, there is no executing script path to describe.
Use an explicit base path for terminal work:
$basePath = (Get-Location).ProviderPath
$configPath = Join-Path -Path $basePath -ChildPath 'config.json'
Get-Content -LiteralPath $configPathAn explicit parameter is often even better when the path should come from the user. PSRafScan's ScriptFileVariableInTerminalPaste rule covers $PSScriptRoot and $PSCommandPath in paste-oriented code.
Definitions can remain in the terminal session
A script has its own script scope. Functions and variables created inside it do not automatically become permanent additions to the caller's global session.
Interactive input is different. A function pasted into the terminal can remain available until it is removed or the session ends:
function Get-ProjectName {
'PSRafScan'
}
Get-ProjectNameThat persistence may be useful, but it should be intentional. The FunctionInsidePasteWrapper rule points out wrapper patterns that can obscure which definitions remain available after a paste.
Multiline input is controlled by the host
A saved file is parsed as a complete source unit. In a terminal, the host and line editor decide whether the current input is complete or whether another line is expected.
Consider a continuation-based pipeline:
Get-Process |
Where-Object CPU -gt 10 |
Sort-Object CPU -DescendingThe source is clear in a file. In a terminal, the outcome depends on how the text is delivered and when the host submits it. Natural PowerShell constructs such as braces and parentheses often communicate continuation more clearly than fragile line endings.
This do loop also depends on receiving the complete construct:
$count = 0
do {
$count++
"Count: $count"
} while ($count -lt 3)PSRafScan includes PasteSensitiveContinuationBlock and PasteSensitiveDoWhile to highlight patterns worth checking in the intended terminal.
Scan for the way the code will be used
For a saved script:
RSX -Path ./candidate.ps1 -IntendedUse Ps1File -FailOn WarningFor code prepared for terminal input:
RSX -Path ./paste-candidate.ps1 -IntendedUse TerminalPaste -FailOn WarningThe second command scans a saved copy of the text while applying terminal-specific rules. This makes the candidate easy to inspect and compare before anything is pasted.
PSRafScan 0.2.0-alpha1 applies 52 rules in both modes. Six are specific to TerminalPaste:
FunctionInsidePasteWrapperPasteSensitiveContinuationBlockPasteSensitiveDoWhileRequiresInTerminalPasteScriptFileVariableInTerminalPasteTopLevelParamInTerminalPaste
Choose with two questions
- Will the code be saved as a
.ps1file and invoked by its path? ChoosePs1File. - Will the code be entered directly into a live PowerShell terminal? Choose
TerminalPaste.
If a block needs script parameters, prerequisite declarations, stable relative paths, repeatable invocation, or source control, keeping it as a saved script is usually the clearer choice.
Related guidance
- Choose Ps1File or TerminalPaste
- Run a PSRafScan review
- Browse terminal-paste rules
- Check a PowerShell script before running it
