Skip to content

Convex CLI always creates .env.local even when environment variables are already set #191

@delkopiso

Description

@delkopiso

The Convex CLI (convex dev) always creates a .env.local file and adds it to .gitignore, even when the required environment variables (CONVEX_DEPLOYMENT, CONVEX_URL, etc.) are already available in the shell environment.

This behavior is problematic for users who:

  • Use tools like direnv with .envrc files
  • Manage secrets with external tools (1Password, AWS Secrets Manager, etc.)
  • Have environment variables set via CI/CD or container orchestration
  • Want to avoid leaving any environment settings in local filesystem

Current Behavior

The CLI creates .env.local in these scenarios even when env vars are already set:

  1. convex dev (with CONVEX_DEPLOY_KEY in environment)
  2. convex dev --url "$CONVEX_URL" (with URL in environment)
  3. convex dev --url "$CONVEX_URL" --admin-key "$CONVEX_ADMIN_KEY" (with both in environment)

Expected Behavior

The CLI should detect existing environment variables and skip file creation when:

  • CONVEX_DEPLOYMENT is already set in the shell environment
  • The appropriate URL variable (e.g., NEXT_PUBLIC_CONVEX_URL) is already set in the shell environment
  • Authentication is available via CONVEX_DEPLOY_KEY or CLI arguments

Reproduction Steps

  1. Set environment variables (e.g., via direnv):

    export CONVEX_DEPLOYMENT="dev:amazing-animal-123"
    export CONVEX_URL="https://amazing-animal-123.convex.cloud"
    export NEXT_PUBLIC_CONVEX_URL="https://amazing-animal-123.convex.cloud"
    export CONVEX_DEPLOY_KEY="dev:amazing-animal-123|eyJ..."
  2. Run convex dev

  3. Observe that .env.local is created despite variables being available

Root Cause Analysis

Looking at the source code in npm-packages/convex/src/cli/lib/envvars.ts:

The envVarWriteConfig function only checks for environment variables in files (.env.local, .env) but not in the shell environment (process.env):

// This only reads from files, not process.env
const existingFileContent = ctx.fs.readUtf8File(envFile);
const config = dotenv.parse(existingFileContent);

Similarly, writeDeploymentEnvVar in deployment.ts only checks file-based environment variables.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions