Release tooling is deliberately limited to Go, POSIX shell, GNU/BSD archive utilities, and the GitHub CLI already available on the GitHub Actions runner. There is no cloud deployment or package-manager automation.
From a clean checkout, run the full deterministic gate:
make release-check FUZZTIME=1s
make package-self-test VERSION=v0.1.0 OUTPUT_DIR=distrelease-check runs formatting, vet, unit/contract/integration tests, the race
suite, a trimmed build, bounded fuzz smoke, and git diff --check. The release
workflow additionally requires that formatting leaves the tagged checkout
unchanged.
package-self-test cross-compiles Linux amd64/arm64, macOS amd64/arm64, and
Windows amd64, then verifies every archive contains the correctly named
opencode-gateway and ocgtw binaries, LICENSE, and README.txt, and
verifies SHA256SUMS.
The repository installer is scripts/install.sh. It builds the current
checkout when Go is available; otherwise it can download a published Unix
archive and its SHA256SUMS manifest over HTTPS. It verifies the exact
checksum before extracting, rejects unexpected archive paths, stages both
binaries before replacement, and never requires root. A release must publish
the expected archive names and SHA256SUMS for the no-Go path to work:
./scripts/install.sh --release --version v0.1.0 --prefix "$HOME/.local"For a local artifact, pass both files explicitly when they are not siblings:
./scripts/install.sh \
--archive /path/to/opencode-gateway_v0.1.0_linux_amd64.tar.gz \
--checksums /path/to/SHA256SUMS \
--prefix "$HOME/.local"The installer has no checksum bypass option. Its Bash release path supports Linux and macOS amd64/arm64; Windows users should download and verify the zip archive manually.
After a successful install, a manifest (.opencode-gateway.manifest next to
the binaries) records the installed version and the SHA-256 hash of each
binary. A re-install refuses to overwrite files that no longer match the
manifest — for example binaries modified after install — unless --force is
used; an uninstall needs the same --force before it deletes modified files.
To update an existing install, use the matching updater:
make update
# or, with the same defaults: ./scripts/update.shLike install, update defaults to the latest published release, or a rebuild
from the checkout when Go is available. It requires the install manifest and
the unmodified binaries recorded there (override with --force), refuses to
downgrade unless --force is given, and is a no-op when the requested version
is already installed:
./scripts/update.sh --version v0.2.0 --dry-run
./scripts/update.sh --version v0.2.0The actual replacement is delegated to scripts/install.sh, so every update
passes the same checksum verification, staging, and manifest rewrite as a
fresh install.
The package script uses the tagged commit time as its default
SOURCE_DATE_EPOCH. To reproduce an artifact exactly, provide the same
version, commit, build date, source epoch, Go toolchain, and source tree:
SOURCE_DATE_EPOCH=1762473600 \
make package-self-test \
VERSION=v0.1.0 \
COMMIT=0123456789ab \
OUTPUT_DIR=/tmp/opencode-gateway-distArchives are named opencode-gateway_VERSION_GOOS_GOARCH.tar.gz; Windows uses
.zip and contains opencode-gateway.exe and ocgtw.exe. Each archive has
one predictable top-level directory and includes only the two binaries, MIT
LICENSE, and minimal README.txt. SHA256SUMS covers the archives only.
This procedure uses an isolated Codex home and a fixed local port. The
credential store is separate from the Codex home and is never included in
release artifacts. The doctor command performs a network /models check only
when a credential is present, so use an isolated environment variable or
ocgtw config status and do not paste the credential into logs.
set -eu
make build
./bin/opencode-gateway version
./bin/opencode-gateway help
rc_dir="$(mktemp -d)"
codex_home="$rc_dir/codex-home"
dist_dir="$rc_dir/dist"
mkdir -p "$codex_home"
./bin/opencode-gateway setup codex --codex-home "$codex_home"
./bin/opencode-gateway setup codex --codex-home "$codex_home" --dry-run
export OPENCODE_GO_API_KEY="${OPENCODE_GO_API_KEY:?set this only in the process environment}"
export OPENCODE_GATEWAY_PORT=18787
./bin/opencode-gateway run >"$rc_dir/gateway.log" 2>&1 &
gateway_pid=$!
trap 'kill "$gateway_pid" 2>/dev/null || true; rm -rf "$rc_dir"' EXIT
curl --fail --silent http://127.0.0.1:18787/health/live
curl --fail --silent http://127.0.0.1:18787/health/ready
./bin/opencode-gateway doctor --codex-home "$codex_home"
SOURCE_DATE_EPOCH="$(git show -s --format=%ct HEAD)" \
make package-self-test VERSION=v0.1.0 COMMIT="$(git rev-parse --short HEAD)" OUTPUT_DIR="$dist_dir"
(cd "$dist_dir" && sha256sum -c SHA256SUMS)On macOS, use shasum -a 256 when sha256sum is unavailable. On Windows,
perform the same isolated setup and health checks with PowerShell and verify
the published checksum using Get-FileHash -Algorithm SHA256. Record the
actual OS/architecture and Codex version; the repository baseline is Codex
CLI 0.146.0 on Go 1.22+.
The RC gate must also confirm that doctor returns exit status 0 for a
healthy configured gateway and a non-zero status when the key, catalog, Codex
config, or gateway is missing. It must confirm that version and help write
safe output and that logs contain neither the key nor request content.
Paid inference is never part of CI, the release workflow, or
make release-check. The existing opt-in text smoke is:
RUN_LIVE_SMOKE=1 ./scripts/live-smoke.shThe required issue #13 live-validation suite is:
RUN_LIVE_SCENARIOS=1 OPENCODE_GO_API_KEY='your-key' \
./scripts/live-scenarios.sh --allIt makes one isolated paid request per selected scenario: text, temporary
repository inspection, a harmless shell command, one standard function/tool
turn, apply_patch editing, a parallel-tool attempt, and cancellation of a
long-running request. The full suite can therefore incur seven billable
requests plus provider-side tool/continuation usage. Select scenario names to
limit cost. The suite requires a built binary, Codex CLI, network access, and
explicit operator authorization; ./scripts/live-scenarios.sh --validate --all
and make live-scenarios-test are credential-free checks.
The suite creates an owner-only temporary Codex home and Git repository, starts the gateway on an ephemeral loopback port, keeps the key only in the gateway child environment, and unsets it for Codex. It never uses the project worktree or executes arbitrary incoming tool text. It retains only structural JSONL and safe diagnostics on failure, cleans up on success, and fails clearly when the live model/provider does not produce a required scenario. It is not a CI or release gate. Record the exact Codex version, OS, architecture, selected scenarios, and actual result before treating the paid gate as complete.
Do not publish from a dirty tree. After the RC procedure, create and push a
vX.Y.Z tag according to the repository's Git policy. The tag workflow runs
make release-check, calls scripts/package-release.sh --self-test, and uses
gh release create to attach archives and SHA256SUMS. It uses the matching
docs/releases/vX.Y.Z.md file when present. Do not create a release manually
before the workflow completes.
After publication, download at least one Unix archive and the Windows archive,
verify their checksums, run opencode-gateway version, and retain the release
asset names and tested Codex/OS versions in the release record.
For a Codex configuration change, use the backup path printed by setup:
./bin/opencode-gateway setup codex --codex-home "$codex_home" --restore \
"/absolute/path/to/backup-opencode-gateway-..."To uninstall the binaries, use the matching uninstaller:
make uninstall
# or, with the same defaults: ./scripts/uninstall.shThe uninstaller removes exactly the files recorded in the install manifest,
after verifying each file still matches its recorded hash; a file modified
since install is left in place unless --force is given. Without a manifest
it refuses to guess what to remove and exits with an error. --dry-run lists
the removals without changing anything. The uninstaller never needs Go.
./scripts/uninstall.sh --install-dir "$HOME/.local/bin" --dry-run
./scripts/uninstall.sh --force # remove modified files, or canonical names without a manifestCodex configuration is left untouched by the uninstaller. To also roll back
the Codex setup, pass the Codex home: the latest
backup-opencode-gateway-* directory there is restored through the installed
binary before the binaries are removed.
./scripts/uninstall.sh --codex-home "$HOME/.codex"Without --codex-home, remove the managed opencode-gateway-go and
opencode-gateway-zen providers, the two session profiles, and the catalog
from the Codex home only after taking a backup, or use the setup backup to
restore the exact pre-setup files. The gateway does not install a service or
write outside the selected Codex home and release directory.