envcat get
title: envcat get audience: Developer difficulty: Intermediate estimated_read_time: 15 min prerequisites:
- CLI installed
- Access to env.cat service
- Browser for approval related_pages:
- ./installation.md
- ../device-approval.md
- ../api-reference/requests.md
Request environment variables from env.cat and inject them into your shell.
Synopsis
envcat get [flags]
The envcat get command creates an approval request, displays a URL/QR code for browser approval, waits for the user to approve, receives encrypted secrets, and outputs them in the specified format.
Description
How it works:
- Generate keypair - CLI creates ephemeral Ed25519 keypair
- Create request - POST to
/api/v1/requestswith public key - Display approval URL - Show URL and QR code in terminal
- Poll for approval - Check server every 3 seconds for up to 5 minutes
- Receive ciphertext - Get encrypted secrets from server
- Decrypt locally - Decrypt with private key (only CLI can decrypt)
- Output - Print shell exports, Fish commands, or write .env file
Security:
- End-to-end encryption - Server never sees plaintext secrets
- Ephemeral keys - New keypair generated for each request
- Single-use - Request deleted after approval
- Zero-trust - No long-lived credentials
Flags
--api-base
Type: string
Default: https://env.cat
Required: No
API base URL for the env.cat instance.
Examples:
# Production instance (default)
envcat get --bundle dev/api
# Self-hosted instance
envcat get --api-base https://envcat.yourcompany.com
# Ngrok tunnel for testing
envcat get --api-base https://abc123.ngrok.app
Notes:
- Include protocol (
https://recommended) - Do not include trailing slash
- Always use HTTPS in production
--bundle
Type: string
Default: ""
Required: No (but recommended)
Bundle name or ID to request secrets from.
Examples:
# Request by name (hierarchical)
envcat get --bundle dev/api
envcat get --bundle staging/frontend
envcat get --bundle prod/database
# Request by ID (UUID)
envcat get --bundle a1b2c3d4-e5f6-7890-abcd-ef1234567890
Naming conventions:
{environment}/{service}
dev/api
staging/api
prod/api
{team}/{project}
team-alpha/mobile
team-beta/analytics
{purpose}/{environment}
database/dev
cache/prod
What happens:
- If provided: Approval UI pre-selects this bundle
- If omitted: User chooses bundle during approval
Best practice: Always specify --bundle for automation and clarity.
--keys
Type: string slice (comma-separated)
Default: nil (all keys in bundle)
Required: No
Specific keys to request from the bundle.
Examples:
# Request single key
envcat get --bundle dev/api --keys DATABASE_URL
# Request multiple keys (comma-separated, no spaces)
envcat get --bundle dev/api --keys DATABASE_URL,REDIS_URL,API_KEY
# Request with spaces (quote the value)
envcat get --bundle dev/api --keys "DATABASE_URL, REDIS_URL"
Approval behavior:
- Approval UI shows only requested keys
- User cannot approve keys not in the request
- Reduces secrets exposure (principle of least privilege)
Use cases:
# Only need database credentials
envcat get --bundle dev/api --keys DATABASE_URL,DB_PASSWORD
# Only need API key for testing
envcat get --bundle prod/payments --keys STRIPE_SECRET_KEY
# Exclude sensitive keys when debugging
envcat get --bundle prod/api --keys PORT,LOG_LEVEL,NODE_ENV
--format
Type: string
Default: sh
Allowed values: sh, fish, .env
Required: No
Output format for environment variables.
Format: sh (default)
Shell-safe exports for bash/zsh:
envcat get --bundle dev/api --format sh
Output:
export DATABASE_URL='postgres://user:pass@localhost:5432/db'
export API_KEY='sk_live_abc123xyz'
export PORT='3000'
Usage:
# Inject into current shell
eval "$(envcat get --bundle dev/api --format sh)"
# Verify variables loaded
echo $DATABASE_URL
Quoting: Values wrapped in single quotes with proper escaping for special characters.
Format: fish
Fish shell exports:
envcat get --bundle dev/api --format fish
Output:
set -x DATABASE_URL postgres://user:pass@localhost:5432/db
set -x API_KEY sk_live_abc123xyz
set -x PORT 3000
Usage:
# Fish shell
envcat get --bundle dev/api --format fish | source
# Verify
echo $DATABASE_URL
Format: .env
Dotenv file format:
envcat get --bundle dev/api --format .env
Output:
DATABASE_URL=postgres://user:pass@localhost:5432/db
API_KEY=sk_live_abc123xyz
PORT=3000
Usage:
# Write to file
envcat get --bundle dev/api --format .env > .env
# Or use --write flag (recommended)
envcat get --bundle dev/api --write .env
Notes:
- No
exportprefix - No quotes (unless value contains special chars)
- Compatible with Docker, direnv, dotenv libraries
--write
Type: string
Default: ""
Required: No
Write output to a file instead of stdout. Implies --format .env.
Examples:
# Write to .env
envcat get --bundle dev/api --write .env
# Write to custom path
envcat get --bundle dev/api --write config/.env.local
# Write to absolute path
envcat get --bundle prod/db --write /etc/myapp/.env
Behavior:
- Sets format to
.envautomatically (ignores--formatflag) - Creates file with
0600permissions (owner read/write only) - Overwrites existing file (no prompt)
- Displays warning if file is in git repository
File permissions:
envcat get --bundle dev/api --write .env
ls -l .env
# -rw------- 1 user user 256 Oct 22 15:30 .env
Git warning:
envcat get --bundle dev/api --write .env
# ⚠️ Warning: .env appears to be in a git repository.
# Make sure to add it to .gitignore to avoid committing secrets!
Loading into shell:
# Write file
envcat get --bundle dev/api --write .env
# Load into shell
set -a && source .env && set +a
--file
Type: string
Default: ""
Required: No
Alias for --write. Works identically.
Examples:
# Identical to --write
envcat get --bundle dev/api --file .env
envcat get --bundle dev/api --file config/.env.local
Why both flags?
--write- Consistent with other CLI tools--file- Shorter, more intuitive for some users
Choose whichever you prefer. Both work the same way.
-h, --help
Show help for envcat get command.
envcat get --help
Examples
Basic Usage
Request all keys from a bundle:
envcat get --bundle dev/api
Output:
┌─────────────────────────────────────────┐
│ Approval Required │
│ │
│ Open this URL in your browser: │
│ https://env.cat/approve/abc123xyz │
│ │
│ Or scan this QR code: │
│ ████ ▄▄▄▄▄ █▀█ █▄▀▀▀█▄█ ▄▄▄▄▄ ████ │
│ ... │
│ │
│ Waiting for approval... │
│ (expires in 4:58) │
└─────────────────────────────────────────┘
# After approval:
✓ Approved! Received 3 variable(s)
export DATABASE_URL='postgres://user:pass@localhost:5432/db'
export API_KEY='sk_live_abc123xyz'
export PORT='3000'
Eval Pattern (Recommended)
Inject into current shell:
eval "$(envcat get --bundle dev/api)"
Verify:
echo $DATABASE_URL
# postgres://user:pass@localhost:5432/db
echo $API_KEY
# sk_live_abc123xyz
Benefits:
- No files created (ephemeral)
- No cleanup needed
- Secrets only in current shell session
Write to .env File
Create .env file:
envcat get --bundle dev/api --file .env
Output:
┌─────────────────────────────────────────┐
│ Approval Required │
│ ... │
└─────────────────────────────────────────┘
✓ Approved! Received 3 variable(s)
✓ Written to .env
Load into shell:
set -a && source .env && set +a
Cleanup:
rm .env
Request Specific Keys
Only request database credentials:
envcat get --bundle dev/api --keys DATABASE_URL,DB_PASSWORD
Approval UI shows:
- ✓ DATABASE_URL
- ✓ DB_PASSWORD
- (other keys not shown)
Fish Shell
Fish shell integration:
envcat get --bundle dev/api --format fish | source
Output:
set -x DATABASE_URL postgres://...
set -x API_KEY sk_live_abc123xyz
set -x PORT 3000
CI/CD Integration
GitHub Actions:
- name: Get secrets
run: |
curl -fsSL https://env.cat/cli/install.sh | sh
envcat get --bundle ci/github --file .env
source .env
Note: CI/CD approval requires automation (future feature) or pre-approved tokens.
Multiple Environments
Switch environments easily:
# Development
eval "$(envcat get --bundle dev/api)"
npm run dev
# Staging (new shell)
eval "$(envcat get --bundle staging/api)"
npm run dev
# Production (new shell)
eval "$(envcat get --bundle prod/api)"
npm start
Docker Compose
Generate .env for Docker:
envcat get --bundle dev/api --file .env
docker-compose up
docker-compose.yml:
services:
api:
env_file:
- .env
Subshell (Isolated Environment)
Run command with secrets in isolated subshell:
(eval "$(envcat get --bundle dev/api)" && npm start)
Benefits:
- Secrets only available during
npm start - Parent shell unaffected
- Automatic cleanup when subshell exits
Common Patterns
Daily Development Workflow
Morning routine:
cd ~/projects/myapp
eval "$(envcat get --bundle dev/api)"
npm run dev
Client Switching (Freelancers)
Switch between client projects:
# Client A
cd ~/clients/client-a
eval "$(envcat get --bundle client-a/api)"
# Client B
cd ~/clients/client-b
eval "$(envcat get --bundle client-b/api)"
Testing with Production Data
Use production secrets for local testing:
eval "$(envcat get --bundle prod/api --keys DATABASE_URL)"
npm run test:integration
Warning: Only request what you need to reduce exposure.
Direnv Integration
.envrc file:
#!/bin/bash
eval "$(envcat get --bundle dev/api)"
Usage:
cd ~/projects/myapp
# direnv automatically loads secrets
Troubleshooting
Request Expired
Error:
Error: request expired after 300 seconds
Solution:
Run command again and approve faster (5-minute window).
envcat get --bundle dev/api
Approval URL 404
Error:
# Browser shows "Request not found"
Solution:
- Check URL is complete (entire URL copied)
- Request may have expired (run
envcat getagain) - Verify API base URL is correct
No Variables Received
Output:
⚠️ No variables received
Reasons:
- No keys selected during approval
- Bundle is empty
- Network error during approval
Solution:
Run again and select keys during approval.
Git Warning
Warning:
⚠️ Warning: .env appears to be in a git repository.
Make sure to add it to .gitignore to avoid committing secrets!
Solution:
Add to .gitignore:
echo ".env" >> .gitignore
git add .gitignore
git commit -m "Add .env to gitignore"
Permission Denied (Write)
Error:
Error: write .env: permission denied
Solution:
Check directory permissions:
ls -ld .
# drwxr-xr-x 10 user user 4096 Oct 22 15:30 .
# If needed, fix permissions
chmod u+w .
SSL Certificate Error
Error:
Error: x509: certificate signed by unknown authority
Solution:
Update CA certificates or use self-signed cert flag (development only):
# Development only - do not use in production
export GODEBUG=x509ignoreCN=0
Advanced Usage
Custom Polling Interval
Future feature: Customize polling interval
envcat get --bundle dev/api --poll-interval 1s
Timeout Override
Future feature: Custom timeout
envcat get --bundle dev/api --timeout 10m
Offline Mode
Future feature: Use cached secrets when offline
envcat get --bundle dev/api --offline
Exit Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | General error |
2 | Request expired |
3 | Approval denied |
4 | Network error |
5 | Decryption failed |
Usage in scripts:
if envcat get --bundle dev/api --file .env; then
echo "Secrets loaded successfully"
docker-compose up
else
echo "Failed to get secrets (exit code: $?)"
exit 1
fi
See Also
- CLI Installation - Install envcat CLI
- Output Formats - Format comparison
- Examples - More use cases
- Troubleshooting - Common issues
- Approval Flow - How approval works