# Exporting secrets from Doppler or Infisical

> The CLI commands that turn a Doppler config or an Infisical environment into a .env file, the defaults that change what you get, and what stays behind.

URL: https://crunu.com/blog/export-secrets-from-doppler-or-infisical
Language: en
Updated: 2026-10-30

Both tools print an environment as a `.env` file from their command line. In Doppler it's `doppler secrets download --no-file --format env`, run for each project and config. In Infisical it's `infisical export --format=dotenv`, run for each environment and folder path; newer CLIs also have it as `infisical sm export`. What you get is the current value of each secret, nothing more. Version history, access rules, integrations that push secrets elsewhere, rotation and dynamic secret setups stay behind. Check two Infisical defaults before you trust an export: personal overrides replace shared values, and only one folder path is exported at a time.

This post covers the commands, the defaults that change the output, and how to bring the files into another tool without leaving copies around. If you're comparing the two before deciding anything, see [Doppler vs Infisical](https://crunu.com/compare/doppler-vs-infisical).

## What an export contains

|                | Doppler                                                 | Infisical                                                |
| -------------- | ------------------------------------------------------- | -------------------------------------------------------- |
| Command        | `doppler secrets download`                              | `infisical export` (`infisical sm export` in newer CLIs) |
| Unit           | one config of one project                               | one environment and one folder path                      |
| Default format | JSON                                                    | dotenv                                                   |
| Default output | an encrypted fallback file, unless `--no-file`          | standard output, unless `--output-file`                  |
| Other formats  | `yaml`, `env`, `env-no-quotes`, `docker`, `dotnet-json` | `dotenv-export`, `dotenv-eval`, `json`, `csv`, `yaml`    |

Doppler's formats are listed on its page on accessing secrets ([Doppler: accessing secrets](https://docs.doppler.com/docs/accessing-secrets)). Infisical's are in the CLI source, where the `--format` flag reads "dotenv, dotenv-export, dotenv-eval, json, csv, yaml" ([Infisical CLI source](https://github.com/Infisical/cli/blob/main/packages/cmd/export.go)).

## Doppler: one config at a time

```sh
doppler secrets download -p web-app -c dev  --no-file --format env > dev.env
doppler secrets download -p web-app -c stg  --no-file --format env > stg.env
doppler secrets download -p web-app -c prd  --no-file --format env > prd.env
```

`web-app` is an example project, and `dev`, `stg` and `prd` are Doppler's usual config names; use yours. `-p` and `-c` are the same project and config flags you use with `doppler run`.

`--no-file` matters. Without it, Doppler's CLI documentation says the command "will save as an encrypted fallback file" instead of printing the secrets ([Doppler CLI](https://docs.doppler.com/docs/cli)). With it, the plaintext goes to standard output, and the redirect writes it to disk.

Doppler is clear about that last part: "We **strongly** recommend against downloading secrets in plain text to the file system." Its documentation recommends plaintext downloads only with process substitution, so a command that expects a file gets one without anything touching the disk. A migration does need a file, briefly, so treat these files as the most sensitive thing on the computer until they're gone.

## Infisical: check the defaults first

The CLI source shows the flags and their defaults. Four of them change what a migration export contains:

- **`--env`** defaults to `dev`. Name the environment every time.
- **`--path`** defaults to `/`, the root folder. Secrets in subfolders need their own export with their own `--path`.
- **`--secret-overriding`** defaults to true and "prioritizes personal secrets, if any, with the same name over shared secrets." If the person exporting has personal overrides, the file contains their values, not the team's.
- **`--expand`** defaults to true and "parse\[s] shell parameter expansions in your secrets", so references to other secrets arrive as resolved values. `--include-imports` also defaults to true and adds imported secrets.

For a migration, ask for the shared values explicitly:

```sh
infisical export --env=dev     --path=/ --format=dotenv --secret-overriding=false > dev.env
infisical export --env=staging --path=/ --format=dotenv --secret-overriding=false > staging.env
infisical export --env=prod    --path=/ --format=dotenv --secret-overriding=false > prod.env
```

Add `--projectId` if the directory isn't linked to the project, and one line per subfolder you use.

Infisical's reference adds a caution about the output itself: `dotenv` "writes each secret as `KEY='value'`", and it and `dotenv-export` don't escape quotes inside values ([Infisical CLI reference](https://infisical.com/docs/cli/reference)). A value that contains a single quote will break the line it's on. Search the export for values with quotes and check those by hand, or use `dotenv-eval`, which quotes each value safely.

## Check the files before importing

An export that silently missed a folder or picked up someone's override looks exactly like a correct one. Two quick checks catch most problems without printing a single value.

First, count. The number of lines with a name in each file should match the number of secrets the old tool's dashboard shows for that config or environment:

```sh
grep -c '^[A-Za-z_][A-Za-z0-9_]*=' prod.env
```

Second, compare names across environments. Staging and production usually share most names, so a name that appears in one and not the other deserves a look:

```sh
cut -d= -f1 staging.env | sort > staging.names
cut -d= -f1 prod.env | sort > prod.names
comm -3 staging.names prod.names
```

`comm -3` prints the names that exist in only one of the two files. Some differences are intentional, such as a debug flag that only staging has. Others mean a value lives in a folder, an import or a personal override the export didn't treat the way you expected. Fix the export rather than the file, so you can repeat it if needed.

## What stays behind

An export is a snapshot of values. Everything that makes the old tool a system rather than a list doesn't come with it:

- **History.** Past versions and who changed what stay in the old tool.
- **Access rules.** Who could read which project or environment has to be rebuilt.
- **Integrations.** Both tools push secrets into other services: Doppler to cloud secret stores, GitHub, Vercel, Netlify and more, Infisical through its Secret Syncs. Those targets keep their last values until something else updates them.
- **Rotation and dynamic secrets.** Doppler documents dynamic secrets on its Enterprise plan, and Infisical on its Advanced plan. Credentials issued on demand don't exist as values to export, and the setup that issues them doesn't transfer.
- **Audit logs.** Export them separately if you need to keep them, and check your plan's retention first.

Make a list of each integration and each dynamic or rotated secret before you start. Those are the items that need a decision, not just a copy.

## Bringing the files into Crunu

Crunu has no importer for Doppler or Infisical. You move values as files: create a project for each Doppler project or Infisical project, an environment for each config or environment, and drag the `.env` files onto the matching environments. Crunu reads env files as a table of [environment variables](https://crunu.com/learn/environment-variable), shows the names without values before you add them, and saves each environment as a signed version encrypted on your device. The server stores the ciphertext and metadata such as names, not the values.

*Figure: Priya Natarajan dragged the .aws folder from her computer onto the payments-api production environment. Crunu recognized two files and proposes where each one goes: \~/.aws/config, marked as able to run commands, and \~/.aws/credentials. Only field names such as aws_access_key_id are listed; values are not shown. The cursor rests on Add (2).*

A few things are worth doing as you go:

- **Multiline values.** Certificates and private keys often sit in a `.env` as one escaped line. In Crunu, a file can hold any text, so a PEM key can be its own file in the environment, with the path where it belongs on a computer.
- **Folders.** Infisical subfolders become either separate files in one environment or separate environments, depending on whether the same people need them.
- **Compare after import.** **Compare environments** lists the variables that exist in only one environment and the ones that differ, with values hidden until you choose **Show values**. A name missing from production that's present in staging is usually a folder or import you didn't export.

*Figure: Environment comparison for payments-api at Kiteline, a fictional company: staging on the left, production on the right. Chips count 6 different variables, 1 only in production, 1 only in staging, 2 identical and 2 files only in production. Every value stays hidden behind dots. OPENAI_API_KEY, which exists only in staging, is checked, and the cursor rests on Copy → to production.*

## Handle the exports like the secrets they are

- Export on a computer you trust, into a directory that isn't synced, backed up or inside a Git repository.
- Keep the files only as long as the import takes. Delete them, and empty the trash.
- Don't paste them into chat to "send them over". If two people need to do the import, both sign in and drag their own copy.
- If an export did end up somewhere shared, reissue those values at their providers. The [rotation pages](https://crunu.com/rotate/stripe) cover common providers, and [why .env files in chat are a liability](https://crunu.com/blog/why-env-files-in-chat-are-a-liability) explains why a copy in chat outlives the conversation.

## After the switch

Replace `doppler run --` and `infisical run --` with `crunu run --env <project>/<environment> --`. Servers become machines running the Crunu agent, and pipelines get a service token each, bound to their repository and branch with OIDC.

Integrations need the most thought. Crunu has no built-in sync to Vercel, Cloudflare, AWS Secrets Manager or GitHub Secrets. Where you relied on one, either let the platform's servers fetch from Crunu at run time, or push values from CI with a recipe such as `crunu run -- vercel env add …` using a production token with a CI binding. Decide that before you switch off the old sync, or the target keeps stale values without anyone noticing.

The guide to [sharing .env files with a team](https://crunu.com/guides/share-env-files-with-a-team) covers the day-to-day setup afterwards, and [Crunu vs Doppler](https://crunu.com/alternatives/doppler) and [Crunu vs Infisical](https://crunu.com/alternatives/infisical) compare the products.

## Checklist

- [ ] List every project, config or environment, and every Infisical folder path
- [ ] List integrations, rotated secrets and dynamic secrets separately
- [ ] Doppler exports use `--no-file --format env`
- [ ] Infisical exports name `--env` and `--path` and use `--secret-overriding=false`
- [ ] Values with quotes or line breaks checked by hand
- [ ] Environments compared after import
- [ ] Export files deleted; anything that leaked is reissued

## Sources

- [Accessing secrets, Doppler Docs](https://docs.doppler.com/docs/accessing-secrets), checked October 30, 2026.
- [CLI, Doppler Docs](https://docs.doppler.com/docs/cli), checked October 30, 2026.
- [export.go, Infisical CLI source on GitHub](https://github.com/Infisical/cli/blob/main/packages/cmd/export.go), checked October 30, 2026.
- [CLI reference, Infisical Docs](https://infisical.com/docs/cli/reference), checked October 30, 2026.
