CLI agents

opencode

Route opencode through Sentisec in its provider config — Claude models over the Anthropic wire, or Kimi over the OpenAI-compatible wire.

opencode is an open-source terminal coding agent. It reads its providers from ~/.config/opencode/opencode.json, and each provider block can point at any Anthropic-compatible or OpenAI-compatible base URL — which is all Sentisec needs.

The dashboard generates these blocks for you under Settings → Connect: choose OpenCode, pick a wire, copy the JSON. This page documents the same two shapes so you can write the file by hand.

Install opencode first:

npm install -g opencode-ai
# or: brew install sst/tap/opencode
opencode --version

Claude models, over the Anthropic wire

opencode uses @ai-sdk/anthropic for Claude. The only Sentisec-specific values are baseURL and apiKey.

~/.config/opencode/opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "npm": "@ai-sdk/anthropic",
      "options": {
        "baseURL": "https://api.sentisec.ch/ws/<your-workspace-id>",
        "apiKey": "sk_sentisec_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      },
      "models": {
        "claude-sonnet-4": {},
        "claude-opus-4-7": {}
      }
    }
  },
  "model": "anthropic/claude-sonnet-4"
}
Info
With or without /v1

@ai-sdk/anthropic posts to <baseURL>/messages. Your workspace answers Messages at both /ws/<id>/messages and /ws/<id>/v1/messages, so the URL above, which is what Settings → Connect writes, and the same URL ending in /v1 both work. The /v1 form is the one the AI SDK guidance uses. Never end the URL in /messages. Claude Code is different: it appends /v1/messages itself, so its ANTHROPIC_BASE_URL stops at the workspace id.

Your workspace needs an Anthropic credential for this to dispatch — see the Anthropic provider.

Kimi (Moonshot), over the OpenAI-compatible wire

Kimi speaks the OpenAI shape, so opencode uses @ai-sdk/openai-compatible. Note the /v1 suffix on the base URL, and the X-Sentisec-Upstream-Provider header, which pins the upstream regardless of the model id you send.

~/.config/opencode/opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "sentisec-kimi": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Sentisec → Kimi",
      "options": {
        "baseURL": "https://api.sentisec.ch/ws/<your-workspace-id>/v1",
        "apiKey": "sk_sentisec_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "headers": {
          "X-Sentisec-Upstream-Provider": "kimi"
        }
      },
      "models": {
        "kimi-k2.7-code": {},
        "kimi-k3": {},
        "kimi-k2.7-code-highspeed": {},
        "kimi-k2.6": {}
      }
    }
  },
  "model": "sentisec-kimi/kimi-k2.7-code"
}

Order matters in that models block: opencode's default-model picker takes the first entry, so kimi-k2.7-code leads. It is the same default the dashboard's Connect wizard writes. Note the dot in the ids — Moonshot spells them kimi-k2.6, never kimi-k2-6.

You need a Kimi credential in your workspace for this to dispatch — see the Kimi provider.

Pinning the upstream

X-Sentisec-Upstream-Provider accepts the id of any provider connected on your workspace — see providers for the list. Sentisec strips the header before forwarding the request upstream, so it never reaches the vendor.

Two failure modes are worth recognising:

  • 503 provider_unavailable — that provider is not available on this release.
  • 401 no_upstream_credential — the provider is available, but your workspace has no key for it. Add one under Settings → Providers, in Provider keys.

Without the header, Sentisec picks the upstream from the model id (claude- → Anthropic, gpt-/o1 → OpenAI, kimi-/moonshot- → Kimi, gemini- → Gemini).

Using both at once

Register both providers in one config and switch inside opencode with /model:

{
  "provider": {
    "anthropic": { "…": "the Anthropic block above" },
    "sentisec-kimi": { "…": "the Kimi block above" }
  },
  "model": "anthropic/claude-sonnet-4"
}
> /model sentisec-kimi/kimi-k2.7-code

Whichever provider opencode picks, the request flows through the integrity engine and lands in the dashboard under Sessions.

Protected docs