Pull mode reference

What does envilder do when you run it without --push or exec? It reads envilder.json, fetches every mapped secret from AWS SSM Parameter Store or Azure Key Vault and writes the values to .env. An existing file is updated in place, keys the map file does not declare stay as they are, and a secret that does not exist is skipped with a warning.

Prerequisites

  • The envilder CLI.
  • A map file, envilder.json by default, that maps each variable to a secret identifier.
  • Read access to every mapped secret: ssm:GetParameter on AWS (plus kms:Decrypt when a parameter uses a customer-managed key), or the Get secret permission on Azure Key Vault, for example through the Key Vault Secrets User role.
  • Credentials the provider SDK can find: an AWS profile, SSO session or environment variables, or an Azure sign-in such as az login or a managed identity.

Synopsis

envilder [--map=<file>] [--envfile=<file>] \
  [--provider=aws|azure] [--vault-url=<url>] [--profile=<name>]

Pull is the default mode: there is no pull subcommand. Run envilder with no options to read envilder.json and write .env in the current directory. Adding --push, or --key, --value and --secret-path, switches to push mode, and envilder exec is a separate subcommand.

Options

OptionDefaultDescription
--mapenvilder.json in the current directoryMap file to read. The run stops if the file is missing or the value is empty.
--envfile.envFile to write. Created when it does not exist, updated in place when it does. Its directory must already exist.
--provider$config.provider, then awsaws or azure, in any case. Any other value stops the run before a secret is read.
--vault-url$config.vaultUrlKey Vault URL, for example https://my-vault.vault.azure.net. Required with azure.
--profile$config.profile, then the default AWS credential chainNamed AWS profile. With azure it is ignored and a warning is printed.

An option that takes a path or a name never accepts a value that starts with -. In envilder --map --envfile=.env, --map has no value, so the run stops with error: option '--map <path>' argument missing instead of reading --envfile=.env as a path. envilder --help lists every option.

How $config and flags combine

Each setting comes from the first source that defines it: the flag, then $config in the map file, then the default. A flag replaces only the field it names, so the other $config fields still apply. Take this production map file:

envilder.prod.jsonjson
{
  "$config": { "provider": "aws", "profile": "prod-account" },
  "DB_PASSWORD": "/my-app/prod/db-password"
}
envilder.prod.jsonjson
{
  "$config": {
    "provider": "azure",
    "vaultUrl": "https://my-app-prod.vault.azure.net"
  },
  "DB_PASSWORD": "my-app-prod-db-password"
}

The first command uses the settings in the file. The second overrides one field and keeps the rest:

envilder --map=envilder.prod.json --envfile=.env.prod
envilder --map=envilder.prod.json --envfile=.env.prod --profile=ci-readonly

The second command reads the same parameters with the ci-readonly profile. The provider still comes from $config.

envilder --map=envilder.prod.json --envfile=.env.prod
envilder --map=envilder.prod.json --envfile=.env.prod \
  --vault-url=https://my-app-dr.vault.azure.net

The second command reads the same secret names from another vault. The provider still comes from $config.

Full precedence rules in the map file reference

Example: update an existing .env

The map file declares four variables. In the vault, SENTRY_DSN does not exist and FEATURE_FLAG is empty. The project already has a .env file:

envilder.jsonjson
{
  "DB_PASSWORD": "/my-app/dev/db-password",
  "API_TOKEN": "/my-app/dev/api-token",
  "SENTRY_DSN": "/my-app/dev/sentry-dsn",
  "FEATURE_FLAG": "/my-app/dev/feature-flag"
}
.envdotenv
# Local settings
LOG_LEVEL=debug
DB_PASSWORD=old-password
SENTRY_DSN=https://old-dsn.example.com/1

Run envilder from the project root. Expected output with AWS:

envilder
☁ AWS identity · account=123456789012 · region=eu-west-1 · profile=default

🪙  RESOLVING SECRETS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ✓ DB_PASSWORD         → ***************ord
  ✓ API_TOKEN           → ***************c21
  ✗ SENTRY_DSN           secret not found (path: *******************dsn) — skipped
  ⚠ FEATURE_FLAG         no value found (path: *********************lag) — skipped

⭐ LEVEL CLEARED  —  2/4 secrets loaded · .env written

With Azure the AWS identity line is not printed; the rest is the same. Values are masked: one longer than 10 characters shows its last 3, a shorter one is hidden entirely, and paths show their last 3 characters. The skipped lines are warnings on stderr; the rest goes to stdout.

The .env file afterwards:

.envdotenv
# Local settings
LOG_LEVEL=debug
DB_PASSWORD=local-dev-password
SENTRY_DSN=https://old-dsn.example.com/1
API_TOKEN=dev-token-7f3a9c21

How an existing .env is updated

  • A mapped variable that is already in the file is replaced in place: same line, same inline comment, and the same quotes when they still hold the new value.
  • A line that already holds the right value is not rewritten, so a run with nothing new leaves the file byte for byte identical.
  • Lines the map file does not declare (LOG_LEVEL above), comments, blank lines, order and line endings are kept.
  • Variables that are not in the file yet are appended at the end. A new file ends with a line break.
  • A skipped secret keeps the value the file already had (SENTRY_DSN above). Envilder never removes a line.
  • Before writing, Envilder reads the result back the way dotenv does. If any value would be lost or changed, it writes nothing and stops with an error that names the variables, never their values.

Quoting, multiline values and the one value a .env file cannot hold are covered in what a secret can contain

⚠️
The .env file contains the real secret values. Add it to .gitignore and delete it when you no longer need it, or use envilder exec to avoid the file altogether.

Missing, empty and failing secrets

A secret that does not exist (ParameterNotFound in AWS SSM, 404 in Key Vault) or whose value is empty is skipped with a warning. The other secrets are still written, the summary counts only the resolved ones (2/4 above) and the exit code is 0.

Any other failure, such as access denied, missing credentials or a network error, stops the run. Envilder lists each affected variable with its masked path and the reason, leaves the .env file untouched and exits with 1:

💥 GAME OVER — some secrets could not be fetched
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  ✗ API_TOKEN           → ******************ken

  ⮕ WHY?
     User: arn:aws:sts::123456789012:assumed-role/dev/session is not authorized to perform: ssm:GetParameter on resource: arn:aws:ssm:eu-west-1:123456789012:parameter/my-app/dev/api-token …

When an AWS SSO session has expired and both stdin and stdout are a terminal, Envilder asks Run 'aws sso login --profile dev' now? [y/N]. If you accept and the login succeeds, it retries once. In CI, or if you decline, it prints the command to run and exits with 1. If a missing secret must also stop the run, use envilder exec: it never starts a command with an incomplete set of secrets.

Common errors

MessageFix
No map file found. Provide --map or create envilder.json in the current directory.Run envilder from the directory that holds envilder.json, or pass --map=path/to/file.json.
Failed to read map file: config/envilder.jsonThe file given with --map does not exist or cannot be read. Relative paths start at the current directory.
Invalid JSON in parameter map file: envilder.jsonFix the JSON syntax of the map file. A trailing comma or a comment is the usual cause.
Could not load credentials from any providersThe AWS SDK found no credentials. Run aws configure or aws sso login, or pass --profile with a configured profile.
User: arn:aws:sts::123456789012:assumed-role/dev/session is not authorized to perform: ssm:GetParameter on resource: …The credentials work but cannot read that parameter. Allow ssm:GetParameter on its ARN, plus kms:Decrypt for a customer-managed key.
vaultUrl is required when using Azure provider. Set it in $config.vaultUrl in your map file or via --vault-url flag.Add "vaultUrl": "https://<vault-name>.vault.azure.net" to $config, or pass --vault-url.
Your AWS SSO session for profile "dev" ran out of lives.Run aws sso login --profile dev, then run envilder again. In a terminal Envilder offers to run the login for you.
Cannot represent the value for "API_TOKEN" in a dotenv-compatible format without data lossThe value cannot be written to a .env file without changing it, and nothing was written. Read that secret with envilder exec or an SDK, or store it encoded (for example base64).