Quick answer: An API environment is just a named set of variables: base URLs, credentials, and feature flags. Keeping those in plain, version-controlled files instead of cloud workspaces gives you diffs, review, and the ability to switch environments without a login. The one rule that matters is keeping secrets out of the committed files; reference a local, ignored store or a vault rather than pasting tokens into the environment definition.

I moved teams off cloud-managed environments after a painful but familiar incident. A base URL change for a staging service was made inside one person's hosted workspace, so it worked for them and nobody else, and there was no history to show what had changed. Three engineers lost an afternoon chasing a "flaky" API that was actually fine; they were silently pointing at different hosts. The same change in a tracked file would have been a one-line commit everyone pulled, with a clear author and a revert button.

What an environment actually contains

Strip away the workspace UI and an environment is a small key-value map with a few variable types. Most requests then reference those variables by name rather than hardcoding values.

  • Base URLs that differ between local, staging, and production.
  • Non-secret settings such as tenant IDs, region codes, and feature flags.
  • Secret references that point to credentials stored elsewhere, never the raw secret.

A plain-file setup typically keeps one file per environment plus a shared schema. Here is a straightforward version.

# environments/local.env -- committed, contains no secrets
BASE_URL=https://api-local.powerduck.com
REGION=us-east-1
TENANT_ID=tenant_local
TOKEN_REF=local-dev-token

# .env.secrets -- git-ignored, holds the actual value
local-dev-token=eyJ...realtoken

The request layer substitutes the reference and resolves the secret from the ignored store at runtime, so the committed file stays safe to share.

Cloud workspaces versus plain files

The hosted approach is convenient on day one, but it hides the variables inside an account and makes change tracking difficult. The table below compares the two on the things that matter during real work.

DimensionCloud workspacePlain files
Change historyHidden inside the app, if availableGit diff with author and revert
Team consistencyEach member can diverge silentlyEveryone pulls the same file
Offline useOften requires a loginWorks fully offline
SecretsStored on the vendor's serversReferenced locally or in your vault
OnboardingInvite and configure per accountClone the repo and add a secrets file

Keeping secrets out of the repository

The single mistake that turns a convenient file-based workflow into a security incident is committing a real token. Defend against it in layers rather than relying on discipline.

  1. add a .gitignore rule that excludes every secrets file and use a checked-in .example template instead;
  2. run a pre-commit hook that scans staged files for token-like strings;
  3. prefer references that resolve against a local store or a secrets manager, so the committed file never contains the value.
# .gitignore
.env.secrets
*.local
environments/*.secret.env

# resolve a reference at runtime
const value = process.env[ref] || secretStore.get(ref);

If a token ever does get committed, treat it as compromised: rotate it first, then clean history. Removing the file alone is not enough because the value remains in past commits.

Switching environments without friction

The goal is for "point at staging instead of local" to be a one-command change that cannot be partially applied. Wrap the selection in a small script or a variable that picks the environment file, and keep the names consistent across files so every required variable is present in every environment. A validation step that checks the local file against the shared variable schema catches a missing key before a request fails mysteriously.

Use an example template to keep the shape honest

Check in a .env.example that lists every variable with an empty placeholder and a short comment, so a new hire can see the full shape without anyone sharing a real value. When a variable is added, update the template in the same commit that introduces it; the validation step then fails a local or CI run if any real environment is missing the new key. This also catches naming drift early, such as two files calling the same token reference by different names, which otherwise surfaces only as a confusing undefined value at request time.

Treat the environment files like other source code

Review changes to them, run them through the same CI, and keep a code owners rule so a base URL or a tenant change cannot merge without a second pair of eyes. That is the real advantage of the plain-file approach: environments stop being invisible per-user state and become ordinary, auditable artifacts that the whole team shares, which is exactly what prevents the silent divergence that wasted our afternoon.

FAQ

Is it safe to store environment files in git?

The non-secret variables are safe and should be tracked. Keep actual credentials in a git-ignored local file or a vault and reference them by name, so the committed environment never contains a raw token.

What do I gain over a hosted workspace?

Git history, reviews, offline access, and guaranteed team consistency. A base URL change becomes a visible commit everyone pulls rather than a hidden per-account setting that can diverge.

How do I switch between local and staging?

Use one command or a variable that selects the environment file, and validate the chosen file against a shared schema so no required variable is missing before a request runs.

What if a real secret is accidentally committed?

Rotate the credential immediately, since it remains in history, then remove and clean the repository. Add pre-commit scanning and a strict gitignore to prevent a repeat.

This is part of the Postman Alternatives in 2026 hub — start there for the broader local-first workflow these environment files plug into.