CLI exec

Ejecuta un comando con los secretos en su entorno, sin escribir ningún archivo .env.

Comando exec

envilder exec resuelve todos los secretos del map file y arranca un comando con esos valores en su entorno. No se escribe nada en disco: no hay ningún archivo .env que añadir al .gitignore, mantener sincronizado o borrar. El map file y su $config funcionan exactamente igual que en el modo pull.

Uso

envilder exec [options] [--] <command> [args...]

Dónde empieza tu comando: la regla del --

Primero van las opciones de Envilder. Tu comando empieza en el primer argumento que no es una opción de Envilder, o justo después del -- si lo hay. Todo lo que viene a continuación llega tal cual a tu comando, aunque parezca una opción de Envilder. El -- es opcional: solo lo necesitas cuando el propio comando empieza por -.

# Todo es de npm
envilder exec npm run dev

# --map es de Envilder, el resto es de npm
envilder exec --map=cfg.json npm run dev

# --map=x es de npm: va después del comando
envilder exec npm run dev --map=x

# Lo mismo, con un separador explícito
envilder exec --map=cfg.json -- npm run dev

Opciones

OpciónDescripción
--mapRuta al map file (por defecto: envilder.json)
--profilePerfil AWS CLI. Tiene prioridad sobre $config.profile
--provideraws o azure. Tiene prioridad sobre $config.provider
--vault-urlURL del Azure Key Vault. Tiene prioridad sobre $config.vaultUrl

Las opciones de Envilder van después de exec, nunca antes. Una opción escrita antes de exec se rechaza con el código de salida 125, y Envilder te muestra el comando corregido:

$ envilder --map=config/prod.json exec -- npm start
error: Put envilder options after "exec": envilder exec --map=config/prod.json -- npm …

El modo exec nunca lee ni escribe ningún archivo .env y nunca sube secretos, así que --envfile, --push, --key, --value y --secret-path se rechazan con el código de salida 125 antes de cualquier llamada al proveedor. Una opción desconocida antes del comando también es un error: una errata como --mapp nunca llega a tu comando por accidente.

OpciónMensaje
--envfile--envfile cannot be used with exec: exec mode never reads or writes a .env file.
--push--push cannot be used with exec.
--key, --value, --secret-pathSingle-secret push options cannot be used with exec.

Ejemplos

# Arranca el servidor de desarrollo con los secretos de envilder.json
npx envilder exec -- npm run dev

# Usa un map file concreto
envilder exec --map=config/envilder.json -- node server.js

# Azure Key Vault con flags de la CLI
envilder exec --provider=azure   --vault-url=https://my-vault.vault.azure.net -- dotnet run

# Docker Compose puede interpolar los secretos en compose.yaml
envilder exec -- docker compose up

O intégralo en los scripts de tu package.json:

package.jsonjson
{
  "scripts": {
    "dev": "envilder exec -- vite",
    "start": "envilder exec --map=config/prod.json -- node server.js"
  }
}

Salida

El stdout es de tu comando. Toda la salida de Envilder va a stderr, así que envilder exec -- node print.js > out.json solo escribe en out.json la salida de tu comando. Si todo va bien, Envilder muestra una única línea de resumen que solo nombra el programa, porque los argumentos pueden contener secretos:

envilder: 2 secrets resolved (aws, profile=dev) → npm …

Casos de uso habituales

En todos los casos los valores solo existen en el entorno de tu comando y de los procesos que arranque, Envilder nunca crea un archivo .env, y el código de salida de tu comando pasa a ser el código de salida de Envilder. Lo que el comando haga después con los valores depende de él: Docker, por ejemplo, guarda el entorno de un contenedor en sus metadatos en disco (visibles con docker inspect) hasta que se elimina el contenedor.

Arranca LocalStack con su token de autenticación

Cuándo lo necesitas: LocalStack necesita LOCALSTACK_AUTH_TOKEN y no quieres el token en un archivo .env ni en el historial de tu shell.

envilder.jsonjson
{
  "LOCALSTACK_AUTH_TOKEN": "/envilder/development/localstack/authToken"
}

Con Docker Compose, haz referencia a la variable en compose.yaml. Compose toma su valor del entorno en el que se ejecuta, así que no hace falta ningún archivo .env:

compose.yamlyaml
services:
  localstack:
    image: localstack/localstack:stable
    ports:
      - "4566:4566"
    environment:
      LOCALSTACK_AUTH_TOKEN: ${LOCALSTACK_AUTH_TOKEN}
envilder exec -- docker compose up

Con Docker a secas, -e NOMBRE sin valor copia la variable del entorno del cliente docker, así que el token nunca aparece en la línea de comandos:

envilder exec -- docker run --rm -e LOCALSTACK_AUTH_TOKEN -p 4566:4566 localstack/localstack:stable

Tienes la misma configuración con Testcontainers (TypeScript, Python, .NET) y Aspire en envilder-examples

Tests de integración que arrancan contenedores

Cuándo lo necesitas: tus tests arrancan contenedores (por ejemplo, con Testcontainers) y leen un token o unas credenciales del entorno (process.env, os.environ, Environment.GetEnvironmentVariable) para pasárselos.

envilder exec -- npm test
envilder exec -- dotnet test
envilder exec -- pytest

Si los tests fallan, se conserva su código de salida y la CI sigue fallando. Si un secreto no se puede resolver, los tests no arrancan y el código de salida es 125.

Migraciones de base de datos y scripts puntuales

Cuándo lo necesitas: una herramienta de migraciones o un script necesita DATABASE_URL una sola vez, y no quieres la cadena de conexión en disco. Usa --map para ejecutar el mismo comando contra otro entorno.

envilder.jsonjson
{
  "DATABASE_URL": "/my-app/development/database/url"
}
envilder exec -- npx prisma migrate deploy
envilder exec -- python scripts/backfill.py

Terraform y otras herramientas IaC

Cuándo lo necesitas: una variable de entrada de Terraform contiene un secreto. Terraform lee las variables de entorno TF_VAR_<nombre> como valores de la variable de entrada <nombre>.

envilder.jsonjson
{
  "TF_VAR_db_password": "/my-app/development/database/password"
}
envilder exec -- terraform plan

Declara la variable con sensitive = true para que Terraform la oculte en la salida del plan. Terraform sigue guardando en el estado los valores que escribe en los recursos, así que protege el estado como siempre.

Servidor de desarrollo local con scripts de package.json

Cuándo lo necesitas: todo el equipo debe arrancar la aplicación con los mismos secretos ejecutando npm run dev.

package.jsonjson
{
  "scripts": {
    "dev": "envilder exec -- next dev"
  }
}

Añade envilder como dependencia de desarrollo (npm install --save-dev envilder) para que el script lo encuentre en node_modules/.bin.

Un paso de GitHub Actions

Cuándo lo necesitas: un paso de un workflow necesita los secretos, y solo ese paso. Configura las credenciales de AWS con OIDC y ejecuta tu comando con npx envilder exec:

permissions:
  id-token: write # Required for OIDC
  contents: read

steps:
  - uses: actions/checkout@v5
  - uses: aws-actions/configure-aws-credentials@v5
    with:
      role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
      aws-region: us-east-1
  - run: npx envilder exec -- npm test

Los valores resueltos se registran en el enmascarado de logs de GitHub antes de que arranque el comando, y los pasos siguientes no los ven.

Varios comandos con los mismos secretos

Cuándo lo necesitas: quieres encadenar comandos o seguir trabajando en una shell que tenga los secretos.

envilder exec -- sh -c 'npm run migrate && exec npm start'
envilder exec -- bash

Pon todo el script de sh -c entre comillas simples para que tu shell no ejecute el && fuera de envilder exec. El exec delante del último comando sustituye la shell por ese comando, así que las señales que reenvía Envilder llegan directamente a npm start. En la shell interactiva, todos los comandos que ejecutes ven los secretos; escribe exit para salir.

Comportamiento

Códigos de salida

Los códigos de salida siguen los de GNU env y docker run, así puedes distinguir un fallo de Envilder del código de salida de tu comando:

CódigoSignificado
nTu comando terminó con el código n
128 + nTu comando fue detenido por la señal n (por ejemplo, 137 para SIGKILL)
125Envilder falló antes de arrancar el comando: opciones incorrectas, comando ausente, ningún map file, secretos sin resolver o credenciales caducadas
126El comando existe pero el sistema operativo impidió ejecutarlo (por ejemplo, Permission denied)
127No se encontró el comando

Los modos pull y push siguen saliendo con 1 cuando fallan.

Fail-closed

El modo pull avisa y se salta un secreto que falta. El modo exec nunca arranca tu comando con un conjunto de secretos incompleto: si algún secreto falta, está vacío o no se puede leer (por ejemplo, por acceso denegado), el comando no arranca, Envilder lista las variables afectadas con sus rutas enmascaradas y sale con 125. Los valores se resuelven una sola vez, al arrancar el comando.

Entorno

Tu comando hereda todo el entorno de la shell que ejecuta Envilder, más todas las variables del map file. Manda el map file: cuando una variable heredada tiene el mismo nombre que una mapeada, el comando recibe el valor del proveedor, y Envilder muestra los nombres (nunca los valores) en stderr:

Overriding inherited variables: API_KEY

Envilder no arranca ninguna shell adicional: los argumentos llegan a tu comando como una lista. Pero tu propia shell interpreta la línea antes, así que pon entre comillas lo que no deba interpretar: '$DB_URL' o '&&' entre comillas simples llegan literalmente al comando, mientras que un $DB_URL sin comillas se expande con el valor de tu shell (no con el secreto resuelto) y un && sin comillas ejecuta un segundo comando fuera de envilder exec. Si necesitas funciones de la shell con los secretos, arranca una explícitamente:

envilder exec -- sh -c 'echo $DB_URL'

Enmascarado en GitHub Actions

Cuando GITHUB_ACTIONS=true, Envilder registra cada valor resuelto en el enmascarado de logs de GitHub (::add-mask::), de modo que los valores que imprima tu comando aparecen enmascarados en el log del job. Todos los registros se escriben en stderr antes de que arranque el comando; si alguno no se puede escribir, el comando no arranca (código de salida 125). La GitHub Action de Envilder no ofrece el modo exec: ejecuta la CLI desde un paso run.

- run: npx envilder exec -- npm test

No redirijas el stderr de envilder exec fuera del log del paso (por ejemplo, con 2> fichero o 2>/dev/null): es de ahí de donde el runner lee las máscaras. El runner lee stdout y stderr por canales separados, así que un valor que tu comando imprima enseguida puede llegar al log, en casos raros, antes de que se haya procesado su máscara.

Señales

stdin, stdout y stderr se heredan y se conserva el TTY, así que los REPL, las shells y las preguntas interactivas funcionan como siempre. El Ctrl+C de un terminal llega directamente a tu comando. SIGTERM y SIGHUP (por ejemplo, de docker stop o Kubernetes) se reenvían al comando, y Envilder espera a que termine, sin ningún tiempo límite propio, antes de devolver su código de salida. Las señales solo llegan al hijo directo: un lanzador como npm debe encargarse de detener a sus propios hijos.

⚠️
No es un sandbox. El modo exec nunca crea un archivo .env y no toca los que ya existen: si vienes del modo pull, borra tú mismo tu .env antiguo. No aísla el proceso. Tu comando y todos los procesos que arranque pueden leer los secretos de su entorno, incluida cualquier herramienta o agente de IA de programación que ejecute env o printenv a través de él. En Linux, otros procesos del mismo usuario pueden leer /proc/<pid>/environ. Ejecuta solo comandos de confianza con los secretos que mapeas.
💡
Ejemplos ejecutables. Arranca LocalStack con envilder exec docker run, con el token de autenticación resuelto desde AWS SSM sin ningún archivo .env (Docker lo guarda en los metadatos del contenedor hasta que se elimina), o sigue paso a paso push, pull y exec con npx envilder: envilder-examples · cli

Guía completa del comando exec en GitHub: detalles de Windows, recuperación SSO y todos los mensajes de error