Skip to main content
The Rehydra OpenCode plugin intercepts the conversation between OpenCode and the LLM. It automatically detects PII and secrets in all messages, replaces them with placeholders before they leave your machine, and transparently restores real values before any tool executes locally.

Installation

npm install @rehydra/opencode
Add the plugin to your opencode.json:
{
  "plugin": ["@rehydra/opencode"]
}
The plugin automatically detects PII (emails, phone numbers, credit cards, etc.) and secrets (API keys, JWTs, connection strings, etc.) in all messages. It also reads .env in your project root to catch exact secret values wherever they appear.
Requires Node.js 18+ and depends on the rehydra SDK package (installed automatically).

Configuration

For custom settings, create .opencode/plugins/rehydra.ts:
import { createRehydraPlugin } from "@rehydra/opencode";

export default createRehydraPlugin({
  // Scan multiple env files
  envFiles: [".env", ".env.local", ".env.production"],

  // Always redact these values, even if not in .env
  redactValues: ["sk-live-abc123..."],

  // Minimum value length to consider a secret (default: 8)
  minValueLength: 6,

  // Re-enable URL and IP_ADDRESS detection (disabled by default)
  disableTypes: [],
});

Options

OptionTypeDefaultDescription
envFilesstring[][".env"].env files to scan for secret values
redactValuesstring[][]Explicit values to always redact
minValueLengthnumber8Minimum value length to consider a secret
disableTypesstring[]["URL", "IP_ADDRESS"]PII types to skip — URLs and IP addresses are disabled by default since coding agents routinely work with these values
localestringLocale hint for anonymization (e.g., de-DE)
policyAnonymizationPolicyPolicy overrides for anonymization behavior
tagFormatTagFormat{ open: "<", close: "/>", keyword: "PII" }Tag format for PII placeholders (also available via anonymizer.tagFormat)
anonymizerAnonymizerConfigAdvanced: full anonymizer config (overrides envFiles, redactValues, and minValueLength)

What Gets Detected

The plugin uses Rehydra’s full detection suite automatically — no configuration needed. Structured PII — detected via pattern matching:
  • Emails, phone numbers, credit card numbers
  • IBANs, BIC/SWIFT codes, account numbers
  • IP addresses, URLs (disabled by default — set disableTypes: [] to enable)
  • Tax IDs, national IDs
Secrets — detected via provider-specific patterns:
  • API keys (OpenAI, Anthropic, GitHub, Stripe, Slack, and others)
  • JWTs, private keys (PEM), connection strings
  • AWS access keys and secret keys
  • Secret values in .env files and JSON/YAML/TOML configs
Soft PII (optional, via NER model — not recommended due to significant added latency):
  • Names, organizations, locations, addresses
Additional sources:
  • Exact values from .env files (matched anywhere in text)
  • Explicit values passed via redactValues

How It Works

The plugin uses five OpenCode hooks — everything runs locally and no data leaves your machine except the scrubbed conversation sent to the LLM provider.
HookWhat it does
messages.transformScrubs PII and secrets from all message text and tool outputs before they reach the LLM
system.transformInjects an instruction telling the LLM to treat placeholders as real values
tool.execute.beforeRestores real values in tool arguments before local execution
tool.execute.afterRestores real values in displayed tool output
text.completeRestores real values in LLM response text shown to you
The system prompt instruction is only injected after at least one secret has been anonymized, keeping prompts clean when no secrets are present.

Session Handling

Each OpenCode session gets its own Rehydra session. PII mappings are consistent within a session — the same secret always maps to the same placeholder, so the LLM can reason about relationships between values without seeing the real data.

Tool Argument Rehydration

When the LLM generates a tool call (e.g., a shell command containing a placeholder), the plugin deep-walks all argument values and restores real secrets before execution. This means commands like git push, curl, or zwrm secrets set receive the actual credential values.
OpenCode’s tool.execute.before hook passes args by reference — the plugin mutates args in-place rather than replacing the object, which is required for the rehydrated values to take effect.

Logging

Plugin activity is logged to OpenCode’s log directory (~/.local/share/opencode/log/). Run OpenCode with --log-level DEBUG for detailed output.
INFO service=rehydra scrubbed={"ENV_VAR_SECRET":2} messageCount=3 scrubbed 2 secret(s) from messages
INFO service=rehydra tool=bash callID=call_abc123 rehydrated PII tags in tool args

Custom Tag Format

Use tagFormat to change placeholder delimiters, for example when XML-style tags interfere with your workflow:
import { createRehydraPlugin } from "@rehydra/opencode";

export default createRehydraPlugin({
  tagFormat: { open: "[[", close: "]]" },
});
This produces placeholders like [[PII type="EMAIL" id="1"]] instead of <PII type="EMAIL" id="1"/>.

Advanced: Full Anonymizer Config

For full control, pass an anonymizer config directly. This overrides envFiles, redactValues, and minValueLength:
import { createRehydraPlugin } from "@rehydra/opencode";

export default createRehydraPlugin({
  anonymizer: {
    secrets: {
      enabled: true,
      envFiles: [".env", ".env.local"],
      minValueLength: 6,
    },
    ner: {
      mode: "quantized",
    },
  },
});
See the createAnonymizer API reference for all available options.

Next Steps

PII Types

See all PII types Rehydra can detect

LLM Proxy

Anonymize API calls in server-side workflows