Step one: file variables
Before environments, the format gives you file-level variables: declare @name = value at the top, reference it as {{name}} anywhere in the file:
@baseUrl = https://dev.api.example.com
### List orders
GET {{baseUrl}}/orders
### Create an order
POST {{baseUrl}}/orders
Content-Type: application/json
{ "sku": "KARVE-1" }
That solves repetition inside one file. The remaining problem: to point those requests at staging instead of dev, you have to edit the file — and that edit shows up in Git. (Variables themselves are covered in the format guide.)
What an environment is
An environment is a named set of variable values that lives outside the .http file. The file references {{baseUrl}} and {{token}}; the environment decides what those mean right now. Switch environment, and every request in every file follows — no edits, no diffs. The .http ecosystem has two conventions for storing them.
Convention 1: http-client.env.json
The VS Code REST Client, Visual Studio 2022, and the JetBrains HTTP Client read a JSON file named http-client.env.json placed next to the .http file (or in a parent directory). One JSON object per named environment; a special $shared environment supplies defaults:
{
"$shared": { "apiVersion": "v2" },
"dev": { "baseUrl": "https://dev.api.example.com" },
"prod": { "baseUrl": "https://api.example.com" }
}
You pick the active environment from a dropdown in the editor, and {{baseUrl}} resolves accordingly. A companion http-client.env.json.user file (kept out of Git) holds per-developer secrets in the JetBrains flavor.
Karve doesn't read http-client.env.json today — it uses plain .env files instead (next section). Files that reference one stay valid and portable; only the variable values need to move.
Convention 2: dotenv .env files (Karve)
Karve keeps environments in the format ops tooling already uses: dotenv. One environment = one .env file on disk, plain KEY=value lines:
# .env.dev
baseUrl=https://dev.api.example.com
token=dev-token-here
# .env.prod
baseUrl=https://api.example.com
token=prod-token-here
How it works in the app:
- Register your .env files in the Environments panel (or create new ones from a template there).
- Click one to make it active — app-wide, shown in the status bar so you always know which server you're about to hit.
- Send any request: the active file's values fill every {{variable}}. Edits to the .env apply on the next send — no reload.
Because an environment is just a file, it behaves like one: commit .env.dev for the team, git-ignore .env.prod with real credentials, copy one to a teammate, or edit it in Karve itself — .env files open in a plain-text tab.
Precedence: the file wins
When the same name is defined in both places, the file-level @var overrides the environment value. Think of the environment as the shared base and the file as the local override — handy for pinning one request to a specific host while everything else follows the active environment. Karve matches the VS Code REST Client here, so files keep behaving the same when they move between tools.
# active .env sets baseUrl=https://api.example.com
@baseUrl = http://localhost:5000 # ← this wins inside this file
GET {{baseUrl}}/health
Keeping secrets out of Git
The pattern that works:
- Reference secrets only as {{token}} in the committed .http file — never inline.
- Put real values in a .env that's listed in .gitignore.
- Commit a placeholder .env.example so teammates know which keys to fill in.
A token pasted straight into a .http file lands in your Git history the moment you commit. Route every secret through an environment.
Auth headers specifically — bearer tokens, Basic auth, API keys — are covered in the authentication guide.
Common questions
What is http-client.env.json?
A JSON environments file read by the VS Code REST Client, Visual Studio 2022, and JetBrains HTTP Client — one object per named environment, with $shared as the defaults block. It sits next to your .http files.
Can I use a .env file with .http files?
Yes — that's Karve's model. Register .env files in the Environments panel, activate one, and its values fill your {{variables}} on every send.
Which value wins if a variable is defined twice?
The file's @var beats the environment value — environment as base, file as override. Same rule in Karve, VS Code, and Visual Studio.