Skip to content

envi pack

Create an encrypted blob from your stored environment configuration that can be shared with team members.

Usage

bash
envi pack

Description

The pack command finds all .env files in your repository, encrypts them, and automatically copies the encrypted blob to your clipboard. This blob can be safely shared with team members through communication channels like Slack, email, or messaging platforms.

Note: Pack works completely independently of capture and global storage. It reads environment files directly from your repository and creates an encrypted blob - no capture needed!

Encryption Methods

pack resolves the encryption key in this order:

  1. envi.config.maml with encryption_key (preferred) - Generated by envi create-key and committed to the repo. The most reliable option because the key is stable across dependency updates.
  2. Manifest-derived key - Fallback when no envi.config.maml is present. The key is an MD5 hash of a manifest file's contents. Supported manifests: package.json (JavaScript/TypeScript), Cargo.toml (Rust), go.mod (Go), pyproject.toml (Python), composer.json (PHP), pubspec.yaml (Dart/Flutter), pom.xml (Java/Maven), settings.gradle.kts (Kotlin), settings.gradle (Java/Gradle). Custom manifests: add via envi config manifest_files add <filename> - see Multi-Language Support.
  3. Custom secret prompt - Used when neither of the above is available. Must be at least 8 characters; you'll need to share both the blob AND the secret with the recipient.

When to use envi.config.maml

The manifest fallback is fine for most ad-hoc sharing. Run envi create-key once and commit envi.config.maml if you find that blobs in chat or onboarding docs keep breaking after teammates run pnpm install (or equivalent) — it gives you a key that's stable across dependency updates, at the cost of binding decryption to the (private) source repo.

Why prefer envi.config.maml over manifest-derived keys?

  • The manifest hash changes whenever the file changes (e.g., pnpm install updating pnpm-lock.yaml or any line of package.json), which invalidates older blobs.
  • A committed envi.config.maml survives dependency updates indefinitely.
  • The recipient doesn't need to be on the same dependency state as the sender.

Examples

Projects with envi.config.maml

After running envi create-key once and committing envi.config.maml:

bash
envi pack

Output:

✔ Finding repository root...
Repository root: /Users/you/projects/myapp
✔ Searching for env files...
✔ Found 3 file(s) to pack
✔ Reading environment files...
ℹ Using encryption_key from envi.config.maml
✔ Encrypting configuration...
✔ Copying blob to clipboard!

Blob is now on your clipboard!
Share it with colleagues who have the same envi.config.maml committed in their checkout
They can restore it using: envi unpack

Anyone with the same checkout (and therefore the same envi.config.maml) can decrypt by running envi unpack.

Projects with Manifest Files

If envi.config.maml is not present, pack falls back to manifest-derived keys (works with JavaScript/TypeScript, Rust, Go, Python, PHP, etc.):

bash
envi pack

Output:

✔ Finding repository root...
Repository root: /Users/you/projects/myapp
✔ Searching for env files...
✔ Found 3 file(s) to pack
✔ Reading environment files...
Using package.json for encryption key
⚠ Note: Only team members with the same package.json can decrypt this blob
✔ Encrypting configuration...
✔ Copying blob to clipboard...
✔ Blob copied to clipboard!

Blob is now on your clipboard!
Share it with team members who have the same manifest file
They can restore it using: envi unpack

The blob is now in your clipboard and ready to paste into Slack, email, or any messaging platform. Your team members can simply run envi unpack without any arguments - it will automatically read the blob from their clipboard!

Note: The output will mention the specific manifest file found (package.json, Cargo.toml, go.mod, etc.). The encryption key is derived from that file's contents.

Projects without Supported Manifest Files

For projects without a supported manifest file, you'll be prompted for a secret:

bash
envi pack

Interactive flow:

✔ Finding repository root...
Repository root: /Users/you/projects/myapp
✔ Searching for env files...
✔ Found 2 file(s) to pack
✔ Reading environment files...
⚠ No supported manifest file found in repository root
This is expected for some project types.
You'll need to provide a secret for encryption.

? Enter an encryption secret: ********

Using custom secret for encryption
✔ Encrypting configuration...
✔ Copying blob to clipboard...
✔ Blob copied to clipboard!

Blob is now on your clipboard!
Share the blob and the secret with your team members
They will be prompted for the secret when running: envi unpack

The blob is automatically copied to your clipboard. Share both the blob (paste from clipboard) and the secret you entered with your team members.

How It Works

  1. Finds project root - Locates your project root (looks for version control markers: .git, .jj, .hg, .svn, or prompts for confirmation)
  2. Searches for env files - Finds all .env, .env.*, .dev.vars, and .dev.vars.* files in your repository
  3. Reads environment files - Parses each file, preserving comments and structure
  4. Resolves encryption key in priority order:
    • If envi.config.maml exists in the repo root with encryption_key set, use it
    • Otherwise check for supported manifest files (package.json, Cargo.toml, go.mod, pyproject.toml, composer.json, pubspec.yaml, pom.xml, settings.gradle.kts, settings.gradle) and derive an MD5-hash key from the first match
    • Otherwise prompt for a custom secret (minimum 8 characters)
  5. Compresses data - Uses gzip compression to reduce blob size by ~50%
  6. Encrypts data - Uses AES-256-GCM encryption with authentication on compressed data
  7. Formats blob - Wraps encrypted data in __envi_start__ and __envi_end__ delimiters
  8. Copies to clipboard - Automatically copies the blob to your system clipboard for easy sharing

Clipboard Feature

The blob is automatically copied to your clipboard, making it incredibly easy to share:

  1. Run envi pack
  2. Paste (Cmd+V / Ctrl+V) directly into Slack, Teams, email, or any messaging app
  3. Your team member copies the blob and runs envi unpack (no arguments needed!)
  4. The blob is automatically read from their clipboard and decrypted

If clipboard operations fail (e.g., in headless environments), the blob is displayed in the terminal instead.

Security Considerations

⚠️ Critical Security Warning

IMPORTANT: Blobs encrypted with manifest files (automatic encryption) are only secure while your codebase remains private.

The Risk

When using manifest-based encryption (package.json, Cargo.toml, go.mod, etc.):

  • Anyone with access to your codebase can decrypt your blobs
  • An attacker could iterate through git commit history to find the commit that decrypts the blob
  • Never post blobs in publicly accessible locations

Safe sharing channels:

  • ✅ Private direct messages
  • ✅ Password managers (1Password, Bitwarden)
  • ✅ Encrypted messaging (Signal, etc.)

Unsafe sharing channels:

  • ❌ Public Slack/Discord channels
  • ❌ Public GitHub issues or wikis
  • ❌ Public documentation
  • ❌ Team wikis accessible to contractors
  • ❌ Any location that might become public

For truly sensitive data: Use a custom strong secret (minimum 20+ random characters) instead of relying on manifest-based encryption. See the Sharing Environment Configurations guide for detailed security information.

Using Manifest-Based Encryption (Automatic)

Pros:

  • No need to share secrets separately
  • Works out of the box for teams
  • Blob can only be decrypted in the same codebase
  • Automatic key consistency across the team
  • Supports many languages (JavaScript/TypeScript, Rust, Go, Python, PHP, Dart, Java, etc.)

Cons:

  • ⚠️ Insecure if codebase is compromised - See warning above
  • Blob becomes unreadable if manifest file changes (even a single character difference)
  • Cannot be used as historical reference if manifest is updated
  • Only works with supported project types
  • MD5 hash means any whitespace or formatting change in manifest breaks decryption

Using Custom Secret Encryption

Pros:

  • Secure even if codebase is compromised (if secret is strong and kept separate)
  • Blob remains readable regardless of codebase changes
  • Can be stored as historical reference
  • Full control over who can decrypt
  • Works for any project type

Cons:

  • Must share secret separately (through secure channel)
  • Secret must be remembered/stored securely
  • Requires manual secret management

Recommendation: For production credentials or highly sensitive data, always use a custom strong secret (20+ random characters) regardless of project type.

See Also

Released under the MIT License.