From 027ac21f5ac28724464951179bc2f49c10bee673 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Tue, 11 Aug 2026 10:48:56 +1000 Subject: [PATCH 1/5] feat(desktop): publish v2 beta builds --- .github/workflows/beta.yml | 29 +++++++--- .github/workflows/nix-hashes.yml | 2 +- .github/workflows/publish.yml | 27 +++++++--- .../src/commands/handlers/service/start.ts | 2 +- .../desktop/electron-builder.config.test.ts | 40 +++++++------- packages/desktop/electron-builder.config.ts | 2 +- packages/desktop/scripts/prebuild.ts | 3 +- packages/desktop/scripts/utils.ts | 25 ++++++++- packages/desktop/src/main/background-cli.ts | 1 + script/beta.ts | 54 +++++++------------ script/publish.ts | 38 ++++++------- 11 files changed, 129 insertions(+), 94 deletions(-) diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index e93d5fbdb260..a2bee99b178e 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -5,6 +5,8 @@ on: schedule: - cron: "0 * * * *" +concurrency: beta-sync + jobs: sync: runs-on: blacksmith-4vcpu-ubuntu-2404 @@ -16,22 +18,33 @@ jobs: uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 + ref: v2 - name: Setup Bun uses: ./.github/actions/setup-bun - - name: Setup Git Committer - id: setup-git-committer - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} + - name: Configure git user + run: | + git config --global user.name "github-actions[bot]" + git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" - name: Install OpenCode run: bun i -g opencode-ai - name: Sync beta branch + id: sync env: - GH_TOKEN: ${{ steps.setup-git-committer.outputs.token }} + GH_TOKEN: ${{ github.token }} OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - run: bun script/beta.ts + run: bun script/beta.ts --prepare + + - name: Setup Git Committer + if: steps.sync.outputs.changed == 'true' + uses: ./.github/actions/setup-git-committer + with: + opencode-app-id: ${{ vars.OPENCODE_APP_ID }} + opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} + + - name: Push beta branch + if: steps.sync.outputs.changed == 'true' + run: git push origin beta --force --no-verify diff --git a/.github/workflows/nix-hashes.yml b/.github/workflows/nix-hashes.yml index ce1d9237fde5..7932f10cddb5 100644 --- a/.github/workflows/nix-hashes.yml +++ b/.github/workflows/nix-hashes.yml @@ -6,7 +6,7 @@ permissions: on: workflow_dispatch: push: - branches: [dev, beta] + branches: [dev] paths: - "bun.lock" - "package.json" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f18b7929594f..ed67261bfea1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -91,7 +91,7 @@ jobs: opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - name: Build legacy CLI - if: github.ref_name != 'v2' + if: github.ref_name != 'v2' && github.ref_name != 'beta' run: ./packages/opencode/script/build.ts ${{ (github.ref_name == 'beta' && '--sourcemaps') || '' }} env: OPENCODE_VERSION: ${{ needs.version.outputs.version }} @@ -109,7 +109,7 @@ jobs: GH_TOKEN: ${{ steps.committer.outputs.token }} - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: github.ref_name != 'v2' + if: github.ref_name != 'v2' && github.ref_name != 'beta' with: name: opencode-cli path: | @@ -117,7 +117,7 @@ jobs: packages/opencode/dist/opencode-linux* - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: github.ref_name != 'v2' + if: github.ref_name != 'v2' && github.ref_name != 'beta' with: name: opencode-cli-windows path: packages/opencode/dist/opencode-windows* @@ -132,7 +132,7 @@ jobs: build-node-cli: needs: version - if: github.repository == 'anomalyco/opencode' + if: github.repository == 'anomalyco/opencode' && github.ref_name != 'beta' strategy: fail-fast: false matrix: @@ -184,7 +184,7 @@ jobs: - build-cli - version runs-on: blacksmith-4vcpu-windows-2025 - if: github.repository == 'anomalyco/opencode' && github.ref_name != 'v2' + if: github.repository == 'anomalyco/opencode' && github.ref_name != 'v2' && github.ref_name != 'beta' env: AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} @@ -282,6 +282,7 @@ jobs: build-electron: needs: - version + - build-cli if: github.repository == 'anomalyco/opencode' && github.ref_name != 'v2' continue-on-error: false env: @@ -335,6 +336,12 @@ jobs: with: install-flags: ${{ matrix.settings.bun_install_flags }} + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + if: github.ref_name == 'beta' + with: + name: opencode-preview-cli + path: packages/cli/dist + - name: Azure login if: runner.os == 'Windows' uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 @@ -393,6 +400,7 @@ jobs: VITE_SENTRY_DSN: ${{ vars.WEB_SENTRY_DSN }} VITE_SENTRY_ENVIRONMENT: ${{ (github.ref_name == 'beta' && 'beta') || 'production' }} VITE_SENTRY_RELEASE: desktop@${{ needs.version.outputs.version }} + RUST_TARGET: ${{ matrix.settings.target }} - name: Package if: needs.version.outputs.release @@ -496,29 +504,31 @@ jobs: registry-url: "https://registry.npmjs.org" - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - if: github.ref_name != 'v2' + if: github.ref_name != 'v2' && github.ref_name != 'beta' with: name: opencode-cli path: packages/opencode/dist - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - if: github.ref_name != 'v2' + if: github.ref_name != 'v2' && github.ref_name != 'beta' with: name: opencode-cli-windows path: packages/opencode/dist - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - if: github.ref_name != 'v2' + if: github.ref_name != 'v2' && github.ref_name != 'beta' with: name: opencode-cli-signed-windows path: packages/opencode/dist - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + if: github.ref_name != 'beta' with: name: opencode-preview-cli path: packages/cli/dist - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + if: github.ref_name != 'beta' with: pattern: opencode-node-cli-* path: packages/cli/dist/node @@ -587,3 +597,4 @@ jobs: LATEST_YML_DIR: /tmp/latest-yml TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} + OPENCODE_DESKTOP_ONLY: ${{ github.ref_name == 'beta' }} diff --git a/packages/cli/src/commands/handlers/service/start.ts b/packages/cli/src/commands/handlers/service/start.ts index dfdbac3997a8..42cef9bf341c 100644 --- a/packages/cli/src/commands/handlers/service/start.ts +++ b/packages/cli/src/commands/handlers/service/start.ts @@ -8,7 +8,7 @@ import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.start, Effect.fn("cli.service.start")(function* () { - const transport = yield* Service.ensure(yield* ServiceConfig.options()) + const transport = yield* Service.ensure(yield* ServiceConfig.options({ checkVersion: true })) process.stdout.write(transport.url + EOL) }), ) diff --git a/packages/desktop/electron-builder.config.test.ts b/packages/desktop/electron-builder.config.test.ts index 3fb1adb6c175..d143117f045f 100644 --- a/packages/desktop/electron-builder.config.test.ts +++ b/packages/desktop/electron-builder.config.test.ts @@ -57,35 +57,35 @@ test("keeps a hidden prod launcher for old Linux pins", async () => { expect(desktop).toContain("NoDisplay=true") }) -test("bundles the CLI outside the dev app archive", async () => { - const previous = process.env.OPENCODE_CHANNEL - process.env.OPENCODE_CHANNEL = "dev" - const module = await import("./electron-builder.config.ts?cli-resource") - const config = module.default as Configuration - if (previous === undefined) delete process.env.OPENCODE_CHANNEL - else process.env.OPENCODE_CHANNEL = previous - - expect(config.files).toContain("!resources/opencode-cli*") - expect(config.extraResources).toContainEqual({ - from: "resources/", - to: "", - filter: ["opencode-cli*"], - }) -}) - -for (const channel of ["beta", "prod"] as const) { - test(`does not bundle the CLI in ${channel} builds`, async () => { +for (const channel of ["dev", "beta"] as const) { + test(`bundles the CLI outside the ${channel} app archive`, async () => { const previous = process.env.OPENCODE_CHANNEL process.env.OPENCODE_CHANNEL = channel - const module = await import(`./electron-builder.config.ts?no-cli-resource=${channel}`) + const module = await import(`./electron-builder.config.ts?cli-resource=${channel}`) const config = module.default as Configuration if (previous === undefined) delete process.env.OPENCODE_CHANNEL else process.env.OPENCODE_CHANNEL = previous - expect(config.extraResources).not.toContainEqual({ + expect(config.files).toContain("!resources/opencode-cli*") + expect(config.extraResources).toContainEqual({ from: "resources/", to: "", filter: ["opencode-cli*"], }) }) } + +test("does not bundle the CLI in prod builds", async () => { + const previous = process.env.OPENCODE_CHANNEL + process.env.OPENCODE_CHANNEL = "prod" + const module = await import("./electron-builder.config.ts?no-cli-resource=prod") + const config = module.default as Configuration + if (previous === undefined) delete process.env.OPENCODE_CHANNEL + else process.env.OPENCODE_CHANNEL = previous + + expect(config.extraResources).not.toContainEqual({ + from: "resources/", + to: "", + filter: ["opencode-cli*"], + }) +}) diff --git a/packages/desktop/electron-builder.config.ts b/packages/desktop/electron-builder.config.ts index 508c0df5e914..e4cf6f423ca4 100644 --- a/packages/desktop/electron-builder.config.ts +++ b/packages/desktop/electron-builder.config.ts @@ -57,7 +57,7 @@ const getBase = (appId: string): Configuration => ({ }, files: ["out/**/*", "resources/**/*", "!resources/opencode-cli*"], extraResources: [ - ...(channel === "dev" + ...(channel !== "prod" ? [ { from: "resources/", diff --git a/packages/desktop/scripts/prebuild.ts b/packages/desktop/scripts/prebuild.ts index 8d1041180ab5..5d5714db5272 100644 --- a/packages/desktop/scripts/prebuild.ts +++ b/packages/desktop/scripts/prebuild.ts @@ -1,10 +1,11 @@ #!/usr/bin/env bun import { $ } from "bun" -import { downloadCliToResources, resolveChannel } from "./utils" +import { copyBuiltCliToResources, downloadCliToResources, resolveChannel } from "./utils" const channel = resolveChannel() await $`bun ./scripts/copy-icons.ts ${channel}` await $`bun ./scripts/copy-metainfo.ts ${channel}` if (channel === "dev") await downloadCliToResources() +if (channel === "beta") await copyBuiltCliToResources() diff --git a/packages/desktop/scripts/utils.ts b/packages/desktop/scripts/utils.ts index e5f87491e15b..ef9b85644422 100644 --- a/packages/desktop/scripts/utils.ts +++ b/packages/desktop/scripts/utils.ts @@ -82,13 +82,34 @@ export async function downloadCliToResources() { } finally { await rm(directory, { recursive: true, force: true }) } + await prepareCli(dest) + + console.log(`Copied ${cli.package} to ${dest}`) +} + +export async function copyBuiltCliToResources() { + const cli = getCurrentCli() + const dest = windowsify("resources/opencode-cli") + await copyFile( + join( + "../cli/dist", + cli.package.replace("@opencode-ai/", ""), + "bin", + cli.os === "win32" ? "opencode2.exe" : "opencode2", + ), + dest, + ) + await prepareCli(dest) + + console.log(`Copied the same-run ${cli.package} build to ${dest}`) +} + +async function prepareCli(dest: string) { if (process.platform !== "win32") await chmod(dest, 0o755) if (process.platform === "win32" && process.env.GITHUB_ACTIONS === "true") { await $`pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File ../../script/sign-windows.ps1 ${dest}` } if (process.platform === "darwin") await $`codesign --force --sign - ${dest}` - - console.log(`Copied ${cli.package} to ${dest}`) } export function windowsify(path: string) { diff --git a/packages/desktop/src/main/background-cli.ts b/packages/desktop/src/main/background-cli.ts index 66602d51f116..04a34a4d6561 100644 --- a/packages/desktop/src/main/background-cli.ts +++ b/packages/desktop/src/main/background-cli.ts @@ -85,6 +85,7 @@ async function run( ) { logger.log("v2 CLI command started", { binary, args }) const env = { ...process.env } + env.OPENCODE_DISABLE_AUTOUPDATE = "1" if (options.stateHome === undefined) delete env.XDG_STATE_HOME else env.XDG_STATE_HOME = options.stateHome return execFileAsync(binary, args, { env, windowsHide: true }).then( diff --git a/script/beta.ts b/script/beta.ts index d738c36ff017..4c65cdffa604 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -4,6 +4,7 @@ import { $ } from "bun" import fs from "fs/promises" const model = "opencode/gpt-5.3-codex" +const prepare = process.argv.includes("--prepare") interface PR { number: number @@ -86,7 +87,7 @@ async function build() { console.log(" Running final build smoke check...") try { - await $`./script/build.ts --single`.cwd("packages/opencode") + await $`./script/build.ts --single`.cwd("packages/cli") return true } catch (err) { console.log(`Build failed: ${err}`) @@ -200,7 +201,7 @@ async function smoke(prs: PR[], applied: number[]) { "The beta merge batch is complete, but the deterministic final smoke check failed.", `Merged PRs on HEAD:\n${done}`, "Run `bun typecheck` at the repo root.", - "Run `./script/build.ts --single` in `packages/opencode`.", + "Run `./script/build.ts --single` in `packages/cli`.", "Fix any merge-caused issues until both commands pass.", "Do not create a commit.", ].join("\n") @@ -220,21 +221,16 @@ async function main() { console.log("Fetching open PRs with beta label...") const stdout = - await $`gh pr list --state open --draft=false --label beta --json number,title,author,labels --limit 100`.text() + await $`gh pr list --state open --draft=false --base v2 --label beta --json number,title,author,labels --limit 100`.text() const prs: PR[] = JSON.parse(stdout).sort((a: PR, b: PR) => a.number - b.number) console.log(`Found ${prs.length} open PRs with beta label`) - if (prs.length === 0) { - console.log("No team PRs to merge") - return - } - - console.log("Fetching latest dev branch...") - await $`git fetch origin dev` + console.log("Fetching latest v2 branch...") + await $`git fetch origin v2` console.log("Checking out beta branch...") - await $`git checkout -B beta origin/dev` + await $`git checkout -B beta origin/v2` const applied: number[] = [] const failed: FailedPR[] = [] @@ -262,7 +258,7 @@ async function main() { if (!(await fix(pr, files, prs, applied, idx))) { await cleanup() failed.push({ number: pr.number, title: pr.title, reason: "Merge conflicts" }) - await commentOnPR(pr.number, "Merge conflicts with dev branch") + await commentOnPR(pr.number, "Merge conflicts with v2 branch") continue } } else { @@ -318,33 +314,18 @@ async function main() { await $`git fetch origin beta` const localTree = (await $`git rev-parse beta^{tree}`.text()).trim() - const remoteTrees = (await $`git log origin/dev..origin/beta --format=%T`.text()).split("\n") - - const matchIdx = remoteTrees.indexOf(localTree) - if (matchIdx !== -1) { - if (matchIdx !== 0) { - console.log(`Beta branch contains this sync, but additional commits exist after it. Leaving beta branch as is.`) - } else { - console.log("Beta branch has identical contents, no push needed") - } + const remoteTree = (await $`git rev-parse origin/beta^{tree}`.text()).trim() + if (localTree === remoteTree) { + console.log("Beta branch has identical contents, no push needed") + await outputChanged(false) return } if (!(await smoke(prs, applied))) throw new Error("Final smoke check failed") - await $`git fetch origin beta` - - const validatedTree = (await $`git rev-parse beta^{tree}`.text()).trim() - const remoteTreesAfterSmoke = (await $`git log origin/dev..origin/beta --format=%T`.text()).split("\n") - const matchIdxAfterSmoke = remoteTreesAfterSmoke.indexOf(validatedTree) - if (matchIdxAfterSmoke !== -1) { - if (matchIdxAfterSmoke !== 0) { - console.log( - `Beta branch contains this validated sync, but additional commits exist after it. Leaving beta branch as is.`, - ) - } else { - console.log("Validated beta branch now matches remote contents, no push needed") - } + if (prepare) { + await outputChanged(true) + console.log("Validated beta branch is ready to push") return } @@ -354,6 +335,11 @@ async function main() { console.log("Successfully synced beta branch") } +async function outputChanged(changed: boolean) { + if (!process.env.GITHUB_OUTPUT) return + await fs.appendFile(process.env.GITHUB_OUTPUT, `changed=${changed}\n`) +} + main().catch((err) => { console.error("Error:", err) process.exit(1) diff --git a/script/publish.ts b/script/publish.ts index 4baf6b03b772..f02b06880c5f 100755 --- a/script/publish.ts +++ b/script/publish.ts @@ -35,32 +35,34 @@ if (Script.release && !Script.preview) { await prepareReleaseFiles() -console.log("\n=== schema ===\n") -await $`bun ./packages/schema/script/publish.ts` +if (Bun.env.OPENCODE_DESKTOP_ONLY !== "true") { + console.log("\n=== schema ===\n") + await $`bun ./packages/schema/script/publish.ts` -console.log("\n=== theme ===\n") -await $`bun ./packages/theme/script/publish.ts` + console.log("\n=== theme ===\n") + await $`bun ./packages/theme/script/publish.ts` -console.log("\n=== ai ===\n") -await $`bun ./packages/ai/script/publish.ts` + console.log("\n=== ai ===\n") + await $`bun ./packages/ai/script/publish.ts` -console.log("\n=== util ===\n") -await $`bun ./packages/util/script/publish.ts` + console.log("\n=== util ===\n") + await $`bun ./packages/util/script/publish.ts` -console.log("\n=== protocol ===\n") -await $`bun ./packages/protocol/script/publish.ts` + console.log("\n=== protocol ===\n") + await $`bun ./packages/protocol/script/publish.ts` -console.log("\n=== client ===\n") -await $`bun ./packages/client/script/publish.ts` + console.log("\n=== client ===\n") + await $`bun ./packages/client/script/publish.ts` -console.log("\n=== cli ===\n") -await $`bun ./packages/cli/script/publish.ts` + console.log("\n=== cli ===\n") + await $`bun ./packages/cli/script/publish.ts` -console.log("\n=== plugin ===\n") -await $`bun ./packages/plugin/script/publish.ts` + console.log("\n=== plugin ===\n") + await $`bun ./packages/plugin/script/publish.ts` -console.log("\n=== ui ===\n") -await $`bun ./packages/ui/script/publish.ts` + console.log("\n=== ui ===\n") + await $`bun ./packages/ui/script/publish.ts` +} if (Script.release) { await $`bun ./packages/desktop/scripts/finalize-latest-json.ts` From d000c61a76ae46e0512a50649c6d5fd765edfbed Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Tue, 11 Aug 2026 11:37:04 +1000 Subject: [PATCH 2/5] refactor(desktop): simplify beta publication --- .github/workflows/beta.yml | 29 +++------- .github/workflows/nix-hashes.yml | 2 +- .github/workflows/publish.yml | 13 +---- .../src/commands/handlers/service/start.ts | 2 +- packages/desktop/scripts/prebuild.ts | 4 +- packages/desktop/scripts/utils.ts | 29 ++-------- packages/desktop/src/main/background-cli.ts | 1 - script/beta.ts | 54 ++++++++++++------- script/publish.ts | 2 +- 9 files changed, 52 insertions(+), 84 deletions(-) diff --git a/.github/workflows/beta.yml b/.github/workflows/beta.yml index a2bee99b178e..e93d5fbdb260 100644 --- a/.github/workflows/beta.yml +++ b/.github/workflows/beta.yml @@ -5,8 +5,6 @@ on: schedule: - cron: "0 * * * *" -concurrency: beta-sync - jobs: sync: runs-on: blacksmith-4vcpu-ubuntu-2404 @@ -18,33 +16,22 @@ jobs: uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: fetch-depth: 0 - ref: v2 - name: Setup Bun uses: ./.github/actions/setup-bun - - name: Configure git user - run: | - git config --global user.name "github-actions[bot]" - git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" + - name: Setup Git Committer + id: setup-git-committer + uses: ./.github/actions/setup-git-committer + with: + opencode-app-id: ${{ vars.OPENCODE_APP_ID }} + opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - name: Install OpenCode run: bun i -g opencode-ai - name: Sync beta branch - id: sync env: - GH_TOKEN: ${{ github.token }} + GH_TOKEN: ${{ steps.setup-git-committer.outputs.token }} OPENCODE_API_KEY: ${{ secrets.OPENCODE_API_KEY }} - run: bun script/beta.ts --prepare - - - name: Setup Git Committer - if: steps.sync.outputs.changed == 'true' - uses: ./.github/actions/setup-git-committer - with: - opencode-app-id: ${{ vars.OPENCODE_APP_ID }} - opencode-app-secret: ${{ secrets.OPENCODE_APP_SECRET }} - - - name: Push beta branch - if: steps.sync.outputs.changed == 'true' - run: git push origin beta --force --no-verify + run: bun script/beta.ts diff --git a/.github/workflows/nix-hashes.yml b/.github/workflows/nix-hashes.yml index 7932f10cddb5..ce1d9237fde5 100644 --- a/.github/workflows/nix-hashes.yml +++ b/.github/workflows/nix-hashes.yml @@ -6,7 +6,7 @@ permissions: on: workflow_dispatch: push: - branches: [dev] + branches: [dev, beta] paths: - "bun.lock" - "package.json" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ed67261bfea1..1f95f7389261 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -132,7 +132,7 @@ jobs: build-node-cli: needs: version - if: github.repository == 'anomalyco/opencode' && github.ref_name != 'beta' + if: github.repository == 'anomalyco/opencode' strategy: fail-fast: false matrix: @@ -282,7 +282,6 @@ jobs: build-electron: needs: - version - - build-cli if: github.repository == 'anomalyco/opencode' && github.ref_name != 'v2' continue-on-error: false env: @@ -336,12 +335,6 @@ jobs: with: install-flags: ${{ matrix.settings.bun_install_flags }} - - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - if: github.ref_name == 'beta' - with: - name: opencode-preview-cli - path: packages/cli/dist - - name: Azure login if: runner.os == 'Windows' uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2.3.0 @@ -400,7 +393,6 @@ jobs: VITE_SENTRY_DSN: ${{ vars.WEB_SENTRY_DSN }} VITE_SENTRY_ENVIRONMENT: ${{ (github.ref_name == 'beta' && 'beta') || 'production' }} VITE_SENTRY_RELEASE: desktop@${{ needs.version.outputs.version }} - RUST_TARGET: ${{ matrix.settings.target }} - name: Package if: needs.version.outputs.release @@ -522,13 +514,11 @@ jobs: path: packages/opencode/dist - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - if: github.ref_name != 'beta' with: name: opencode-preview-cli path: packages/cli/dist - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - if: github.ref_name != 'beta' with: pattern: opencode-node-cli-* path: packages/cli/dist/node @@ -597,4 +587,3 @@ jobs: LATEST_YML_DIR: /tmp/latest-yml TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }} - OPENCODE_DESKTOP_ONLY: ${{ github.ref_name == 'beta' }} diff --git a/packages/cli/src/commands/handlers/service/start.ts b/packages/cli/src/commands/handlers/service/start.ts index 42cef9bf341c..dfdbac3997a8 100644 --- a/packages/cli/src/commands/handlers/service/start.ts +++ b/packages/cli/src/commands/handlers/service/start.ts @@ -8,7 +8,7 @@ import { ServiceConfig } from "../../../services/service-config" export default Runtime.handler( Commands.commands.service.commands.start, Effect.fn("cli.service.start")(function* () { - const transport = yield* Service.ensure(yield* ServiceConfig.options({ checkVersion: true })) + const transport = yield* Service.ensure(yield* ServiceConfig.options()) process.stdout.write(transport.url + EOL) }), ) diff --git a/packages/desktop/scripts/prebuild.ts b/packages/desktop/scripts/prebuild.ts index 5d5714db5272..72f3b5a30a03 100644 --- a/packages/desktop/scripts/prebuild.ts +++ b/packages/desktop/scripts/prebuild.ts @@ -1,11 +1,11 @@ #!/usr/bin/env bun import { $ } from "bun" -import { copyBuiltCliToResources, downloadCliToResources, resolveChannel } from "./utils" +import { downloadCliToResources, resolveChannel } from "./utils" const channel = resolveChannel() await $`bun ./scripts/copy-icons.ts ${channel}` await $`bun ./scripts/copy-metainfo.ts ${channel}` if (channel === "dev") await downloadCliToResources() -if (channel === "beta") await copyBuiltCliToResources() +if (channel === "beta") await downloadCliToResources("next") diff --git a/packages/desktop/scripts/utils.ts b/packages/desktop/scripts/utils.ts index ef9b85644422..0a33040a0542 100644 --- a/packages/desktop/scripts/utils.ts +++ b/packages/desktop/scripts/utils.ts @@ -69,12 +69,12 @@ export function getCurrentCli(target = RUST_TARGET ?? nativeTarget()) { return binaryConfig } -export async function downloadCliToResources() { +export async function downloadCliToResources(version = CLI_VERSION) { const cli = getCurrentCli() const directory = await mkdtemp(join(tmpdir(), "opencode-cli-")) const dest = windowsify("resources/opencode-cli") try { - await $`bun install --no-save --cwd ${directory} ${`${cli.package}@${CLI_VERSION}`} ${`--os=${cli.os}`} ${`--cpu=${cli.cpu}`}` + await $`bun install --no-save --cwd ${directory} ${`${cli.package}@${version}`} ${`--os=${cli.os}`} ${`--cpu=${cli.cpu}`}` await copyFile( join(directory, "node_modules", cli.package, "bin", cli.os === "win32" ? "opencode2.exe" : "opencode2"), dest, @@ -82,34 +82,13 @@ export async function downloadCliToResources() { } finally { await rm(directory, { recursive: true, force: true }) } - await prepareCli(dest) - - console.log(`Copied ${cli.package} to ${dest}`) -} - -export async function copyBuiltCliToResources() { - const cli = getCurrentCli() - const dest = windowsify("resources/opencode-cli") - await copyFile( - join( - "../cli/dist", - cli.package.replace("@opencode-ai/", ""), - "bin", - cli.os === "win32" ? "opencode2.exe" : "opencode2", - ), - dest, - ) - await prepareCli(dest) - - console.log(`Copied the same-run ${cli.package} build to ${dest}`) -} - -async function prepareCli(dest: string) { if (process.platform !== "win32") await chmod(dest, 0o755) if (process.platform === "win32" && process.env.GITHUB_ACTIONS === "true") { await $`pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File ../../script/sign-windows.ps1 ${dest}` } if (process.platform === "darwin") await $`codesign --force --sign - ${dest}` + + console.log(`Copied ${cli.package}@${version} to ${dest}`) } export function windowsify(path: string) { diff --git a/packages/desktop/src/main/background-cli.ts b/packages/desktop/src/main/background-cli.ts index 04a34a4d6561..66602d51f116 100644 --- a/packages/desktop/src/main/background-cli.ts +++ b/packages/desktop/src/main/background-cli.ts @@ -85,7 +85,6 @@ async function run( ) { logger.log("v2 CLI command started", { binary, args }) const env = { ...process.env } - env.OPENCODE_DISABLE_AUTOUPDATE = "1" if (options.stateHome === undefined) delete env.XDG_STATE_HOME else env.XDG_STATE_HOME = options.stateHome return execFileAsync(binary, args, { env, windowsHide: true }).then( diff --git a/script/beta.ts b/script/beta.ts index 4c65cdffa604..d738c36ff017 100755 --- a/script/beta.ts +++ b/script/beta.ts @@ -4,7 +4,6 @@ import { $ } from "bun" import fs from "fs/promises" const model = "opencode/gpt-5.3-codex" -const prepare = process.argv.includes("--prepare") interface PR { number: number @@ -87,7 +86,7 @@ async function build() { console.log(" Running final build smoke check...") try { - await $`./script/build.ts --single`.cwd("packages/cli") + await $`./script/build.ts --single`.cwd("packages/opencode") return true } catch (err) { console.log(`Build failed: ${err}`) @@ -201,7 +200,7 @@ async function smoke(prs: PR[], applied: number[]) { "The beta merge batch is complete, but the deterministic final smoke check failed.", `Merged PRs on HEAD:\n${done}`, "Run `bun typecheck` at the repo root.", - "Run `./script/build.ts --single` in `packages/cli`.", + "Run `./script/build.ts --single` in `packages/opencode`.", "Fix any merge-caused issues until both commands pass.", "Do not create a commit.", ].join("\n") @@ -221,16 +220,21 @@ async function main() { console.log("Fetching open PRs with beta label...") const stdout = - await $`gh pr list --state open --draft=false --base v2 --label beta --json number,title,author,labels --limit 100`.text() + await $`gh pr list --state open --draft=false --label beta --json number,title,author,labels --limit 100`.text() const prs: PR[] = JSON.parse(stdout).sort((a: PR, b: PR) => a.number - b.number) console.log(`Found ${prs.length} open PRs with beta label`) - console.log("Fetching latest v2 branch...") - await $`git fetch origin v2` + if (prs.length === 0) { + console.log("No team PRs to merge") + return + } + + console.log("Fetching latest dev branch...") + await $`git fetch origin dev` console.log("Checking out beta branch...") - await $`git checkout -B beta origin/v2` + await $`git checkout -B beta origin/dev` const applied: number[] = [] const failed: FailedPR[] = [] @@ -258,7 +262,7 @@ async function main() { if (!(await fix(pr, files, prs, applied, idx))) { await cleanup() failed.push({ number: pr.number, title: pr.title, reason: "Merge conflicts" }) - await commentOnPR(pr.number, "Merge conflicts with v2 branch") + await commentOnPR(pr.number, "Merge conflicts with dev branch") continue } } else { @@ -314,18 +318,33 @@ async function main() { await $`git fetch origin beta` const localTree = (await $`git rev-parse beta^{tree}`.text()).trim() - const remoteTree = (await $`git rev-parse origin/beta^{tree}`.text()).trim() - if (localTree === remoteTree) { - console.log("Beta branch has identical contents, no push needed") - await outputChanged(false) + const remoteTrees = (await $`git log origin/dev..origin/beta --format=%T`.text()).split("\n") + + const matchIdx = remoteTrees.indexOf(localTree) + if (matchIdx !== -1) { + if (matchIdx !== 0) { + console.log(`Beta branch contains this sync, but additional commits exist after it. Leaving beta branch as is.`) + } else { + console.log("Beta branch has identical contents, no push needed") + } return } if (!(await smoke(prs, applied))) throw new Error("Final smoke check failed") - if (prepare) { - await outputChanged(true) - console.log("Validated beta branch is ready to push") + await $`git fetch origin beta` + + const validatedTree = (await $`git rev-parse beta^{tree}`.text()).trim() + const remoteTreesAfterSmoke = (await $`git log origin/dev..origin/beta --format=%T`.text()).split("\n") + const matchIdxAfterSmoke = remoteTreesAfterSmoke.indexOf(validatedTree) + if (matchIdxAfterSmoke !== -1) { + if (matchIdxAfterSmoke !== 0) { + console.log( + `Beta branch contains this validated sync, but additional commits exist after it. Leaving beta branch as is.`, + ) + } else { + console.log("Validated beta branch now matches remote contents, no push needed") + } return } @@ -335,11 +354,6 @@ async function main() { console.log("Successfully synced beta branch") } -async function outputChanged(changed: boolean) { - if (!process.env.GITHUB_OUTPUT) return - await fs.appendFile(process.env.GITHUB_OUTPUT, `changed=${changed}\n`) -} - main().catch((err) => { console.error("Error:", err) process.exit(1) diff --git a/script/publish.ts b/script/publish.ts index f02b06880c5f..7c2590ab9bba 100755 --- a/script/publish.ts +++ b/script/publish.ts @@ -35,7 +35,7 @@ if (Script.release && !Script.preview) { await prepareReleaseFiles() -if (Bun.env.OPENCODE_DESKTOP_ONLY !== "true") { +if (Script.channel !== "beta") { console.log("\n=== schema ===\n") await $`bun ./packages/schema/script/publish.ts` From 73253b389cf8d14da312c9a3f4ff345742233494 Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Tue, 11 Aug 2026 11:49:29 +1000 Subject: [PATCH 3/5] fix(desktop): preserve beta CLI target --- .github/workflows/publish.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1f95f7389261..f117260286f6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -393,6 +393,7 @@ jobs: VITE_SENTRY_DSN: ${{ vars.WEB_SENTRY_DSN }} VITE_SENTRY_ENVIRONMENT: ${{ (github.ref_name == 'beta' && 'beta') || 'production' }} VITE_SENTRY_RELEASE: desktop@${{ needs.version.outputs.version }} + RUST_TARGET: ${{ matrix.settings.target }} - name: Package if: needs.version.outputs.release From eac79ba6aebcd8e9fd9728ccf8f3e44dde29659e Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Tue, 11 Aug 2026 13:51:08 +1000 Subject: [PATCH 4/5] fix(desktop): negotiate shared server version --- bun.lock | 1 + packages/desktop/package.json | 1 + packages/desktop/src/main/background-cli.ts | 71 +++++++-------------- packages/desktop/src/main/index.ts | 4 +- packages/desktop/src/main/server.ts | 5 +- 5 files changed, 29 insertions(+), 53 deletions(-) diff --git a/bun.lock b/bun.lock index 12dc5a491d97..12b5771fa730 100644 --- a/bun.lock +++ b/bun.lock @@ -439,6 +439,7 @@ "@actions/artifact": "4.0.0", "@lydell/node-pty": "catalog:", "@opencode-ai/app": "workspace:*", + "@opencode-ai/client": "workspace:*", "@opencode-ai/ui": "workspace:*", "@sentry/solid": "catalog:", "@sentry/vite-plugin": "catalog:", diff --git a/packages/desktop/package.json b/packages/desktop/package.json index 47550938e3f9..390b7c704ebf 100644 --- a/packages/desktop/package.json +++ b/packages/desktop/package.json @@ -37,6 +37,7 @@ "@actions/artifact": "4.0.0", "@lydell/node-pty": "catalog:", "@opencode-ai/app": "workspace:*", + "@opencode-ai/client": "workspace:*", "@opencode-ai/ui": "workspace:*", "@sentry/solid": "catalog:", "@sentry/vite-plugin": "catalog:", diff --git a/packages/desktop/src/main/background-cli.ts b/packages/desktop/src/main/background-cli.ts index 66602d51f116..ec37429a4b79 100644 --- a/packages/desktop/src/main/background-cli.ts +++ b/packages/desktop/src/main/background-cli.ts @@ -1,3 +1,4 @@ +import { Service } from "@opencode-ai/client/service" import { execFile } from "node:child_process" import { existsSync } from "node:fs" import { chmod, copyFile, mkdir, rename, rm } from "node:fs/promises" @@ -8,52 +9,34 @@ import { app } from "electron" const execFileAsync = promisify(execFile) const root = dirname(fileURLToPath(import.meta.url)) -const stateHome = process.env.XDG_STATE_HOME -const desktopStateNames = ["ai.opencode.desktop.dev", "ai.opencode.desktop.beta", "ai.opencode.desktop"] type Logger = { log(message: string, meta?: Record): void error(message: string, meta?: Record): void } -export async function startBackgroundCli(logger: Logger, shellStateHome?: string) { +export async function startBackgroundCli(logger: Logger) { const bundled = app.isPackaged ? join(process.resourcesPath, executableName()) : join(root, "../../resources", executableName()) logger.log("v2 CLI executable resolved", { bundled, packaged: app.isPackaged }) - const version = await run(bundled, ["--version"], logger) + const version = parseVersion(await run(bundled, ["--version"], logger)) const binary = app.isPackaged ? await installCli(bundled, version, logger) : bundled - - const candidates = [ - ...new Set([stateHome, shellStateHome, ...desktopStateNames.map((name) => join(app.getPath("appData"), name))]), - ].filter((candidate) => candidate === undefined || existsSync(candidate)) - const discovered = await Promise.all( - candidates.map(async (candidate) => ({ - stateHome: candidate, - url: serviceUrl(await run(binary, ["service", "status"], logger, { stateHome: candidate })), - })), - ) - const found = discovered.find((candidate) => candidate.url !== undefined) - logger.log("v2 CLI background instance checked", { - detected: Boolean(found), - ...endpoint(found?.url), - }) - - const daemonStateHome = found?.stateHome ?? stateHome - const url = await run(binary, ["service", "start"], logger, { stateHome: daemonStateHome }) - const password = await run(binary, ["service", "get", "password"], logger, { - redact: true, - stateHome: daemonStateHome, + const service = await Service.ensure({ + version, + command: [binary, "serve", "--service"], + onStart: (reason, previousVersion) => logger.log("v2 CLI background service starting", { reason, previousVersion }), }) + if (service.auth?.type !== "basic") throw new Error("V2 CLI background service did not provide authentication") logger.log("v2 CLI background service ready", { - existing: Boolean(found), - username: "opencode", - ...endpoint(url), + username: service.auth.username, + version, + ...endpoint(service.url), }) return { - url, - username: "opencode", - password, + url: service.url, + username: service.auth.username, + password: service.auth.password, } } @@ -77,21 +60,13 @@ async function installCli(source: string, version: string, logger: Logger) { return destination } -async function run( - binary: string, - args: string[], - logger: Logger, - options: { redact?: boolean; stateHome?: string } = {}, -) { +async function run(binary: string, args: string[], logger: Logger) { logger.log("v2 CLI command started", { binary, args }) - const env = { ...process.env } - if (options.stateHome === undefined) delete env.XDG_STATE_HOME - else env.XDG_STATE_HOME = options.stateHome - return execFileAsync(binary, args, { env, windowsHide: true }).then( + return execFileAsync(binary, args, { windowsHide: true }).then( (result) => { const stdout = result.stdout.trim() const stderr = result.stderr.trim() - logger.log("v2 CLI command completed", { args, stdout: options.redact ? "[redacted]" : stdout, stderr }) + logger.log("v2 CLI command completed", { args, stdout, stderr }) return stdout }, (error: unknown) => { @@ -99,7 +74,7 @@ async function run( logger.error("v2 CLI command failed", { args, error: error instanceof Error ? error.message : String(error), - stdout: options.redact && output.stdout ? "[redacted]" : (output.stdout?.trim() ?? ""), + stdout: output.stdout?.trim() ?? "", stderr: output.stderr?.trim() ?? "", }) throw error @@ -107,11 +82,11 @@ async function run( ) } -function serviceUrl(status: string) { - if (URL.canParse(status)) return status - if (!status.startsWith("running ")) return - const url = status.slice("running ".length).trim() - return URL.canParse(url) ? url : undefined +function parseVersion(output: string) { + const marker = output.lastIndexOf(" v") + const version = marker === -1 ? output : output.slice(marker + 2) + if (!version) throw new Error("V2 CLI did not provide a version") + return version } function endpoint(url: string | undefined) { diff --git a/packages/desktop/src/main/index.ts b/packages/desktop/src/main/index.ts index 0cb08b1945d3..3dd31571268c 100644 --- a/packages/desktop/src/main/index.ts +++ b/packages/desktop/src/main/index.ts @@ -181,7 +181,7 @@ const main = Effect.gen(function* () { return } - const shellEnv = preferAppEnv(app.getPath("userData")) + preferAppEnv() app.on("second-instance", (_event: Event, argv: string[]) => { const urls = argv.filter((arg: string) => arg.startsWith("opencode://")) @@ -310,7 +310,7 @@ const main = Effect.gen(function* () { useEnvProxy() logger.log("starting v2 background service") - const sidecar = yield* Effect.promise(() => startBackgroundCli(logger, shellEnv?.XDG_STATE_HOME)) + const sidecar = yield* Effect.promise(() => startBackgroundCli(logger)) yield* Deferred.succeed(serverReady, { url: sidecar.url, username: sidecar.username, diff --git a/packages/desktop/src/main/server.ts b/packages/desktop/src/main/server.ts index 36f58772b468..0242d38806f1 100644 --- a/packages/desktop/src/main/server.ts +++ b/packages/desktop/src/main/server.ts @@ -17,17 +17,16 @@ export function setDefaultServerUrl(url: string | null) { getStore().delete(DEFAULT_SERVER_URL_KEY) } -export function preferAppEnv(userDataPath: string) { +export function preferAppEnv() { const shell = process.platform === "win32" ? null : getUserShell() const shellEnv = shell ? loadShellEnv(shell, getLogger()) : null + if (!shellEnv?.XDG_STATE_HOME) delete process.env.XDG_STATE_HOME Object.assign(process.env, { ...shellEnv, OPENCODE_EXPERIMENTAL_ICON_DISCOVERY: "true", OPENCODE_EXPERIMENTAL_FILEWATCHER: "true", OPENCODE_CLIENT: "desktop", - XDG_STATE_HOME: process.env.XDG_STATE_HOME ?? userDataPath, }) - return shellEnv } export async function checkHealth(url: string, password?: string | null): Promise { From f6d55902fea44991e668daf30dc1774401e7426d Mon Sep 17 00:00:00 2001 From: LukeParkerDev <10430890+Hona@users.noreply.github.com> Date: Tue, 11 Aug 2026 14:16:01 +1000 Subject: [PATCH 5/5] refactor(desktop): clarify CLI target name --- .github/workflows/publish.yml | 4 ++-- packages/desktop/scripts/copy-bundles.ts | 4 ++-- packages/desktop/scripts/utils.ts | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f117260286f6..881666883004 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -377,7 +377,7 @@ jobs: env: OPENCODE_VERSION: ${{ needs.version.outputs.version }} OPENCODE_CHANNEL: ${{ (github.ref_name == 'beta' && 'beta') || 'prod' }} - RUST_TARGET: ${{ matrix.settings.target }} + OPENCODE_CLI_TARGET: ${{ matrix.settings.target }} - name: Build run: bun run build @@ -393,7 +393,7 @@ jobs: VITE_SENTRY_DSN: ${{ vars.WEB_SENTRY_DSN }} VITE_SENTRY_ENVIRONMENT: ${{ (github.ref_name == 'beta' && 'beta') || 'production' }} VITE_SENTRY_RELEASE: desktop@${{ needs.version.outputs.version }} - RUST_TARGET: ${{ matrix.settings.target }} + OPENCODE_CLI_TARGET: ${{ matrix.settings.target }} - name: Package if: needs.version.outputs.release diff --git a/packages/desktop/scripts/copy-bundles.ts b/packages/desktop/scripts/copy-bundles.ts index 6ef3335eb79a..edc1462c0934 100644 --- a/packages/desktop/scripts/copy-bundles.ts +++ b/packages/desktop/scripts/copy-bundles.ts @@ -1,9 +1,9 @@ import { $ } from "bun" import * as path from "node:path" -import { RUST_TARGET } from "./utils" +import { CLI_TARGET } from "./utils" -if (!RUST_TARGET) throw new Error("RUST_TARGET not defined") +if (!CLI_TARGET) throw new Error("OPENCODE_CLI_TARGET not defined") const BUNDLE_DIR = "dist" const BUNDLES_OUT_DIR = path.join(process.cwd(), "dist/bundles") diff --git a/packages/desktop/scripts/utils.ts b/packages/desktop/scripts/utils.ts index 0a33040a0542..34b0405d9f03 100644 --- a/packages/desktop/scripts/utils.ts +++ b/packages/desktop/scripts/utils.ts @@ -13,46 +13,46 @@ export function resolveChannel(): Channel { return "dev" } -export const CLI_BINARIES: Array<{ rustTarget: string; package: string; os: string; cpu: string }> = [ +export const CLI_BINARIES: Array<{ target: string; package: string; os: string; cpu: string }> = [ { - rustTarget: "aarch64-apple-darwin", + target: "aarch64-apple-darwin", package: "@opencode-ai/cli-darwin-arm64", os: "darwin", cpu: "arm64", }, { - rustTarget: "x86_64-apple-darwin", + target: "x86_64-apple-darwin", package: "@opencode-ai/cli-darwin-x64-baseline", os: "darwin", cpu: "x64", }, { - rustTarget: "aarch64-pc-windows-msvc", + target: "aarch64-pc-windows-msvc", package: "@opencode-ai/cli-windows-arm64", os: "win32", cpu: "arm64", }, { - rustTarget: "x86_64-pc-windows-msvc", + target: "x86_64-pc-windows-msvc", package: "@opencode-ai/cli-windows-x64-baseline", os: "win32", cpu: "x64", }, { - rustTarget: "x86_64-unknown-linux-gnu", + target: "x86_64-unknown-linux-gnu", package: "@opencode-ai/cli-linux-x64-baseline", os: "linux", cpu: "x64", }, { - rustTarget: "aarch64-unknown-linux-gnu", + target: "aarch64-unknown-linux-gnu", package: "@opencode-ai/cli-linux-arm64", os: "linux", cpu: "arm64", }, ] -export const RUST_TARGET = Bun.env.RUST_TARGET +export const CLI_TARGET = Bun.env.OPENCODE_CLI_TARGET function nativeTarget() { const { platform, arch } = process @@ -62,8 +62,8 @@ function nativeTarget() { throw new Error(`Unsupported platform: ${platform}/${arch}`) } -export function getCurrentCli(target = RUST_TARGET ?? nativeTarget()) { - const binaryConfig = CLI_BINARIES.find((item) => item.rustTarget === target) +export function getCurrentCli(target = CLI_TARGET ?? nativeTarget()) { + const binaryConfig = CLI_BINARIES.find((item) => item.target === target) if (!binaryConfig) throw new Error(`CLI configuration not available for target '${target}'`) return binaryConfig