Skip to main content

Overview

Environment variables allow you to configure your skills without hardcoding sensitive information like API keys.
Never hardcode secrets in your code! Always use environment variables.

Using Environment Variables

Import the env Function

import { env } from 'lua-cli';

export class SendEmailTool implements LuaTool {
  async execute(input: any) {
    const apiKey = env('SENDGRID_API_KEY');
    const fromEmail = env('FROM_EMAIL') || '[email protected]';
    
    if (!apiKey) {
      throw new Error('SENDGRID_API_KEY not configured');
    }
    
    // Use the API key...
  }
}

Setting Environment Variables

Quick Setup: Use lua env command for an interactive interface to manage environment variables in both sandbox and production environments.
lua env
There are two ways to set environment variables, loaded in this priority order:
1

System Environment

Variables from your system environment
export API_KEY=value
2

.env File

Variables from .env file in project root
# .env
API_KEY=value
.env file overrides system environment variables. For production, use lua env command to manage variables on the server.
Create a .env file in your project root:
# External API Keys
STRIPE_API_KEY=sk_test_abc123
SENDGRID_API_KEY=SG.xyz789
OPENAI_API_KEY=sk-abc123

# Configuration
API_BASE_URL=https://api.example.com
ENABLE_DEBUG=false
MAX_RETRIES=3

.gitignore

Always add .env to .gitignore!
# .gitignore
.env
.env.local
.env.*.local

.env.example

Create a .env.example file to document required variables:
# .env.example
STRIPE_API_KEY=your_stripe_key_here
SENDGRID_API_KEY=your_sendgrid_key_here
API_BASE_URL=https://api.example.com
Commit .env.example to git, but never commit .env!

Method 2: Interactive Command

Use the lua env command for an interactive interface:
1

Run Command

lua env
2

Select Environment

Choose Sandbox (.env file) or Production (API)
3

Manage Variables

Add, update, delete, or view variables through interactive menu
4

Changes Saved

Variables are saved to .env (sandbox) or API (production)

Complete Guide

See full documentation for the lua env command

Example: External API Integration

Stripe Payment Tool

import { LuaTool, env } from 'lua-cli';
import { z } from 'zod';

export default class CreatePaymentTool implements LuaTool {
  name = "create_payment";
  description = "Create a payment link for checkout";
  
  inputSchema = z.object({
    amount: z.number().positive(),
    currency: z.string().default('USD'),
    description: z.string()
  });

  async execute(input: z.infer<typeof this.inputSchema>) {
    // Get API key from environment
    const stripeKey = env('STRIPE_API_KEY');
    
    // Validate it exists
    if (!stripeKey) {
      throw new Error('STRIPE_API_KEY not configured. Please set it in .env or lua.skill.yaml');
    }
    
    // Use the key
    const response = await fetch('https://api.stripe.com/v1/checkout/sessions', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${stripeKey}`,
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: new URLSearchParams({
        'line_items[0][price_data][currency]': input.currency,
        'line_items[0][price_data][unit_amount]': (input.amount * 100).toString(),
        'line_items[0][price_data][product_data][name]': input.description,
        'line_items[0][quantity]': '1',
        'mode': 'payment',
        'success_url': 'https://example.com/success',
        'cancel_url': 'https://example.com/cancel'
      })
    });
    
    const session = await response.json();
    
    return {
      paymentUrl: session.url,
      sessionId: session.id
    };
  }
}

.env File

STRIPE_API_KEY=sk_test_51Abc123...

Best Practices

# Good
STRIPE_API_KEY=...
SENDGRID_API_KEY=...
WEATHER_API_KEY=...

# Bad
KEY1=...
SECRET=...
TOKEN=...
const maxRetries = parseInt(env('MAX_RETRIES') || '3');
const apiUrl = env('API_BASE_URL') || 'https://api.example.com';
const apiKey = env('STRIPE_API_KEY');
if (!apiKey) {
  throw new Error('STRIPE_API_KEY is required');
}
Create .env.example with all required variables and example values
// BAD!
const apiKey = 'sk_test_abc123';

// GOOD!
const apiKey = env('API_KEY');
Always add .env to .gitignore
// BAD!
console.log('API Key:', apiKey);

// GOOD!
console.log('API Key:', apiKey ? '***' : 'not set');

Common Patterns

Pattern: Required Variable

const apiKey = env('REQUIRED_KEY');
if (!apiKey) {
  throw new Error('REQUIRED_KEY environment variable is not set');
}

Pattern: Optional with Default

const apiUrl = env('API_URL') || 'https://api.example.com';
const timeout = parseInt(env('TIMEOUT') || '5000');
const debug = env('DEBUG') === 'true';

Pattern: Validation

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

Pattern: Environment-Specific Configuration

const environment = env('NODE_ENV') || 'development';
const apiKey = environment === 'production' 
  ? env('PROD_API_KEY')
  : env('DEV_API_KEY');

Testing with Environment Variables

In lua test

Environment variables are automatically loaded from .env when you run:
lua test

In lua chat

Environment variables are loaded based on selected mode:
lua chat
  • Sandbox mode: Uses .env file
  • Production mode: Uses production variables from server

Troubleshooting

Problem: env('MY_VAR') returns undefinedSolutions:
  1. Check spelling in .env file
  2. Ensure .env is in project root
  3. Restart lua chat if running
  4. For production, use lua env to verify variables on server
Problem: Updated .env but changes not visibleSolution: Restart the CLI command:
# Stop current process (Ctrl+C)
lua chat  # Start again
Problem: Works locally but not when deployedSolution: Use lua env to manage production variables:
lua env  # Select Production mode
# Add production API keys

Example Project Structure

my-skill/
├── .env                    # Local secrets (not in git)
├── .env.example           # Template (in git)
├── .gitignore             # Contains .env
├── lua.skill.yaml         # Production config
├── src/
│   ├── index.ts
│   └── tools/
│       └── MyTool.ts      # Uses env('VAR_NAME')
└── package.json

Next Steps