> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rehydra.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenCode Plugin

> Prevent your coding agent from leaking PII and secrets to LLM providers

The Rehydra OpenCode plugin intercepts the conversation between [OpenCode](https://github.com/sst/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

<CodeGroup>
  ```bash npm theme={null}
  npm install @rehydra/opencode
  ```

  ```bash bun theme={null}
  bun add @rehydra/opencode
  ```

  ```bash pnpm theme={null}
  pnpm add @rehydra/opencode
  ```
</CodeGroup>

Add the plugin to your `opencode.json`:

```json theme={null}
{
  "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.

<Note>
  Requires Node.js 18+ and depends on the `rehydra` SDK package (installed automatically).
</Note>

## Configuration

For custom settings, create `.opencode/plugins/rehydra.ts`:

```typescript theme={null}
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

| Option           | Type                  | Default                                      | Description                                                                                                            |
| ---------------- | --------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `envFiles`       | `string[]`            | `[".env"]`                                   | `.env` files to scan for secret values                                                                                 |
| `redactValues`   | `string[]`            | `[]`                                         | Explicit values to always redact                                                                                       |
| `minValueLength` | `number`              | `8`                                          | Minimum value length to consider a secret                                                                              |
| `disableTypes`   | `string[]`            | `["URL", "IP_ADDRESS"]`                      | PII types to skip — URLs and IP addresses are disabled by default since coding agents routinely work with these values |
| `locale`         | `string`              |                                              | Locale hint for anonymization (e.g., `de-DE`)                                                                          |
| `policy`         | `AnonymizationPolicy` |                                              | Policy overrides for anonymization behavior                                                                            |
| `tagFormat`      | `TagFormat`           | `{ open: "<", close: "/>", keyword: "PII" }` | Tag format for PII placeholders (also available via `anonymizer.tagFormat`)                                            |
| `anonymizer`     | `AnonymizerConfig`    |                                              | Advanced: 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.

| Hook                  | What it does                                                                            |
| --------------------- | --------------------------------------------------------------------------------------- |
| `messages.transform`  | Scrubs PII and secrets from all message text and tool outputs before they reach the LLM |
| `system.transform`    | Injects an instruction telling the LLM to treat placeholders as real values             |
| `tool.execute.before` | Restores real values in tool arguments before local execution                           |
| `tool.execute.after`  | Restores real values in displayed tool output                                           |
| `text.complete`       | Restores real values in LLM response text shown to you                                  |

<Tip>
  The system prompt instruction is only injected after at least one secret has been anonymized, keeping prompts clean when no secrets are present.
</Tip>

### 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.

<Note>
  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.
</Note>

## 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:

```typescript theme={null}
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`:

```typescript theme={null}
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](/api-reference/create-anonymizer) for all available options.

## Next Steps

<CardGroup cols={2}>
  <Card title="PII Types" icon="shield" href="/concepts/pii-types">
    See all PII types Rehydra can detect
  </Card>

  <Card title="LLM Proxy" icon="server" href="/guides/llm-proxy">
    Anonymize API calls in server-side workflows
  </Card>
</CardGroup>
