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.
There are two ways to set environment variables, loaded in this priority order:
System Environment
Variables from your system environment
.env File
Variables from .env file in project root
.env file overrides system environment variables. For production, use lua env command to manage variables on the server.
Method 1: .env File (Recommended for Development)
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:
Select Environment
Choose Sandbox (.env file) or Production (API)
Manage Variables
Add, update, delete, or view variables through interactive menu
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
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
✅ Do: Use descriptive names
# Good
STRIPE_API_KEY = ...
SENDGRID_API_KEY = ...
WEATHER_API_KEY = ...
# Bad
KEY1 = ...
SECRET = ...
TOKEN = ...
✅ Do: Provide defaults for non-secrets
const maxRetries = parseInt ( env ( 'MAX_RETRIES' ) || '3' );
const apiUrl = env ( 'API_BASE_URL' ) || 'https://api.example.com' ;
✅ Do: Validate critical variables
const apiKey = env ( 'STRIPE_API_KEY' );
if ( ! apiKey ) {
throw new Error ( 'STRIPE_API_KEY is required' );
}
✅ Do: Document required variables
Create .env.example with all required variables and example values
❌ Don't: Hardcode secrets
// BAD!
const apiKey = 'sk_test_abc123' ;
// GOOD!
const apiKey = env ( 'API_KEY' );
❌ Don't: Commit .env to git
Always add .env to .gitignore
❌ Don't: Log sensitive values
// 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:
In lua chat
Environment variables are loaded based on selected mode:
Sandbox mode : Uses .env file
Production mode : Uses production variables from server
Troubleshooting
Problem : env('MY_VAR') returns undefinedSolutions :
Check spelling in .env file
Ensure .env is in project root
Restart lua chat if running
For production, use lua env to verify variables on server
Changes not taking effect
Problem : Updated .env but changes not visibleSolution : Restart the CLI command:# Stop current process (Ctrl+C)
lua chat # Start again
Different values in dev vs production
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