From 4eb67cdd77c1b7725c621116300f91cbb535a721 Mon Sep 17 00:00:00 2001 From: Caian Ertl Date: Fri, 3 Jul 2026 20:17:43 -0300 Subject: [PATCH 1/3] ci(release): enable npm, crates.io, and pypi publishing for v0.1.0 Activate the previously stubbed publish steps in the three non-Go release trains, matching the configured credentials: crates.io via CARGO_REGISTRY_TOKEN, npm via NPM_TOKEN with provenance, and PyPI via Trusted Publishing (OIDC). The npm publish runs `napi pre-publish --skip-gh-release` to ship the per-platform packages, then `npm publish --ignore-scripts` for the main package; --ignore-scripts stops the prepublishOnly hook from re-running pre-publish with its default --gh-release in a token-less job. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/release-crate.yml | 21 +++++++-------------- .github/workflows/release-npm.yml | 21 +++++++++------------ .github/workflows/release-pypi.yml | 16 +++++++--------- 3 files changed, 23 insertions(+), 35 deletions(-) diff --git a/.github/workflows/release-crate.yml b/.github/workflows/release-crate.yml index 8c37a52..e615d19 100644 --- a/.github/workflows/release-crate.yml +++ b/.github/workflows/release-crate.yml @@ -1,8 +1,8 @@ # Publishes the `codexcw` core crate to crates.io. # -# Triggered by tags of the form `rust-v*` (e.g. `rust-v0.1.0`). The publish step -# is intentionally commented out until the first release is cut; the active -# `--dry-run` step verifies the crate packages cleanly. +# Triggered by tags of the form `rust-v*` (e.g. `rust-v0.1.0`). A `--dry-run` +# step verifies the crate packages cleanly, then it is published with +# CARGO_REGISTRY_TOKEN. name: Release (crate) on: @@ -31,14 +31,7 @@ jobs: - name: Verify packaging run: devbox run -- cargo publish -p codexcw --dry-run - # PLACEHOLDER — enable on the first release. - # Prefer crates.io Trusted Publishing (OIDC) via the official auth action; - # CARGO_REGISTRY_TOKEN is the fallback. - # - # - name: Authenticate (OIDC) - # uses: rust-lang/crates-io-auth-action@v1 - # id: auth - # - name: Publish - # run: devbox run -- cargo publish -p codexcw - # env: - # CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} + - name: Publish + run: devbox run -- cargo publish -p codexcw + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index 2fb7461..2636816 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -1,8 +1,8 @@ # Builds per-platform native addons and publishes @c3-oss/codexcw to npm. # -# Triggered by tags of the form `node-v*`. The publish step is commented out -# until the first release; the build matrix runs and uploads artifacts so the -# pipeline is exercised. +# Triggered by tags of the form `node-v*`. The build matrix produces the native +# addons; the publish job ships the per-platform packages and the main package +# with npm provenance (NPM_TOKEN). name: Release (npm) on: @@ -90,12 +90,9 @@ jobs: - name: Distribute artifacts into npm dirs run: npx napi artifacts --npm-dir npm --build-output-dir artifacts - # PLACEHOLDER — enable on the first release. Uses npm OIDC provenance; - # NPM_TOKEN is the fallback. - # - # - name: Publish - # run: | - # npx napi pre-publish -t npm --skip-gh-release - # npm publish --access public --provenance - # env: - # NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Publish + run: | + npx napi pre-publish -t npm --skip-gh-release + npm publish --access public --provenance --ignore-scripts + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release-pypi.yml b/.github/workflows/release-pypi.yml index 27eba9c..5966308 100644 --- a/.github/workflows/release-pypi.yml +++ b/.github/workflows/release-pypi.yml @@ -1,7 +1,8 @@ # Builds wheels and an sdist and publishes `codexcw` to PyPI. # -# Triggered by tags of the form `py-v*`. The publish step is commented out until -# the first release; the wheel/sdist matrix runs and uploads artifacts. +# Triggered by tags of the form `py-v*`. The wheel/sdist matrix builds the +# artifacts; the publish job ships them to PyPI via Trusted Publishing (OIDC), +# so no token is needed once the publisher is configured on PyPI. name: Release (PyPI) on: @@ -79,10 +80,7 @@ jobs: path: dist merge-multiple: true - # PLACEHOLDER — enable on the first release. Uses PyPI Trusted Publishing - # (OIDC); no token needed once the publisher is configured on PyPI. - # - # - name: Publish - # uses: pypa/gh-action-pypi-publish@release/v1 - # with: - # packages-dir: dist + - name: Publish + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist From 22c621541589f8f6ee1337b7dee0e437e0d0c076 Mon Sep 17 00:00:00 2001 From: Caian Ertl Date: Fri, 3 Jul 2026 20:17:52 -0300 Subject: [PATCH 2/3] docs(node): add npm package readme Give @c3-oss/codexcw a README so it renders on npmjs.com instead of a blank page, and include it in the published `files`. Co-Authored-By: Claude Opus 4.8 (1M context) --- bindings/node/README.md | 38 ++++++++++++++++++++++++++++++++++++++ bindings/node/package.json | 1 + 2 files changed, 39 insertions(+) create mode 100644 bindings/node/README.md diff --git a/bindings/node/README.md b/bindings/node/README.md new file mode 100644 index 0000000..2c5c09f --- /dev/null +++ b/bindings/node/README.md @@ -0,0 +1,38 @@ +# `@c3-oss/codexcw` + +Run the [Codex CLI](https://developers.openai.com/codex/cli) non-interactively +from Node.js — spawn `codex exec --json`, decode its JSONL event stream, and +consume runs as results, live event streams, or per-event callbacks. A native +addon backed by a Rust core (napi-rs), with prebuilt binaries for macOS, Linux +(gnu + musl), and Windows. + +## Install + +```bash +npm install @c3-oss/codexcw +``` + +The `codex` executable must be on `PATH`, authenticated, and new enough to +support `codex exec --json`. + +## Usage + +The API is async-only: every call returns a `Promise`, and event streams are +`AsyncIterable`s consumed with `for await`. + +```ts +import { Runner } from '@c3-oss/codexcw' + +const runner = new Runner() + +const result = await runner.run({ prompt: 'say hi' }) +console.log(result.finalMessage) +``` + +Full recipes — streaming, resume, sandbox/approval, batches, structured output, +and error handling — are in +[`docs/examples/typescript.md`](../../docs/examples/typescript.md). + +## License + +CC0-1.0 diff --git a/bindings/node/package.json b/bindings/node/package.json index a84e64b..609d7fd 100644 --- a/bindings/node/package.json +++ b/bindings/node/package.json @@ -21,6 +21,7 @@ } }, "files": [ + "README.md", "index.js", "index.mjs", "index.d.ts", From eee8eb59a13e117a59d958735a8e5dca74cb431b Mon Sep 17 00:00:00 2001 From: Caian Ertl Date: Fri, 3 Jul 2026 20:38:40 -0300 Subject: [PATCH 3/3] ci(runners): run all pipelines on blacksmith Move every workflow off GitHub-hosted runners onto Blacksmith (2vcpu Linux, 6vcpu macOS, 2vcpu Windows), mirroring the c3-oss/mcp-plane convention: matrix jobs keep `matrix.os` as the display/cache-key label and add a `matrix.runs-on` Blacksmith label. The quality job passes GITHUB_TOKEN to lychee to avoid anonymous GitHub rate limits. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 38 ++++++++++++++++++++--------- .github/workflows/release-crate.yml | 2 +- .github/workflows/release-go.yml | 2 +- .github/workflows/release-npm.yml | 18 +++++++------- .github/workflows/release-pypi.yml | 20 +++++++-------- 5 files changed, 48 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f501117..ed753e5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ permissions: jobs: quality: name: commit + docs + secrets - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 @@ -33,11 +33,15 @@ jobs: run: devbox run -- pnpm exec commitlint --config commitlint.config.cjs --from "$BASE_SHA" --to "$HEAD_SHA" - name: Run quality gates + env: + # Lychee falls back to anonymous GitHub requests without this, which + # are heavily rate-limited in CI. + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: devbox run -- just quality go-test: name: go / tidy + vet + test - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 @@ -70,7 +74,7 @@ jobs: go-lint: name: go / golangci-lint - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 @@ -84,7 +88,7 @@ jobs: go-security: name: go / gosec + govulncheck - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 @@ -100,11 +104,15 @@ jobs: go-build: name: go / build / ${{ matrix.os }} - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.runs-on }} strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + include: + - os: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 + - os: macos-latest + runs-on: blacksmith-6vcpu-macos-latest steps: - name: Checkout uses: actions/checkout@v7 @@ -127,7 +135,7 @@ jobs: rust: name: rust / fmt + clippy + test + audit - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 @@ -149,11 +157,15 @@ jobs: node: name: node / ${{ matrix.os }} - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.runs-on }} strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + include: + - os: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 + - os: macos-latest + runs-on: blacksmith-6vcpu-macos-latest steps: - name: Checkout uses: actions/checkout@v7 @@ -171,11 +183,15 @@ jobs: python: name: python / ${{ matrix.os }} - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.runs-on }} strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest] + include: + - os: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 + - os: macos-latest + runs-on: blacksmith-6vcpu-macos-latest steps: - name: Checkout uses: actions/checkout@v7 diff --git a/.github/workflows/release-crate.yml b/.github/workflows/release-crate.yml index e615d19..60ad543 100644 --- a/.github/workflows/release-crate.yml +++ b/.github/workflows/release-crate.yml @@ -17,7 +17,7 @@ permissions: jobs: publish: if: startsWith(github.ref, 'refs/tags/rust-v') - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index 8c5260d..8b9abcd 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -11,7 +11,7 @@ permissions: jobs: goreleaser: if: startsWith(github.ref, 'refs/tags/v') - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index 2636816..121558f 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -21,18 +21,18 @@ defaults: jobs: build: name: build / ${{ matrix.target }} - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.runs-on }} strategy: fail-fast: false matrix: include: - - { os: ubuntu-latest, target: x86_64-unknown-linux-gnu } - - { os: ubuntu-latest, target: aarch64-unknown-linux-gnu, cross: true } - - { os: ubuntu-latest, target: x86_64-unknown-linux-musl, cross: true } - - { os: ubuntu-latest, target: aarch64-unknown-linux-musl, cross: true } - - { os: macos-latest, target: x86_64-apple-darwin } - - { os: macos-latest, target: aarch64-apple-darwin } - - { os: windows-latest, target: x86_64-pc-windows-msvc } + - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: x86_64-unknown-linux-gnu } + - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: aarch64-unknown-linux-gnu, cross: true } + - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: x86_64-unknown-linux-musl, cross: true } + - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: aarch64-unknown-linux-musl, cross: true } + - { os: macos-latest, runs-on: blacksmith-6vcpu-macos-latest, target: x86_64-apple-darwin } + - { os: macos-latest, runs-on: blacksmith-6vcpu-macos-latest, target: aarch64-apple-darwin } + - { os: windows-latest, runs-on: blacksmith-2vcpu-windows-2025, target: x86_64-pc-windows-msvc } steps: - name: Checkout uses: actions/checkout@v7 @@ -68,7 +68,7 @@ jobs: name: publish needs: build if: startsWith(github.ref, 'refs/tags/node-v') - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 diff --git a/.github/workflows/release-pypi.yml b/.github/workflows/release-pypi.yml index 5966308..e9ac844 100644 --- a/.github/workflows/release-pypi.yml +++ b/.github/workflows/release-pypi.yml @@ -17,18 +17,18 @@ permissions: jobs: wheels: name: wheels / ${{ matrix.os }} / ${{ matrix.target }} - runs-on: ${{ matrix.os }} + runs-on: ${{ matrix.runs-on }} strategy: fail-fast: false matrix: include: - - { os: ubuntu-latest, target: x86_64, manylinux: auto } - - { os: ubuntu-latest, target: aarch64, manylinux: auto } - - { os: ubuntu-latest, target: x86_64, manylinux: musllinux_1_1 } - - { os: ubuntu-latest, target: aarch64, manylinux: musllinux_1_1 } - - { os: macos-latest, target: x86_64, manylinux: auto } - - { os: macos-latest, target: aarch64, manylinux: auto } - - { os: windows-latest, target: x64, manylinux: auto } + - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: x86_64, manylinux: auto } + - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: aarch64, manylinux: auto } + - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: x86_64, manylinux: musllinux_1_1 } + - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: aarch64, manylinux: musllinux_1_1 } + - { os: macos-latest, runs-on: blacksmith-6vcpu-macos-latest, target: x86_64, manylinux: auto } + - { os: macos-latest, runs-on: blacksmith-6vcpu-macos-latest, target: aarch64, manylinux: auto } + - { os: windows-latest, runs-on: blacksmith-2vcpu-windows-2025, target: x64, manylinux: auto } steps: - name: Checkout uses: actions/checkout@v7 @@ -50,7 +50,7 @@ jobs: sdist: name: sdist - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Checkout uses: actions/checkout@v7 @@ -72,7 +72,7 @@ jobs: name: publish needs: [wheels, sdist] if: startsWith(github.ref, 'refs/tags/py-v') - runs-on: ubuntu-latest + runs-on: blacksmith-2vcpu-ubuntu-2404 steps: - name: Download artifacts uses: actions/download-artifact@v8