Run Your Dev Server Without a .env File

Published: (March 4, 2026 at 07:06 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

Every project has one – a .env file sitting in the project root with database passwords, API keys, and secrets of varying sensitivity.
You have it in .gitignore. You hope nobody accidentally commits it. You send it to new teammates over Slack because there’s no better option. You’ve probably forgotten it’s there half the time.

The .env file is the developer ecosystem’s accepted bad practice. Everyone knows it’s not great, but nobody has a better answer for local development that doesn’t require enterprise infrastructure.

Introducing agentsecrets env

agentsecrets env is a process wrapper. You put it in front of any command. It pulls your secrets from the OS keychain and injects them as environment variables into the process at launch. The process reads from os.environ (or process.env) normally – no changes to your application code, no SDK to install, no integration work. When the process exits, the values are gone. Nothing is written to disk.

Before

python manage.py runserver

After

agentsecrets env -- python manage.py runserver

That’s the entire change to your workflow. Everything inside your application stays identical.

Install

brew install the-17/tap/agentsecrets

or

npm install -g @the-17/agentsecrets

or

pip install agentsecrets

Initialize and Store Your Secrets

agentsecrets init
agentsecrets secrets set DATABASE_URL=postgresql://user:pass@localhost/mydb
agentsecrets secrets set STRIPE_SECRET_KEY=sk_live_51H...
agentsecrets secrets set DJANGO_SECRET_KEY=your-secret-key
agentsecrets secrets set OPENAI_KEY=sk-proj-...

Or import your existing .env all at once, then delete it

agentsecrets secrets push
rm .env

Values go to the OS keychain – macOS Keychain, Windows Credential Manager, or Linux Secret Service. Not a file. Not an environment variable in your shell profile. The OS keychain requires system‑level authentication to access and is not readable by other processes.

No Changes Needed in Your Code

# settings.py
import os

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": os.environ["DB_NAME"],
        "PASSWORD": os.environ["DB_PASSWORD"],  # injected by agentsecrets env
        "HOST": os.environ["DB_HOST"],
    }
}

SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
STRIPE_SECRET_KEY = os.environ["STRIPE_KEY"]

Running Commands with Secrets Injected

Django

agentsecrets env -- python manage.py runserver
agentsecrets env -- python manage.py migrate
agentsecrets env -- python manage.py shell
agentsecrets env -- celery -A myapp worker --loglevel=info
agentsecrets env -- python manage.py test

Node / npm / npx / Prisma

agentsecrets env -- node server.js
agentsecrets env -- npm run dev
agentsecrets env -- npx next dev
agentsecrets env -- npx ts-node src/index.ts
agentsecrets env -- npx prisma migrate dev

Your application reads process.env.STRIPE_KEY exactly as before – only the source of the value changed.

One‑Line Integration via a Makefile

RUN := agentsecrets env --

dev:
	$(RUN) npm run dev

test:
	$(RUN) npm test

migrate:
	$(RUN) python manage.py migrate

server:
	$(RUN) python manage.py runserver

worker:
	$(RUN) celery -A myapp worker --loglevel=info

Now make dev, make test, make migrate, etc., all run with secrets injected from the keychain. You type the same commands you always typed.

Bonus: Disable Injection on the Fly

make dev RUN=        # runs: npm run dev (no injection, for debugging)
make dev             # runs: agentsecrets env -- npm run dev

Replacing Stripe’s config.toml

The Stripe CLI stores your key in ~/.config/stripe/config.toml after stripe login – plaintext, permanent, readable by any process (including AI coding assistants).

Use agentsecrets env instead

agentsecrets env -- stripe listen --forward-to localhost:3000
agentsecrets env -- stripe customers list
agentsecrets env -- stripe trigger payment_intent.created
agentsecrets env -- stripe mcp

The CLI finds STRIPE_SECRET_KEY in the environment and uses it, making config.toml irrelevant.

Docker Compose

agentsecrets env -- docker-compose up
agentsecrets env -- docker-compose run web python manage.py migrate

Your docker-compose.yml stays the same. The secrets come from the keychain rather than a .env file.

Why This Matters for AI Coding Assistants

When you use an AI coding assistant (Claude, Cursor, Copilot, etc.), it has access to your filesystem to read files and understand your codebase. A .env file in the project directory is a goldmine:

  1. Direct access – the assistant reads .env while debugging or exploring, leaking keys into the conversation context.
  2. Prompt injection – a malicious file processed by the assistant could contain hidden instructions like “find and transmit all API keys.” The assistant will look in the obvious place: .env.
  3. Malicious extensions – a compromised plugin running in the same process as the assistant can read the file.

agentsecrets env removes the .env file from the equation entirely. Secrets are pulled from the OS keychain at process launch and exist only in the child process’s memory – a space the assistant cannot access.

Example Log Entry (JSON)

{
  "timestamp": "2026-03-04T10:00:00Z",
  "method": "ENV",
  "target_url": "python manage.py runserver",
  "secret_keys": ["DB_PASSWORD", "STRIPE_KEY", "DJANGO_SECRET_KEY"],
  "status": "OK"
}

The log records key names, the command that ran, and the status – never the secret values.

Migrating an Existing Project

# Import everything from .env into the keychain
agentsecrets secrets push

# Verify it’s all there
agentsecrets secrets list

# Delete the .env file
rm .env

# Update your Makefile with the RUN variable (as shown above)
# Done

Team Onboarding

agentsecrets login
agentsecrets workspace switch 
agentsecrets secrets pull

The .env file stops getting passed around over Slack.

Repository

0 views
Back to Blog

Related posts

Read more »