Skip to content

Output Formats

Hush can output secrets in multiple formats to match what each package in your monorepo expects.

Available Formats

FormatOutput FileUse Case
dotenv.env.development / .env.productionNext.js, Vite, Expo, Remix, Node.js, etc.
wrangler.dev.varsCloudflare Workers & Pages
json.env.development.jsonAWS Lambda, serverless, JSON configs
shell.env.development.shCI/CD pipelines, Docker builds
yaml.env.development.yamlKubernetes ConfigMaps, Docker Compose

dotenv

Standard .env file format. The most common choice for Node.js applications.

Configuration

targets:
- name: app
path: ./packages/app
format: dotenv

Output

File: .env.development

Terminal window
DATABASE_URL=postgres://localhost/mydb
API_KEY=sk_test_xxx
DEBUG=true

Compatibility

Works with every major framework:

FrameworkClient Prefix
Next.jsNEXT_PUBLIC_*
ViteVITE_*
Create React AppREACT_APP_*
Vue CLIVUE_APP_*
NuxtNUXT_PUBLIC_*
AstroPUBLIC_*
SvelteKitPUBLIC_*
ExpoEXPO_PUBLIC_*
GatsbyGATSBY_*
Remix(server-only)
Node.js(any)

wrangler

Cloudflare Wrangler format for Workers development.

Configuration

targets:
- name: api
path: ./packages/api
format: wrangler

The best way to use Hush with Wrangler is hush run, which keeps secrets in memory and never writes them to disk:

Terminal window
# Recommended approach - secrets never touch disk
hush run -t api -- wrangler dev

When you use hush run with a Wrangler target, Hush automatically:

  1. Decrypts secrets to memory
  2. Sets CLOUDFLARE_INCLUDE_PROCESS_ENV=true (tells Wrangler to read from process.env)
  3. Passes secrets to Wrangler via environment variables

Alternative: hush decrypt (Secrets on Disk)

If you need to write secrets to disk (not recommended), use hush decrypt --force:

Output File: .dev.vars

Terminal window
DATABASE_URL=postgres://localhost/mydb
STRIPE_SECRET_KEY=sk_test_xxx
JWT_SECRET=super-secret-key

How Wrangler Loads Environment Variables

Understanding Wrangler’s loading order helps troubleshoot issues:

PrioritySourceBehavior
1st.dev.vars fileIf exists, blocks all other sources
2nd.env filesLoads if no .dev.vars; merges with process.env
3rdprocess.envOnly if CLOUDFLARE_INCLUDE_PROCESS_ENV=true
4thwrangler.toml [vars]Base layer

Key insight: If a .dev.vars file exists (even if empty!), Wrangler ignores CLOUDFLARE_INCLUDE_PROCESS_ENV entirely.

Troubleshooting

Secrets not appearing in your Worker?

  1. Check for .dev.vars file:

    Terminal window
    ls -la .dev.vars

    If it exists, delete it:

    Terminal window
    rm .dev.vars
  2. Use hush run instead of hush decrypt:

    Terminal window
    # Wrong - creates .dev.vars which blocks future hush run usage
    hush decrypt --force
    # Right - keeps secrets in memory
    hush run -t api -- wrangler dev
  3. Check your Wrangler version: Older versions of Wrangler may not support CLOUDFLARE_INCLUDE_PROCESS_ENV. Update to the latest:

    Terminal window
    npm update wrangler
  4. Verify Hush is targeting correctly:

    Terminal window
    hush status

Push to Production

Hush can push secrets to Cloudflare Workers:

Terminal window
# Preview what would be pushed
hush push --dry-run
# Push production secrets
hush push
# Push specific target only
hush push -t api

This runs wrangler secret put for each variable.

Cloudflare Pages

For Cloudflare Pages projects, use any format for local development and add a push_to configuration to enable pushing secrets.

Configuration

targets:
- name: app
path: ./app
format: dotenv
include:
- NEXT_PUBLIC_*
push_to:
type: cloudflare-pages
project: my-pages-project # Your Cloudflare Pages project name

Local Development

The format: dotenv setting creates .env.development or .env.production files for local development, which frameworks like Next.js, Vite, etc. read automatically.

Push to Production

Terminal window
# Preview what would be pushed
hush push -t app --dry-run --verbose
# Push production secrets to Cloudflare Pages
hush push -t app

This uses wrangler pages secret bulk to push all secrets at once.

Template Expansion

If your target uses subdirectory templates, expansions are resolved before pushing:

Terminal window
# app/.env (template)
NEXT_PUBLIC_API_URL=${API_URL}
NEXT_PUBLIC_STRIPE_KEY=${STRIPE_PUBLISHABLE_KEY}

When you run hush push -t app, these ${VAR} references are resolved against your root secrets, and the expanded values are pushed to Cloudflare Pages.

json

JSON object format for applications that consume JSON configuration.

Configuration

targets:
- name: shared
path: ./packages/shared
format: json

Output

File: .env.development.json

{
"DATABASE_URL": "postgres://localhost/mydb",
"API_KEY": "sk_test_xxx",
"DEBUG": "true"
}

Use Cases

  • Configuration files that need JSON
  • Tools that read JSON config
  • API responses or fixtures
  • Type-safe config loading

shell

Sourceable shell script with export statements.

Configuration

targets:
- name: scripts
path: ./scripts
format: shell

Output

File: .env.development.sh

#!/bin/sh
export DATABASE_URL="postgres://localhost/mydb"
export API_KEY="sk_test_xxx"
export DEBUG="true"

Usage

Terminal window
# Source the file to set environment variables
source .env.development.sh
# Or in a script
#!/bin/bash
source ./scripts/.env.production.sh
./deploy.sh

Use Cases

  • CI/CD pipelines
  • Shell scripts
  • Docker build arguments
  • Makefile targets

yaml

YAML format for Kubernetes ConfigMaps, Docker Compose, and other YAML-based configuration.

Configuration

targets:
- name: k8s
path: ./k8s
format: yaml

Output

File: .env.development.yaml

DATABASE_URL: "postgres://localhost/mydb"
API_KEY: "sk_test_xxx"
DEBUG: "true"
REDIS_URL: "redis://localhost:6379"

Use Cases

  • Kubernetes ConfigMaps and Secrets
  • Docker Compose environment files
  • Helm chart values
  • Any YAML-based configuration

Creating a Kubernetes ConfigMap

For Kubernetes deployments, use hush run to inject secrets into your kubectl commands:

Terminal window
# Run kubectl with secrets injected
hush run -e production -- kubectl apply -f k8s/
# Or use hush push for Cloudflare Workers
hush push

For ConfigMaps, consider using external secrets operators or injecting secrets at runtime rather than writing them to files.

Docker Compose Integration

docker-compose.yml
services:
app:
env_file:
- ./config/.env.development.yaml

Choosing a Format

Your StackRecommended Format
Next.js, Vite, CRA, Vue, Nuxtdotenv
Astro, SvelteKit, Remixdotenv
Expo / React Nativedotenv
Gatsbydotenv
Cloudflare Workers & Pageswrangler
AWS Lambda, serverlessjson
Kubernetes, Docker Composeyaml
CI/CD pipelines, shell scriptsshell
Node.js / general backenddotenv

Multiple Formats

You can use different formats for different targets:

targets:
# Next.js app uses dotenv
- name: web
path: ./apps/web
format: dotenv
include:
- NEXT_PUBLIC_*
# Cloudflare Worker uses wrangler
- name: api
path: ./apps/api
format: wrangler
exclude:
- NEXT_PUBLIC_*
# Lambda functions use JSON
- name: lambda
path: ./packages/lambda
format: json
# Kubernetes uses YAML
- name: k8s
path: ./k8s
format: yaml
exclude:
- NEXT_PUBLIC_*
# CI scripts use shell
- name: ci
path: ./scripts
format: shell