# Environment variables

> How midcode lists the variables your site reads from its .env files, shows which are missing without ever showing a value, and the rules it follows when it writes one.

- Page: https://midcode.app/docs/data/env
- From the midcode docs. Every page as Markdown: https://midcode.app/llms.txt
- Status: This ships with the next release of midcode. The version you can download today (1.1.2) doesn't have it yet.
- Beta: midcode labels this beta.

Environment variables are the keys and addresses your site reads without having them written in its code: a database's connection string, an API key, the site's own URL. midcode lists the ones your project has, the ones it asks for and doesn't have, and lets you give one a value.

One rule shapes the whole view: **a value goes in and never comes back out.** midcode tells you whether a variable is set, never what it holds.

## Open it

Open **Database** in the top bar and choose **Environment variables**, under **Site** in the list on the left. It works with or without a database connected.

## What the list shows

midcode reads every file in the project's root called `.env` or `.env.<something>`: `.env`, `.env.local`, `.env.production`, `.env.development.local`. A file whose name ends in `.example`, `.sample`, `.template`, `.dist` or `.defaults` is an example: what it lists is asked for, never set.

It also reads your code for the variables it uses: `process.env.NAME`, `process.env['NAME']` and `import.meta.env.NAME`, in JavaScript and TypeScript, Vue, Svelte and Astro files.

Each variable is one row:

| Part | What it says |
| --- | --- |
| The mark | A green check: it has a value in some file. An amber warning: no value yet |
| **public** | Its name starts with `NEXT_PUBLIC_`, `VITE_`, `PUBLIC_`, `NUXT_PUBLIC_`, `REACT_APP_`, `EXPO_PUBLIC_` or `GATSBY_`: it's sent to the browser with the page, so never put a secret in it |
| The line under the name | The files where it has a value (`.env.local · .env`), or why it's listed without one: "Asked for in .env.example", "Read in the code", or "Empty" |
| The file beside it | The code file that reads it, or how many do |

A variable counts as missing when no file gives it a value and something wants it: an example file lists it, the code reads it, or a file has it with nothing after the `=`. Missing variables come first, and the header counts them ("2 without a value").

Variables your platform or your tools set by themselves are not listed only because the code reads them: `NODE_ENV`, `PORT`, `HOST`, `CI`, `MODE`, `DEV`, `PROD`, `BASE_URL`, `VERCEL_*`, `NETLIFY_*`, `RAILWAY_*`, `RENDER_*`, `FLY_*` and a few more.

## Values are never shown

The files are read in midcode's main process, which tells the window only which variables are set, where, and where they're read. The value field is a password field. What you type is sent to be written, and the window keeps no copy: after **Save** the field is empty again. Nothing in this view puts a value in a report or in front of your agent. See [Privacy and security](https://midcode.app/docs/reference/privacy.md).

The view says it at the bottom: "midcode shows which are set, never what they hold. A value you type is written to the file and not kept here."

## Writing a value

1. Click **Set** on a variable without a value, **Change** on one that has it, or **New variable**.
2. Type the value. For a new variable, type its name too: it's upper-cased as you type, and anything but letters, digits and `_` becomes `_`.
3. Choose the **File**. It starts on the file the variable is already in, or on the project's local file: `.env.local` in Next.js, Vite, Astro, SvelteKit, Nuxt, Remix and React Router projects (and wherever one exists), `.env` otherwise. Example files aren't offered.
4. Click **Save**, or press `Enter`. midcode says "Written to" and the file.

### The rules

- **A secret is not written to a file git would publish.** midcode asks git whether the file is ignored (`git check-ignore`). If it isn't, nothing is written and midcode says: "`.env` isn't ignored by git: a value put there would be published with your code. Use .env.local."
- **A public variable is the exception.** One with a public prefix can be written to any file: it reaches the browser anyway.
- A project with no git repository has nothing to publish to, so the value is written.
- A name is letters, digits and `_`, and doesn't start with a digit.
- Like every edit in midcode, it needs a [license or a running trial](https://midcode.app/docs/start/install.md).

### What gets written

The variable's line is replaced where it is. Every other line of the file, comments included, stays as it was:

```diff title=".env.local"
 NEXT_PUBLIC_SITE_URL=http://localhost:3000
-RESEND_API_KEY=
+RESEND_API_KEY=re_123abc
```

A variable the file doesn't have is added at the end:

```diff title=".env.local"
 RESEND_API_KEY=re_123abc
+STRIPE_SECRET_KEY=sk_test_abc
```

A value made only of letters, digits and `_ @ % + = : , . / -` is written bare. Anything else is written in double quotes, with quotes and line breaks escaped:

```text title=".env.local"
MAIL_FROM="Akila Studio <hello@example.com>"
```

If the file doesn't exist, midcode creates it, readable only by your user.

## Removing a variable

Hover a variable that's in a file and click **Remove**. midcode asks first: its line is taken out of every file that has it (not the example files), and "There's no undo: keep the value somewhere if you'll need it."

## Warnings

A banner appears above the list for each file that holds a value of a non-public variable and isn't ignored by git: "`.env` isn't ignored by git: what's in it is published with your code." Add the file to `.gitignore`, or move its secrets to `.env.local`.

## Where else midcode writes a variable

**Give it to the site**, in the Database overview, writes one variable through the same rules: `DATABASE_URL`, with the connection string of a database you connected by hand. See [Give it to the site](https://midcode.app/docs/data/database.md).

When your agent adds sign-in or a service, it's asked to leave keys as placeholders in `.env.local` and their names in `.env.example`. They show up here as missing: see [Sign-in and users](https://midcode.app/docs/data/users.md).

## Limits

- Environment variables is in beta and not in the released version yet.
- Writing or removing a variable has no `⌘Z`: these edits don't go through midcode's history.
- Only `.env` files in the project's root are read, and only `NAME=value` lines. A value that spans several lines isn't understood.
- A line written as `export NAME=…` is read, and comes back as `NAME=…` when midcode writes it.
- Reads in the code are found by pattern. `const { API_KEY } = process.env`, a computed `process.env[name]`, and other languages' ways (`os.environ` in Python, `ENV[]` in Ruby, `env()` in PHP files) aren't found.
- midcode doesn't send variables to [Vercel](https://midcode.app/docs/publish/vercel.md) or any other host. A value you set here is on your Mac; set it again where the site is deployed.
- midcode writes the file and doesn't restart your dev server. Whether a new value is picked up without a restart is up to your framework: see [Open a project](https://midcode.app/docs/start/open-a-project.md).
