name: k8e-sandbox-skill description: K8E sandbox skill — execute code and shell commands in gVisor/Kata/Firecracker-isolated pods. All code execution must go through the sandbox, never on the host. Trigger when user asks to run, execute, test, try, install, analyze code or data files. user-invocable: true
K8E Sandbox
All code execution goes through k8e-sandbox-cli — never run code directly on the host. Each session is a gVisor/Kata/Firecracker-isolated pod with kernel-level egress enforcement. Mistakes can't damage the host.
Trigger keywords (English): "run this", "execute", "test it", "install X", "check if this works", "analyze this data"
Trigger keywords (中文): "帮我跑", "运行", "试试", "执行", "测试", "安装并使用", "分析这个CSV", "处理这个文件", "看看输出", "帮我算"
Pre-flight
Before any sandbox operation, check that the CLI is authenticated to the gateway:
# Local mode (on the K8E server) — auto-discovery, no login needed
# Remote mode — check for valid mTLS certificate
if ! k8e-sandbox-cli status 2>/dev/null | jq -e .available >/dev/null 2>&1; then
echo "⚠ Sandbox not reachable. For remote access, log in first:"
echo " k8e-sandbox-cli login --endpoint <server-ip>:50051 --apikey <your-api-key>"
exit 1
fi
If the sandbox is unreachable, ask the user:
"I need K8E sandbox access to run code securely. For a remote cluster, provide:
- The server address (e.g.
<server-ip>:50051)- Your API key (get it from the server:
k8e sandbox-apikey create my-agent)I'll run
k8e-sandbox-cli login --endpoint <server-ip>:50051 --apikey <your-key>to set up mTLS credentials."
After a successful login, credentials are cached in ~/.k8e/sandbox/ (client.crt, client.key, ca.crt) and auto-renewed — no need to set environment variables per session.
mTLS Setup (remote access)
The sandbox gateway uses mTLS with dynamically-issued client certificates. First-time setup:
# Obtain a client certificate (valid 30 days, auto-renewed)
k8e-sandbox-cli login --endpoint <server-ip>:50051 --apikey k8e-abc123...
Credentials are cached in ~/.k8e/sandbox/ and auto-renew when expiring within 7 days. No API key env vars needed after the initial login.
If the server's IP/hostname changes, the cached CA cert will no longer match. Clear the cache and log in again:
rm -f ~/.k8e/sandbox/ca.crt ~/.k8e/sandbox/client.crt ~/.k8e/sandbox/client.key
k8e-sandbox-cli login --endpoint <new-ip>:50051 --apikey <your-key>
Environment
Download the platform-specific binary (~44MB) from GitHub Releases.
| Platform | Binary |
|---|---|
| macOS Intel | k8e-sandbox-cli-darwin-amd64 |
| macOS Apple Silicon | k8e-sandbox-cli-darwin-arm64 |
| Linux x86_64 | k8e-sandbox-cli-linux-amd64 |
| Linux ARM64 | k8e-sandbox-cli-linux-arm64 |
| Windows x86_64 | k8e-sandbox-cli-windows-amd64.exe |
# Download and make executable
curl -sLO https://github.com/xiaods/k8e/releases/latest/download/k8e-sandbox-cli-linux-amd64
chmod +x k8e-sandbox-cli-linux-amd64
# On the K8E server node, auto-discovery works automatically
./k8e-sandbox-cli-linux-amd64 run "echo hello"
# From a remote client, log in once (obtains mTLS client certificate)
# (Get the API key from the server: k8e sandbox-apikey create my-agent)
./k8e-sandbox-cli-linux-amd64 login --endpoint <your-public-ip>:50051 --apikey k8e-abc123...
# After login, subsequent commands work without --apikey:
./k8e-sandbox-cli-linux-amd64 run "echo hello"
Command Reference
| Command | Purpose | Key flags |
|---|---|---|
k8e-sandbox-cli login |
Authenticate and obtain mTLS cert (remote access) | --apikey, --endpoint, --device-name |
k8e-sandbox-cli run <code> |
Execute code or shell command | --lang python|bash|node|ts, --session-id, --tenant, --timeout 30, --raw |
k8e-sandbox-cli status |
Check service + current session | — |
k8e-sandbox-cli create |
New session (manual lifecycle) | --runtime gvisor|kata|firecracker, --allowed-hosts, --manifest, --git-repo |
k8e-sandbox-cli destroy <sid> |
Destroy session | — |
k8e-sandbox-cli write <sid> <path> |
Write file to /workspace | content via stdin, --mode w|a |
k8e-sandbox-cli read <sid> <path> |
Read file from /workspace | --raw (plain text output) |
k8e-sandbox-cli list <sid> |
List workspace files | --since <unix_ts> |
k8e-sandbox-cli subagent <parent-sid> |
Spawn child sandbox (depth 1) | shares parent /workspace PVC |
k8e-sandbox-cli confirm <sid> <action> |
Gate destructive action on human approval | --timeout 30, --no-wait |
k8e-sandbox-cli approve <approval-id> |
Approve pending confirm | --reject, --reason |
k8e-sandbox-cli benchmark |
Measure cold start / warm claim / lifecycle latency | --pool-size 3, --iterations 3 |
k8e-sandbox-cli snapshot save <sid> <name> |
Save workspace to disk | — |
k8e-sandbox-cli snapshot restore <name> |
Create session from saved snapshot | --runtime, --tenant |
k8e-sandbox-cli snapshot list |
List saved snapshots | — |
k8e-sandbox-cli snapshot delete <name> |
Delete a snapshot | — |
k8e-sandbox-cli install-skill [claude|codex|pi|all] |
Install this skill into agent config | — |
k8e-sandbox-cli run <code> [--lang python|bash|node|ts] [--session-id <id>] [--tenant <id>] [--timeout <seconds>] [--raw]
Code source: argument > stdin. Language default: bash.
| Language | Single-line | Multi-line |
|---|---|---|
| python | python3 -c "..." |
writes /tmp/_k8e_run.py |
| node/js | node -e "..." |
writes /tmp/_k8e_run.js |
| ts | tsx -e "..." |
writes /tmp/_k8e_run.ts |
| bash | pass-through | pass-through |
Mode table
| Mode | Behavior | Output | Exit code |
|---|---|---|---|
| Default (JSON) | Wait for completion | {"stdout":"...","stderr":"...","exit_code":0,"session_id":"sess-xxx"} |
match command |
--raw |
Stream in real-time | plain text to stdout | match command |
Session lifecycle
| Mode | How it works | State location |
|---|---|---|
| Auto (default) | run auto-creates session if none exists |
~/.k8e/sandbox/default/state.json |
| Tenant | --tenant my-project for cross-process reuse |
~/.k8e/sandbox/{tenant}/state.json |
| Manual | create → run --session-id → destroy |
no state file |
Auto-sessions persist across run calls within the same process. Use --tenant to persist across process restarts. Use manual mode when you need custom runtime or egress settings.
Egress rules
Default allowed hosts (kernel-level Cilium eBPF enforcement):
pypi.org, files.pythonhosted.org, registry.npmjs.org, github.com, raw.githubusercontent.com
Override with --allowed-hosts on create. Everything else blocked.
Typical Scenarios
Scenario 1: Quick code execution (most common)
→ k8e-sandbox-cli run "print('hello')" --lang python
→ parse JSON output, display stdout to user
No session management needed. CLI auto-creates and reuses.
Scenario 2: Install package then use it
1. k8e-sandbox-cli run "pip install pandas" --lang bash
2. k8e-sandbox-cli run "python3 -c 'import pandas; print(pandas.__version__)'" --lang bash
Same auto-session reused across both calls.
Scenario 3: Write file, execute, read results
1. k8e-sandbox-cli write $SID /workspace/analyze.py <<'PYEOF'
import pandas as pd
df = pd.read_csv('/workspace/data.csv')
print(df.describe())
PYEOF
2. echo "name,value\na,1\nb,2" | k8e-sandbox-cli write $SID /workspace/data.csv
3. k8e-sandbox-cli run "python3 /workspace/analyze.py" --session-id $SID
4. k8e-sandbox-cli read $SID /workspace/result.json --raw | jq .
Scenario 4: Custom egress + explicit session
1. SID=$(k8e-sandbox-cli create --runtime gvisor --allowed-hosts pypi.org,api.example.com | jq -r .session_id)
2. k8e-sandbox-cli run "curl -s https://api.example.com/data" --session-id $SID
3. k8e-sandbox-cli destroy $SID
Scenario 5: Parallel sub-agents
1. SUB1=$(k8e-sandbox-cli subagent $PARENT | jq -r .session_id)
2. SUB2=$(k8e-sandbox-cli subagent $PARENT | jq -r .session_id)
3. k8e-sandbox-cli run "python3 task_a.py" --session-id $SUB1 --raw &
4. k8e-sandbox-cli run "python3 task_b.py" --session-id $SUB2 --raw &
5. wait
Sub-agents share parent /workspace PVC, communicate via files. Max depth 1.
Scenario 6: Human approval for destructive actions
1. k8e-sandbox-cli confirm $SID "delete /workspace/production-data" → blocks, outputs approval prompt to stderr
2. Show the stderr output to user — they copy the approve command
3. Command returns {"approved": true} on success
For non-blocking registration: add --no-wait, get approval_id, call k8e-sandbox-cli approve $AID later.
Scenario 7: Workspace snapshot save/restore
# Save current workspace
k8e-sandbox-cli snapshot save $SID my-analysis
# Later, restore from snapshot into a new session
SID=$(k8e-sandbox-cli snapshot restore my-analysis | jq -r .session_id)
k8e-sandbox-cli read $SID /workspace/result.json --raw
Error reference
| Exit code | Cause | Action |
|---|---|---|
| 2 | client certificate required |
Remote access requires mTLS. Run k8e-sandbox-cli login --endpoint <ip>:50051 --apikey <key>. |
| 2 | certificate has been revoked |
API key was deleted. Obtain a new key and re-login. |
| 2 | tls: failed to verify certificate |
Server cert or CA mismatch. Clear ~/.k8e/sandbox/ca.crt and re-login. |
| 2 | Sandbox service unreachable | Check k8e-sandbox-cli status, ensure gateway is running |
| 1 | Command failed / session not found | Parse error message from JSON; create new session if expired |
| 8 (ResourceExhausted) | warm pool full |
All sandbox pods are in use. Wait for an active session to finish, or add more server memory. |
| 8 (ResourceExhausted) | rate limit exceeded |
Too many requests. Slow down and retry after a few seconds. |
| non-zero | Command inside sandbox failed | Check stderr in JSON output |
JSON error output format:
{"error":"description","detail":"specific cause"}
{"ok":false,"error":"reason"}
Isolated runtimes
| Runtime | Isolation | Boot time | Requirement |
|---|---|---|---|
gvisor (default) |
Userspace kernel | ~10ms | runsc binary |
kata |
VM (QEMU) | ~500ms | kata-runtime |
firecracker |
Hardware microVM | ~125ms | /dev/kvm |
Use --runtime firecracker only when /dev/kvm is available. gVisor is the recommended default — no KVM required.
Your role
Do:
- Run ALL code through
k8e-sandbox-cli run, never on host - Use
--lang pythonfor.pycode,--lang bashfor shell commands - Use
--rawfor long-running output (training, streaming) - Use
jqto parse JSON output:k8e-sandbox-cli run "..." | jq -r .stdout - Auto-manage sessions (default mode) unless custom settings needed
- Show stderr from
confirmto user verbatim
Don't:
- Never run
python3,node,pip,npm,curldirectly on host - Never use
k8e-sandbox-cli runwithsudo - Don't create sessions manually when auto-mode works