<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tom Jordi Ruesch</title>
    <description>The latest articles on DEV Community by Tom Jordi Ruesch (@toju_04278f69).</description>
    <link>https://dev.to/toju_04278f69</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3841809%2F52c048bb-7dca-47ea-a76d-7074ad36f4b5.png</url>
      <title>DEV Community: Tom Jordi Ruesch</title>
      <link>https://dev.to/toju_04278f69</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/toju_04278f69"/>
    <language>en</language>
    <item>
      <title>Stop Sending Your .env to OpenAI: A Privacy Layer for OpenCode</title>
      <dc:creator>Tom Jordi Ruesch</dc:creator>
      <pubDate>Tue, 24 Mar 2026 14:45:09 +0000</pubDate>
      <link>https://dev.to/toju_04278f69/stop-sending-your-env-to-openai-a-privacy-layer-for-opencode-3kc3</link>
      <guid>https://dev.to/toju_04278f69/stop-sending-your-env-to-openai-a-privacy-layer-for-opencode-3kc3</guid>
      <description>&lt;p&gt;AI coding agents are the most productive and the most dangerous tools on your machine.&lt;/p&gt;

&lt;p&gt;They read your files, execute shell commands, write infrastructure code, and reason about your entire project context. To do any of this well, they need access to the real stuff: API keys, database credentials, JWTs, connection strings. The kind of values that live in &lt;code&gt;.env&lt;/code&gt; files and should never leave your device.&lt;/p&gt;

&lt;p&gt;But they do leave your device. Every single message you send to your coding agent (including the one where you pasted your Stripe secret key to debug a webhook) is transmitted to an LLM provider's inference endpoint. The model sees everything.&lt;/p&gt;

&lt;p&gt;This is the fundamental tension: the agent needs your secrets to be useful (or at least to be autonomous), but the LLM doesn't need to see your secrets to reason about them.&lt;/p&gt;

&lt;p&gt;We built a plugin to resolve this. Today we're releasing &lt;code&gt;@rehydra/opencode&lt;/code&gt;, a privacy layer for OpenCode that anonymizes secrets before they reach the LLM and restores them before any tool executes locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the LLM Actually Sees
&lt;/h2&gt;

&lt;p&gt;Let's make this concrete. You ask your agent to set an environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You: "Set the Stripe key to sk_live_4eC39HqLyjWDarjtT1zdp7dc"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without the plugin, that secret hits the LLM provider's API verbatim. With it, the LLM receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Set the Stripe key to &amp;lt;PII type="ENV_VAR_SECRET" id="1"/&amp;gt;"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model treats the placeholder as the real value. It reasons about it, generates commands with it, references it in follow-up messages. When it produces a tool call like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;STRIPE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;PII &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ENV_VAR_SECRET"&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The plugin intercepts the command before it executes on your machine and restores the real credential. Your shell runs export &lt;code&gt;STRIPE_KEY=sk_live_4eC39HqLyjWDarjtT1zdp7dc&lt;/code&gt;. The LLM never saw it.&lt;/p&gt;

&lt;p&gt;This is the same principle behind &lt;a href="https://www.rehydra.ai/blog/semantic-redaction-vs-regex-why-context-matters-for-pii" rel="noopener noreferrer"&gt;Semantic Redaction&lt;/a&gt;: typed placeholders that preserve structure and meaning, not generic [REDACTED] tokens that turn your conversation into garbage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Session Consistency Matters
&lt;/h2&gt;

&lt;p&gt;If you've read our piece on why context matters for PII, you know that naive redaction (replacing everything with &lt;code&gt;***&lt;/code&gt;) destroys an LLM's ability to reason. The same principle applies here.&lt;/p&gt;

&lt;p&gt;Each OpenCode session gets its own Rehydra session with consistent mappings. The same API key always maps to the same placeholder. If your database password and your Redis password are different, the LLM sees two distinct tokens. If you reference the same secret three times across different messages, it's the same &lt;code&gt;&amp;lt;PII id="1"/&amp;gt;&lt;/code&gt; every time.&lt;/p&gt;

&lt;p&gt;This consistency is what lets the model maintain referential integrity across a long conversation. It can reason about which secret goes where without ever knowing what the secret actually is.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Gets Caught
&lt;/h2&gt;

&lt;p&gt;The plugin uses Rehydra's full detection engine — the same hybrid Regex + ONNX pipeline, adapted for the coding agent use case.&lt;/p&gt;

&lt;p&gt;Secrets (pattern-based): API keys from major providers (OpenAI, Anthropic, GitHub, Stripe, AWS, Slack), JWTs, PEM private keys, connection strings, AWS credentials.&lt;/p&gt;

&lt;p&gt;Environment variables: The plugin reads your &lt;code&gt;.env&lt;/code&gt; files and matches those exact values anywhere they appear in conversation, even if they don't follow a known pattern. If it's in your &lt;code&gt;.env&lt;/code&gt;, it's scrubbed.&lt;/p&gt;

&lt;p&gt;Structured PII: Emails, phone numbers, credit card numbers, IBANs, tax IDs. Twenty-eight types in total.&lt;/p&gt;

&lt;p&gt;We disable URL and IP address detection by default because coding agents work with these constantly (you probably don't want &lt;code&gt;localhost:3000&lt;/code&gt; redacted). You can flip that with a single config option.&lt;/p&gt;

&lt;p&gt;Rehydra can also redact unstructured PII like Names, Places, your Birthday, etc. For the OpenCode plugin we decided to disable this by default as well. The local NER model required for this just adds too much latency and overhead for too little added value. But also here, you can switch it on in the configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @rehydra/opencode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add to &lt;code&gt;opencode.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plugin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@rehydra/opencode"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. The plugin reads .env in your project root and starts scrubbing immediately. No configuration file, no API key, no account.&lt;/p&gt;

&lt;p&gt;For teams with specific requirements, you can customize the behavior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRehydraPlugin&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rehydra/opencode&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;createRehydraPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;envFiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.env&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.env.local&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.env.production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;redactValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sk-live-abc123...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;minValueLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;disableTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;  &lt;span class="c1"&gt;// Re-enable URL and IP detection&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What This Doesn't Do
&lt;/h2&gt;

&lt;p&gt;This isn't a VPN. It doesn't mask your identity or anonymize your network traffic.&lt;/p&gt;

&lt;p&gt;It isn't a compliance certification. It's a technical control — a deterministic layer that prevents specific sensitive values from leaving your machine during AI-assisted development.&lt;/p&gt;

&lt;p&gt;And it isn't destructive. Unlike regex scrubbing for analytics pipelines, this is fully reversible. Your data is abstracted during transit and restored for local execution. Nothing is lost (that's the whole point of &lt;a href="https://github.com/rehydra-ai/rehydra-sdk" rel="noopener noreferrer"&gt;Rehydra&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;As coding agents evolve from autocomplete into autonomous systems that deploy infrastructure, manage secrets, and interact with production APIs, the security surface grows with them. We can't keep sending raw credentials to third-party inference endpoints and hoping for the best.&lt;/p&gt;

&lt;p&gt;Security doesn't have to mean crippling your tools. By applying the same semantic anonymization we use for translation workflows, we let coding agents reason about your secrets without ever seeing them.&lt;/p&gt;

&lt;p&gt;The agent stays powerful. Your secrets stay local.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/rehydra-ai/rehydra-sdk" rel="noopener noreferrer"&gt;github.com/rehydra-ai/rehydra-sdk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NPM: &lt;code&gt;npm install @rehydra/opencode&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://docs.rehydra.ai" rel="noopener noreferrer"&gt;docs.rehydra.ai&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>vibecoding</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
