sha256:78b3e1b7a7a2107f1a366d626d17607bf62f703feff40c492fcd4643070d1c6a
Last pushed
about 6 hours by sbx
Type
Sandbox Kit
Manifest digest
sha256:78b3e1b7a7a2107f1a366d626d17607bf62f703feff40c492fcd4643070d1c6a
schemaVersion: "3"
displayName: OpenCode
description: OpenCode, the open-source terminal coding agent, with every provider credential resolved by the sandbox proxy.
sourceUrl: https://github.com/anomalyco/opencode
version: 2.0.29
kind: workload
provides:
- [email protected]
- deb/[email protected]
- deb/[email protected]
- deb/base-files@14
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/ca-certificates-java@20260311
- deb/ca-certificates@20260816
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/gcc-16-base@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/less@668
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libasan8@16
- deb/[email protected]
- deb/libatomic1@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libcc1-0@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libgcc-s1@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libgomp1@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libhwasan0@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libitm1@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libjpeg8@8
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/liblsan0@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libstdc++6@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/libtsan2@16
- deb/libubsan1@16
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/lto-disabled-list@79
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/tzdata@2026
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
capabilities:
- type: com.docker.sandbox/sbx@1
- type: com.docker.sandbox/network-policy@1
config:
runtime:
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
- type: com.docker.sandbox/credential@1
optional: true
config:
apiKey:
inject:
- domain: api.anthropic.com
format: '%s'
header: x-api-key
- domain: claude.ai
format: '%s'
header: x-api-key
- domain: console.anthropic.com
format: '%s'
header: x-api-key
name: ANTHROPIC_API_KEY
proxyManaged: true
phase: runtime
service: anthropic
description: Anthropic API access
- type: com.docker.sandbox/credential@1
optional: true
config:
apiKey:
inject:
- domain: api.business.githubcopilot.com
format: Bearer %s
header: Authorization
- domain: api.enterprise.githubcopilot.com
format: Bearer %s
header: Authorization
- domain: api.github.com
format: Bearer %s
header: Authorization
- domain: api.githubcopilot.com
format: Bearer %s
header: Authorization
- domain: api.individual.githubcopilot.com
format: Bearer %s
header: Authorization
- domain: copilot.github.com
format: Bearer %s
header: Authorization
- domain: github.com
format: Bearer %s
header: Authorization
- domain: raw.githubusercontent.com
format: Bearer %s
header: Authorization
name: ""
phase: runtime
service: github
description: GitHub and Copilot access
- type: com.docker.sandbox/credential@1
optional: true
config:
apiKey:
inject:
- domain: aiplatform.googleapis.com
format: '%s'
header: x-goog-api-key
- domain: generativelanguage.googleapis.com
format: '%s'
header: x-goog-api-key
- domain: oauth2.googleapis.com
format: '%s'
header: x-goog-api-key
- domain: vertexai.googleapis.com
format: '%s'
header: x-goog-api-key
name: GOOGLE_GENERATIVE_AI_API_KEY
proxyManaged: true
phase: runtime
service: google
description: Google AI API access
- type: com.docker.sandbox/credential@1
optional: true
config:
apiKey:
inject:
- domain: api.groq.com
format: Bearer %s
header: Authorization
name: GROQ_API_KEY
proxyManaged: true
phase: runtime
service: groq
description: Groq API access
- type: com.docker.sandbox/credential@1
optional: true
config:
apiKey:
inject:
- domain: api.openai.com
format: Bearer %s
header: Authorization
- domain: openai.com
format: Bearer %s
header: Authorization
name: OPENAI_API_KEY
proxyManaged: true
oauth:
credentialFile:
path: ~/.local/share/opencode/auth.json
structure:
openai:
access: '{{.AccessToken}}'
expires: '{{.ExpiresAt}}'
refresh: '{{.RefreshToken}}'
type: oauth
resourceHosts:
- chatgpt.com
sentinels:
accessToken: oai-oat01-proxy-managed
refreshToken: oai-ort01-proxy-managed
tokenEndpoint:
host: auth.openai.com
path: /oauth/token
phase: runtime
service: openai
description: OpenAI API access (API key or ChatGPT OAuth)
- type: com.docker.sandbox/credential@1
optional: true
config:
apiKey:
inject:
- domain: openrouter.ai
format: Bearer %s
header: Authorization
name: OPENROUTER_API_KEY
proxyManaged: true
phase: runtime
service: openrouter
description: OpenRouter API access
- type: com.docker.sandbox/credential@1
optional: true
config:
apiKey:
inject:
- domain: api.x.ai
format: Bearer %s
header: Authorization
name: XAI_API_KEY
proxyManaged: true
phase: runtime
service: xai
description: xAI API access
- type: com.docker.sandbox/lifecycle@1
config:
startup:
- background: true
command:
- sh
- -c
- command -v apt-get > /dev/null 2>&1 && (apt-get update -qq -y > /dev/null 2>&1 || true)
description: Update apt package cache in background
user: "0"
- 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
description: Register the sandbox MCP gateway in ~/.config/opencode/opencode.json
env:
- MCP_GATEWAY_URL
- MCP_SENTINEL_TOKEN_NAME
user: agent
- 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"
description: Seed OpenCode's GitHub Copilot provider from the GH_TOKEN sentinel
env:
- GH_TOKEN
- SBX_CRED_GITHUB_MODE
user: agent
- command:
- sh
- -c
- |
set -e
auth="$HOME/.local/share/opencode/auth.json"
mkdir -p "$(dirname "$auth")"
exec 9>>"$(dirname "$auth")/.credentials-sync.lock"
flock 9
if ! existing=$(opencode auth export --standalone); then
echo "unable to read OpenCode v2 credentials; leaving them unchanged" >&2
exit 0
fi
if [ -e "$auth" ] && [ ! -f "$auth" ]; then
echo "auth.json is not a regular file; leaving v2 credentials unchanged" >&2
exit 0
fi
if [ -f "$auth" ]; then
if ! credentials=$(jq -c --arg github_token "${GH_TOKEN:-}" '
def oauth($integration; $id; $method; $label; $access; $refresh):
.[$integration] as $credential |
if ($credential | type) == "object"
and ($credential.type == "oauth")
and ($access != "")
and ($credential.access == $access)
and ($credential.refresh == $refresh)
and (($credential.refresh | type) == "string")
and (($credential.access | type) == "string")
and ($credential.expires | type == "number" and . >= 0 and . == floor)
then {
id: $id, integrationID: $integration, label: $label, active: true,
value: ({type: "oauth", methodID: $method, refresh: $credential.refresh, access: $credential.access, expires: $credential.expires}
+ (if (($credential.accountId | type) == "string") or (($credential.enterpriseUrl | type) == "string")
then {metadata: ({} + (if ($credential.accountId | type) == "string" then {accountID: $credential.accountId} else {} end)
+ (if ($credential.enterpriseUrl | type) == "string" then {enterpriseUrl: $credential.enterpriseUrl} else {} end))}
else {} end))
else empty end;
[oauth("openai"; "sbx-openai"; "chatgpt-browser"; "Sandbox OpenAI"; "oai-oat01-proxy-managed"; "oai-ort01-proxy-managed"), oauth("github-copilot"; "sbx-github-copilot"; "device"; "Sandbox GitHub Copilot"; $github_token; $github_token)]' "$auth"); then
echo "auth.json is not valid OpenCode OAuth data; leaving v2 credentials unchanged" >&2
exit 0
fi
else
credentials='[]'
fi
if ! sync=$(jq -cn --argjson existing "$existing" --argjson desired "$credentials" '
def managed($wanted):
.id == $wanted.id
or ($wanted.desired != null and .label == "OAuth" and .integrationID == $wanted.integrationID and .value == $wanted.desired.value);
["openai", "github-copilot"] | map(
. as $integration |
{integrationID: $integration, id: ("sbx-" + $integration),
desired: ([$desired[] | select(.integrationID == $integration)][0])}
| . as $wanted
| ($existing | map(select(.integrationID == $wanted.integrationID))) as $records
| ($records | map(select(.active == true)) | .[0]) as $active
| {integrationID: $wanted.integrationID, id: $wanted.id, desired: $wanted.desired,
remove: [$records[] | select(managed($wanted)) | .id],
previousActiveID: (if $active != null and ($active | managed($wanted)) then $active.id else null end),
activate: ($wanted.desired != null and $active != null and ($active | managed($wanted)))}
)'); then
echo "unable to reconcile OpenCode v2 credentials; leaving them unchanged" >&2
exit 0
fi
if ! removed=$(jq -cn --argjson existing "$existing" --argjson sync "$sync" '
[$sync[] as $change | $existing[] |
select(.integrationID == $change.integrationID and (.id as $id | $change.remove | index($id)))]'); then
echo "unable to save managed OpenCode credentials for rollback" >&2
exit 0
fi
printf '%s\n' "$sync" | jq -r '.[] | .integrationID as $integration | .remove[]? | [$integration, .] | @tsv' |
while IFS="$(printf '\t')" read -r integration id; do
opencode auth logout "$integration" "$id" --standalone >/dev/null 2>&1 || true
done
if [ "$credentials" != "[]" ] && ! printf '%s\n' "$credentials" | opencode auth import --standalone >/dev/null; then
echo "unable to import sandbox OAuth credentials into OpenCode v2" >&2
if [ "$removed" != "[]" ] && ! printf '%s\n' "$removed" | opencode auth import --standalone >/dev/null; then
echo "unable to restore managed OpenCode credentials after failed import" >&2
exit 1
fi
if ! printf '%s\n' "$sync" | jq -r '.[] | select(.previousActiveID != null) | [.integrationID, .previousActiveID] | @tsv' |
while IFS="$(printf '\t')" read -r integration id; do
opencode auth switch "$integration" "$id" --standalone >/dev/null
done; then
echo "unable to restore the managed OpenCode credential selection after failed import" >&2
exit 1
fi
echo "restored managed OpenCode credentials after failed import" >&2
exit 0
fi
printf '%s\n' "$sync" | jq -r '.[] | select(.activate) | [.integrationID, .id] | @tsv' |
while IFS="$(printf '\t')" read -r integration id; do
opencode auth switch "$integration" "$id" --standalone >/dev/null
done
description: Import sandbox OAuth credentials into OpenCode v2
env:
- GH_TOKEN
user: agent
- type: com.docker.sandbox/agent-context@1
config:
filename: AGENTS.md
args:
version:
default: 2.0.29
description: OpenCode release to install
pattern: ^[0-9]+\.[0-9]+\.[0-9]+$
buildArg: OPENCODE_VERSION