Sharing Environment Configurations
Learn how to safely share environment configurations with your team members using Envi's encrypted blob feature.
Overview
Envi allows you to securely share environment configurations with team members through encrypted blobs. This is useful when:
- Onboarding new team members
- Sharing configurations across different machines
- Providing environment setup for code review or testing
- Distributing configurations in team documentation
Quick Start
Sender (creating the blob):
# Pack reads .env files directly from your repository
# No need to capture first!
envi pack
# Blob is automatically copied to clipboardReceiver (using the blob):
# Copy the blob from chat/email and run (reads from clipboard automatically)
envi unpack
# Files are restored directly to your repositoryNote: Pack and unpack work completely independently of capture and restore. Pack reads environment files directly from your repository and creates an encrypted blob. Unpack decrypts the blob and restores files directly to your repository. No global storage needed!
How It Works
Encryption & Compression
Envi uses gzip compression followed by AES-256-GCM encryption with authentication to secure your environment data. Compression reduces blob size by approximately 50%, making blobs easier to share in chat applications and reducing copy-paste errors.
Automatic encryption (when a manifest file is detected):
- The encryption key is automatically derived from your project's manifest file
- Supported manifests:
package.json(JavaScript/TypeScript),Cargo.toml(Rust),go.mod(Go),pyproject.toml(Python),composer.json(PHP),pubspec.yaml(Dart),pom.xml(Java),settings.gradle(Gradle), and more - ✅ No need to share secrets separately
- ✅ Only team members with the same codebase can decrypt
- ✅ Automatic key consistency across the team
- ⚠️ Blobs become unreadable if manifest file changes
Custom secret encryption (when no manifest detected, or by choice):
- You'll be prompted to enter a custom encryption secret when packing
- ✅ Works for any project type
- ✅ Full control over encryption
- ⚠️ Must securely share the secret with your team
Blob Format
Blobs are formatted with delimiters for easy identification:
__envi_start__
[base64 encoded encrypted data]
__envi_end__This format makes blobs:
- Easy to copy-paste
- Identifiable in messages
- Resilient to formatting changes (whitespace, newlines, indentation are automatically handled)
- Safe to share in chat applications that might reformat text
Clipboard Integration
Envi automatically handles clipboard operations to make sharing seamless:
When packing:
- The blob is automatically copied to your system clipboard
- You can immediately paste it into Slack, email, or any messaging platform
- If clipboard operations fail (e.g., headless environments), the blob is displayed in the terminal
When unpacking:
- If you don't provide a blob argument, envi automatically reads from your clipboard
- Simply copy the blob from chat/email and run
envi unpack - No need to manually paste the blob as a command argument
Sharing Methods
Method 1: Automatic Encryption (Manifest-based)
Best for: Regular team collaboration when a manifest file is present (JavaScript/TypeScript, Rust, Go, Python, PHP, etc.)
How to share:
# Sender
envi pack
# Blob is automatically copied to clipboard - paste into chat/email
# Receiver (in same codebase)
# Copy the blob from chat/email, then:
envi unpack
# Automatically reads from clipboard and decrypts using project manifestPros:
- No secret management needed
- Automatic team synchronization
- Simple workflow
- Works out of the box
Cons:
- Stops working if manifest file changes
- Not suitable for historical reference
- Only works with supported project types
Works with: JavaScript/TypeScript (package.json), Rust (Cargo.toml), Go (go.mod), Python (pyproject.toml), PHP (composer.json), Dart (pubspec.yaml), Java/Kotlin (Gradle/Maven), and more.
Method 2: Custom Secret (Any Project or Long-term Storage)
Best for: Projects without manifest files, long-term storage, or documentation
How to share:
# Sender (will be prompted for secret)
envi pack
? Enter an encryption secret: ********
# Blob is automatically copied to clipboard
# Share both the blob (paste from clipboard) AND the secret
# Receiver (will be prompted for secret)
# Copy the blob from chat/email, then:
envi unpack
# Automatically reads from clipboard
? Enter the decryption secret: ********Pros:
- Works for any project type (Python, Go, Rust, etc.)
- Works regardless of codebase changes
- Can be stored in documentation
- Survives dependency updates
Cons:
- Must manage and share secret separately
- Secret must be communicated securely
Best Practices
Choosing an Encryption Method
Use automatic encryption (when manifest file is present) when:
- Sharing with current team members in same codebase
- Quick environment setup
- Active development phase
- Working with supported project types (JS/TS, Rust, Go, Python, PHP, etc.)
Use custom secret (prompted when no manifest, or for extra security) when:
- Working with projects without manifest files
- Documenting setup in README
- Creating onboarding materials
- Long-term storage needs
- Sharing across different projects
- Maximum security for production credentials
Secret Management
When using custom secrets (projects without manifest files or by choice):
Choose meaningful secrets:
bash# When prompted, use descriptive secrets ? Enter an encryption secret: mycompany-api-setup-2024 # Avoid weak or generic secrets ? Enter an encryption secret: abc123Share secrets securely:
- Use password managers
- Encrypted communication
- Team documentation tools
- NOT in public channels
Rotate secrets periodically:
bash# When creating new blob, use updated secret envi pack ? Enter an encryption secret: mycompany-api-setup-2025
Blob Sharing
Safe channels:
- Private Slack/Teams channels
- Direct messages
- Company wiki (with access control)
- Password-protected documents
Avoid:
- Public repositories
- Public Slack channels
- Unencrypted emails
- Social media
Common Workflows
Onboarding New Team Member
Projects with Manifest Files (JS/TS, Rust, Go, Python, etc.)
Prepare onboarding blob:
bash# One-time setup by team lead envi pack # Automatically uses project manifest for encryptionAdd to documentation:
markdown## Environment Setup Run this command with the blob from #team-secrets: ```bash envi unpack <blob> ```New member runs:
bashgit clone <repository> cd <repository> # Install dependencies (npm/pnpm, cargo, go mod, pip, etc.) # Copy blob from #team-secrets, then: envi unpack # Automatically reads from clipboard and decrypts using project manifest
Projects without Manifest Files
Prepare onboarding blob:
bash# One-time setup by team lead envi pack ? Enter an encryption secret: onboarding-2024Add to documentation:
markdown## Environment Setup Run this command with the blob from #team-secrets: ```bash envi unpack <blob> # When prompted, enter: onboarding-2024 ```New member runs:
bashgit clone <repository> cd <repository> # Copy blob from #team-secrets, then: envi unpack ? Enter the decryption secret: onboarding-2024
Quick Team Sync
When everyone needs updated environment variables:
# Team member with updated config
envi pack
# Blob is now on clipboard - paste into team Slack channel
# Team members copy blob and run
envi unpack
# Automatically reads from clipboard and restores filesCode Review Setup
Share environment needed for testing a branch:
# PR author adds blob to PR description (from envi pack)
# Reviewer copies blob and runs:
git checkout feature-branch
envi unpack # Reads blob from clipboard
npm run dev # Now has correct environmentVariable Redaction
Envi provides a variable redaction feature to prevent accidental sharing of personal or sensitive tokens. This is especially important when sharing blobs with team members.
What is Redaction?
Redaction allows you to mark specific environment variables as "redacted". When you capture or pack environment files, these variables:
- Are replaced with a placeholder (
__envi_redacted__) in storage and blobs - Preserve their real values in your local files during restore/unpack operations
- Cannot be shared via encrypted blobs or global storage
This protects personal tokens like:
- Personal access tokens (GitHub, GitLab, etc.)
- API keys tied to individual accounts
- Developer-specific credentials
- Local development secrets
Default Redacted Variables
By default, Envi redacts:
GITHUB_PAT- GitHub Personal Access Token
Why GITHUB_PAT is Redacted by Default
GITHUB_PAT is a personal access token that belongs to an individual GitHub user, not your organization.
🧠 Practical Implications
✅ You can use a GITHUB_PAT to access org resources if that user has access to them
❌ You cannot create a PAT that belongs to the organization itself — it always belongs to a user (or bot user)
⚠️ Using a real user's PAT for org automation is discouraged — it can break when that user leaves or their password resets
For team automation: Use GitHub Apps, deploy keys, or organization-level tokens instead.
For local development: Each developer needs their own GITHUB_PAT, which is why it's redacted by default to prevent accidental sharing.
Managing Redacted Variables
Add a variable to the redaction list:
envi config redact add SLACK_WEBHOOK_URLRemove a variable from the redaction list:
envi config redact remove GITHUB_PATList all redacted variables:
envi config redact listHow Redaction Works
When capturing or packing:
envi capture
# or
envi pack
# Output shows what was redacted:
⚠ Redacted 2 variable(s): GITHUB_PAT, SLACK_WEBHOOK_URL
These values will be stored as __envi_redacted__When restoring or unpacking:
envi restore
# or
envi unpack
# If redacted variables are found and you have existing files:
ℹ Preserved redacted variable(s) from existing files in 2 file(s)Example Workflow
Setting Up Redaction for Your Team
# Each developer adds their personal tokens to redaction list
envi config redact add GITHUB_PAT
envi config redact add PERSONAL_API_KEY
# Create blob to share with team
envi pack
# The blob will NOT contain GITHUB_PAT or PERSONAL_API_KEY values
# They are stored as __envi_redacted__ insteadReceiving a Blob with Redacted Variables
# Receive blob from teammate
envi unpack
# If you already have a .env file with real values:
# → Redacted variables preserve your existing values
# → Non-redacted variables are updated from blob
# If you don't have a .env file:
# → Redacted variables will be set to __envi_redacted__
# → You need to manually add the real valuesUse Cases
Personal Tokens
Each developer has their own personal access token:
# In your .env
GITHUB_PAT=ghp_YourPersonalToken123
SHARED_API_KEY=shared-team-key-456
# Add personal token to redaction
envi config redact add GITHUB_PAT
# When you pack and share:
# → GITHUB_PAT is redacted (not shared)
# → SHARED_API_KEY is included in blobDeveloper-Specific Configuration
Different developers need different values:
# Developer A's .env
LOCAL_DB_PORT=5432
DEVELOPER_NAME=alice
API_DEBUG_MODE=true
# Developer A adds personal config to redaction
envi config redact add DEVELOPER_NAME
envi config redact add LOCAL_DB_PORT
# When sharing blob:
# → API_DEBUG_MODE is shared with team
# → DEVELOPER_NAME and LOCAL_DB_PORT remain personalHybrid Sharing
Mix team-shared and personal variables:
# .env file
# Team-shared variables
DATABASE_URL=postgres://localhost/myapp
API_ENDPOINT=https://api.example.com
# Personal variables (redacted)
GITHUB_PAT=ghp_personal123
SLACK_WEBHOOK_URL=https://hooks.slack.com/yourwebhook
# Configure redaction
envi config redact add GITHUB_PAT
envi config redact add SLACK_WEBHOOK_URL
# Share with team
envi pack
# → DATABASE_URL and API_ENDPOINT are shared
# → GITHUB_PAT and SLACK_WEBHOOK_URL are redactedBest Practices
DO redact:
- ✅ Personal access tokens (GitHub, GitLab, Bitbucket) - These are tied to individual user accounts
- ✅ Developer-specific API keys
- ✅ Individual Slack/Discord webhooks
- ✅ Local development credentials
- ✅ Machine-specific configuration
DON'T redact:
- ❌ Team-shared API keys - Meant to be shared across the team
- ❌ Shared service credentials - Used by all developers
- ❌ Organization-level tokens - GitHub Apps, deploy keys, etc.
- ❌ Common development URLs
- ❌ Team database credentials
- ❌ Public configuration values
Tips:
- Add redaction before first capture/pack - Set up your redaction list early to avoid accidentally sharing personal tokens
- Document team standards - Agree which variables should be redacted across the team
- Review before sharing - Check the redaction warning when packing to ensure correct variables are redacted
- Keep existing files - When unpacking, keep your existing
.envfiles so redacted variables preserve their real values
Configuration Location
Redaction configuration is stored globally at ~/.envi/config.maml:
use_version_control = false
manifest_files = [
"package.json"
"Cargo.toml"
"go.mod"
# ... full list of supported manifest files
]
redacted_variables = ["GITHUB_PAT", "SLACK_WEBHOOK_URL"]This configuration is personal to your machine and won't be shared with others.
Troubleshooting
"Failed to decrypt blob"
Causes:
- Different manifest file (projects using automatic encryption)
- Wrong custom secret (custom encrypted blobs)
- Corrupted blob
Solutions:
For projects with automatic encryption:
# If automatic decryption fails, you'll be prompted:
envi unpack <blob>
Found package.json - attempting decryption
⚠ Failed to decrypt with manifest file
? Enter the decryption secret: ________For projects with custom secrets:
# Ensure you're entering the correct secret
envi unpack <blob>
? Enter the decryption secret: ________ (ask sender for this)If issues persist:
- Verify you have the same manifest file as sender (for automatic encryption)
- Ask sender to re-create blob if it may be corrupted
- For projects with different manifests, sender can create new blob with custom secret
"Invalid blob format"
Cause: Incomplete copy-paste
Solution: Ensure you copied entire blob including:
__envi_start__
[full encrypted string]
__envi_end__"No manifest file found"
Cause: Not in repository root, or working with a project type without a supported manifest
Solutions:
If your project has a supported manifest file:
# Navigate to repo root where manifest exists
cd path/to/repo/root
envi unpack <blob>If your project doesn't have a manifest file:
# This is expected - you'll be prompted for secret
envi unpack <blob>
No manifest file found - this is expected for some project types
? Enter the decryption secret: ________Security Considerations
⚠️ Critical Security Warning
IMPORTANT: Encrypted blobs are only secure while your codebase remains private.
The Vulnerability
When using automatic encryption (based on your project's manifest file):
- The encryption key is derived from your project manifest (e.g.,
package.jsonfor JavaScript/TypeScript,Cargo.tomlfor Rust,go.modfor Go, etc.) - If someone gains access to your codebase, they can decrypt any blob you've shared
- An attacker could iterate through git commit history to find the commit that decrypts the blob
Example attack scenario:
# Attacker gets access to your repository
git clone your-private-repo
cd your-private-repo
# They have the blob you posted somewhere
# They can try every commit to decrypt it
for commit in $(git log --all --format=%H); do
git checkout $commit
echo "Trying commit $commit..."
envi unpack <your-blob> 2>/dev/null && echo "DECRYPTED!" && break
doneSafe Sharing Practices
DO NOT post blobs in:
- ❌ Public Slack/Discord channels
- ❌ Public GitHub issues
- ❌ Public documentation
- ❌ Team wikis accessible by contractors
- ❌ Shared drives with broad access
- ❌ Any location that might become public later
SAFE channels (when codebase is private):
- ✅ Private Slack/Teams DMs
- ✅ 1Password/Bitwarden shared vaults
- ✅ Encrypted messaging (Signal, etc.)
- ✅ Face-to-face communication
- ✅ Internal password managers
ALWAYS SAFE (recommended for sensitive data): Use a custom strong secret instead of package.json-based encryption:
# When packing, use a strong custom secret
envi pack
? Enter an encryption secret: [generate a strong random password]
# This secret is NOT in your git history
# Attacker cannot derive it from codebase
# Share the secret through a separate secure channelWhat's Protected
- ✅ Environment variable names
- ✅ Environment variable values
- ✅ File paths and structure
- ✅ Comments in env files
What's NOT Protected
- ❌ The fact that you're using Envi
- ❌ That a blob exists
- ❌ Project identifier (if using automatic encryption based on manifest)
- ❌ The contents if someone gets your codebase (when using manifest-based encryption)
Security Recommendations
For Automatic Encryption (Manifest-based)
- Treat blobs as temporarily secure - They're safe as long as codebase stays private
- Never post in public channels - Even if your repo is currently private
- Assume codebase might leak - Ex-employees, contractor access, future open-sourcing
- Rotate secrets regularly - Create new blobs periodically
- Use custom secrets for sensitive data - Production credentials, API keys, etc.
Applies to: JavaScript/TypeScript, Rust, Go, Python, PHP, Dart, Java/Kotlin, and all projects using manifest-based encryption.
For Custom Secret Encryption (Any Project)
- Use strong secrets - Minimum 20+ random characters
- Never share secret in same channel as blob - Use separate secure communication
- Store secrets in password manager - Don't rely on memory
- Rotate secrets periodically - Especially when team members leave
- Use different secrets per environment - dev vs staging vs production
General Best Practices
- Never commit blobs to version control - Even private repos
- Audit who has access - Know who can decrypt your blobs
- Remove old blobs - Delete from chat history when secrets change
- Monitor codebase access - Track who has access to private repos
- Have an incident plan - Know what to do if credentials are exposed
Related Commands
envi pack- Create encrypted blobenvi unpack- Decrypt and restore blobenvi capture- Capture environment filesenvi restore- Restore from storageenvi config redact- Manage redacted variables
Example Scenarios
Scenario 1: Emergency Environment Fix
A critical env variable is missing for the team:
# Developer A fixes locally
# Edit .env with correct value
# Share fix immediately
envi pack
# Blob is on clipboard - paste into team chat
# Team members copy blob and apply fix
envi unpack
# Files are restored directlyScenario 2: Multi-Project Setup
Setting up multiple related projects:
JavaScript/TypeScript projects:
# Create blob for each project (automatic encryption)
cd project-a && envi pack # Paste blob-a into docs
cd ../project-b && envi pack # Paste blob-b into docs
# New developer sets up both (automatic decryption)
cd project-a && npm install
# Copy blob-a from docs
envi unpack
cd ../project-b && npm install
# Copy blob-b from docs
envi unpackMixed or non-JS/TS projects:
# Create blob for each project with same secret
cd project-a && envi pack
? Enter an encryption secret: multi-2024
# Paste blob-a into docs
cd ../project-b && envi pack
? Enter an encryption secret: multi-2024
# Paste blob-b into docs
# New developer sets up both with same secret
cd project-a
# Copy blob-a from docs
envi unpack
? Enter the decryption secret: multi-2024
cd ../project-b
# Copy blob-b from docs
envi unpack
? Enter the decryption secret: multi-2024Scenario 3: Documented Onboarding
README with embedded instructions:
For JavaScript/TypeScript projects:
## Development Setup
1. Clone repository
2. Install dependencies: `pnpm install`
3. Setup environment:
- Get blob from @tech-lead or #engineering channel
- Copy the blob and run:
```bash
envi unpack
```The blob will automatically decrypt using package.json 4. Start dev server: pnpm dev
For non-JavaScript/TypeScript projects:
```markdown
## Development Setup
1. Clone repository
2. Setup environment:
- Get blob and secret from @tech-lead or #engineering channel
- Copy the blob and run:
```bash
envi unpack
# Enter secret when prompted- Start dev server
## FAQ
**Q: Can I store blobs in git?**
A: No, treat blobs like passwords. Use secure channels only.
**Q: How long is a blob valid?**
A: Forever, as long as you have the correct secret/package.json.
**Q: Can I decrypt my own blobs later?**
A: Yes. For manifest-based encryption, as long as you have the same manifest file. For custom secret encryption, you need to remember/store the secret you used.
**Q: Is the blob the same each time?**
A: No, encryption includes random salt, so each pack creates a unique blob even with same data.
**Q: What if I lose the secret?**
A: For custom secret encryption, you cannot decrypt the blob without the secret. You'll need to re-capture and create a new blob. For manifest-based encryption, the "secret" is your manifest file (package.json, Cargo.toml, etc.) which is version controlled.