docs/commands/env.md
Sync project environment and manage environment variables.
Manage environment variables via cloud or local storage. Supports:
| Backend | Location | Config |
|---|---|---|
cloud | Cloud (myflow.sh) | Default, requires login |
local | ~/.config/flow/env-local/ | No account needed |
Cloud behavior:
env_source = "cloud" plus a service_token, Flow keeps a compatibility plaintext mirror for those project keys until the host fetch path is upgraded.Force local backend:
# Via environment variable
export FLOW_ENV_BACKEND=local
# Or in ~/.config/flow/config.ts
export default {
flow: { env: { backend: "local" } }
}
If the current project has an unambiguous deploy env source such as:
[host]
env_source = "local"
then f env will also use the local backend automatically in that project.
~/.config/flow/env-local/
├── <project-name>/
│ ├── production.env
│ ├── staging.env
│ └── dev.env
└── personal/
└── production.env
Storage behavior:
.env files under ~/.config/flow/env-local/.personal/production.env keeps Flow-managed references, not raw secret values.FLOW_ENV_LOCAL_PLAINTEXT=1 is set, Flow falls back to plaintext personal local storage.# Store a personal secret
f env set API_KEY=sk-xxx
# List variables (default action when logged in)
f env
# Run command with env vars injected
f env run -- npm start
# Get a value
f env get API_KEY -f value
For project-scoped keys used by local + ship flows (for example, assistant keys):
# Store in project space (recommended for app/server env)
f env project set -e dev OPENROUTER_API_KEY=sk-...
f env project set -e production OPENROUTER_API_KEY=sk-...
f env project set -e dev OPENROUTER_MODEL=anthropic/claude-sonnet-4.5
f env project set -e production OPENROUTER_MODEL=anthropic/claude-sonnet-4.5
Notes:
f env get -e production -f value OPENROUTER_API_KEY at runtime when a ship script needs to inject a missing key.| Command | Description |
|---|---|
login | Authenticate with cloud |
set | Set a single env var |
get | Get specific env var(s) |
list | List env vars for this project |
delete | Delete env var(s) |
pull | Fetch env vars and write to .env |
push | Push local .env to cloud |
apply | Apply env vars to Cloudflare worker |
setup | Interactive wizard to push env vars |
run | Run command with env vars injected |
status | Show current auth status |
keys | Show configured env keys from flow.toml |
sync | Sync project settings and hub workflow |
bootstrap | Bootstrap Cloudflare secrets from flow.toml |
unlock | Unlock env reads (Touch ID on macOS) |
Store a personal environment variable:
# Basic set
f env set API_KEY=sk-xxx
# Personal envs always use the production personal store
f env set GITHUB_TOKEN=ghp_xxx
| Option | Short | Description |
|---|---|---|
--personal | Compatibility flag; set already targets personal envs |
Store a project-scoped environment variable:
f env project set -e dev DATABASE_URL=postgres://localhost/app
f env project set -e production PUBLIC_API_BASE_URL=https://api.example.com
Notes:
Retrieve environment variables:
# Get as KEY=VALUE
f env get API_KEY
# API_KEY=sk-xxx
# Get just the value
f env get API_KEY -f value
# sk-xxx
# Get as JSON
f env get API_KEY -f json
# {"API_KEY": "sk-xxx"}
# Get multiple
f env get API_KEY DATABASE_URL
# From personal store
f env get --personal GITHUB_TOKEN -f value
| Option | Short | Description |
|---|---|---|
--environment <ENV> | -e | Environment (default: production) |
--format <FORMAT> | -f | Output: env, json, or value (default: env) |
--personal | Fetch from personal store |
List all environment variables:
# List production vars
f env list
# List staging vars
f env list -e staging
Output:
Environment: production
API_KEY OpenAI API key
DATABASE_URL PostgreSQL connection string
REDIS_URL -
Run a command with environment variables injected:
# Inject all project env vars
f env run -- npm start
# Inject specific keys
f env run -k API_KEY -k DATABASE_URL -- node server.js
# From personal store
f env run --personal -k GITHUB_TOKEN -- gh repo list
# Multiple keys from personal
f env run --personal -k TELEGRAM_BOT_TOKEN -k TELEGRAM_API_ID -- ./start.sh
| Option | Short | Description |
|---|---|---|
--environment <ENV> | -e | Environment (default: production) |
--keys <KEYS> | -k | Specific keys to inject (repeatable) |
--personal | Fetch from personal store |
# Start app with production secrets
f env run -- npm run start
# Run with staging environment
f env run -e staging -- npm run dev
# Telegram bot with personal tokens
f env run --personal -k TELEGRAM_BOT_TOKEN -- pnpm tsx src/bot.ts
Fetch all env vars and write to .env file:
# Write to .env
f env pull
# Pull staging vars
f env pull -e staging
Creates or overwrites .env in current directory with all project variables.
Upload local .env file to cloud:
f env push
Reads .env from current directory and stores all variables.
Interactive wizard for pushing env vars:
f env setup
If [cloudflare] env_source = "cloud" is set in flow.toml, this runs a guided
prompt based on env_keys/env_vars. Otherwise it guides you through:
.env fileRemove environment variables:
# Delete single key
f env delete API_KEY
# Delete multiple
f env delete API_KEY DATABASE_URL
Authenticate with cloud:
f env login
Prompts for API base URL and token. On macOS, the token is stored in Keychain and Flow uses Touch ID to unlock env reads.
Check authentication status:
f env status
Output:
cloud Status
Token: stored in Keychain
API: https://myflow.sh
Project: myproject
Apply env vars to Cloudflare worker (uses [cloudflare] config in flow.toml):
f env apply
Requires env_source = "cloud" in your [cloudflare] config.
Show env keys configured in flow.toml without printing values:
f env keys
On macOS, unlock env reads for the day (Touch ID):
f env unlock
Flow supports three environments:
| Environment | Description |
|---|---|
production | Production secrets (default) |
staging | Staging/preview secrets |
dev | Development secrets |
Use -e flag with project-scoped commands:
f env project set DATABASE_URL=postgres://staging... -e staging
f env list -e dev
f env run -e staging -- npm run preview
| Type | Flag | Scope | Use Case |
|---|---|---|---|
| Project | (default for get, list, run, project ...) | Current project | API keys, database URLs |
| Personal | --personal | Global/user | GitHub token, Telegram bot token |
Personal variables are tied to your user account, not a specific project.
f env set writes personal vars. Use f env project set for project vars.
# Use a personal token in any project
f env run --personal -k ANTHROPIC_API_KEY -- ./my-script
You can store project envs under a named cloud space by configuring env_space
and env_space_kind in flow.toml.
# flow.toml
env_space = "nikiv"
env_space_kind = "personal"
env_space_kind = "project" (default) uses the project name.env_space_kind = "personal" routes project envs to your personal space.This affects f env pull, f env push, f env list, f env apply, and service
token creation.
# 1. Authenticate
f env login
# 2. Set up secrets
f env project set DATABASE_URL=postgres://... -e production
f env project set API_KEY=sk-xxx -e production
# 3. Verify
f env list
# 4. Run app
f env run -- npm start
# Set staging secrets
f env project set DATABASE_URL=postgres://staging... -e staging
f env project set API_KEY=sk-test-xxx -e staging
# Test with staging env
f env run -e staging -- npm run preview
# Store once
f env set --personal GITHUB_TOKEN=ghp_xxx
f env set --personal TELEGRAM_BOT_TOKEN=xxx
# Use anywhere
f env run --personal -k GITHUB_TOKEN -- gh repo list
[tasks.start]
command = "f env run -- npm start"
[tasks.bot]
command = "f env run --personal -k TELEGRAM_BOT_TOKEN -- node bot.js"
Run f env login to authenticate with cloud.
Check environment name - default is production:
f env list -e staging # Check staging instead
Ensure command comes after --:
f env run -k API_KEY -- npm start # Correct
f env run -k API_KEY npm start # May not work