| name | add-hub-template |
| description | Add or update a Blaxel Sandbox Hub image/template under hub/. Use when adding a new hub image, sandbox image, runtime image, template.json, Dockerfile, hidden/internal image, or workflow-dispatch build option in the blaxel-ai/sandbox repository. |
Add a Sandbox Hub Image
Use this skill for new images under hub/<name>/, including visible templates and hidden/internal runtime images.
Scope First
- Check repository instructions at the relevant scope before editing.
- Inspect nearby templates:
- generic base:
hub/base-image, hub/node, hub/ts-app, hub/py-app
- entrypoint examples:
hub/expo, hub/vite, hub/nextjs
- hidden/internal examples:
hub/benchmark, hub/vibekit-*
- Check the current git status and preserve unrelated user changes.
- Decide whether the image is user-facing or internal:
- User-facing: add useful metadata and README mention.
- Internal/platform-managed: set
"hidden": true and avoid README marketing.
Required Files
Create or update:
hub/<name>/Dockerfile
hub/<name>/template.json
.github/workflows/build.yaml
Usually update for local testing:
Only update README.md for visible user-facing templates. Do not list hidden/internal images as normal templates.
Dockerfile Rules
Follow the existing multi-stage pattern:
ARG SANDBOX_VERSION=latest
FROM ghcr.io/blaxel-ai/sandbox:${SANDBOX_VERSION} AS sandbox-api
FROM <runtime-base>
RUN <install required runtime tools>
WORKDIR /blaxel
COPY --from=sandbox-api /sandbox-api /usr/local/bin/sandbox-api
RUN chmod +x /usr/local/bin/sandbox-api
EXPOSE 8080
ENV HOME=/blaxel
ENTRYPOINT ["/usr/local/bin/sandbox-api"]
Rules:
- Always include the
ARG SANDBOX_VERSION=latest stage unless the image has a specific reason not to.
- Copy
/sandbox-api from the sandbox-api stage into /usr/local/bin/sandbox-api.
- Expose
8080 for sandbox-api.
- Only expose app/dev ports when they are intrinsic to that template. Do not expose dynamic app ports for platform-managed hidden images.
- If an entrypoint script is needed, keep
sandbox-api running as the control plane and test the real startup path.
- Keep runtime dependencies explicit. If the runner supports
s3://, gs://, or Azure Blob, install and test rclone.
template.json Rules
Minimal shape:
{
"name": "<name>",
"displayName": "<Display Name>",
"categories": [],
"description": "Short description.",
"longDescription": "Longer description.",
"url": "https://github.com/blaxel-ai/sandbox",
"icon": "https://blaxel.ai/logo.png",
"memory": 2048,
"ports": [
{
"name": "sandbox-api",
"target": 8080,
"protocol": "HTTP"
}
],
"enterprise": false,
"coming_soon": false
}
For hidden/internal images, add:
"hidden": true
Port rule: put only stable ports in template.json. If another service creates previews with a caller-provided runtime.port, leave that dynamic port out of the template.
GitHub Workflow
Update .github/workflows/build.yaml every time a new hub image is added:
- Add
<name> under on.workflow_dispatch.inputs.sandbox.options.
- Keep alphabetical-ish order near existing options.
The automatic build matrix uses folders under hub/, so the directory is enough for push/tag auto-detection. The workflow_dispatch options list is separate and must be updated manually.
docker-compose
Add a service when local build/run is useful:
<name>:
platform: linux/amd64
build:
context: .
dockerfile: hub/<name>/Dockerfile
env_file:
- .env
ports:
- "8080:8080"
- "3010:3010"
Add app ports only when they are stable template ports. Avoid dynamic platform-managed app ports.
Validation
Run the cheapest structural checks first:
jq empty hub/<name>/template.json
find hub/<name> -maxdepth 1 -name '*.sh' -print -exec sh -n {} \;
ruby -e 'require "yaml"; YAML.load_file(".github/workflows/build.yaml"); puts "yaml-ok"'
Build with an explicit platform:
docker build --platform linux/amd64 -t blaxel/<name>:test -f hub/<name>/Dockerfile .
Prefer explicit docker build --platform linux/amd64 over docker compose build on Apple Silicon. Some local compose providers ignore the service platform when pulling ghcr.io/blaxel-ai/sandbox:latest and fail on arm64.
If the image has a runner or entrypoint script, smoke-test it inside the built image with realistic env vars and mounted test input. Verify:
- required binaries exist (
command -v <tool>)
- source materialization works
- pre-start/setup hooks run in the intended order
- the final command starts or exits as expected
When feasible, start the sandbox API and check:
curl http://localhost:8080/health
curl -X POST http://localhost:8080/process \
-H "Content-Type: application/json" \
-d '{"command": "echo hello", "waitForCompletion": true}'
Final Checklist