Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/guide/integrations/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ lang: en-US

| Title | Author | Date | Tags |
| --- | --- | --- | --- |
| [OpenCode Integration Guide](./opencode.md) | Sam-Hui-dot | 2026-07-05 | integration, opencode, coding-agent, agent |
| [Pi Agent Integration Guide](./pi-agent.md) | chaojixinren | 2026-07-01 | integration, pi-agent, coding-agent, agent |
245 changes: 245 additions & 0 deletions docs/guide/integrations/opencode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
---
title: OpenCode Integration Guide
author: Sam-Hui-dot
date: 2026-07-05
tags:
- integration
- opencode
- coding-agent
- agent
lang: en-US
---

# OpenCode Integration Guide

[中文文档](../../zh/guide/integrations/opencode.md)

Run [OpenCode](https://opencode.ai/), an open-source terminal coding agent,
inside CubeSandbox MicroVMs. This guide pairs with the runnable
[`examples/opencode-integration`](https://github.com/TencentCloud/CubeSandbox/tree/master/examples/opencode-integration)
project.

## Integration Target and Version

| Component | Version |
|---|---|
| OpenCode CLI | `opencode-ai` pinned by `OPENCODE_VERSION` build arg |
| Node.js | 22, installed through NodeSource |
| CubeSandbox base image | `ghcr.io/tencentcloud/cubesandbox-base:2026.16` |
| Host SDKs | `e2b>=2.4.1`, `cubesandbox>=0.3.0` |
| CubeSandbox platform | `>=0.3.0` for pause/resume; CubeEgress required for header injection |

OpenCode's documented non-interactive mode is `opencode run [message..]`. The
example uses:

```bash
opencode run --model <provider/model> --dir /workspace --auto --format json "<prompt>"
```

## Why Run OpenCode Inside CubeSandbox

OpenCode can edit files, execute commands, install packages, and call LLM APIs.
Running it in CubeSandbox gives each coding task a disposable MicroVM boundary:

| Concern | CubeSandbox pattern |
|---|---|
| Isolation | One MicroVM per task or session |
| Reproducibility | Boot from a pinned template image |
| Fast reuse | Pause/resume preserves `/workspace` and OpenCode state |
| Network control | Default-deny egress with explicit LLM host allow rules |
| Secret handling | CubeEgress can inject API keys on the wire |
| Reviewability | Host scripts verify generated files and test results |

## Prerequisites

- A running CubeSandbox deployment; CubeAPI reachable at `http://<node>:3000`.
- `cubemastercli` on `$PATH`.
- Docker plus a registry reachable from Cube nodes.
- Python 3.10+ for host-side driver scripts.
- An LLM provider API key supported by OpenCode.

## Integration Steps

### 1. Build the template image

```bash
cd examples/opencode-integration
docker build --platform linux/amd64 \
-t <registry>/opencode-cube:latest .
docker push <registry>/opencode-cube:latest
```

The image installs Node.js, OpenCode, `git`, `ripgrep`, Python, and small
inspection tools on top of the CubeSandbox base image.

### 2. Register the Cube template

```bash
cubemastercli tpl create-from-image \
--image <registry>/opencode-cube:latest \
--writable-layer-size 4G \
--expose-port 49983 \
--probe 49983 \
--probe-path /health
```

The inherited CubeSandbox base entrypoint keeps envd on port `49983` and serves
the standard `/health` endpoint.

### 3. Configure the host driver

```bash
cp .env.example .env
pip install -r requirements.txt
```

Set:

```bash
E2B_API_URL=http://<node>:3000
E2B_API_KEY=e2b_000000
CUBE_TEMPLATE_ID=<template-id>
OPENCODE_MODEL=openai/gpt-4.1-mini
OPENAI_API_KEY=<provider-key>
```

For custom endpoints, set `OPENCODE_BASE_URL`. If it is not set, the scripts
also accept provider-specific variables such as `OPENAI_BASE_URL`. The scripts
write an `opencode.json` in the sandbox workspace with
`provider.<provider_prefix>.options.baseURL`.

When validating against the repository's `dev-env/` VM, set
`CUBE_DEV_SIDECAR=1` so the host-side SDK routes sandbox traffic through
`examples/e2b-dev-sidecar`.

`network_policy.py` uses the native `cubesandbox` SDK. When running that script
against `dev-env/`, also set:

```bash
CUBE_API_URL=http://127.0.0.1:13000
CUBE_PROXY_NODE_IP=127.0.0.1
CUBE_PROXY_PORT_HTTP=11080
```

### 4. Run the one-shot coding task

```bash
python3 run_opencode.py --dry-run
python3 run_opencode.py
```

The script seeds a small Python project, runs OpenCode, then verifies:

- `calculator.add` was implemented.
- `python3 -m unittest discover -v` passes.
- `result.md` contains the marker `OPENCODE_CUBE_OK`.

### 5. Demonstrate session persistence

```bash
python3 resume_opencode.py
```

The first turn writes `plan.md`, pauses the sandbox, reconnects to the same
sandbox, verifies `/workspace` and OpenCode's state directory survived, then
continues the task and checks `OPENCODE_RESUME_OK`.

### 6. Restrict egress and inject credentials

```bash
python3 network_policy.py
```

The strict path uses the native `cubesandbox` SDK:

- `allow_internet_access=False` makes egress default-deny.
- A CubeEgress rule allows only the configured LLM host.
- `Inject` attaches the real provider credential as an HTTP header.
- The sandbox process receives only a placeholder key.

Set `OPENCODE_LLM_HOST` when the LLM API host differs from the provider
default, especially when using `OPENCODE_BASE_URL` or a provider-specific
`<PROVIDER>_BASE_URL`:

```bash
OPENCODE_LLM_HOST=api.openai.com python3 network_policy.py
```

Use `--skip-agent` to verify policy behavior without spending LLM tokens:

```bash
python3 network_policy.py --skip-agent
```

## Key Code Snippets

Headless OpenCode command construction:

```python
opencode_command(
prompt,
workspace="/workspace",
model="openai/gpt-4.1-mini",
title="cube-opencode-demo",
)
```

Restricted egress rule:

```python
Rule(
name="allow_openai_llm",
match=Match(scheme="https", sni="api.openai.com", host="api.openai.com"),
action=Action(
allow=True,
audit="metadata",
inject=[Inject(
header="Authorization",
secret=secret,
format="Bearer ${SECRET}",
)],
),
)
```

## Caveats

- OpenCode still needs a real LLM provider key for live runs.
- `--auto` lets OpenCode perform edits and commands without interactive approval;
use it only inside the isolated sandbox boundary.
- Direct env injection in `run_opencode.py` is convenient for local validation
and known secret values are redacted from failure output, but shared clusters
should prefer `network_policy.py`.
- Custom provider support depends on OpenCode's provider configuration and the
target endpoint's compatibility with the selected model.
- The example Dockerfile uses the NodeSource setup script for readability.
Production images should pin and verify Node.js package sources or mirror the
artifacts internally.

## Validation

From `examples/opencode-integration`:

```bash
python3 -m py_compile env_utils.py _opencode_common.py run_opencode.py resume_opencode.py network_policy.py
python3 -m unittest discover . -p 'test_*.py'
bash -n build-template.sh
docker build --platform linux/amd64 -t opencode-cube:verify .
docker run --rm opencode-cube:verify opencode --version
```

Live CubeSandbox validation:

```bash
python3 run_opencode.py
python3 resume_opencode.py
python3 network_policy.py --skip-agent
python3 network_policy.py
```

## References

- [OpenCode CLI documentation](https://opencode.ai/docs/cli/)
- [OpenCode provider documentation](https://opencode.ai/docs/providers/)
- [CubeSandbox OpenCode example](https://github.com/TencentCloud/CubeSandbox/tree/master/examples/opencode-integration)
- [CubeSandbox Security Proxy](../security-proxy.md)
1 change: 1 addition & 0 deletions docs/zh/guide/integrations/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ lang: zh-CN

| 标题 | 作者 | 日期 | 标签 |
| --- | --- | --- | --- |
| [OpenCode 集成指南](./opencode.md) | Sam-Hui-dot | 2026-07-05 | integration, opencode, coding-agent, agent |
| [Pi Agent 集成指南](./pi-agent.md) | chaojixinren | 2026-07-01 | integration, pi-agent, coding-agent, agent |
Loading
Loading