Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions .github/workflows/release-cua-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: Release CUA CLI

on:
push:
tags:
- "cua-cli/v*"

permissions:
contents: read
id-token: write

concurrency:
group: release-cua-cli-${{ github.ref_name }}
cancel-in-progress: false

jobs:
publish:
runs-on: ubuntu-latest
timeout-minutes: 30
env:
PTYWRIGHT_ZIG_VERSION: "0.15.2"
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0

- name: Verify tag is on main
run: |
git fetch origin main:refs/remotes/origin/main
git merge-base --is-ancestor "$GITHUB_SHA" origin/main

- uses: actions/setup-node@v5
with:
node-version: 24
registry-url: https://registry.npmjs.org

- name: Ensure npm supports trusted publishing
run: npm install -g npm@^11.5.1

- run: npm ci

- name: Verify package version matches tag
run: |
node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";

const tag = process.env.GITHUB_REF_NAME;
const prefix = "cua-cli/v";
if (!tag?.startsWith(prefix)) {
throw new Error(`Expected tag to start with ${prefix}, got ${tag}`);
}

const tagVersion = tag.slice(prefix.length);
const pkg = JSON.parse(readFileSync("packages/cli/package.json", "utf8"));
if (pkg.version !== tagVersion) {
throw new Error(`Tag version ${tagVersion} does not match ${pkg.name} package.json version ${pkg.version}`);
}

console.log(`${pkg.name}@${pkg.version}`);
EOF

- name: Cache Zig toolchain
uses: actions/cache@v4
with:
path: .dev/tools/zig-x86_64-linux-${{ env.PTYWRIGHT_ZIG_VERSION }}
key: zig-${{ runner.os }}-${{ env.PTYWRIGHT_ZIG_VERSION }}

- name: Install Zig ${{ env.PTYWRIGHT_ZIG_VERSION }}
run: |
set -euo pipefail
ZIG_DIR=".dev/tools/zig-x86_64-linux-${PTYWRIGHT_ZIG_VERSION}"
if [ ! -x "${ZIG_DIR}/zig" ]; then
mkdir -p .dev/tools
curl -fsSL "https://ziglang.org/download/${PTYWRIGHT_ZIG_VERSION}/zig-x86_64-linux-${PTYWRIGHT_ZIG_VERSION}.tar.xz" \
| tar -xJ -C .dev/tools
fi
"${ZIG_DIR}/zig" version
echo "${GITHUB_WORKSPACE}/${ZIG_DIR}" >> "${GITHUB_PATH}"

- name: Cache ptywright native artifacts
uses: actions/cache@v4
with:
path: |
packages/ptywright/.cache
packages/ptywright/native/build
key: ptywright-${{ runner.os }}-${{ hashFiles('packages/ptywright/GHOSTTY_UPSTREAM', 'packages/ptywright/native/**', 'packages/ptywright/scripts/**') }}

- run: npm run build --workspace @onkernel/cua-ai
- run: npm run build --workspace @onkernel/cua-agent

- name: Build ptywright (native binding)
run: npm run build --workspace @onkernel/ptywright

- name: Build cua-cli
run: npm run build --workspace @onkernel/cua-cli

- name: Verify runtime dependencies are published
run: |
node -p 'require("./packages/cli/package.json").dependencies["@onkernel/cua-ai"]' \
| xargs -I{} npm view @onkernel/cua-ai@{} version
node -p 'require("./packages/cli/package.json").dependencies["@onkernel/cua-agent"]' \
| xargs -I{} npm view @onkernel/cua-agent@{} version

- name: CLI unit tests
env:
PTYWRIGHT_REQUIRED: "1"
run: npm test --workspace @onkernel/cua-cli

- name: Pack tarball
run: npm pack --workspace @onkernel/cua-cli --pack-destination "$RUNNER_TEMP"

- name: CLI bin smoke test
run: |
SMOKE_DIR=$(mktemp -d)
cd "$SMOKE_DIR"
npm init -y > /dev/null
npm install "$RUNNER_TEMP"/onkernel-cua-cli-*.tgz
OUTPUT=$(./node_modules/.bin/cua --help)
echo "$OUTPUT"
echo "$OUTPUT" | grep -q "Usage:"
echo "$OUTPUT" | grep -q "cua \[options\] \[prompt\.\.\.\]"

- name: Publish to npm
run: npm publish --workspace @onkernel/cua-cli --access public
70 changes: 69 additions & 1 deletion docs/npm-releases.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# npm releases

`@onkernel/cua-ai` and `@onkernel/cua-agent` publish from package-specific tags:
`@onkernel/cua-ai`, `@onkernel/cua-agent`, and `@onkernel/cua-cli` publish from
package-specific tags:

- `cua-ai/v0.1.0` runs `.github/workflows/release-cua-ai.yml`
- `cua-agent/v0.1.0` runs `.github/workflows/release-cua-agent.yml`
- `cua-cli/v0.1.0` runs `.github/workflows/release-cua-cli.yml`

The tag version must match the target package's `package.json` version, and the
tagged commit must be contained in `main`.
Expand All @@ -16,13 +18,15 @@ Configure each package on npm with a GitHub Actions trusted publisher:
| --- | --- | --- | --- | --- |
| `@onkernel/cua-ai` | `kernel` | `cua` | `release-cua-ai.yml` | leave blank |
| `@onkernel/cua-agent` | `kernel` | `cua` | `release-cua-agent.yml` | leave blank |
| `@onkernel/cua-cli` | `kernel` | `cua` | `release-cua-cli.yml` | leave blank |

The same configuration can be created from the npm CLI:

```sh
npm install -g npm@^11.10.0
npm trust github @onkernel/cua-ai --repo kernel/cua --file release-cua-ai.yml
npm trust github @onkernel/cua-agent --repo kernel/cua --file release-cua-agent.yml
npm trust github @onkernel/cua-cli --repo kernel/cua --file release-cua-cli.yml
```

npm requires packages to exist before a trusted publisher can be configured. If
Expand All @@ -47,3 +51,67 @@ After `@onkernel/cua-ai@0.1.0` is available on npm:
git tag cua-agent/v0.1.0
git push origin cua-agent/v0.1.0
```

## Releasing `@onkernel/cua-cli` 0.1.0

`@onkernel/cua-cli` has not been published yet. npm requires a package to exist
before a trusted publisher can be configured for it, so the first release is a
manual publish from a local checkout. Subsequent releases come from
`cua-cli/v*` tags via `.github/workflows/release-cua-cli.yml`.

The CLI's runtime dependencies, including `@onkernel/cua-ai`,
`@onkernel/cua-agent`, `@onkernel/sdk`, `@earendil-works/pi-coding-agent`,
and `@earendil-works/pi-tui`, must already be on npm at the pinned versions
before publishing; verify with `npm view @onkernel/cua-ai@<version>` etc. if
unsure.

First-publish steps (run from a maintainer machine with an npm account in the
`onkernel` org and Zig available on `PATH` for the ptywright dev build):

```sh
# 1. Fresh checkout of main
git clone https://github.com/kernel/cua.git
cd cua
git checkout main
git pull --ff-only

# 2. Install and build the workspace (Node >= 22.19)
npm ci
npm run build

# 3. Run cua-cli unit tests with the native ptywright binding required
PTYWRIGHT_REQUIRED=1 npm test --workspace @onkernel/cua-cli

# 4. Pre-publish smoke test: pack the tarball, install it into a fresh temp
# project, and run the installed `cua` bin. Do NOT proceed to step 5 until
# this passes — published npm versions are immutable, and the tag-driven
# workflow runs this same check on subsequent releases.
PACK_DIR=$(mktemp -d)
npm pack --workspace @onkernel/cua-cli --pack-destination "$PACK_DIR"
SMOKE_DIR=$(mktemp -d)
(cd "$SMOKE_DIR" && npm init -y > /dev/null && \
npm install "$PACK_DIR"/onkernel-cua-cli-*.tgz && \
./node_modules/.bin/cua --help)

# 5. Log in to npm as a user in the onkernel org, then publish
npm login
npm publish --workspace @onkernel/cua-cli --access public
```

After `@onkernel/cua-cli@0.1.0` is on the registry, configure the trusted
publisher — either via the package page in the npm web UI (Settings →
Publishing access → Add trusted publisher) using the row from the
[trusted publishing setup](#trusted-publishing-setup) table, or from the CLI:

```sh
npm install -g npm@^11.10.0
npm trust github @onkernel/cua-cli --repo kernel/cua --file release-cua-cli.yml
```

From `0.1.1` onward, bump `packages/cli/package.json` on `main`, then tag and
push:

```sh
git tag cua-cli/v0.1.1
git push origin cua-cli/v0.1.1
```
4 changes: 4 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,32 @@
"name": "@onkernel/cua-cli",
"version": "0.1.0",
"description": "Kernel-cloud-browser computer-use TUI built on @onkernel/cua-agent and pi-tui",
"license": "MIT",
"type": "module",
"main": "./dist/cli.js",
"types": "./dist/cli.d.ts",
"repository": {
"type": "git",
"url": "git+https://github.com/kernel/cua.git",
"directory": "packages/cli"
},
"bugs": {
"url": "https://github.com/kernel/cua/issues"
},
"homepage": "https://github.com/kernel/cua/tree/main/packages/cli#readme",
"bin": {
"cua": "./dist/cli.js"
},
"files": [
"dist",
"README.md"
],
"publishConfig": {
"access": "public"
},
"engines": {
"node": ">=22.19.0"
},
"scripts": {
"build": "tsc -b && chmod +x dist/cli.js",
"clean": "tsc -b --clean",
Expand Down
Loading