sha256:ac41cd03a915274bf878b660dbf418a496d69d52e84425ab0b824c937d6ad498
Last pushed
3 days by sbx
Type
Sandbox Kit
Manifest digest
sha256:ac41cd03a915274bf878b660dbf418a496d69d52e84425ab0b824c937d6ad498
schemaVersion: "2"
kind: sandbox
name: opencode
version: 1.0.0
displayName: OpenCode
description: OpenCode, the open-source terminal coding agent, with every provider credential resolved by the sandbox proxy.
sandbox:
image: docker.io/sbx/opencode-image:latest
entrypoint:
- opencode
agentInstructions:
filename: AGENTS.md
permissions:
network:
allow:
- api.anthropic.com
- claude.ai
- console.anthropic.com
- api.business.githubcopilot.com
- api.enterprise.githubcopilot.com
- api.github.com
- api.githubcopilot.com
- api.individual.githubcopilot.com
- copilot.github.com
- github.com
- raw.githubusercontent.com
- aiplatform.googleapis.com
- generativelanguage.googleapis.com
- oauth2.googleapis.com
- vertexai.googleapis.com
- api.groq.com
- api.openai.com
- openai.com
- openrouter.ai
- api.x.ai
- auth.openai.com
- chatgpt.com
- '**.githubusercontent.com'
- codeload.github.com
- registry.npmjs.org
- opencode.ai
- '*.opencode.ai'
- archive.ubuntu.com
- security.ubuntu.com
- ports.ubuntu.com
- download.docker.com
credentials:
- service: anthropic
apiKey:
name: ANTHROPIC_API_KEY
proxyManaged: true
inject:
- domain: api.anthropic.com
header: x-api-key
format: '%s'
- domain: claude.ai
header: x-api-key
format: '%s'
- domain: console.anthropic.com
header: x-api-key
format: '%s'
- service: github
apiKey:
name: ""
inject:
- domain: api.business.githubcopilot.com
header: Authorization
format: Bearer %s
- domain: api.enterprise.githubcopilot.com
header: Authorization
format: Bearer %s
- domain: api.github.com
header: Authorization
format: Bearer %s
- domain: api.githubcopilot.com
header: Authorization
format: Bearer %s
- domain: api.individual.githubcopilot.com
header: Authorization
format: Bearer %s
- domain: copilot.github.com
header: Authorization
format: Bearer %s
- domain: github.com
header: Authorization
format: Bearer %s
- domain: raw.githubusercontent.com
header: Authorization
format: Bearer %s
- service: google
apiKey:
name: GOOGLE_GENERATIVE_AI_API_KEY
proxyManaged: true
inject:
- domain: aiplatform.googleapis.com
header: x-goog-api-key
format: '%s'
- domain: generativelanguage.googleapis.com
header: x-goog-api-key
format: '%s'
- domain: oauth2.googleapis.com
header: x-goog-api-key
format: '%s'
- domain: vertexai.googleapis.com
header: x-goog-api-key
format: '%s'
- service: groq
apiKey:
name: GROQ_API_KEY
proxyManaged: true
inject:
- domain: api.groq.com
header: Authorization
format: Bearer %s
- service: openai
apiKey:
name: OPENAI_API_KEY
proxyManaged: true
inject:
- domain: api.openai.com
header: Authorization
format: Bearer %s
- domain: openai.com
header: Authorization
format: Bearer %s
oauth:
tokenEndpoint:
host: auth.openai.com
path: /oauth/token
resourceHosts:
- chatgpt.com
sentinels:
accessToken: oai-oat01-proxy-managed
refreshToken: oai-ort01-proxy-managed
credentialFile:
path: ~/.local/share/opencode/auth.json
structure:
openai:
access: '{{.AccessToken}}'
expires: '{{.ExpiresAt}}'
refresh: '{{.RefreshToken}}'
type: oauth
skipIfEnv:
- OPENAI_API_KEY
- service: openrouter
apiKey:
name: OPENROUTER_API_KEY
proxyManaged: true
inject:
- domain: openrouter.ai
header: Authorization
format: Bearer %s
- service: xai
apiKey:
name: XAI_API_KEY
proxyManaged: true
inject:
- domain: api.x.ai
header: Authorization
format: Bearer %s
setup:
startup:
- command:
- sh
- -c
- '{ command -v apt-get && apt-get update -qq -y || true; } >/dev/null 2>&1 </dev/null &'
user: root
description: Update apt package cache in background
- command:
- sh
- -c
- |
set -e
[ -n "$MCP_GATEWAY_URL" ] || exit 0
mkdir -p "$HOME/.config/opencode"
cat > "$HOME/.config/opencode/opencode.json" <<EOF
{
"\$schema": "https://opencode.ai/config.json",
"mcp": {
"mcp-gateway": {
"type": "remote",
"url": "$MCP_GATEWAY_URL",
"enabled": true,
"headers": {
"Authorization": "Bearer $MCP_SENTINEL_TOKEN_NAME"
}
}
}
}
EOF
user: agent
description: Register the sandbox MCP gateway in ~/.config/opencode/opencode.json
- command:
- sh
- -c
- |
set -e
umask 077
# Local sandboxes always carry GH_TOKEN and say via the mode var whether a
# credential backs it; cloud sets GH_TOKEN only when one does and no mode var.
[ -n "${GH_TOKEN:-}" ] || exit 0
[ "${SBX_CRED_GITHUB_MODE:-}" != none ] || exit 0
auth="$HOME/.local/share/opencode/auth.json"
mkdir -p "$(dirname "$auth")"
# A canceled start can leave its seed running; retries must recheck auth.json after it finishes.
exec 9>>"$(dirname "$auth")/.copilot-seed.lock"
flock 9
# mv would nest the seed inside a directory here and still exit 0.
if [ -e "$auth" ] && [ ! -f "$auth" ]; then
echo "auth.json is not a regular file; leaving the GitHub Copilot provider unseeded" >&2
exit 0
fi
# Every start re-fires this seed. One pass keeps an entry that fits OpenCode's Oauth schema and still
# carries the token as refresh (so an exchanged access survives), leaves a malformed file alone, and re-seeds the rest.
if ! merged=$({ if [ -s "$auth" ]; then cat "$auth"; else echo '{}'; fi; } | jq -s --arg token "$GH_TOKEN" '
if length != 1 or (.[0] | type) != "object" then error("auth.json must hold exactly one JSON object")
elif (.[0]."github-copilot" | type == "object" and .type == "oauth" and .refresh == $token
and (.access | type) == "string" and (.expires | type == "number" and . >= 0 and . == floor)
and ((has("accountId") | not) or (.accountId | type) == "string")
and ((has("enterpriseUrl") | not) or (.enterpriseUrl | type) == "string")) then empty
else .[0] | ."github-copilot" = {type: "oauth", refresh: $token, access: $token, expires: 0} end'); then
echo "auth.json is not a single JSON object; leaving the GitHub Copilot provider unseeded" >&2
exit 0
fi
[ -n "$merged" ] || exit 0
# The temp name is unpredictable, so a stale or crashed leftover is never installed. The
# same uid owns this directory, so no write pattern here is a boundary against a co-resident process.
tmp=$(mktemp "$(dirname "$auth")/auth.json.XXXXXX")
trap 'rm -f "$tmp"' EXIT
printf '%s\n' "$merged" > "$tmp"
mv -f "$tmp" "$auth"
user: agent
description: Seed OpenCode's GitHub Copilot provider from the GH_TOKEN sentinel