Nº 016/Engineering/4 min read/
The env Command — Secrets Without the .env File
The developer who reaches for agentsecrets env is not building an AI agent. They are running a Django server, a Node process, a Celery worker, or a shell script, using AI tools as part of their workflow, and they know that putting a database password in a .env file is not where the story should end.
agentsecrets env is a process wrapper. Put it in front of any command and the process starts with your project secrets available as environment variables, resolved from the OS keychain at spawn time and injected directly into the child process's address space without anything written to disk.
How it works mechanically
When you run agentsecrets env -- python manage.py runserver, the CLI reads the active project configuration, calls the OS keychain for all secrets in that project, builds the child process environment from the current environment plus the injected secrets, and spawns the command with stdin, stdout, and stderr wired straight through.
agentsecrets env -- python manage.py runserver
agentsecrets env -- npm run dev
agentsecrets env -- celery -A myapp worker --loglevel=info
agentsecrets env -- stripe mcp
The child process reads from its environment exactly as it always has, so Django's os.environ["DB_PASSWORD"] and Node's process.env.STRIPE_KEY both work without any changes to application code. The difference is where those values came from before the process started.
The agentsecrets parent process passes the values to the child at spawn time via the OS process creation interface. The values exist in the child's address space, not the parent's, and are gone when the child exits.
The Makefile pattern
The lowest-friction way to use agentsecrets env in a project is to define it as a prefix variable in your Makefile.
RUN := agentsecrets env --
dev:
$(RUN) python manage.py runserver
test:
$(RUN) pytest
migrate:
$(RUN) python manage.py migrate
worker:
$(RUN) celery -A myapp worker --loglevel=info
make dev runs with secrets injected. You can override the variable from the shell to strip injection entirely for debugging:
make dev RUN= # runs: python manage.py runserver, no injection
make dev # runs: agentsecrets env -- python manage.py runserver
The pattern works because agentsecrets env is transparent to the process it wraps. Exit codes pass through correctly, which matters in CI/CD pipelines where a failing test suite needs to exit non-zero. Signals forward to the child, so Ctrl+C behaves as expected.
Why this matters for AI tooling workflows
A developer using AI tools in their workflow has an expanded attack surface compared to a developer running traditional software. AI tools, agents, and plugins often have filesystem access as a default capability. A .env file sitting at a known path in a project directory is readable by any of them.
agentsecrets env means the secrets are not there to be read. They go from the OS keychain into the child process memory at spawn time. Between invocations, the credentials exist in the keychain, which the OS protects. The .env file pattern puts credentials in a location where filesystem access is sufficient to reach them. The keychain pattern requires defeating OS-level access controls.
For a developer working with tools that have broad permissions, that is a meaningful difference in the actual attack surface rather than a theoretical one.
What it does not do
agentsecrets env injects values into environment variables. Once they are in the environment, they are in the process's accessible memory for the duration of its lifetime. If the process is an AI agent that processes untrusted external inputs, those values are reachable by anything the agent can be instructed to do.
For that use case, the proxy path provides a stronger guarantee. The agent makes authenticated API calls without the credential value ever entering its context. agentsecrets env and the proxy solve different problems for different kinds of processes, and understanding which one applies depends on what the process does with the credentials once it has them.
The audit log
Every agentsecrets env invocation writes to the audit log with the command that was run, the key names that were injected, the timestamp, and the status. The values are not logged, only the names, which is the same constraint applied across the entire audit log schema.
{
"method": "ENV",
"target_url": "python manage.py runserver",
"secret_keys": ["DB_PASSWORD", "STRIPE_KEY", "DJANGO_SECRET_KEY"],
"status": "OK"
}
A developer reviewing the audit log can see exactly which secrets were injected into which processes and when, without the log itself becoming a source of credential exposure.
Part 08 covers the Python SDK, why the no-get() constraint is a design decision rather than a limitation, and what it means to build a library around a deliberate absence.
AgentSecrets is open source and MIT licensed. The full architecture is at agentsecrets.theseventeen.co. The repository is at github.com/The-17/agentsecrets.