OpenCode 2 publishes its CLI as @opencode/cli (opencode-ai stops at
1.19.x), so install that package and pin it to 2.0.32.
Also fix what the v2 migration invalidates:
- renovate.json: track @opencode/cli instead of opencode-ai, otherwise
the pin is never bumped.
- opencode-attach: `opencode attach` no longer exists in v2. Point the
client at the server with `--server <url>` instead (appended after a
subcommand when one is given); auth still comes from
OPENCODE_SERVER_PASSWORD / OPENCODE_PASSWORD.
- README/AGENTS: v2 package name, entrypoint, serve defaults, API
surface (/global/health is gone, everything lives under authenticated
/api/*), and removal of OPENCODE_SERVER_USERNAME (the username is
always `opencode` in v2).
The entrypoint stays ["opencode"] on purpose: existing deployments pass
`serve ...` at runtime, and OpenCode 2 is invoked the same way.
This repository builds and publishes a Docker image for [OpenCode](https://opencode.ai), the open source AI coding agent. The image runs OpenCode in headless server mode (`opencode serve`) and is automatically rebuilt and pushed to Docker Hub (`jcabillot/opencode`) every night by a Gitea Actions pipeline.
This repository builds and publishes a Docker image for [OpenCode](https://opencode.ai), the open source AI coding agent. The image ships OpenCode 2, runs it in headless server mode (`opencode serve`), and is automatically rebuilt and pushed to Docker Hub (`jcabillot/opencode`) every night by a Gitea Actions pipeline.
## Repository structure
@@ -17,18 +17,25 @@ This repository builds and publishes a Docker image for [OpenCode](https://openc
## Dependency management
- **Always pin versions** in the Dockerfile `npm install` command (e.g. `opencode-ai@1.16.2 n2-soul@9.0.9`). Never leave packages unpinned.
- **Always pin versions** in the Dockerfile `npm install` command (e.g. `@opencode/cli@2.0.32 n2-soul@9.0.9`). Never leave packages unpinned.
- **Update renovate customManagers** when adding, removing, or renaming a dependency tracked in the Dockerfile. Each pinned package must have a corresponding `customManager` entry in `renovate.json` with a regex `matchStrings` pattern that captures the version. If a dependency is added without a renovate entry, Renovatebot will not open automated PRs for it.
- **apt packages** (apt-get install lines in Dockerfile) and **COPY --from** image references are not currently tracked by Renovate. Pinning these manually is acceptable for now but adding renovate managers for them is encouraged.
- **Install**: `npm i -g opencode-ai@<version> n2-soul@<version>` — installs OpenCode and Soul globally, both pinned.
- **Base image**: `node:26-trixie` — Debian-based Node.js image (not Alpine) so that downstream images can still use `apt-get` and Node-based MCP servers keep working.
- **Install**: `npm i -g @opencode/cli@<version> n2-soul@<version>` — installs OpenCode 2 and Soul globally, both pinned.`@opencode/cli` replaced `opencode-ai` as the published package in OpenCode 2; `--allow-scripts=@opencode/cli` is required for its `postinstall` to select the native binary.
- **Version check**: `RUN opencode --version` after install to validate the build and record the installed version in build logs.
- **Dedicated user**: a non-root `opencode` user and group are created with `groupadd`/`useradd` (UID/GID 1000). All runtime steps run as this user.
- **Cluster tooling**: `kubectl` is copied from the official `registry.k8s.io/kubectl` image (multi-stage COPY).
- **Entrypoint**: `["opencode"]` — arguments are passed at runtime (e.g. `serve`).
- **Entrypoint**: `["opencode"]` — arguments are passed at runtime; `serve` starts the headless server. Bare `opencode` opens the TUI, so the server is always invoked explicitly.
## OpenCode 2 notes
- The npm package is `@opencode/cli` (bins `opencode` and `opencode2`); `opencode-ai` stops at 1.19.x and must not come back.
-`opencode attach` no longer exists: point a client at a server with `opencode --server <url>` (after the subcommand when one is given). `opencode-attach` wraps this.
- The server always authenticates: username is fixed to `opencode`, password comes from `OPENCODE_SERVER_PASSWORD` or `OPENCODE_PASSWORD`, and a random one is generated and logged when neither is set.
- The v1 REST API was replaced (`/global/health` is gone, every route now lives under `/api/*` and requires auth). Any client calling the v1 API — e.g. `perso/opencode-dispatch` — must be migrated separately.
## CI/CD conventions (Gitea Actions)
@@ -44,17 +51,17 @@ This repository builds and publishes a Docker image for [OpenCode](https://openc
docker build -t opencode .
# Run the server on all interfaces
docker run -it -p 4096:4096 opencode --hostname 0.0.0.0
docker run -it -p 4096:4096 opencode serve --hostname 0.0.0.0
@@ -4,7 +4,7 @@ Docker image for running [OpenCode](https://opencode.ai) as a headless HTTP serv
## What is OpenCode?
OpenCode is an open source AI coding agent available as a terminal interface, desktop app, or IDE extension. This image runs it in server mode (`opencode serve`), exposing an HTTP API that clients can connect to.
OpenCode is an open source AI coding agent available as a terminal interface, desktop app, or IDE extension. This image ships OpenCode 2 and runs it in server mode (`opencode serve`), exposing an HTTP API and web UI that clients can connect to.
## Pull
@@ -12,7 +12,7 @@ OpenCode is an open source AI coding agent available as a terminal interface, de
docker pull jcabillot/opencode
```
The image is rebuilt and pushed to Docker Hub automatically every night via the Jenkins pipeline.
The image is rebuilt and pushed to Docker Hub automatically every night by the Gitea Actions pipeline.
## Build locally
@@ -22,14 +22,16 @@ docker build -t opencode .
## Run
The entrypoint is the `opencode` binary; pass `serve` to start the headless server:
```bash
docker run -it -p 4096:4096 jcabillot/opencode
docker run -it -p 4096:4096 jcabillot/opencode serve
```
By default the server listens on `127.0.0.1:4096`. To expose it on all interfaces:
The server listens on `127.0.0.1:4096` by default. To expose it on all interfaces:
```bash
docker run -it -p 4096:4096 jcabillot/opencode --hostname 0.0.0.0
docker run -it -p 4096:4096 jcabillot/opencode serve --hostname 0.0.0.0
Authentication uses HTTP basic auth. The default username is `opencode`, override it with `OPENCODE_SERVER_USERNAME`.
Authentication uses HTTP basic auth. The username is always `opencode`; the password is read from `OPENCODE_SERVER_PASSWORD` (or `OPENCODE_PASSWORD`). When neither is set, OpenCode 2 generates a random password and prints it to the log at startup — the server is never left unauthenticated.
## Troubleshooting helper
The image includes an `opencode-attach` wrapper in `PATH` that runs:
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.