@opensoftware/harness-opencode
v0.2.2
Published
harness-opencode: runs opencode behind the harness port through its own ACP server, asking before each edit and command, with a tool allowlist, cancel within 5 seconds and a run record with tokens.
Readme
covers: [adapters/harness/opencode/src/**]
harness-opencode
Runs opencode behind the factory's harness port. The client talks ACP to harness-opencode as to any agent; the
adapter starts opencode's own ACP server opencode acp behind the harness proxy. Every session asks before each edit
and command, a tool allowlist holds whatever the agent tries, a cancelled turn ends within 5 seconds, and each session
exports as a run record with the tokens opencode reported. Decision:
ADR 0053. The port's scenarios are in
ports/harness/features/.
Quick start
Point opencode at a model gateway and let the client approve reads and edits; every other tool call is refused without asking it:
OPENAI_BASE_URL=https://gateway.example.com/v1 OPENAI_API_KEY=<gateway key> OPENAI_MODEL=gpt-5.5 \
npx @opensoftware/harness-opencode run --allow read,editThe adapter now speaks ACP on stdin and stdout. After the session, export it:
npx @opensoftware/harness-opencode transcript <session ID>It writes $OUTPUT/run-record.json and $OUTPUT/transcript.jsonl.
How it behaves
- The harness proxy does what every harness adapter does: sessions and prompts pass through, a prompt sent while
a turn runs reaches opencode within the turn, tool calls of kinds outside
--alloware refused without asking the client, a cancelled turn that has not ended after 3 seconds is stopped, and each session is recorded (harness-proxy). - opencode asks first. The adapter's configuration lets reading, searching and the todo list run without asking,
asks before every other tool, such as each edit (kind
edit) and each command (kindexecute), and denies web fetch and web search.OPENCODE_DISABLE_PROJECT_CONFIGkeeps a folder'sopencode.jsonfrom asking less, and keeps its instructions from the model. - Its own settings. opencode keeps its settings, logins and sessions in
OSF_DATA/opencode, never in the user's home. It reads no rules from the user's home (~/.config/opencode/AGENTS.md,~/.claude/CLAUDE.md) and writes nothing there. It reads no Claude Code settings or skills, no skills in.agents/skills, loads no external plugins, and turns off auto update, the models.dev fetch, LSP downloads, sharing and the title call. - The model gateway. One provider
osfwith@ai-sdk/openai-compatiblecalls the chat completions API atOPENAI_BASE_URLwithOPENAI_API_KEYas its bearer token and the modelOPENAI_MODEL. WithoutOPENAI_MODEL,runis a usage error. - The run record has
osf.harness.nameopencode,osf.harness.versionopencode's version and the tokens of all turns ingen_ai.usage.*. opencode reports no cost over ACP. - Platforms. The adapter runs the binary of
opencode-<platform>-<arch>thatopencode-aiinstalls: Linux with glibc, macOS and Windows, on x64 and arm64.
Commands
| Command | What it does |
| --- | --- |
| harness-opencode run [--allow <kinds>] | Start opencode and run the adapter on stdio until opencode exits. |
| harness-opencode transcript <session ID> | Write the session's run record to $OUTPUT/run-record.json and its transcript to $OUTPUT/transcript.jsonl. |
Releases
release-please opens a release pull request from the Conventional Commits under adapters/harness/opencode/. Merging
it creates the tag harness-opencode-v<version>. The workflow .github/workflows/publish-harness-opencode.yml then
builds the package and publishes it to npm as @opensoftware/harness-opencode. The first release is 0.1.0; until
1.0.0, a breaking change raises the minor version. The one-time setup is the same as for contracts
(contracts/README.md). No credential is stored in the repository.
Configuration
| Variable | Type | Default | Meaning |
| --- | --- | --- | --- |
| OUTPUT | string | "." | Folder that transcript writes run-record.json and transcript.jsonl to. |
| OSF_DATA | string | ".harness-opencode" | Folder where run records every session as sessions/.jsonl and opencode keeps its settings, logins and sessions, in opencode/. |
| OTEL_RESOURCE_ATTRIBUTES | string | | Resource attributes of the run as key=value pairs, set by the launcher, for example osf.run.id=…,osf.work_item.id=…,osf.factory.version=…. run keeps them with each session; transcript writes them into the run record. |
| OTEL_SERVICE_NAME | string | | The service.name of the run record. Default: harness-opencode. |
| OPENAI_BASE_URL | string | "https://api.openai.com/v1" | Base URL of the OpenAI-compatible chat completions API that opencode calls, ending in /v1, for example the inference gateway. |
| OPENAI_API_KEY | string | | The key opencode sends to the model API, for example a gateway key or a placeholder that the egress proxy replaces. |
| OPENAI_MODEL | string | | The model opencode asks for, for example gpt-5.5. Required. |
| OSF_EFFORT | string | | The effort level of the session's model, set by the launcher (ADR 0078). The adapter sets it as the reasoningEffort option of the gateway's model. Default: none, the model's own default. |
Scenarios
The adapter passes every @conformance scenario of the harness port and its own scenarios in features/, against
the real opencode with the testkit's model gateway.
