To set a variable for the current terminal only, use $env:NAME = "value" in PowerShell, set NAME=value in Command Prompt, or export NAME=value in bash and zsh. To make it permanent, use the Environment Variables dialog on Windows, or add the export line to ~/.zshrc (macOS) or ~/.bashrc (most Linux) and open a new terminal.
Temporary vs permanent: what's the difference?
Every running program has its own copy of the environment, inherited from the program that started it. A temporary variable changes only the copy held by your current shell, so it disappears when you close that window. A permanent variable is stored somewhere new processes read at startup: the registry on Windows, or a shell startup file on macOS and Linux.
That inheritance is also why a new terminal is needed after a permanent change. Windows that are already open, and programs started from them, still hold the environment they got when they started. Microsoft's setx documentation says it plainly: variables set with setx "are available in future command windows only, not in the current command window."
How to set a temporary variable on Windows
In PowerShell:
$env:GREETING = "hello"
$env:GREETING
Example output:
hello
List all variables with Get-ChildItem Env: and delete one with Remove-Item Env:GREETING.
In Command Prompt (cmd.exe):
set GREETING=hello
echo %GREETING%
Don't put spaces around the =: set GREETING = hello creates a variable named GREETING (with a trailing space) whose value starts with a space. Also, cmd expands %GREETING% when it reads a line, so this one-liner prints the literal text %GREETING%, not hello:
set GREETING=hello& echo %GREETING%
Put the two commands on separate lines and it works.
How to set a permanent variable on Windows
With the dialog (safest). Press Win, type environment, and choose Edit environment variables for your account. Or go the long way, as Microsoft documents it: Control Panel > System > Advanced system settings, the Advanced tab, then Environment Variables.... The top list holds User variables (only your account); the bottom list holds System variables (every account, needs administrator rights). Windows writes these to the registry, so they persist across restarts.
With PowerShell. The .NET method takes a scope as its third argument:
[Environment]::SetEnvironmentVariable('GREETING', 'hello', 'User')
Use 'Machine' instead of 'User' for a system-wide variable, from PowerShell run as administrator. Setting the value to an empty string, '', deletes it from that scope.
With setx.
setx GREETING hello
setx writes to your user variables; add /m to write a system variable (administrator prompt required). It has two documented traps:
- A 1024-character limit. Microsoft's reference: "the content is cropped if you go over 1024 characters, and that the cropped text is what's applied to the target variable." On an existing variable that means silent data loss.
- It flattens references. If a variable contains
%JAVA_HOME%,setxstores the expanded value instead, so later changes toJAVA_HOMEno longer flow through.
Both matter most for PATH. Never run setx PATH "%PATH%;C:\Tools". In a terminal, %PATH% is the user and system PATH combined, so the command copies the system entries into your user PATH, and on a machine with a long PATH it truncates the result at 1024 characters. On the Windows 11 machine we tested, the combined PATH was already 1,329 characters (35 folders), while the user part alone was 344.
How to add a folder to PATH on Windows
PATH is the list of folders Windows searches when you type a command name. Entries are separated by semicolons (;) on Windows and by colons (:) on macOS and Linux.
Use the dialog: open Edit environment variables for your account, select Path in the User list, click Edit, then New, and paste the folder (for example C:\Tools). Click OK on every window, then open a new terminal and check:
$env:Path -split ';'
For the current PowerShell session only, append to it:
$env:Path += ';C:\Tools'
How to set a temporary variable on macOS and Linux
export GREETING=hello
echo "$GREETING"
Again, no spaces around =. Without export, GREETING=hello creates a shell variable that programs you start from that shell cannot see. To set a variable for a single command only, put it in front of the command:
PORT=3001 npm start
Remove a variable with unset GREETING, and list everything with env or printenv.
How to set a permanent variable on macOS (zsh)
Since macOS 10.15 Catalina, zsh is the default login and interactive shell for new accounts. Add the line to ~/.zshrc, which zsh reads for every interactive shell:
echo 'export GREETING=hello' >> ~/.zshrc
source ~/.zshrc
source applies the file to the current window; new windows read it automatically. Use single quotes in the echo so the line is written literally. If you upgraded from an older macOS and still use bash, check with echo $SHELL.
How to set a permanent variable on Linux (bash)
Most Linux distributions default to bash. Which file it reads depends on how it starts, according to the bash manual:
| Shell type | Files read | Typical case |
|---|---|---|
| Interactive login shell | /etc/profile, then the first of ~/.bash_profile, ~/.bash_login, ~/.profile | SSH login, text console |
| Interactive non-login shell | ~/.bashrc | A terminal window in a desktop session |
For a desktop user, ~/.bashrc is usually right. Many distributions' default ~/.profile or ~/.bash_profile also loads ~/.bashrc, so one line covers both; check yours before relying on it.
echo 'export GREETING=hello' >> ~/.bashrc
source ~/.bashrc
For a variable that every user and every program should get, including ones not started from a shell, Linux systems with PAM read /etc/environment. It is not a shell script: it takes plain KEY=VAL lines, one per line, so write GREETING=hello without export and without expecting $OTHER references to be expanded. Edit it with sudo; it takes effect at your next login.
How to add a folder to PATH on macOS and Linux
Add this line to ~/.zshrc or ~/.bashrc:
export PATH="$HOME/bin:$PATH"
Putting the new folder first makes its programs win over same-named ones elsewhere; put it after $PATH to do the opposite. Always include $PATH. export PATH="$HOME/bin" on its own replaces the whole list, and basic commands such as ls stop working in that shell until you open a new one. Check the result with:
echo "$PATH" | tr ':' '\n'
If the variable still isn't picked up
- You're in an old window. Open a new terminal. If the variable is used by an IDE or editor's built-in terminal, restart the whole application, not just the terminal tab.
- Wrong file for your shell. Run
echo $SHELL; a line in~/.bashrcdoes nothing for zsh, and vice versa. - Wrong case on macOS or Linux. Names are case-sensitive there:
Pathis notPATH. On Windows they are not. - A later line overrides it. Search the startup files for other assignments:
grep -n GREETING ~/.zshrc ~/.zprofile ~/.bashrc ~/.profile. To compare a file before and after an edit, the larely diff checker shows exactly which lines changed.
Frequently asked questions
- Are environment variable names case-sensitive?
- On Windows, no: Path, PATH and path are the same variable. On macOS and Linux, yes: PATH and Path are two different variables, and only PATH is used to find programs. Use upper case everywhere to avoid surprises.
- How do I delete an environment variable?
- For the current session: Remove-Item Env:NAME in PowerShell, set NAME= in Command Prompt, or unset NAME in bash and zsh. For a permanent Windows variable, delete it in the Environment Variables dialog or run [Environment]::SetEnvironmentVariable('NAME', '', 'User') in PowerShell. On macOS and Linux, remove the export line from your shell startup file and open a new terminal.
- Should I put secrets such as API keys in environment variables?
- Environment variables are a common way to pass secrets to programs, and better than hard-coding them in source code. They are not encrypted, though: any program running as your user can read them, and a permanent variable is stored in plain text in the registry or your shell startup file. Keep such files private and never commit them to a repository.
- Why does my variable work in the terminal but not in my IDE or app?
- Programs read their environment once, when they start, from whatever launched them. An IDE opened before you set the variable, or launched from the Dock or Start menu rather than from your terminal, won't see a variable defined only in a shell startup file or set after it started. Restart the program; on Windows, set the variable permanently in the user scope so every new program gets it.