Skip to content

Feature: env:pull and env:push commands for syncing .env files #76

@JoshSalway

Description

@JoshSalway

Description

The Forge CLI has env:pull and env:push commands that let developers sync entire .env files between local and remote environments. The Cloud CLI only supports individual variable management via environment:variables.

Current workflow (tedious)

# To sync local .env to Cloud, must add variables one by one:
cloud environment:variables --action=set --key=APP_KEY --value=base64:... 
cloud environment:variables --action=set --key=DB_HOST --value=...
# Or replace all at once (but requires formatting as key=value pairs)

Proposed workflow

# Download all env vars from an environment as a .env file
cloud env:pull production > .env.production
cloud env:pull staging --output=.env.staging

# Upload a local .env file to an environment (merge by default)
cloud env:push staging --file=.env.staging
cloud env:push production --file=.env.production --force

# Destructive overwrite (replace ALL vars)
cloud env:push staging --file=.env.staging --replace --force

Design consideration: injected vs custom variables

Laravel Cloud injects platform-managed environment variables when you attach resources (databases, caches, etc.). For example DB_HOST, DB_PASSWORD, DB_DATABASE, CACHE_STORE are set automatically by the platform.

Risk with replace mode

If env:push --replace overwrites ALL variables with a local .env file, it could:

  • Remove platform-injected vars (DB credentials, cache config)
  • Overwrite database passwords with stale local values
  • Break the environment silently

Suggested safety measures

  1. Default to merge (addVariables) — only add/update vars, never remove. This is safe for injected vars.
  2. --replace flag for destructive overwrite — explicitly opt-in to replacing all vars.
  3. Warn about injected vars — if the API distinguishes injected from custom vars, show a warning before replacing:
    ⚠ This will overwrite 3 platform-managed variables: DB_HOST, DB_PASSWORD, CACHE_STORE
    Are you sure? (yes/no)
    
  4. env:pull should annotate injected vars — so users know which ones the platform manages:
    # Managed by Laravel Cloud (attached database)
    DB_HOST=ep-xxx.pg.laravel.cloud
    DB_PASSWORD=npg_xxx
    
    # Custom variables
    APP_NAME=MyApp
    STRIPE_KEY=sk_test_xxx

Question for maintainers

Does the API distinguish between injected and custom variables in the response? If so, both pull and push should respect that distinction.

What happens today if you do the wrong thing?

Currently there is no feedback. If you env:push a local .env that is missing DB_HOST (because your local dev uses sqlite), the platform-injected DB_HOST gets silently removed and your app crashes on the next request with a database connection error. There is no warning, no confirmation of what changed, and no way to undo.

Implementation notes

  • env:pull fetches environment variables via the existing API and formats them as a .env file
  • env:push should default to addVariables (merge) and offer --replace for full overwrite
  • Both should support --application and --environment flags for CI usage
  • Should respect --hide-secrets flag on pull
  • Interactive mode should show a diff of what will change before applying

Prior art

Environment

  • Cloud CLI: v0.1.14

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions