OS X
Environment Variables
Mac Operating System
OS X Development
System Configuration

Setting environment variables on OS X

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Setting environment variables on macOS depends on where your process starts. Terminal shells, GUI apps launched from Finder, and launch daemons do not share the same initialization files. If you choose the wrong location for an environment variable, everything may look correct in terminal while your app still cannot see it.

Understand Scope Before Editing Files

You should decide the target scope first:

  • current shell session only.
  • every new shell for one user.
  • system service or launch daemon process.
  • GUI app started outside terminal.

Using the right scope prevents brittle setups and accidental secret exposure.

Session-Only Variables

For one terminal session, set with export:

bash
export APP_ENV=development
export API_BASE_URL=https://example.internal
echo "$APP_ENV"

This lasts until the shell exits. It is ideal for temporary testing and one-off commands.

Persistent Variables for Terminal Shells

Modern macOS uses zsh by default. Common file choices:

  • ~/.zshrc for interactive shell settings.
  • ~/.zprofile for login shell settings.

For development variables used in normal terminal work, ~/.zshrc is usually appropriate.

bash
echo 'export APP_ENV=development' >> ~/.zshrc
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

If you still use bash, equivalent files include ~/.bash_profile and ~/.bashrc.

Environment for GUI Apps

A common macOS surprise is that Finder-launched apps do not read your shell config files. If an IDE or GUI app needs variables, shell-only exports may not work.

For user-level persistent GUI process environment, you can use launchctl:

bash
launchctl setenv APP_ENV development
launchctl setenv API_BASE_URL https://example.internal

Verify:

bash
launchctl getenv APP_ENV

This applies to processes in your launch session. You may need to restart apps to pick up changes.

Project-Specific Approach

For team development, avoid putting project secrets in global shell files. Prefer project-local env files and explicit loading in tooling.

Example with a .env file and Node:

bash
APP_ENV=development
API_BASE_URL=https://example.internal
javascript
import "dotenv/config";

console.log(process.env.APP_ENV);

This keeps project configuration versioned and easier to share safely across contributors.

Security and Maintenance Practices

Environment variables are convenient but not automatically secure:

  • avoid storing long-term secrets in shell history or committed files.
  • use secret managers for production credentials.
  • keep .env in .gitignore when it contains sensitive values.
  • audit old variables periodically to remove stale values.

Also document required variables in a template file such as .env.example so new developers can bootstrap quickly without copying random shell snippets.

Debugging Missing Variables

When a process cannot read expected variables, check:

  1. which shell is active using echo $SHELL.
  2. whether the config file was sourced.
  3. whether the process is terminal-launched or GUI-launched.
  4. whether the variable name has typos or overwritten values.

For process-specific debugging:

bash
env | sort | grep APP_ENV

This helps confirm what the current process actually sees.

Common Pitfalls

  • Adding exports to ~/.zshrc and expecting Finder-launched apps to inherit them.
  • Storing sensitive secrets in globally readable shell files.
  • Mixing bash and zsh config files without knowing which shell is running.
  • Forgetting to reload shell configuration after edits.
  • Relying on machine-global settings instead of project-local configuration.

Summary

  • Environment variables on macOS are scope-dependent.
  • Use export for session-only values and shell config files for terminal persistence.
  • Use launchctl when GUI apps need environment values.
  • Prefer project-local env files for team workflows and portability.
  • Treat secrets carefully and document required variables explicitly. Revisit these settings after major shell or macOS upgrades to keep behavior consistent.

Course illustration
Course illustration

All Rights Reserved.