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
14 changes: 8 additions & 6 deletions DIVERGENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ future `packages/codev-*`) never conflict and are not tracked here.
| --- | --- | --- | --- |
| `packages/core/src/global.ts` | `const app = "opencode"` → `"codev-code"` | Config/data/cache/state dirs under `~/.config/codev-code` etc. | Keep ours (the one constant); take upstream's surrounding changes. |
| `packages/opencode/src/index.ts` | `scriptName("opencode")` → `"codev"`; `show()` prefix check `"opencode "` → `"codev "` | Help/usage text shows the real user-facing command (the `codev` hub forwards unknown commands to this binary). The `show()` check must always match the scriptName. | Keep our two strings; take upstream's surrounding changes. |
| `packages/opencode/package.json` | bin key `opencode` → `codev-code` (shim path `./bin/opencode` unchanged) | Installed binary is named `codev-code`. | Keep our bin key; take upstream's other fields. |
| `package.json` (root) | Added `release` script delegating to packages/opencode | `bun run release` works from the repo root. | Keep our release line; take upstream's other fields. |
| `packages/opencode/package.json` | bin key `opencode` → `codev-code` (shim path `./bin/opencode` unchanged); added `release` script | Installed binary is named `codev-code`; `bun run release` publishes the version in this file (upstream-synced; script/release.ts is fork-only). | Keep our bin key and release line; take upstream's other fields including `version`. |
| `bun.lock` | Mirrors the bin key rename above | Lockfile records workspace bin mappings. | Regenerate with `bun install`; never hand-merge. |
| `packages/opencode/script/build.ts` | Platform packages' `package.json` name `codev-code-<platform>` (dist dir names unchanged — the bun compile target derives from them) | npm publishing under the fork's names. | Keep our `name:` line; take upstream's surrounding changes. |
| `packages/opencode/script/publish.ts` | `PUBLISH_NAME = "codev-code"` const; published-name→dir map; main pkg name + bin key; env-guarded exit before the Docker/AUR/Homebrew section | npm-only publishing under the fork's names (unscoped, public on npmjs); upstream's other channels target anomalyco infra. | Keep our names + early exit; take upstream's npm-section changes above the exit. |
Expand All @@ -31,11 +32,12 @@ future `packages/codev-*`) never conflict and are not tracked here.
direct `codev-code upgrade` would still install stock opencode. Patch or disable the
upgrade command before distributing outside the team.
- **Publishing**: npm packages publish as `codev-code` / `codev-code-<platform>` — unscoped,
therefore PUBLIC on npmjs (like `codev-ai`). Local-only for now (no CI workflow), run from
`packages/opencode` with npm publish auth in place:
`OPENCODE_VERSION=<x.y.z> OPENCODE_CHANNEL=latest bun run script/build.ts && bun run script/publish.ts`.
Docker/AUR/Homebrew/GitHub-release channels are upstream-only and disabled. The binary
inside platform packages is still named `opencode` (cosmetic).
therefore PUBLIC on npmjs (like `codev-ai`). Local-only for now (no CI workflow): run
`bun run release [channel] [--skip-build]` from `packages/opencode` with npm publish
auth in place. The version comes from package.json (upstream-synced — releases track
the upstream version the fork was built from; suffix like `-codev.1` for fork-only
re-releases). Docker/AUR/Homebrew/GitHub-release channels are upstream-only and
disabled. The binary inside platform packages is still named `opencode` (cosmetic).
- **UI branding**: TUI logo (`UI.logo()`), desktop/web app names and assets — all still
upstream-branded. Cosmetic; not worth the merge-conflict surface until the product ships
beyond the team.
Expand Down
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,28 @@ bun test

Upstream's [AGENTS.md](AGENTS.md) and [CONTRIBUTING.md](CONTRIBUTING.md) conventions (commit style, code style, package layout) apply here unchanged.

## Publishing to npm

Releases publish the unscoped — therefore **public** — [`codev-code`](https://www.npmjs.com/package/codev-code) package plus one `codev-code-<platform>-<arch>` binary package per platform. The version comes from `packages/opencode/package.json` (single source of truth). That field is upstream-synced, so each release carries the upstream version the fork was built from.

```sh
npm login # once per machine
bun run release # from the repo root: builds all platforms (~15-20 min), then publishes
```

Variants:

```sh
bun run release beta # publish under the `beta` dist-tag instead of `latest`
bun run release --skip-build # reuse an existing dist/ (must match the package.json version)
```

Notes:

- With 2FA-on-publish, npm may prompt once per package (13 of them). A granular automation token avoids that: `npm config set //registry.npmjs.org/:_authToken <token>`.
- The wrapper refuses to run when the version is already on npm. For a fork-only re-release between upstream syncs, set a suffixed version in `packages/opencode/package.json` (e.g. `1.17.13-codev.1`); the next sync takes upstream's value back.
- Verify after publishing: `npm view codev-code` and `npm install -g codev-code && codev-code --version`.

## Syncing with upstream

A scheduled GitHub Action ([`sync-upstream.yml`](.github/workflows/sync-upstream.yml)) merges upstream `dev` into `main` weekly and opens a PR. It can also be run on demand (Actions → sync-upstream → Run workflow) against any upstream branch or tag.
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"packageManager": "bun@1.3.14",
"scripts": {
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
"release": "bun run --cwd packages/opencode release",
"dev:desktop": "bun --cwd packages/desktop dev",
"dev:web": "bun --cwd packages/app dev",
"dev:console": "ulimit -n 10240 2>/dev/null; bun run --cwd packages/console/app dev",
Expand Down
1 change: 1 addition & 0 deletions packages/opencode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"bench:test": "bun run script/bench-test-suite.ts",
"profile:test": "bun run script/profile-test-files.ts",
"build": "bun run script/build.ts",
"release": "bun run script/release.ts",
"dev": "bun run --conditions=browser ./src/index.ts",
"dev:temporary": "bun run --conditions=browser ./src/temporary.ts"
},
Expand Down
65 changes: 65 additions & 0 deletions packages/opencode/script/release.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env bun
import { $ } from "bun"
import pkg from "../package.json"

// Local release wrapper (fork-only file): `bun run release [channel] [--skip-build]`.
//
// The version is read from package.json — the single source of truth. That
// field stays upstream-synced (their release pipeline rewrites it), so fork
// releases track the upstream version they were built from. For a fork-only
// re-release between upstream syncs, bump with a suffix (e.g. 1.17.13-codev.1)
// and let the next sync take upstream's value back.
//
// Channel is the npm dist-tag and defaults to `latest`; pass e.g. `beta` for
// pre-releases. `--skip-build` publishes an existing dist/ after verifying it
// was built with the same version (the build stamps the version into the
// binaries and manifests).
const skipBuild = process.argv.includes("--skip-build")
const args = process.argv.slice(2).filter((a) => a !== "--skip-build")
const version = pkg.version
const channel = args[0] ?? "latest"

if (!/^\d+\.\d+\.\d+(-[\w.]+)?$/.test(version)) {
console.error(`package.json version ${JSON.stringify(version)} is not a valid release version.`)
process.exit(1)
}

console.log(`Releasing codev-code@${version} (dist-tag: ${channel}${skipBuild ? ", skipping build" : ""})`)

if (skipBuild) {
const manifests = [...new Bun.Glob("*/package.json").scanSync({ cwd: `${import.meta.dirname}/../dist` })]
const built = manifests.length
? ((await Bun.file(`${import.meta.dirname}/../dist/${manifests[0]}`).json()) as { version: string }).version
: undefined
if (built !== version) {
console.error(
built
? `dist/ was built for version ${built}, but package.json says ${version} — rerun without --skip-build.`
: "No dist/ found — rerun without --skip-build.",
)
process.exit(1)
}
}

// Fail fast on auth before a 15+ minute build. With 2FA-on-publish npm may
// still prompt per published package (13 of them); a granular token
// (`npm config set //registry.npmjs.org/:_authToken <token>`) avoids that.
if ((await $`npm whoami`.nothrow().quiet()).exitCode !== 0) {
console.error("Not logged in to npm. Run `npm login` (or configure an auth token) first.")
process.exit(1)
}

// publish.ts skips already-published versions, so a forgotten bump (or an
// unsynced upstream version) would otherwise "succeed" while publishing
// nothing. Catch it up front.
if ((await $`npm view codev-code@${version} version`.nothrow().quiet()).exitCode === 0) {
console.error(`codev-code@${version} is already published — bump the version in packages/opencode/package.json.`)
process.exit(1)
}

const env = { ...process.env, OPENCODE_VERSION: version, OPENCODE_CHANNEL: channel }
if (!skipBuild) await $`bun ${import.meta.dirname}/build.ts`.env(env)
await $`bun ${import.meta.dirname}/publish.ts`.env(env)

console.log(`\nReleased codev-code@${version} (dist-tag: ${channel})`)
console.log(`Verify: npm view codev-code@${version} && npm install -g codev-code`)
Loading