opencode-runtime
Python runtime for deploying and managing OpenCode instances at scale.
Running OpenCode for a single developer is simple.
Running OpenCode for many users, isolated repositories, persistent workspaces, multiple OpenCode instances, and production workloads requires infrastructure.
OpenCode Runtime provides that infrastructure.
Use this when you need to:
- Run OpenCode for multiple users or teams from a Python backend
- Give each user an isolated workspace with no shared state
- Embed OpenCode in a SaaS product or internal platform
- Manage OpenCode instance lifecycles (start, health-check, reuse, stop)
- Stream OpenCode responses to your application in real time
What it provides:
- One instance per user — automatically started, isolated, and reused
- Filesystem isolation — each user gets a private workspace; no shared state
- Lifecycle management — health-checked startup, graceful shutdown, stale process recovery
- Streaming — consume every OpenCode event as it arrives
- Native OpenCode config — your existing
opencode.json, agents, and skills drop in unchanged
Install
pip install opencode-runtime
Requires opencode on PATH:
npm install -g opencode-ai
Usage
Ask
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime() as r:
session = await r.session()
response = await session.ask("Explain this repo")
print(response.text)
Config
Pass a raw opencode.json dict to control model, permissions, and any other OpenCode-native setting:
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime(
config={"model": "anthropic/claude-sonnet-4-5", "permission": {"bash": "deny"}},
) as r:
session = await r.session()
response = await session.ask("Analyse the architecture")
print(response.text)
Materials
Pass a directory of OpenCode-native files — AGENTS.md, opencode.json, .opencode/skills/, etc. — and they are copied into the server before it starts:
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime(materials="./opencode-materials") as r:
session = await r.session()
response = await session.ask("Follow the instructions in AGENTS.md")
print(response.text)
Isolation
Set project_dir and runtime_dir to give the server its own HOME, config, and conversation history — separate from your real environment:
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime(
project_dir="/path/to/project",
runtime_dir=".opencode-runtime",
materials="./opencode-materials",
) as r:
session = await r.session()
response = await session.ask("What does this project do?")
print(response.text)
Per-user sessions
Each unique user_id gets its own isolated server and conversation history:
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime(runtime_dir=".opencode-runtime") as r:
session = await r.session(user_id="u_1")
response = await session.ask("What does this project do?")
print(response.text)
Multi-tenant
Add workspace to isolate by tenant. Different (workspace, user_id) → different server. Same combination → server reused:
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime(runtime_dir=".opencode-runtime") as r:
s1 = await r.session(workspace="org_a", user_id="u_1")
s2 = await r.session(workspace="org_b", user_id="u_2")
r1 = await s1.ask("What does this project do?")
r2 = await s2.ask("List the main dependencies")
Session continuation
Multiple ask() calls on the same session continue the same conversation — OpenCode keeps the full history server-side:
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime() as r:
session = await r.session()
await session.ask("Explain this repo")
await session.ask("Which file should I start with?") # has full context
To resume a conversation in a future session, store session.session_id and pass it back:
# First session
async with OpenCodeRuntime() as r:
session = await r.session()
await session.ask("Explain this repo")
saved_id = session.session_id # persist this
# Later — resumes the same conversation
async with OpenCodeRuntime() as r:
session = await r.session(session_id=saved_id)
await session.ask("What were we discussing?")
Raw client
Access any OpenCode server endpoint directly:
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime() as r:
session = await r.session()
agents = await session.raw_client.get("/agent")
mcp = await session.raw_client.get("/mcp")
Streaming
For live output, use stream(). It yields every event OpenCode emits as an
OpenCodeEvent with three fields: type (event kind), text (populated for
text-bearing events, None otherwise), and raw (full server payload). See
the OpenCode server docs for all event types.
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime() as r:
session = await r.session()
async for event in session.stream("Review this PR"):
if event.type == "message.part.delta" and event.text:
print(event.text, end="", flush=True)
CLI
opencode-runtime ships with a CLI for managing opencode servers from the terminal. Useful for inspecting what your application is running, debugging sessions, or managing servers independently.
Start a server
opencode-runtime serve
The server runs in the background. Use ps, stop, and health to manage it.
Multi-tenant
Each unique (workspace, user-id) combination gets its own isolated server:
opencode-runtime serve --workspace org_a --user-id u_1
opencode-runtime serve --workspace org_b --user-id u_2
List servers
opencode-runtime ps
ID PID PORT STATUS UPTIME WORKSPACE USER PROJECT
──────────────────────────────────────────────────────────────────────────────────
39dce5beb4debfaa 12051 58409 ● alive Up 5m org_a u_1 ~/Developer/myproject
81fa29acb3e9210f 12088 58411 ● alive Up 3m org_b u_2 ~/Developer/myproject
Check health
opencode-runtime health 39dce5beb4debfaa
Stop a server
opencode-runtime stop 39dce5beb4debfaa
Stop all servers
opencode-runtime stop-all
Library + CLI
Start a server from Python, then inspect and manage it from the terminal:
from opencode_runtime import OpenCodeRuntime
async with OpenCodeRuntime() as r:
session = await r.session()
response = await session.ask("Review this PR")
print(response.text)
# while app.py is running
opencode-runtime ps
opencode-runtime health 39dce5beb4debfaa
opencode-runtime stop 39dce5beb4debfaa
Requirements
- Python 3.10+
opencode1.0+ on PATH
Contributing
See CONTRIBUTING.md.
License
Apache 2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file opencode_runtime-0.4.0.tar.gz.
File metadata
- Download URL: opencode_runtime-0.4.0.tar.gz
- Upload date:
- Size: 28.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9dc37476e36c1ebc5c32c9dbc8b27e086c09822cb8c4f2334f11fff0de2460c8
|
|
| MD5 |
5b245a6e5f90a60f41806d22482889da
|
|
| BLAKE2b-256 |
9710581073c5b8d06f27ea7304a07ecb773f8cb4b02199ec19b80ac2f4ec504e
|
Provenance
The following attestation bundles were made for opencode_runtime-0.4.0.tar.gz:
Publisher:
publish.yml on ashish16052/opencode-runtime
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
opencode_runtime-0.4.0.tar.gz -
Subject digest:
9dc37476e36c1ebc5c32c9dbc8b27e086c09822cb8c4f2334f11fff0de2460c8 - Sigstore transparency entry: 2104183544
- Sigstore integration time:
-
Permalink:
ashish16052/opencode-runtime@65ab39227eefe0bf9a30681dbf5e024cbbf7d26d -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ashish16052
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@65ab39227eefe0bf9a30681dbf5e024cbbf7d26d -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file opencode_runtime-0.4.0-py3-none-any.whl.
File metadata
- Download URL: opencode_runtime-0.4.0-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62250223011a2f6d0a82b21dd8d0c310ce8843fc772c22ac24819b48921a7a1c
|
|
| MD5 |
465ae1ea421333912c820d91c1e0c14f
|
|
| BLAKE2b-256 |
5f9d91ebccff4c64dfc695c107ba56d57ae67b42bd6f4849b98c00f1ffc7ccb3
|
Provenance
The following attestation bundles were made for opencode_runtime-0.4.0-py3-none-any.whl:
Publisher:
publish.yml on ashish16052/opencode-runtime
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
opencode_runtime-0.4.0-py3-none-any.whl -
Subject digest:
62250223011a2f6d0a82b21dd8d0c310ce8843fc772c22ac24819b48921a7a1c - Sigstore transparency entry: 2104183798
- Sigstore integration time:
-
Permalink:
ashish16052/opencode-runtime@65ab39227eefe0bf9a30681dbf5e024cbbf7d26d -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/ashish16052
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@65ab39227eefe0bf9a30681dbf5e024cbbf7d26d -
Trigger Event:
workflow_dispatch
-
Statement type: