sha256:1eb4e2f64e6abdfe5631f43deaa2213fb01e7b1735771efd9b367c2ddb36e99b
Last pushed
13 days by christianhkb
Type
Sandbox Kit
Manifest digest
sha256:1eb4e2f64e6abdfe5631f43deaa2213fb01e7b1735771efd9b367c2ddb36e99b
schemaVersion: "3"
displayName: Pi GCP Development Environment
version: 0.3.0
kind: workload
provides:
- [email protected]
- [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/ca-certificates-java@20260311
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[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/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/less@668
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[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/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- 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/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[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/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[email protected]
- deb/[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]
capabilities:
- group:
capabilities:
- source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[0]
type: com.docker.sandbox/lifecycle@1
config:
files:
- content: |
{
"providers": {
"gcp-oss-maas": {
"baseUrl": "https://aiplatform.googleapis.com/v1/projects/${{ kit.args.project }}/locations/${{ kit.args.location }}/endpoints/openapi",
"api": "openai-completions",
"apiKey": "$GCP_VERTEX_ACCESS_TOKEN",
"authHeader": true,
"models": [
{
"id": "qwen/qwen3-next-80b-a3b-thinking-maas",
"displayName": "Qwen 3 Next 80B Thinking (Agent Platform MaaS)",
"reasoning": true,
"input": ["text"],
"contextWindow": 262144,
"cost": {"input": 0.15, "output": 1.2, "cacheRead": 0, "cacheWrite": 0}
},
{
"id": "qwen/qwen3-next-80b-a3b-instruct-maas",
"displayName": "Qwen 3 Next 80B Instruct (Agent Platform MaaS)",
"reasoning": false,
"input": ["text"],
"contextWindow": 262144,
"cost": {"input": 0.15, "output": 1.2, "cacheRead": 0, "cacheWrite": 0}
},
{
"id": "qwen/qwen3-coder-480b-a35b-instruct-maas",
"displayName": "Qwen 3 Coder 480B Instruct (Agent Platform MaaS)",
"reasoning": false,
"input": ["text"],
"contextWindow": 258000,
"cost": {"input": 0.2, "output": 1.62, "cacheRead": 0.02, "cacheWrite": 0.2}
},
{
"id": "zai-org/glm-5.2-maas",
"displayName": "GLM 5.2 (Agent Platform MaaS)",
"reasoning": true,
"input": ["text"],
"contextWindow": 1000000,
"cost": {"input": 1.4, "output": 4.4, "cacheRead": 0.14, "cacheWrite": 1.4}
},
{
"id": "zai-org/glm-5-maas",
"displayName": "GLM 5 (Agent Platform MaaS)",
"reasoning": true,
"input": ["text"],
"contextWindow": 200000,
"cost": {"input": 1, "output": 3.2, "cacheRead": 0.1, "cacheWrite": 1}
},
{
"id": "deepseek-ai/deepseek-v3.2-maas",
"displayName": "Deepseek v3.2 (Agent Platform MaaS)",
"reasoning": true,
"input": ["text"],
"contextWindow": 163840,
"cost": {"input": 0.56, "output": 1.68, "cacheRead": 0.056, "cacheWrite": 0.56}
},
{
"id": "moonshotai/kimi-k2-thinking-maas",
"displayName": "Kimi K2 Thinking (Agent Platform MaaS)",
"reasoning": true,
"input": ["text"],
"contextWindow": 262144,
"cost": {"input": 0.6, "output": 2.5, "cacheRead": 0.06, "cacheWrite": 0.6}
}
]
},
"gcp-anthropic": {
"baseUrl": "https://aiplatform.googleapis.com/v1/projects/${{ kit.args.project }}/locations/${{ kit.args.location }}/publishers/anthropic",
"api": "anthropic-messages",
"apiKey": "$GCP_VERTEX_ACCESS_TOKEN",
"authHeader": true,
"compat": {
"supportsStrictTools": false
},
"models": [
{
"id": "claude-opus-5-5",
"name": "Claude Opus 5.5 (Agent Platform)",
"reasoning": true,
"thinkingLevelMap": {
"off": null,
"minimal": null,
"low": "low",
"medium": "medium",
"high": "high",
"xhigh": "xhigh",
"max": "max"
},
"input": ["text", "image"],
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": {
"supportsMidConvoEffort": true,
"supportsMidConvoSystemMessages": true,
"supportsMidConvoToolChanges": true,
"forceAdaptiveThinking": true,
"supportsTemperature": false
},
"cost": {"input": 4, "output": 20, "cacheRead": 0.2, "cacheWrite": 5}
},
{
"id": "claude-sonnet-5-5",
"name": "Claude Sonnet 5.5 (Agent Platform)",
"reasoning": true,
"thinkingLevelMap": {
"off": null,
"minimal": null,
"low": "low",
"medium": "medium",
"high": "high",
"xhigh": "xhigh",
"max": "max"
},
"input": ["text", "image"],
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": {
"supportsMidConvoEffort": true,
"supportsMidConvoSystemMessages": true,
"supportsMidConvoToolChanges": true,
"forceAdaptiveThinking": true,
"supportsTemperature": false
},
"cost": {"input": 2, "output": 10, "cacheRead": 0.1, "cacheWrite": 2.5}
},
{
"id": "claude-haiku-5-5",
"name": "Claude Haiku 5.5 (Agent Platform)",
"reasoning": true,
"thinkingLevelMap": {
"minimal": null,
"low": "low",
"medium": "medium",
"high": "high",
"xhigh": "xhigh",
"max": "max"
},
"input": ["text", "image"],
"contextWindow": 1000000,
"maxTokens": 128000,
"compat": {
"supportsMidConvoEffort": true,
"supportsMidConvoSystemMessages": true,
"supportsMidConvoToolChanges": true,
"forceAdaptiveThinking": true,
"supportsTemperature": false
},
"cost": {
"input": 0.1,
"output": 0.5,
"cacheRead": 0.01,
"cacheWrite": 0.125,
"tiers": [
{"inputTokensAbove": 100000, "input": 0.5, "output": 2.5, "cacheRead": 0.05, "cacheWrite": 0.625}
]
}
}
]
}
}
}
mode: "0644"
overwrite: false
path: /home/agent/.pi/agent/models.json
- content: |
import { getApiProvider } from "@earendil-works/pi-ai/compat";
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
export default function (pi: ExtensionAPI) {
const anthropicApi = getApiProvider("anthropic-messages");
if (!anthropicApi) return;
pi.registerProvider("gcp-anthropic", {
api: "anthropic-messages",
streamSimple: (model, context, options) => {
const baseFetch = options?.fetch ?? globalThis.fetch;
const vertexFetch: typeof fetch = async (input, init) => {
const rawUrl =
typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
const url = new URL(rawUrl);
const body = typeof init?.body === "string" ? JSON.parse(init.body) : undefined;
const modelId = body?.model ?? model.id;
if (body) {
delete body.model;
delete body.fallbacks;
body.anthropic_version ??= "vertex-2023-10-16";
}
const specifier = body?.stream ? "streamRawPredict" : "rawPredict";
url.pathname = url.pathname.replace(/\/v1\/messages$/, `/models/${modelId}:${specifier}`);
url.searchParams.delete("beta");
return baseFetch(url.toString(), {
...init,
body: body ? JSON.stringify(body) : init?.body,
});
};
return anthropicApi.streamSimple(model, context, {
...options,
apiKey: undefined,
fetch: vertexFetch,
});
},
});
}
mode: "0644"
overwrite: false
path: /home/agent/.pi/agent/extensions/gcp-anthropic.ts
declarationBlocks:
- "0:0"
source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[0]
- group:
capabilities:
- source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[1]
type: com.docker.sandbox/network-policy@1
config:
runtime:
allow:
- aiplatform.googleapis.com
declarationBlocks:
- "0:0"
source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[1]
- group:
description: Google Cloud Agent Platform AI
capabilities:
- source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[2]
type: com.docker.sandbox/credential@1
config:
apiKey:
inject:
- domain: aiplatform.googleapis.com
format: Bearer %s
header: Authorization
name: GCP_VERTEX_ACCESS_TOKEN
proxyManaged: true
phase: runtime
service: gcp-vertex
description: Google Cloud Agent Platform AI
declarationBlocks:
- "0:0"
source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[2]
- group:
capabilities:
- source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[3]
type: com.docker.sandbox/git-identity@1
declarationBlocks:
- "0:0"
source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[3]
- group:
capabilities:
- source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[4]
type: com.docker.sandbox/ssh-agent@1
config:
authenticate:
- github.com
phase: runtime
sign:
- git
unrestricted: false
declarationBlocks:
- "0:0"
source:
kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
path: capabilities[4]
- group:
capabilities:
- source:
kit: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
path: capabilities[0]
type: com.docker.sandbox/network-policy@1
config:
install:
allow:
- registry.npmjs.org
declarationBlocks:
- "1:0"
source:
kit: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
path: capabilities[0]
- group:
capabilities:
- source:
kit: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
path: capabilities[1]
type: com.docker.sandbox/lifecycle@1
config:
install:
- command: |
set -eu
want="${{ kit.args.version }}"
if [ "$want" != latest ] && pi --version 2>/dev/null | grep -qxF "$want"; then
echo "Pi $want already installed"
exit 0
fi
npm install -g "@earendil-works/pi-coding-agent@$want"
pi --version
description: Install the requested Pi release
env:
- NPM_CONFIG_PREFIX
- HTTP_PROXY
- HTTPS_PROXY
- NODE_EXTRA_CA_CERTS
- SSL_CERT_FILE
user: "1000"
declarationBlocks:
- "1:0"
source:
kit: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
path: capabilities[1]
- group:
description: Push to GitHub over SSH and sign commits with the user's key
capabilities:
- source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[0]
type: com.docker.sandbox/ssh-agent@1
config:
authenticate:
- [email protected]
phase: runtime
sign:
- git
unrestricted: false
description: Push to GitHub over SSH and sign commits with the user's key
declarationBlocks:
- "2:0"
source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[0]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[1]
type: com.docker.sandbox/network-policy@1
config:
runtime:
allow:
- github.com:22
declarationBlocks:
- "2:0"
source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[1]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[2]
type: com.docker.sandbox/lifecycle@1
config:
files:
- content: |
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
description: GitHub's published SSH host keys
mode: "0644"
path: /home/agent/.ssh/github-ssh-known-hosts
startup:
- command: |
set -eu
config="${XDG_CONFIG_HOME:-$HOME/.config}/git/config"
mkdir -p "$(dirname "$config")"
set_default() {
if git config --file "$config" --get "$1" >/dev/null; then
return
else
status=$?
[ "$status" -eq 1 ] || return "$status"
fi
git config --file "$config" "$1" "$2"
}
set_default gpg.format ssh
set_default gpg.ssh.defaultKeyCommand 'ssh-add -L'
set_default commit.gpgsign true
set_default tag.gpgsign true
description: Merge missing signing defaults without replacing user settings
env:
- XDG_CONFIG_HOME
- command: |
set -eu
mkdir -p "$HOME/.ssh"
touch "$HOME/.ssh/known_hosts"
while IFS= read -r key; do
if grep -qxF "$key" "$HOME/.ssh/known_hosts"; then
continue
else
status=$?
[ "$status" -eq 1 ] || exit "$status"
fi
printf '\n%s\n' "$key" >> "$HOME/.ssh/known_hosts"
done < /home/agent/.ssh/github-ssh-known-hosts
description: Merge GitHub host keys while preserving existing entries
declarationBlocks:
- "2:0"
source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[2]
- group:
optional: true
capabilities:
- source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[3]
type: com.docker.sandbox/agent-context@1
config:
contentFile: /usr/share/sandbox/kit/pi-gcp-dev/context.md.parts/0.md
declarationBlocks:
- "2:0"
source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[3]
- group:
optional: true
capabilities:
- source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[4]
type: com.docker.sandbox/agent-context@2
config:
content: |
# GitHub over SSH
git can fetch from and push to GitHub over SSH (`[email protected]:owner/repo`)
with the user's key, through the agent at `$SSH_AUTH_SOCK`. Commits and
tags you make are signed through the same agent; Git may select a
different key from the one GitHub accepts for authentication.
- The agent logs in to github.com as `git` and makes git signatures. It
refuses every other server, account, and kind of signature, so `ssh` to
another host fails by design: do not work around it.
- GitHub's host keys are in `~/.ssh/known_hosts`. If ssh reports a changed
host key, stop and tell the user; never remove the entry or disable
host key checking.
- The key belongs to the user. Push only what the user asked for, and say
which commits you made.
declarationBlocks:
- "2:0"
source:
kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
path: capabilities[4]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[0]
type: com.docker.sandbox/sbx@1
declarationBlocks:
- "3:0"
source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[0]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[1]
type: com.docker.sandbox/network-policy@1
config:
runtime:
allow:
- api.anthropic.com
- registry.npmjs.org
- platform.claude.com
declarationBlocks:
- "3:0"
source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[1]
- group:
description: Anthropic API access (API key or claude.ai OAuth)
optional: true
capabilities:
- source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[2]
type: com.docker.sandbox/credential@1
config:
apiKey:
inject:
- domain: api.anthropic.com
format: '%s'
header: x-api-key
name: ANTHROPIC_API_KEY
proxyManaged: true
oauth:
credentialFile:
path: ~/.pi/agent/auth.json
structure:
anthropic:
access: '{{.AccessToken}}'
expires: '{{.ExpiresAt}}'
refresh: '{{.RefreshToken}}'
type: oauth
resourceHosts:
- api.anthropic.com
sentinels:
accessToken: sk-ant-oat01-proxy-managed
refreshToken: sk-ant-ort01-proxy-managed
tokenEndpoint:
host: platform.claude.com
path: /v1/oauth/token
phase: runtime
service: anthropic
description: Anthropic API access (API key or claude.ai OAuth)
declarationBlocks:
- "3:0"
source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[2]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[3]
type: com.docker.sandbox/lifecycle@1
config:
install:
- command: if [ -n "${HTTP_PROXY:-}" ]; then npm config set proxy="$HTTP_PROXY" https-proxy="${HTTPS_PROXY:-$HTTP_PROXY}"; fi
description: Point npm at the sandbox proxy in ~/.npmrc so pi's runtime npm use (`pi install npm:...`, `pi update`, startup package fetches) works in exec contexts that do not inherit the proxy environment variables
env:
- HTTP_PROXY
- HTTPS_PROXY
user: "1000"
declarationBlocks:
- "3:0"
source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[3]
- group:
description: Drive pi non-interactively
capabilities:
- source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[4]
type: com.docker.sandbox/agent-sessions@1
config:
prompt:
- -p
- '{{.Prompt}}'
description: Drive pi non-interactively
declarationBlocks:
- "3:0"
source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[4]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[5]
type: com.docker.sandbox/agent-context@1
config:
filename: AGENTS.md
declarationBlocks:
- "3:0"
source:
kit: docker.io/docker/sbx-kit-pi:latest
path: capabilities[5]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
path: capabilities[0]
type: com.docker.sandbox/network-policy@1
config:
runtime:
allow:
- api.github.com
declarationBlocks:
- "4:0"
source:
kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
path: capabilities[0]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
path: capabilities[1]
type: com.docker.sandbox/lifecycle@1
config:
install:
- command: |
set -e
# Signing *machinery* stays machine-wide: it is inert unless something
# asks for a signature, and keeping it here means `git commit -S` works
# in any repository in the sandbox.
git config --system gpg.format ssh
# The key command is invoked through /bin/sh rather than executed
# directly. Files shipped under a kit's files/home/ tree land mode
# 0644 when the kit is installed from its OCI artifact -- per-file
# executable bits are not representable in a v2 layer (spec/OCI-v2.md)
# -- and git execs this value itself, so a bare path would die with
# "cannot exec: Permission denied" before a single one of the script's
# own diagnostics could run.
git config --system gpg.ssh.defaultKeyCommand '/bin/sh /home/agent/.config/git/ssh-signing-key-command'
git config --system gpg.ssh.allowedSignersFile /home/agent/.config/git/allowed_signers
# user.signingKey MUST stay unset: git only runs
# gpg.ssh.defaultKeyCommand when it is empty. Setting it to any value
# (even a placeholder) disables dynamic key resolution entirely.
git config --system --unset-all user.signingKey || true
# Signing *policy* is scoped, not machine-wide. Setting
# commit.gpgSign=true in /etc/gitconfig makes every `git commit` in the
# sandbox depend on a live SSH agent — including throwaway repositories
# created by test suites that have nothing to do with the user's work.
# When the forwarded agent goes away, those all fail too.
mkdir -p /etc/git
cat > /etc/git/signing-enabled.inc <<'INC'
# Included by /etc/gitconfig for repositories with a remote.
# See the git-ssh-sign kit.
[commit]
gpgSign = true
[tag]
gpgSign = true
INC
chmod 0644 /etc/git/signing-enabled.inc
# Clear anything an older version of this kit left machine-wide, so a
# re-install converges rather than layering.
git config --system --unset-all commit.gpgSign || true
git config --system --unset-all tag.gpgSign || true
git config --system --unset-all 'includeIf.hasconfig:remote.*.url:**.path' || true
# `includeIf "hasconfig:remote.*.url:**"` needs git >= 2.36. Probe for
# it rather than parsing a version string: build a throwaway repo with
# a remote and see whether the include actually fires. Note that `**`
# is only a cross-slash wildcard when it is a whole path component --
# `[email protected]:**` does NOT match `[email protected]:org/repo.git`, so
# a bare `**` ("has any remote at all") is the pattern to use here.
probe=$(mktemp -d)
git init -q "$probe"
git -C "$probe" remote add origin https://example.invalid/probe.git
printf '[commit]\n\tgpgSign = true\n' > "$probe/inc"
printf '[includeIf "hasconfig:remote.*.url:**"]\n\tpath = %s/inc\n' "$probe" > "$probe/sys"
supported=$(GIT_CONFIG_SYSTEM="$probe/sys" GIT_CONFIG_GLOBAL=/dev/null \
git -C "$probe" config --get commit.gpgSign 2>/dev/null || true)
rm -rf "$probe"
if [ "$supported" = "true" ]; then
git config --system 'includeIf.hasconfig:remote.*.url:**.path' /etc/git/signing-enabled.inc
else
# Old git: an unrecognised includeIf keyword evaluates false, which
# would silently disable signing. Fail closed (sign everywhere)
# rather than fail open (sign nothing).
echo "[git-ssh-sign] git $(git --version | awk '{print $3}') lacks includeIf hasconfig; enabling signing machine-wide" >&2
git config --system commit.gpgSign true
git config --system tag.gpgSign true
fi
if [ "$(git config --system --get core.hooksPath || true)" = "/home/agent/.config/git/hooks" ]; then
git config --system --unset-all core.hooksPath
fi
description: Configure SSH commit signing, scoped to repositories with a remote
user: "0"
declarationBlocks:
- "4:0"
source:
kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
path: capabilities[1]
- group:
capabilities:
- source:
kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
path: capabilities[2]
type: com.docker.sandbox/agent-context@1
config:
contentFile: /usr/share/sandbox/kit/pi-gcp-dev/context.md.parts/1.md
declarationBlocks:
- "4:0"
source:
kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
path: capabilities[2]
args:
location:
default: global
description: Vertex AI endpoint location
project:
required: true
description: GCP project used for Vertex AI
version:
default: 1.1.0
description: Pi release to install (e.g. 1.1.0, or latest)
pattern: ^([0-9]+\.[0-9]+\.[0-9]+|latest)$
kits:
- ref: docker.io/docker/sbx-kit-pi:latest
digest: sha256:7514ea9f2ce3613ea7e07cddf2aee3d8b598ef052ad68623603b20a332326a09
- ref: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
digest: sha256:f8688c83a762ace234fdf6ab6b33c555ffc93b2847101d993a1012f4ccbd08e8
args:
version: ${{ kit.args.version }}
- ref: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
digest: sha256:6167e4536509741b7e626a834249a66a2bd374c56f210684fef25155f6a67ec1
args:
location: ${{ kit.args.location }}
project: ${{ kit.args.project }}
- ref: docker.io/docker/sbx-kit-github-ssh:1.0.0
digest: sha256:ff389a4245fe59e4d6812e9f3ca1219e56cad8019b370aead737f0795fb5db45
- ref: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
digest: sha256:79c6aaca0f08003913a68539c2105a0c4d7109b740aa2cbcadfa103b80336445