What are secrets?
Secrets are encrypted environment variables that you access at runtime through ctx.env. Use them for API keys, database URLs, external service tokens, and any sensitive values.
You have three ways to configure secrets with the CLI:
Inline
.env file
Interactive
Pass KEY=VALUE pairs directly:jelou secrets set query-customer CRM_API_KEY=sk_test_EXAMPLE JELOU_API_KEY=jfn_pat_EXAMPLE
# ✓ Set 2 secrets
Import from a .env file:jelou secrets set query-customer --from-env .env.production
The file follows the standard format:CRM_API_KEY=sk_test_EXAMPLE
JELOU_API_KEY=jfn_pat_EXAMPLE
DATABASE_URL=postgres://user:pass@host:5432/db
Empty lines and comments (#) are ignored. Without arguments, the CLI guides you step by step:jelou secrets set query-customer
# ? Secret key: CRM_API_KEY
# ? Secret value: ****
# ? Add another secret? (y/N) y
# ? Secret key: JELOU_API_KEY
# ? Secret value: ****
# ? Add another secret? (y/N) n
# ✓ Set 2 secrets
Values are masked during input.
Keys must be UPPER_SNAKE_CASE (pattern: ^[A-Z][A-Z0-9_]*$).
Access secrets in your function
Use ctx.env inside the handler:
import { define, z } from "@jelou/functions";
export default define({
name: "send-whatsapp",
description: "Sends a WhatsApp message using the Jelou API",
input: z.object({
phone: z.string().min(10),
message: z.string().min(1),
}),
handler: async (input, ctx) => {
const apiKey = ctx.env.get("JELOU_API_KEY");
const botId = ctx.env.get("BOT_ID");
if (!apiKey) {
ctx.log("Error: JELOU_API_KEY not configured");
return { sent: false, error: "Missing API key" };
}
const res = await fetch("https://api.jelou.ai/v1/messages/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
botId,
phone: input.phone,
message: input.message,
}),
});
return { sent: res.ok, status: res.status };
},
});
ctx.env methods
| Method | Returns | Description |
|---|
ctx.env.get("KEY") | string | undefined | Gets the value of a secret |
ctx.env.has("KEY") | boolean | Checks if a secret exists |
ctx.env.toObject() | Record<string, string> | Gets all secrets as an object |
Blocked variables
Internal platform variables with the __FN_ prefix are blocked. Calling ctx.env.get("__FN_COMPANY_ID") returns undefined.
Local development
In local development, the jelou dev server loads secrets from your .env file:
CRM_API_KEY=sk-test-local123
JELOU_API_KEY=jfn_pat_test_local
DATABASE_URL=postgres://localhost:5432/mydb
You can specify a different file:
jelou dev --env .env.local
Never commit your .env file to the repository. jelou init adds it automatically to .gitignore.
List and delete secrets
jelou secrets list query-customer
# ▸ Key Updated
# ▸ CRM_API_KEY 2 hours ago
# ▸ JELOU_API_KEY 3 days ago
jelou secrets delete query-customer CRM_API_KEY
# ✓ Deleted CRM_API_KEY
Secrets in CI/CD
In CI pipelines, use system environment variables to inject secrets:
- name: Configure secrets and deploy
env:
JELOU_TOKEN: ${{ secrets.JELOU_TOKEN }}
run: |
jelou secrets set query-customer \
CRM_API_KEY=${{ secrets.CRM_API_KEY }} \
JELOU_API_KEY=${{ secrets.JELOU_API_KEY }}
jelou deploy --no-confirm