← Back to Writing
Open Source Developer Tools AI Agents Security OpenCode TypeScript

envsitter-guard: Keeping Secrets Out of Agent Hands

June 10, 2026 · 3 min read

AI coding agents are useful until they aren't. One of the quieter failure modes, the kind that doesn't throw an error but just creates a bad situation, is an agent reading a .env file it had no business reading.

It happens naturally. An agent is working through a codebase, trying to understand configuration, and it reaches for .env because that's where the config lives. It's not malicious. It's just doing what it was asked to do. The result is your API keys, database credentials, and service tokens sitting in the agent's context window, possibly logged, possibly sent somewhere, and definitely not where they should be.

That's the problem envsitter-guard was built to solve.

What it does

envsitter-guard is an OpenCode plugin that intercepts file operations before they reach the tool layer. When an agent tries to read or write a file matching the .env* glob pattern, the plugin blocks the operation before it executes and returns an error that points the agent at EnvSitter tooling instead.

flowchart LR Agent["AI coding agent"] -->|"read .env"| Guard["envsitter-guard"]:::accent Guard x-.-x|"blocked"| Env[".env secrets"]:::gold Guard -->|"redirected"| Tools["EnvSitter safe tools<br/>keys · check · validate · match"] Tools -->|"names and booleans, never values"| Agent

The key design decision is that blocking doesn't mean blind. The plugin exposes a set of safe inspection tools that let agents work with environment configuration without ever seeing values:

  • envsitter_keys lists the keys present in a dotenv file
  • envsitter_check verifies whether a specific key exists
  • envsitter_validate checks dotenv syntax without exposing values
  • envsitter_match verifies a candidate value against a stored secret using HMAC-SHA-256, returning only a boolean
  • envsitter_copy, envsitter_add, and envsitter_set are safe mutation tools that operate in dry-run mode by default

The agent can do its job. It just can't see the secrets.

The underlying library

The plugin is built on top of envsitter, a separate library for safe programmatic inspection of .env files. EnvSitter handles the zero-knowledge verification: when matching secrets, it hashes both the candidate and stored value using HMAC-SHA-256 with a local pepper, then compares digests using constant-time equality. The pepper file is created with mode 0600, and the .envsitter/ directory is gitignored automatically.

If you want to use the underlying tooling without the OpenCode plugin, EnvSitter has a CLI:

npx envsitter keys --file .env

Installation

The simplest install, enabled globally across all projects:

opencode plugin add envsitter-guard

For per-repo use, create .opencode/plugin/envsitter-guard.ts:

import EnvSitterGuard from "envsitter-guard";
export default EnvSitterGuard;
export { EnvSitterGuard } from "envsitter-guard";

Then add the dependency to .opencode/package.json and restart OpenCode.

Why this matters now

Agentic coding tools are moving fast. The default posture of most of them is broad file system access, which is useful for legitimate tasks and a problem when the agent wanders into sensitive territory. Guardrails like envsitter-guard are part of building an agentic development workflow that you'd actually trust in a production codebase.

The plugin is listed in the Awesome OpenCode registry. Source is on GitHub.

[ Resources ]

Enjoyed this? Let me know

0claps