DeepSeek in OpenCode: Excession provider setup

Add Excession as an OpenAI-compatible provider in OpenCode and select DeepSeek V4.1 Flash. This setup passed a configuration and streaming test with the real OpenCode client, run against a localhost fixture.

Prepare OpenCode and your key

Install OpenCode using its official instructions. Create an Excession API key in the dashboard, load it into EXCESSION_API_KEY through your usual secret manager, and check your available funds.

Add the custom provider

Create opencode.json at your project root, or merge these fields into an existing file. OpenCode's configuration documentation explains file precedence and environment substitution. The environment reference keeps the key value out of JSON.

{
  "$schema": "https://opencode.ai/config.json",
  "model": "excession/deepseek/deepseek-v4.1-flash-1017",
  "small_model": "excession/deepseek/deepseek-v4.1-flash-1017",
  "enabled_providers": [
    "excession"
  ],
  "permission": {
    "*": "deny"
  },
  "provider": {
    "excession": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Excession",
      "options": {
        "baseURL": "https://api.excessionlabs.ai/v1",
        "apiKey": "{env:EXCESSION_API_KEY}"
      },
      "models": {
        "deepseek/deepseek-v4.1-flash-1017": {
          "name": "DeepSeek V4.1 Flash"
        }
      }
    }
  }
}

The custom provider ID is excession. OpenCode prefixes it to the API model ID: the selection string excession/deepseek/deepseek-v4.1-flash-1017 becomes deepseek/deepseek-v4.1-flash-1017 on the wire. The example pins both the main and small models. enabled_providers restricts this example to Excession; merge it carefully if you use other providers.

Use @ai-sdk/openai-compatible and a base URL ending in /v1. That selects POST /v1/chat/completions, as described in OpenCode's custom-provider documentation. Other adapters may select a different API format.

The example denies all tool permissions for the first text-only check, so OpenCode can exchange messages but cannot perform coding actions. Afterwards, replace the deny rule with permissions that suit your project, using the OpenCode permission documentation. Our test did not cover tool execution.

Run a first text request

: "${EXCESSION_API_KEY:?Load your Excession API key first}"
opencode run --pure \
  --model "excession/deepseek/deepseek-v4.1-flash-1017" \
  --title "DeepSeek connection check" \
  "Reply with READY."

This non-interactive run selects the model explicitly and skips external plugins. A successful live run should print a short answer. Unlike our mock test, it uses metered inference on your account.

For interactive use, start opencode in the same project and terminal. Use /models to select the Excession entry. Try a small coding task in a disposable directory before you rely on tool calls or edits.

Troubleshoot the provider

What we tested

On 4 November 2026 we ran the actual Claude Code 2.1.318 and OpenCode 1.19.5 clients against an isolated localhost fixture with fake credentials. Each sent the exact model ID, a Bearer credential and a streaming request to its expected endpoint. Both displayed LOCAL_FIXTURE_OK from the fixture and exited successfully.

This was a mock client integration test with no live DeepSeek inference. The fixture supplied the answer, and no model generated it. The test validates configuration, request routing and text-stream parsing. It does not establish production availability, model quality, billing, long conversations, or tool-call and file-edit compatibility.

Inspect the recorded request metadata and results or download the local validation script. Run the script with --claude /path/to/claude --opencode /path/to/opencode, using official client executables. It starts a loopback endpoint, uses fake keys and temporary client configuration, and does not read a real API key. Package setup and client startup may contact public package or model metadata services.

Continue reading