Skip to content
Latchkey

setx and $env: Set Environment Variables in CI

setx writes a persistent environment variable to the registry (User or, with /M, Machine), while $env: and cmd set affect only the current process, so the two are not interchangeable.

The classic Windows CI trap: setx persists a variable but does not update the running shell, so the very next command in the same step cannot see it. Knowing which mechanism to use avoids hours of confusion.

What it does

setx writes a variable to the User (default) or Machine (/M) environment in the registry; it takes effect in *future* processes, not the current one. $env:NAME in PowerShell and set NAME=value in cmd set a variable for the current process and its children only.

Common usage

PowerShell
:: persist for future steps/sessions (machine-wide needs admin)
setx MY_TOOL_HOME "C:\tools\mytool" /M

:: set for the CURRENT process (PowerShell)
$env:PATH = "C:\tools\mytool\bin;$env:PATH"

:: GitHub Actions: persist to later steps via the env file
"MY_VAR=value" | Out-File -Append -Encoding utf8 $env:GITHUB_ENV

Options

ConstructWhat it does
setx NAME valuePersist a User variable (future processes)
setx NAME value /MPersist a Machine variable (needs admin)
$env:NAME = "v"PowerShell: set for the current process
set NAME=value (cmd)cmd: set for the current process
$env:GITHUB_ENV / GITHUB_PATHGitHub Actions files to pass vars/PATH to later steps

In CI

To pass a value to *later* steps on GitHub Actions, append to $env:GITHUB_ENV (or GITHUB_PATH for PATH), not setx, which the runner does not reload mid-job. To use a value *within* the same step, set $env:NAME directly. Use setx only for state that must survive into a different process you launch.

Common errors in CI

The most common bug: setx FOO bar then echo %FOO% in the same step prints nothing, because setx does not change the current process; set %FOO%/$env:FOO directly for immediate use. "ERROR: Access to the registry path is denied." means /M without elevation. "WARNING: The data being saved is truncated to 1024 characters" means the value (often a long PATH) exceeds setx's 1024-char limit; edit PATH another way.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →