How to share a .env file with a teammate safely

Why Slack and email are the wrong channel, and five better options: a shared vault, a self-expiring link, age or gpg, sops, or a secrets manager.

A new teammate needs the project's .env file, and the quickest route is to paste it into a direct message. It is also the route that leaves the most copies of your credentials behind. Here is what to avoid, what to use instead, and how the options trade off.

1. What not to do

2. Before you send anything, shrink what you send

3. Option A: a shared vault in a password manager

If the team already uses 1Password or Bitwarden, store the values there and give the teammate access to the vault. Updates reach everyone, access can be removed, and nothing sits in a chat log.

With 1Password you can go one step further and keep a .env that contains references instead of values, which is safe to commit:

# .env
STRIPE_SECRET_KEY="op://Development/Stripe/secret key"
DATABASE_URL="op://Development/Postgres/connection string"
op run --env-file=.env -- npm run dev

op run resolves each op://vault/item/field reference when the command starts and passes the real values in as environment variables. They never exist in a file on disk.

4. Option B: a self-expiring link

For a one-off handover to someone outside your password manager, send a link that expires:

Set the shortest expiry that works and, where offered, a single view. The link itself is now the secret, so it can travel over Slack, but if the recipient opens it and finds it already used or expired, assume someone else got there first and rotate the values.

5. Option C: encrypt the file with age (or gpg)

age is a small file encryption tool with short keys and no configuration. The teammate generates a key pair and sends you the public half, which is safe to paste anywhere:

brew install age
mkdir -p ~/.config/age
age-keygen -o ~/.config/age/key.txt

age-keygen prints Public key: age1.... You encrypt to that public key and send the result over any channel, Slack included:

age -r age1THEIR_PUBLIC_KEY -o .env.age .env

They decrypt with their private key:

age -d -i ~/.config/age/key.txt -o .env .env.age

If they have an ssh-ed25519 or ssh-rsa key on GitHub, you can skip the key exchange and encrypt to the keys GitHub publishes for their account. age skips key types it does not support, such as ECDSA, with a warning.

curl https://github.com/THEIR_USERNAME.keys | age -R - -o .env.age .env

They decrypt with their SSH private key:

age -d -i ~/.ssh/id_ed25519 -o .env .env.age

Add -a for ASCII output you can paste as text. Pass several -r flags to encrypt one file for several people.

If your team already uses GPG, gpg --encrypt --recipient [email protected] .env does the same job. Avoid passphrase-only encryption (gpg -c or age -p) unless the passphrase travels over a different channel from the file.

6. Option D: commit it encrypted with sops

sops encrypts the values in a .env file and leaves the variable names readable, so the encrypted file can live in the repository and show meaningful diffs. List everyone's age public key in .sops.yaml at the repository root:

creation_rules:
  - path_regex: \.env$
    age: >-
      age1YOUR_PUBLIC_KEY,
      age1TEAMMATE_PUBLIC_KEY
brew install sops
sops encrypt .env > secrets.enc.env
git add .sops.yaml secrets.enc.env

A teammate on the list decrypts with their age key, or runs a command with the values injected into its environment:

export SOPS_AGE_KEY_FILE=~/.config/age/key.txt
sops decrypt secrets.enc.env > .env
sops exec-env secrets.enc.env 'npm run dev'

To add someone, append their key to .sops.yaml and run sops updatekeys secrets.enc.env. Removing someone from the list does not remove their access to the old encrypted file in git history, so rotate the values when a person leaves. sops also works with AWS KMS, GCP KMS, Azure Key Vault and PGP if you would rather not manage age keys.

7. Option E: a secrets manager

Doppler, Infisical, HashiCorp Vault and AWS Secrets Manager hold the values centrally and hand them to the application at runtime, so there is no .env file to share at all. You get per-person access, audit logs, and rotation in one place. The cost is setup: accounts, a CLI on every machine, and a change to how the app starts. It pays off with a larger team, several environments, or a compliance requirement.

8. Which one to use

OptionBest forMain trade-off
Password manager vaultTeams already on 1Password or BitwardenEveryone needs an account in the same team
Self-expiring linkA one-off handoverNo updates; the link is the secret until opened
age or gpgTwo developers, no shared toolingManual; re-send on every change
sopsSecrets versioned with the codeKey list to maintain; old versions stay decryptable
Secrets managerLarger teams, many environmentsSetup and a runtime dependency

Whichever you pick, the file lands on the teammate's Mac as a plain .env again. Make sure it is gitignored there, see how to prevent committing .env files to git, and delete any decrypted copies left in ~/Downloads.