Tired of environment variables vanishing the moment you close CMD?
Windows stores env vars in three spots: the shell’s memory, HKCU\Environment for user scope, and HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment for machine scope.
The set command only creates temporary values; to export environment variables permanently you must write them to the registry with setx or PowerShell’s [Environment]::SetEnvironmentVariable — and note those don’t update your current shell.
This post shows the exact command-line steps, when to pick user vs machine scope, and the common gotchas like PATH truncation and admin rights.
Permanent Methods for Windows Environment Variable Export

Windows keeps environment variables in three spots: the current process memory, the user registry at HKCU\Environment, and the machine registry under HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment. The set command creates temporary variables that only stick around for the current Command Prompt session and any processes it launches. Close that window and they’re gone. When you need variables that survive reboots and new shells, you’ve got to write them into the registry using setx from CMD or PowerShell’s [Environment]::SetEnvironmentVariable method. These persistent methods differ from set in one key way: they don’t update the environment of the shell you’re currently in. You’ll need to open a new terminal to see the changes.
User-level variables appear only for the logged-in user and don’t need special privileges, so they’re the right pick for personal scripts, project configs, or developer tools that other users shouldn’t inherit. System-level variables apply to every account on the machine and require Administrator rights to create or change. A quick setx example: setx BUILD_ENV "production" writes BUILD_ENV to the user registry, while setx BUILD_ENV "production" /M writes it system-wide for every user. The PowerShell version for a persistent user variable is [Environment]::SetEnvironmentVariable("BUILD_ENV","production","User"), and swapping “User” for “Machine” bumps it to system scope.
Beyond command-line tools, Windows has a graphical interface through the System Properties Environment Variables dialog, accessible via sysdm.cpl, and advanced users can edit the registry directly using regedit or reg commands. Each method writes to the same underlying registry keys, so a variable set through the GUI will show up when you query the registry with reg query. The detailed guides for CMD, PowerShell, GUI, and registry techniques appear in the sections that follow.
Differentiating Temporary vs Persistent Windows Variable Export

Temporary variables exist only for the lifetime of the shell process that created them. When you run set DEMO=yes in a Command Prompt window, that DEMO variable is available right away in the same window and automatically inherited by any child process you launch, like an npm build script or an Electron Forge command. But the moment you close CMD, DEMO vanishes. PowerShell’s $Env:DEMO = "yes" works the same way: instant availability in the current session, automatic inheritance by child processes, and complete disappearance when the PowerShell window closes.
Persistent variables survive shell closures and system reboots by living in the Windows registry. The setx command and PowerShell’s [Environment]::SetEnvironmentVariable both write to the registry, so the variable reappears in every new shell session. The catch is that neither setx nor the PowerShell registry method updates the environment of the shell you’re currently in. You’ve got to open a fresh terminal window to see the new value.
Developers use temporary variables for one-off commands, CI/CD build scripts, and quick tests where configuration shouldn’t leak into future sessions:
Build toggles – set DEMO=yes && npm run build enables demo mode for a single build without affecting later runs.
Script isolation – Temporary variables prevent accidental persistence of debug flags or test credentials.
Child-process inheritance – A child process launched from the same shell inherits all temporary variables set by the parent.
Batch-file workflows – Running call env.bat from package.json sets multiple variables in one step for the Node.js process that follows.
Session-scoped overrides – Override a persistent system variable temporarily without altering the registry.
Using PowerShell to Export Windows Environment Variables

PowerShell assigns temporary variables with the $Env: prefix followed by the variable name and an equals sign. Running $Env:API_KEY = "abc123" makes API_KEY available right away in the same PowerShell session and to any child process you start. Close the window and the value gets discarded. To check a temporary variable, type $Env:API_KEY or Get-ChildItem Env:API_KEY in the same shell window.
Persistent variables require the [Environment]::SetEnvironmentVariable method, which writes directly to the Windows registry. The method takes three arguments: the variable name, the value, and the target scope (either “User” for the current account or “Machine” for system-wide availability). Setting a user-level variable looks like this: [Environment]::SetEnvironmentVariable("BUILD_TARGET","release","User"), and the system-level version is [Environment]::SetEnvironmentVariable("BUILD_TARGET","release","Machine"). Machine-level edits demand Administrator privileges, so run PowerShell as admin or the command will silently fail to write the registry key.
A short script that sets multiple persistent user variables might look like:
[Environment]::SetEnvironmentVariable("DB_HOST","localhost","User")
[Environment]::SetEnvironmentVariable("DB_PORT","5432","User")
[Environment]::SetEnvironmentVariable("LOG_LEVEL","debug","User")
[Environment]::SetEnvironmentVariable("FEATURE_FLAG","enabled","User")
After running the script, close the current PowerShell window and open a new one to see the variables. You can confirm persistence by typing $Env:DB_HOST in the fresh session or by querying the registry with reg query "HKCU\Environment" /v DB_HOST. Changes written to the Machine scope require restarting applications and sometimes a full logoff or reboot for all running processes to pick them up, so plan registry edits during a convenient maintenance window if you’re modifying system-wide configuration.
CMD Methods for Exporting Persistent Windows Environment Variables

The set command in Command Prompt creates a variable that exists only for the current session: set BUILD_ENV=production makes BUILDENV available right away, but closing the window erases it. The setx command writes to the registry, making the variable permanent across reboots and new shells. Running setx BUILD_ENV "production" saves BUILDENV to the user registry under HKCU\Environment, and the value will appear in every new Command Prompt, PowerShell, or application you launch after opening a fresh shell.
Adding the /M flag to setx writes the variable to the machine registry at HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment, making it visible to all user accounts. The syntax is setx BUILD_ENV "production" /M, and you’ve got to run CMD as Administrator or the command will fail with an access-denied error. When a value contains spaces or special characters, wrap it in double quotes: setx PROJECT_NAME "My Electron App" prevents CMD from treating the space as a command separator.
Editing the PATH variable with setx follows the same pattern but needs care because setx truncates PATH if the new value exceeds 1024 characters. A safer approach is to append a single directory: first, read the current PATH with echo %PATH%, copy the output, and then run setx PATH "%PATH%;C:\tools\bin" to append the new directory. Deleting a persistent variable is done by setting it to an empty string: setx BUILD_ENV "" removes BUILD_ENV from the registry. To verify changes, open a new Command Prompt and run echo %BUILD_ENV%. The current window will still show the old value or nothing at all because setx doesn’t update the environment of the session that executed it.
Open Command Prompt as Administrator if you need to set a system-wide variable.
Run setx VARIABLE_NAME "value" for user-level persistence or setx VARIABLE_NAME "value" /M for machine-level.
Close the current Command Prompt window.
Open a fresh Command Prompt and run echo %VARIABLE_NAME% to confirm the variable appears.
For PATH edits, always quote the new value and consider appending rather than replacing: setx PATH "%PATH%;C:\new\folder".
GUI Options for Exporting Windows Environment Variables

The graphical method for setting persistent environment variables starts with opening the Run dialog by pressing Windows + R, typing sysdm.cpl, and pressing Enter. This launches the System Properties window. Click the Advanced tab and then the Environment Variables button near the bottom. You’ll see two panes: the top pane labeled “User variables for [username]” and the bottom pane labeled “System variables.” User variables affect only your account and don’t need special privileges. System variables apply to all users and demand Administrator access to the System Properties dialog.
Click New under the User variables section to create a new variable, type the name in the “Variable name” field and the value in the “Variable value” field, then click OK. For PATH edits, select Path from the list, click Edit, and use the Browse or New buttons to add directories. After saving changes, the registry updates right away, but running applications and open shell windows don’t see the new values until they restart. Close all Command Prompt and PowerShell windows, then open fresh ones to verify the change.
Navigate to the dialog – Press Windows + R, type sysdm.cpl, click Advanced, then Environment Variables.
Choose the scope – Use the top pane for user-level variables. Use the bottom pane and run as Administrator for system-level variables.
Create or edit – Click New to add a variable or select an existing one and click Edit to change its value.
PATH management – Editing PATH through the GUI shows a list interface where you can reorder, add, or remove directories without manual string concatenation.
Restart processes – Logoff and log back in or restart applications to propagate the new environment to all running processes, especially for PATH changes that affect command discovery.
Registry-Level Export for Advanced Windows Environment Variable Persistence

User environment variables live in the HKCU\Environment registry key. System variables are stored at HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment. Editing these keys directly through regedit or the reg command line tool gives you complete control over variable creation, modification, and deletion without waiting for GUI dialogs or CMD limitations. This method is particularly useful for automated deployment scripts, Group Policy configurations, or scenarios where you need to set dozens of variables in a single operation.
Reading a variable from the registry uses reg query "HKCU\Environment" /v VARIABLE_NAME for user-level values and reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v VARIABLE_NAME for system-level values. When you modify the registry, Windows broadcasts a WM_SETTINGCHANGE message to notify running applications, but many programs don’t listen for this message. You’ll often need to restart Explorer.exe, sign out and back in, or reboot the machine for all processes to see the change. PATH edits in the registry have a length limit of 2047 characters per key, and exceeding this can break command discovery across the system.
| Registry Path | Purpose |
|---|---|
| HKCU\Environment | User-level environment variables; no admin rights required; affects only the logged-in user. |
| HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment | System-level environment variables; requires admin rights; applies to all users on the machine. |
Registry Commands for Creating and Removing Variables
Adding a variable to the user registry uses the syntax reg add "HKCU\Environment" /v VAR_NAME /t REG_SZ /d "value" /f, where /v specifies the variable name, /t REG_SZ sets the type to string, /d provides the value, and /f forces overwrite without prompting. For system variables, replace HKCU\Environment with the full HKLM path and run the command prompt as Administrator: reg add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v VAR_NAME /t REG_SZ /d "value" /f. Deleting a variable is done with reg delete "HKCU\Environment" /v VAR_NAME /f or the equivalent HKLM command for system-level removal.
After any registry edit, open a new Command Prompt or PowerShell window to verify the change with echo %VAR_NAME% or $Env:VAR_NAME. If the variable doesn’t appear, restart Windows Explorer by killing and restarting explorer.exe or sign out and back in. For critical PATH changes or system-wide variables, a full system restart ensures every process picks up the new environment. Always back up the registry key before bulk edits, especially when scripting automated changes to PATH. A malformed PATH can prevent Windows from finding essential system tools.
Cross-Shell Export Scenarios (WSL, Git Bash, Cygwin)

Git Bash, WSL, and Cygwin all recognize the export command because they emulate UNIX shell behavior on Windows. Running export DEMO=yes in Git Bash creates a variable that exists only for the current Git Bash session and its child processes, identical to how export works on Linux or macOS. WSL is a full Linux kernel running inside Windows, so export behaves exactly as it does on a native Linux installation, setting variables in the shell’s environment and making them available to processes spawned from that shell. Cygwin provides a POSIX-compatible layer, and export variables persist only within the Cygwin environment unless you explicitly call Windows-native commands like setx.
Variables set with export in any of these shells don’t automatically persist across Windows reboots or appear in native Command Prompt or PowerShell sessions. To make a variable permanent in WSL, add the export line to your ~/.bashrc or ~/.zshrc file so it runs every time you open a new terminal. For Git Bash, place export statements in ~/.bash_profile or ~/.bashrc, depending on whether you want them in login shells or all interactive shells. If you need a variable to appear both in UNIX-style shells and in Windows-native environments, use setx or PowerShell’s [Environment]::SetEnvironmentVariable to write it to the Windows registry, then reference it in your shell RC files with export VAR=$VAR to pull the value from the Windows environment into the UNIX shell.
Git Bash persistence – Add export BUILD_ENV=production to ~/.bash_profile to set the variable every time you open Git Bash. It won’t appear in CMD or PowerShell.
WSL cross-boundary – WSL can read Windows environment variables from the host, but changes made with export inside WSL don’t propagate back to Windows.
Cygwin PATH merging – Cygwin merges Windows PATH into its own environment, so directories added with setx on the Windows side become available in Cygwin shells automatically.
Child-process handoff – Running a Windows .exe from Git Bash or WSL passes the UNIX shell’s environment to the Windows process, allowing temporary export values to cross the boundary for that one invocation.
Verifying Exported Windows Environment Variables

After setting a persistent environment variable, open a new Command Prompt or PowerShell window and run echo %VARIABLE_NAME% in CMD or $Env:VARIABLE_NAME in PowerShell. If the variable doesn’t appear, you either set it only for the current session using set or $Env:, or the registry write failed due to missing admin rights. PowerShell offers a second verification method with Get-ChildItem Env: to list all environment variables in the current session, and you can filter by name with Get-ChildItem Env:VARIABLE_NAME.
Open a fresh shell – Close all Command Prompt and PowerShell windows, then open a new one to inherit the updated environment from the registry.
CMD check – Run echo %VARIABLE_NAME% and look for the expected value. An empty output means the variable isn’t set in the current session.
PowerShell check – Type $Env:VARIABLE_NAME or Get-ChildItem Env:VARIABLE_NAME to display the value.
Registry verification – Query the user registry with reg query "HKCU\Environment" /v VARIABLE_NAME or the system registry with reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v VARIABLE_NAME.
Restart applications – If a running application doesn’t see the new variable, restart it to force a reload of the environment from the registry.
Troubleshooting Windows Environment Variable Export Issues

The most common failure is expecting a persistent variable to appear in the same shell where you ran setx or [Environment]::SetEnvironmentVariable. These commands write to the registry but don’t update the current process environment, so you’ve got to open a new terminal to see the value. Quoting mistakes cause silent failures or incorrect values: running setx BUILD_ENV production demo without quotes creates a variable named BUILD_ENV with the value “production” and leaves “demo” as an unrecognized argument, while setx BUILD_ENV "production demo" correctly sets the value to “production demo”.
System-level variables require Administrator privileges. Attempting setx VAR "value" /M from a non-elevated Command Prompt fails with “ERROR: Access is denied.” PATH edits face a 1024-character truncation risk with setx and a 2047-character limit in the registry, so appending long directory lists can silently lose the tail of the PATH. Windows propagates registry changes to new processes right away, but running applications read the environment only once at startup, so Explorer, scheduled tasks, and services often need a restart or a full logoff to pick up changes.
Missing admin rights – System-wide edits fail silently or with access-denied errors if you run CMD or PowerShell without Administrator privileges.
Quoting errors – Values with spaces must be quoted: setx PROJECT "My App" works. setx PROJECT My App doesn’t.
PATH length limits – setx truncates PATH at 1024 characters. Use the GUI or registry edits for longer PATH values.
Stale sessions – Existing shells and applications don’t refresh their environment after registry changes. Always open a new window or restart the process.
Conflicting scopes – A user variable with the same name as a system variable shadows the system value in most contexts, causing confusion when the wrong one takes precedence.
Final Words
You moved straight into permanent options: CMD’s setx, PowerShell’s [Environment]::SetEnvironmentVariable, GUI edits, registry-level changes, plus cross-shell notes and verification tips. The piece focused on core concepts rather than step-by-step walkthroughs.
Remember the big gotchas: set is session-only, setx writes the registry but won’t update the current shell, Machine edits need admin, and PATH changes may require restarting apps. Always check scope (User vs Machine) before changing values.
Pick the right tool, verify with a new shell or reg query, and you’ll make windows export environment variable predictable and painless.
FAQ
Q: What is the difference between temporary and persistent environment variables?
A: The difference between temporary and persistent environment variables is that temporary ones live only in the current shell (set or $Env:VAR) and are inherited by child processes; persistent ones (setx or registry) survive new shells and reboots.
Q: How do I make an environment variable permanent in Windows?
A: Making an environment variable permanent in Windows means writing it to the registry via setx, PowerShell’s [Environment]::SetEnvironmentVariable, or the GUI so HKCU or HKLM holds the value for new shells.
Q: When should I use user vs system environment variables?
A: Use user variables (HKCU) when the setting should affect only your account; use system variables (HKLM) when every user or services need it—system edits require admin rights and impact all processes.
Q: How does setx differ from set, and why don’t setx changes show in the current shell?
A: setx differs from set because setx writes values to the registry for persistence while set only updates the current session; setx doesn’t update the current shell, so only new shells show the change.
Q: How do I set a persistent environment variable from PowerShell?
A: Setting a persistent environment variable from PowerShell uses [Environment]::SetEnvironmentVariable(‘VAR’,’value’,’User’ or ‘Machine’); Machine requires admin rights and affects new shells and services.
Q: How can I verify an exported environment variable?
A: Verifying an exported environment variable uses echo %VAR% in CMD, $Env:VAR or Get-ChildItem Env:VAR in PowerShell, or reg query for registry entries; open a new shell after persistence changes.
Q: How do I remove or unset a persistent environment variable?
A: Removing a persistent environment variable uses setx VAR “” or deleting the registry value under HKCU/HKLM; system-level removals need admin rights and new shells will reflect the deletion.
Q: What are common PATH editing gotchas when exporting variables?
A: Common PATH editing gotchas include hitting Windows PATH length limits, incorrect quoting, duplicating entries, wrong insertion order, and expecting running apps to pick changes without a restart.
Q: How do environment variables behave across WSL, Git Bash, and Cygwin?
A: Environment variables in WSL, Git Bash, and Cygwin are shell-specific and temporary unless added to shell rc files; to persist for Windows processes, use setx or another Windows-native registry method.
Q: What should I check when environment variables don’t apply as expected?
A: When variables don’t apply, check whether you used a session-only set/$Env:, missed quoting, lack admin rights for machine edits, forgot to open a new shell, or hit PATH length or conflict issues.
