Environment Variables
environment.RmdEnvironment variables allow you to configure projr projects without hardcoding values. This is especially useful for managing different configurations across development, testing, and production environments, as well as for securely storing authentication tokens.
This documentation is modeled after Quarto’s environment variables documentation, adapted for projr’s specific implementation.
Overview
projr uses environment files to set default values for environment
variables. These files use a simple KEY=VALUE format and
are read in a specific order to allow for flexible configuration across
different contexts.
Environment File Types
projr uses three types of environment files (in order of precedence):
-
_environment.local- Machine-specific overrides (automatically git-ignored) -
_environment-<profile>- Profile-specific configurations -
_environment- Global defaults
Important: Variables defined in files are only set if not already defined in your system environment. This means:
- System-level environment variables always take precedence
- Already-set session variables are never overridden by file values
- Files with higher precedence override files with lower precedence
Defining Environment Variables
File Format
Environment files use a simple format with one variable per line:
Variable name requirements:
- Must start with a letter (a-z, A-Z)
- Can contain letters, numbers, and underscores
- Pattern:
[a-zA-Z][a-zA-Z0-9_]*
Value handling:
- Values are taken as-is after the
=sign (with leading/trailing whitespace trimmed) - Special characters in values are preserved (spaces, URLs, paths, etc.)
- No quotes needed - quotes become part of the value
- Empty values (
VAR=) are silently ignored
Comments:
- Lines starting with
#are ignored - Inline comments after
#are also ignored
# Build configuration (this is a comment)
PROJR_OUTPUT_LEVEL=std
PROJR_LOG_DETAILED=TRUE # Enable detailed logging (inline comment)
# URLs and paths work without quotes
API_URL=https://api.example.com?param=value
DATA_PATH=/path/to/data
# This line is ignored because the value is empty
# EMPTY_VAR=
# Authentication (move to _environment.local)
# GITHUB_PAT=your_token_hereCreating Environment Files
You can create environment files manually or programmatically:
# Create files manually
file.create("_environment") # Global defaults
file.create("_environment-dev") # Development profile
file.create("_environment.local") # Machine-specific (git-ignored)Activating Environment Variables
Loading Environment Files
Use projr_env_set() to load environment variables from
files:
# Load all environment files in the standard order
projr_env_set()
# Load a specific file
projr_env_set("_environment.local")
# Load multiple specific files
projr_env_set(c("_environment", "_environment-dev"))The standard loading order when calling projr_env_set()
without arguments is:
-
_environment.local(highest priority, machine-specific) -
_environment-<QUARTO_PROFILE>(ifQUARTO_PROFILEenvironment variable is set) -
_environment-<PROJR_PROFILE>(ifPROJR_PROFILEenvironment variable is set) -
_environment(lowest priority, global defaults)
Key behaviors:
- Files are processed in order, with earlier files taking precedence
- If a variable is already set in your environment, it is never overridden
- Non-existent files are silently skipped
- The
_environment.localfile is automatically added to.gitignorewhen created
Using Profiles
Profiles allow you to maintain different configurations for different
scenarios. Both PROJR_PROFILE and
QUARTO_PROFILE are supported.
PROJR_PROFILE
# Set a single profile
Sys.setenv(PROJR_PROFILE = "dev")
projr_env_set() # Loads _environment-dev
# Set multiple profiles (comma or semicolon separated)
Sys.setenv(PROJR_PROFILE = "test,dev")
Sys.setenv(PROJR_PROFILE = "test;dev") # Equivalent
projr_env_set() # Loads _environment-test, then _environment-devProfile format:
- Comma-separated:
"profile1,profile2,profile3" - Semicolon-separated:
"profile1;profile2;profile3" - Whitespace around profile names is automatically trimmed
- Earlier profiles take precedence (e.g., in
"test,dev", test overrides dev)
Special profile names:
-
"default"and"local"are filtered out (handled separately) - Avoid using these as custom profile names
QUARTO_PROFILE
# Quarto profiles are also respected
Sys.setenv(QUARTO_PROFILE = "production")
projr_env_set() # Loads _environment-production
# Multiple Quarto profiles (comma-separated only)
Sys.setenv(QUARTO_PROFILE = "test,production")
projr_env_set()Key differences from PROJR_PROFILE:
- Only supports comma separation (not semicolon)
- Takes precedence over
PROJR_PROFILEin the loading order - When both are set,
QUARTO_PROFILEfiles are loaded beforePROJR_PROFILEfiles
Key Environment Variables
projr recognizes several environment variables that control build behavior:
Build Control Variables
PROJR_OUTPUT_LEVEL - Controls console
output verbosity during builds
-
Values:
"none","std","debug" -
Default:
"none"for dev builds,"std"for production builds - Case-sensitive (must be lowercase)
-
Behaviors:
-
"none": No additional console output -
"std": Standard informational messages -
"debug": Verbose output including debug messages and remote operations details
-
- Can be overridden by explicit
output_levelparameter in build functions
Sys.setenv(PROJR_OUTPUT_LEVEL = "debug")
projr_build_dev() # Shows detailed debug outputPROJR_LOG_DETAILED - Controls whether
detailed build logs are written to files
-
Values: TRUE/FALSE representations
(case-insensitive)
- TRUE:
"TRUE","true","1","YES","yes","Y","y" - FALSE:
"FALSE","false","0","NO","no","N","n"
- TRUE:
-
Default:
"TRUE" -
Behaviors:
- When
TRUE: Creates detailed.qmdlog files incache/projr/log/ - When
FALSE: Still maintains build history (builds.md) but skips detailed logs - History tracking is always maintained regardless of this setting
- When
Sys.setenv(PROJR_LOG_DETAILED = "FALSE")
projr_build_dev() # Skips detailed log files but maintains historyPROJR_CLEAR_OUTPUT - Controls when
output directories are cleared during builds
-
Values:
"pre","post","never" -
Default:
"pre" - Case-sensitive (must be lowercase)
-
Behaviors:
-
"pre": Clear output before build starts -
"post": Clear output after build completes -
"never": Never automatically clear output
-
- Can be overridden by explicit
clear_outputparameter in build functions
Sys.setenv(PROJR_CLEAR_OUTPUT = "never")
projr_build_dev() # Never clears output automaticallyProfile Configuration
PROJR_PROFILE - Specifies which
profile(s) to use
- Format: Comma or semicolon-separated list of profile names
-
Default: None (uses
_projr.ymlonly) -
Example:
PROJR_PROFILE="test,dev"orPROJR_PROFILE="test;dev" -
Behaviors:
- Supports both comma (
,) and semicolon (;) separators - Whitespace around values is automatically trimmed
- Earlier profiles take precedence over later ones
- Special values
"default"and"local"are filtered out (handled separately)
- Supports both comma (
QUARTO_PROFILE - Quarto’s profile
specification
- Format: Comma-separated list of profile names
- Default: None
-
Behavior: Takes precedence over
PROJR_PROFILEfor environment file loading - Only supports comma separation (not semicolon)
Authentication Variables
GITHUB_PAT or
GITHUB_TOKEN - GitHub Personal Access
Token
- Purpose: GitHub Personal Access Token for GitHub API operations
- Default: None
-
Behaviors:
-
GITHUB_PATis checked beforeGITHUB_TOKEN - Falls back to
gitcredspackage if neither is set - Required for creating GitHub repositories and releases
- Should have appropriate scopes (repo, workflow, etc.)
-
-
Storage: Should always be stored in
_environment.local(never committed to git)
OSF_PAT - Open Science Framework
Personal Access Token
- Purpose: Open Science Framework Personal Access Token
- Default: None
- Behavior: Required for OSF remote destinations
-
Storage: Should always be stored in
_environment.local(never committed to git)
# Check authentication setup and get instructions
projr_instr_auth_github() # Get GitHub setup instructions
projr_instr_auth_osf() # Get OSF setup instructionsVariable Precedence
Environment variables follow a strict precedence order to allow for flexible configuration:
System vs File Variables
Already-set variables are never overridden:
# Pre-set value is preserved
Sys.setenv(MY_VAR = "original")
# _environment contains: MY_VAR=new
projr_env_set()
Sys.getenv("MY_VAR") # Still "original", not "new"This ensures that system-level or session-level variables always take priority.
File Precedence
When loading from files, precedence is (highest to lowest):
-
_environment.local- Machine-specific overrides -
_environment-<QUARTO_PROFILE>- Quarto profile-specific -
_environment-<PROJR_PROFILE>- projr profile-specific -
_environment- Global defaults
Function Parameters vs Environment Variables
Function parameters always override environment variables:
# Environment variable is set
Sys.setenv(PROJR_OUTPUT_LEVEL = "debug")
# But function parameter takes precedence
projr_build_dev(output_level = "std") # Uses "std", not "debug"Required Variables
You can document and validate required environment variables by
creating an _environment.required file. This file lists
variable names (one per line) that must be set for builds to proceed
properly.
Format:
Behavior:
- During builds, projr automatically checks that all listed variables are set
- If a required variable is missing, a warning is issued (build continues)
- Comments are supported (lines starting with
#) - This file serves as both documentation and a validation mechanism
Use cases:
- Document mandatory configuration for team members
- Ensure critical credentials are configured before deployment
- Provide a template for local environment setup
Example workflow:
# 1. Create _environment.required with mandatory variables
writeLines(c("GITHUB_PAT", "API_KEY"), "_environment.required")
# 2. Create _environment.local with actual values (git-ignored)
writeLines(c("GITHUB_PAT=ghp_...", "API_KEY=..."), "_environment.local")
# 3. Build will check and warn if any required variables are missing
projr_build_dev()Best Practices
Security
Never commit secrets to version control:
- Always use
_environment.localfor tokens, passwords, and API keys - This file is automatically added to
.gitignoreby projr - Never commit
GITHUB_PAT,OSF_PAT, or similar sensitive values
Example safe setup:
Organization
Use profiles for different environments:
-
_environment-dev- Development settings (verbose output, debug mode) -
_environment-test- Testing settings (moderate output) -
_environment-prod- Production settings (minimal output)
Keep global defaults minimal:
- Use
_environmentonly for settings that apply across all contexts - Put environment-specific settings in profile files
- Use
_environment.localfor machine-specific overrides
Validation
Document requirements:
- List required variables in
_environment.required - Provide example values in
_environment(commented out for secrets) - Include setup instructions in your project README
Test your configuration:
# Verify variables are set correctly
Sys.getenv("PROJR_OUTPUT_LEVEL")
Sys.getenv("GITHUB_PAT")
# Test with different profiles
Sys.setenv(PROJR_PROFILE = "test")
projr_env_set()Common Pitfalls
Case Sensitivity
Most environment variables are case-sensitive (both names and values):
# Correct - lowercase values
Sys.setenv(PROJR_OUTPUT_LEVEL = "debug")
Sys.setenv(PROJR_CLEAR_OUTPUT = "never")
# Incorrect - uppercase values won't work
Sys.setenv(PROJR_OUTPUT_LEVEL = "DEBUG") # Won't work
Sys.setenv(PROJR_CLEAR_OUTPUT = "NEVER") # Won't workException: Boolean values in
PROJR_LOG_DETAILED are case-insensitive:
-
"TRUE","true","True","1","YES","yes","Y","y"all work -
"FALSE","false","False","0","NO","no","N","n"all work
Variable Name Format
Variable names must follow a specific pattern or they’ll be silently ignored:
# Correct - starts with letter, contains only letters, numbers, underscores
MY_VAR=value
MY_VAR_2=value
MyVar=value
# Incorrect - will be ignored
123_VAR=value # Starts with number
MY-VAR=value # Contains hyphen
MY.VAR=value # Contains dotThe pattern enforced is: ^[a-zA-Z][a-zA-Z0-9_]*=
Empty Values
Empty values in environment files are silently ignored:
# This does NOT set VAR to an empty string - the line is skipped
VAR=
# This sets VAR to empty string, but with quotes as part of the value
VAR="" # Literally sets to two double-quote charactersIf a variable name or value is empty (after trimming whitespace), the entire line is skipped.
Profile Names
Avoid using "default" or "local" as profile
names: - These special values are filtered out automatically by projr -
Using them won’t cause errors, but they’ll be ignored
File Format Details
Environment files have specific formatting requirements:
# Correct - standard format
KEY=value
# Incorrect - spaces around = are not supported
KEY = value # Won't parse correctly
# Warning - quotes are included in the value
KEY="value" # Sets KEY to literally "value" (including the quotes)
KEY='value' # Sets KEY to literally 'value' (including the quotes)
# Correct - values with spaces (no quotes needed)
PATH=/path/to/my file.txt # Works correctly
URL=https://example.com?a=b&c=d # Works correctlyRemember: Values are taken as-is after the
= sign (with leading/trailing whitespace trimmed). Special
characters, spaces, and symbols are preserved without needing
quotes.
Already-Set Variables
Variables that are already set in your environment are never overridden by files:
# Set in environment
Sys.setenv(MY_VAR = "original")
# File contains: MY_VAR=new
projr_env_set()
# Original value is preserved
Sys.getenv("MY_VAR") # Still "original", not "new"This is by design - it allows system-level configuration to always take precedence.
See Also
-
?projr_env_set- Load environment variables from files -
?projr_build_dev- Development builds (respects environment variables) -
?projr_build- Production builds (respects environment variables) -
?projr_profile_create- Create new profiles - Quarto Environment Variables - Quarto’s environment variable documentation