Skip to main content

env()

Safely access environment variables in your tools.
import { env } from 'lua-cli';

const apiKey = env('API_KEY');
const baseUrl = env('API_BASE_URL') || 'https://default.com';

Function Signature

env(key: string): string | undefined
key
string
required
Environment variable name to retrieve
Returns: string | undefined - Value of the environment variable, or undefined if not set

Loading Priority

Environment variables are loaded in this order (later overrides earlier):
1

System Environment

Variables from your shell/system
export API_KEY=value
2

.env File

Variables from project .env file
# .env
API_KEY=value
For production, use lua env command to manage variables on the server.

Examples

Basic Usage

import { env } from 'lua-cli';

export class MyTool implements LuaTool {
  async execute(input: any) {
    const apiKey = env('STRIPE_API_KEY');
    
    if (!apiKey) {
      throw new Error('STRIPE_API_KEY not configured');
    }
    
    // Use the API key...
    const response = await fetch('https://api.stripe.com/v1/...', {
      headers: {
        'Authorization': `Bearer ${apiKey}`
      }
    });
    
    return await response.json();
  }
}

With Default Values

const apiUrl = env('API_BASE_URL') || 'https://api.example.com';
const maxRetries = parseInt(env('MAX_RETRIES') || '3');
const debug = env('DEBUG') === 'true';
const timeout = Number(env('TIMEOUT') || 5000);

Multiple Environment Variables

export class EmailTool implements LuaTool {
  async execute(input: any) {
    // Get all required variables
    const apiKey = env('SENDGRID_API_KEY');
    const fromEmail = env('FROM_EMAIL');
    const fromName = env('FROM_NAME') || 'Support Team';
    
    // Validate required variables
    if (!apiKey) {
      throw new Error('SENDGRID_API_KEY is required');
    }
    if (!fromEmail) {
      throw new Error('FROM_EMAIL is required');
    }
    
    // Use variables...
  }
}

Environment-Specific Configuration

export class ApiTool implements LuaTool {
  async execute(input: any) {
    const environment = env('NODE_ENV') || 'development';
    
    // Use different config based on environment
    const apiKey = environment === 'production'
      ? env('PROD_API_KEY')
      : env('DEV_API_KEY');
    
    const baseUrl = environment === 'production'
      ? 'https://api.example.com'
      : 'https://api-dev.example.com';
    
    // Use environment-specific values...
  }
}

Setting Variables

Method 1: .env File (Local Development)

Create .env in project root:
# .env
STRIPE_API_KEY=sk_test_abc123
SENDGRID_API_KEY=SG.xyz789
API_BASE_URL=https://api.example.com
MAX_RETRIES=3
DEBUG=true
Add .env to .gitignore - never commit secrets!
Create .env.example for documentation:
# .env.example
STRIPE_API_KEY=your_stripe_key_here
SENDGRID_API_KEY=your_sendgrid_key_here
API_BASE_URL=https://api.example.com

Method 2: System Environment

Set in your shell:
# Temporary (current session)
export API_KEY=value

# Permanent (add to ~/.bashrc or ~/.zshrc)
echo 'export API_KEY=value' >> ~/.bashrc

Best Practices

const apiKey = env('REQUIRED_KEY');

if (!apiKey) {
  throw new Error(
    'REQUIRED_KEY environment variable is not set. ' +
    'Please add it to your .env file or use `lua env` for production'
  );
}
// ✅ Good
env('STRIPE_API_KEY')
env('SENDGRID_API_KEY')
env('WEATHER_API_KEY')

// ❌ Bad
env('KEY1')
env('SECRET')
env('TOKEN')
// Configuration with sensible defaults
const apiUrl = env('API_URL') || 'https://api.example.com';
const timeout = parseInt(env('TIMEOUT') || '5000');
const retries = parseInt(env('MAX_RETRIES') || '3');

// But NOT for secrets
const apiKey = env('API_KEY'); // No default!
if (!apiKey) throw new Error('API_KEY required');
const apiKey = env('API_KEY');

// ❌ Bad - Exposes secret
console.log('API Key:', apiKey);

// ✅ Good - Masked
console.log('API Key:', apiKey ? '***' : 'not set');
console.log('API Key configured:', !!apiKey);
Environment variables are always strings. Convert when needed:
// Numbers
const port = parseInt(env('PORT') || '3000');
const timeout = Number(env('TIMEOUT') || 5000);

// Booleans
const debug = env('DEBUG') === 'true';
const enabled = env('FEATURE_ENABLED') !== 'false';

// Arrays
const hosts = (env('ALLOWED_HOSTS') || '').split(',');

Common Patterns

Pattern: Required Variable

function getRequiredEnv(key: string): string {
  const value = env(key);
  if (!value) {
    throw new Error(`${key} environment variable is required`);
  }
  return value;
}

// Usage
const apiKey = getRequiredEnv('STRIPE_API_KEY');

Pattern: Validation

const apiKey = env('API_KEY');

if (apiKey && !apiKey.startsWith('sk_')) {
  throw new Error('API_KEY must start with sk_');
}

if (apiKey && apiKey.length < 32) {
  throw new Error('API_KEY is too short');
}

Pattern: Caching

export class MyTool implements LuaTool {
  private static cachedApiKey: string | null = null;
  
  private getApiKey(): string {
    if (!MyTool.cachedApiKey) {
      MyTool.cachedApiKey = env('API_KEY');
      if (!MyTool.cachedApiKey) {
        throw new Error('API_KEY not configured');
      }
    }
    return MyTool.cachedApiKey;
  }
  
  async execute(input: any) {
    const apiKey = this.getApiKey();
    // Use cached key...
  }
}

Security

Never commit secrets to version control!
  • Add .env to .gitignore
  • Use .env.example for documentation
  • Store production secrets using lua env command (server-managed)
  • Rotate keys regularly

.gitignore

# .gitignore
.env
.env.local
.env.*.local

Troubleshooting

Problem: env('MY_VAR') returns undefinedSolutions:
  1. Check spelling in .env file
  2. Ensure .env is in project root
  3. Restart CLI command (variables loaded at startup)
  4. For production, use lua env to verify variables on server
Problem: Updated .env but value unchangedSolution: Restart the command:
# Stop (Ctrl+C)
lua chat  # Start again
Or use lua env to verify and update variables

Next Steps