OpenCode 2 changed provider to providers, npm to package, and options to settings. Its background service also owns provider credentials. The protected key-file method below avoids stale saved credentials and service-environment mismatches.
1. Create a SafetyRouter identity
In the tenant portal, create an API key named for the employee and client—for example Steele-OpenCode2-Mac. Add project tags for reporting and Duplicate Guard.
2. Store the key in a protected file
First place the new key in your current shell:
export SAFETYROUTER_API_KEY='sr_live_...'
Then create a key file on macOS or Linux without adding a trailing newline:
mkdir -p ~/.config/opencode
umask 077
printf '%s' "$SAFETYROUTER_API_KEY" > ~/.config/opencode/safetyrouter.key
chmod 600 ~/.config/opencode/safetyrouter.key
On Windows PowerShell:
$env:SAFETYROUTER_API_KEY = 'sr_live_...'
$keyDirectory = Join-Path $HOME '.config/opencode'
New-Item -ItemType Directory -Force -Path $keyDirectory | Out-Null
[System.IO.File]::WriteAllText(
(Join-Path $keyDirectory 'safetyrouter.key'),
$env:SAFETYROUTER_API_KEY
)
3. Add the v2 provider
Create or update opencode.jsonc. Use a provider ID such as safetyrouter-v2 that has never been connected to a saved OpenCode account. Replace the hostname and modelID with values enabled by your tenant.
{
"$schema": "https://opencode.ai/config.json",
"model": "safetyrouter-v2/company-model",
"providers": {
"safetyrouter-v2": {
"name": "SafetyRouter V2",
"package": "@opencode/ai/providers/openai-compatible",
"settings": {
"baseURL": "https://your-company.safetyrouter.io/v1",
"apiKey": "{file:~/.config/opencode/safetyrouter.key}",
"headerTimeout": 900000,
"chunkTimeout": 900000,
"encoding": "none"
},
"models": {
"company-model": {
"name": "Model through SafetyRouter",
"modelID": "provider/model-name",
"capabilities": {
"tools": true,
"input": ["text"],
"output": ["text"]
},
"limit": {
"context": 128000,
"output": 8192
}
}
}
}
}
}
Do not run /connect for safetyrouter-v2. An active saved account can override the apiKey configured above. If you previously used the ID safetyrouter, keep the new safetyrouter-v2 ID so OpenCode cannot reuse that older credential.
4. Reload and test
opencode service restart
opencode reload
opencode run --model safetyrouter-v2/company-model \
"Reply with exactly: SafetyRouter connected"
For diagnostic logs, the level must be lowercase:
opencode --print-logs --log-level debug
OpenCode may pause while SafetyRouter reviews the input, generates the answer, and inspects the output. Approved content is then emitted as a compatible stream.
OpenCode v2 provider fields, file substitution, service behavior, and credential precedence are documented in the official provider guide, configuration reference, and credential guide.