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
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
- After changing the public Protocol or Server `HttpApi`, run `bun run generate` from `packages/client`. Do not edit `src/generated` or `src/generated-effect` directly.
- Keep runtime dependencies directed from Schema to Core and Protocol, then from Core and Protocol to Server. Client runtime code may depend on Schema and Protocol but never Core or Server; `sdk-next` composes Client, Core, and Server.
- The default branch in this repo is `main`; use `main` or `origin/main` for diffs. (Upstream opencode's default is `dev`; this fork does not have that branch.)
- This repo is a fork of upstream opencode. Every deliberate change to an upstream file must get a row in `DIVERGENCES.md` (file, change, why, on-conflict guidance) in the same PR β€” an unlisted divergence is a bug. Fork-only new files are not tracked there. If the change alters documented behavior (e.g. a keybind default), update the matching docs under `packages/web/src/content/docs/` (en + es) too.
- Before adding a feature, read Divergence policy in `DIVERGENCES.md` and prefer the lowest tier that works: config/plugins/skills/agents first, new `packages/codev-*` workspace packages second, upstream-file edits last. When asked to sync with upstream, follow Syncing with upstream in `DIVERGENCES.md` β€” do not `git merge` upstream refs.

## Branch Names

Expand Down
60 changes: 53 additions & 7 deletions DIVERGENCES.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,61 @@
# Divergences from upstream

Every deliberate change to an upstream file is listed here. When an upstream sync patch
(see README β†’ Syncing with upstream) conflicts, this table tells you what the conflict is
about and how to resolve it. If you edit an upstream file and it is not in this table,
add it β€” an unlisted divergence is a bug.
Every deliberate change to an upstream file is listed in the
[Changed upstream files](#changed-upstream-files) table. When an upstream sync patch
(see [Syncing with upstream](#syncing-with-upstream)) conflicts, the table tells you what
the conflict is about and how to resolve it. If you edit an upstream file and it is not
in the table, add it β€” an unlisted divergence is a bug.

New files that upstream does not have (this file, `NOTICE`, future `packages/codev-*`)
never conflict and are not tracked here.

Sync commits must stay single-author so the repo's contributor list doesn't re-accrue
upstream maintainers β€” see README β†’ Syncing with upstream for why and how.
## Divergence policy

Features go, in order of preference:

1. **Config / plugins / skills / agents** β€” in the [Codev Hub](https://github.com/quickbeard/codev-hub) repo or config packages; zero merge cost.
2. **New workspace packages** (`packages/codev-*`) β€” additive; near-zero merge cost.
3. **Edits to upstream files** β€” last resort. Every such file must be listed in the [Changed upstream files](#changed-upstream-files) table with a reason and a conflict-resolution strategy.

## Syncing with upstream

Syncing is manual and local β€” there is no CI workflow. `main` carries fork commits only
(history was truncated; it shares no ancestry with upstream), so `git merge upstream/...`
does not work. Instead, apply upstream's changes as a 3-way patch between release tags.
The tag the fork is currently on is the `version` in `packages/opencode/package.json`.

```sh
git fetch upstream --tags # also brings in the blobs `git apply -3` needs
git checkout -b sync-upstream main
# FROM = current version in packages/opencode/package.json; TO = target release
FROM=v1.17.15 TO=v1.17.16

# `git apply` is atomic: hunks against files the fork deleted (locales, docs
# translations β€” see the table below) hard-error and roll back the entire patch,
# so filter them out first. A path is skipped only if it existed in FROM and is
# deliberately absent from HEAD; files new in TO still come through.
git diff --name-only $FROM $TO -- . ':(exclude)bun.lock' |
while IFS= read -r f; do
git cat-file -e "$FROM:$f" 2>/dev/null && ! git cat-file -e "HEAD:$f" 2>/dev/null ||
printf '%s\n' "$f"
done |
tr '\n' '\0' | xargs -0 git diff --binary $FROM $TO -- | git apply -3 --index

# Conflicts (files listed as "U" / left with markers): see the Changed upstream
# files table for each file's resolution strategy, then `git add` them.
bun install # regenerate bun.lock, never patch it
bun turbo typecheck
git commit -m "chore: sync upstream $TO"
```

`git apply -3` leaves ordinary conflict markers where our divergences overlap upstream
changes β€” the same conflict surface the old merge had.

**Keep history single-author.** Sync commits are authored only by whoever runs the sync
(a `git apply`'d patch carries no upstream authorship), which is why the repo's contributor
list stays clean. If you ever squash-merge a branch containing commits by others, GitHub
adds `Co-authored-by:` trailers that re-add those people as repo contributors β€” strip them
from the squash message first, or use a plain merge.

## Changed upstream files

Expand Down Expand Up @@ -60,7 +106,7 @@ upstream maintainers β€” see README β†’ Syncing with upstream for why and how.
| `packages/desktop/src/main/index.ts`, `packages/desktop/src/main/windows.ts` | APP_NAMES + window title β†’ "CoDev Code" (Dev/Beta variants too) | Desktop app display name. | Keep our names. |
| `packages/desktop/electron-builder.config.ts` | `productName` Γ—3 β†’ "CoDev Code…"; artifactName β†’ `codev-code-desktop-…`; protocol display name | Installer/product branding. appId (`ai.opencode.desktop`) and the `opencode://` deep-link scheme stay upstream β€” identity plumbing wired into main/index.ts and app deep-links; do not rename casually. | Keep our names; take upstream's other config. |
| `packages/ui/src/assets/favicon/` (favicon-v3.svg, site.webmanifest, favicon-96x96-v3.png, apple-touch-icon-v3.png, web-app-manifest-192/512.png) | New codev mark: blocky "C" in #00cdcd on dark; manifest name "CoDev Code"/"codev" | Web/desktop favicon + PWA branding (served via packages/app/public symlinks). | Keep our assets (binary: take ours wholesale). |
| `AGENTS.md` | Default-branch note: `dev` β†’ `main` (single merged line; upstream has two lines saying local `main` may not exist) | The fork's default branch is `main` (see the workflow-triggers row); agents kept basing diffs on a nonexistent `dev`. | Keep our line; take upstream's other guidance. |
| `AGENTS.md` | Default-branch note: `dev` β†’ `main` (single merged line; upstream has two lines saying local `main` may not exist); added fork bullets requiring every upstream-file change to get a `DIVERGENCES.md` row (and matching en + es doc updates) in the same PR, and pointing agents at this file's Divergence policy (prefer config/plugins, then `packages/codev-*`, upstream edits last) and Syncing with upstream sections | The fork's default branch is `main` (see the workflow-triggers row); agents kept basing diffs on a nonexistent `dev`. Agents edit upstream files without recording the divergence β€” and don't apply the placement policy or sync runbook β€” unless the instructions file says to. | Keep our lines; take upstream's other guidance. |
| `README.md` | Replaced with fork README | Fork identity, sync + divergence policy. | Keep ours entirely. |
| `CONTRIBUTING.md`, `SECURITY.md` | Product-brand prose "OpenCode" β†’ "CoDev Code"; built-CLI command examples `opencode …` β†’ `codev …` | Docs people actually read should name the fork's product. Upstream issue/advisory links, `packages/opencode` paths, and build-output paths stay upstream; env-var mentions follow the env-var rename row. | Keep our strings; take upstream's structural changes. |
| `CONTEXT.md` | Product-brand prose "OpenCode" β†’ "CoDev Code" (title, intro, and defined terms such as "CoDev Code Client" / "Embedded CoDev Code") | The V2 design glossary should name the fork's product; the renamed terms appear only in this file, so nothing desyncs. `@opencode-ai/*` package names stay upstream; env-var mentions follow the env-var rename row. | Keep our brand strings; take upstream's design changes (this file evolves with the V2 session core β€” merge content, re-apply the brand rename). |
Expand Down
48 changes: 2 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,53 +26,9 @@ Notes:
- The wrapper refuses to run when the version is already on npm. For a fork-only re-release between upstream syncs, add a numeric revision to the version in `packages/opencode/package.json` (e.g. `1.17.16-1`, then `1.17.16-2`) β€” the Nth fork build of that upstream release; the next sync takes upstream's value back. Semver sorts the suffixed form below the bare `1.17.16`, but installs follow the `latest` dist-tag, so that quirk is harmless.
- Verify after publishing: `npm view codev-code` and `npm i -g codev-code && codev --version`.

## Syncing with upstream
## Syncing and divergences

Syncing is manual and local β€” there is no CI workflow. `main` carries fork commits only
(history was truncated; it shares no ancestry with upstream), so `git merge upstream/...`
does not work. Instead, apply upstream's changes as a 3-way patch between release tags.
The tag the fork is currently on is the `version` in `packages/opencode/package.json`.

```sh
git fetch upstream --tags # also brings in the blobs `git apply -3` needs
git checkout -b sync-upstream main
# FROM = current version in packages/opencode/package.json; TO = target release
FROM=v1.17.15 TO=v1.17.16

# `git apply` is atomic: hunks against files the fork deleted (locales, docs
# translations β€” see DIVERGENCES.md) hard-error and roll back the entire patch,
# so filter them out first. A path is skipped only if it existed in FROM and is
# deliberately absent from HEAD; files new in TO still come through.
git diff --name-only $FROM $TO -- . ':(exclude)bun.lock' |
while IFS= read -r f; do
git cat-file -e "$FROM:$f" 2>/dev/null && ! git cat-file -e "HEAD:$f" 2>/dev/null ||
printf '%s\n' "$f"
done |
tr '\n' '\0' | xargs -0 git diff --binary $FROM $TO -- | git apply -3 --index

# Conflicts (files listed as "U" / left with markers): see DIVERGENCES.md for
# each file's resolution strategy, then `git add` them.
bun install # regenerate bun.lock, never patch it
bun turbo typecheck
git commit -m "chore: sync upstream $TO"
```

`git apply -3` leaves ordinary conflict markers where our divergences overlap upstream
changes β€” the same conflict surface the old merge had.

**Keep history single-author.** Sync commits are authored only by whoever runs the sync
(a `git apply`'d patch carries no upstream authorship), which is why the repo's contributor
list stays clean. If you ever squash-merge a branch containing commits by others, GitHub
adds `Co-authored-by:` trailers that re-add those people as repo contributors β€” strip them
from the squash message first, or use a plain merge.

## Divergence policy

Features go, in order of preference:

1. **Config / plugins / skills / agents** β€” in the [Codev Hub](https://github.com/quickbeard/codev-hub) repo or config packages; zero merge cost.
2. **New workspace packages** (`packages/codev-*`) β€” additive; near-zero merge cost.
3. **Edits to upstream files** β€” last resort. Every such file must be listed in [DIVERGENCES.md](DIVERGENCES.md) with a reason and a conflict-resolution strategy.
The upstream sync procedure and the divergence policy live in [DIVERGENCES.md](DIVERGENCES.md).

## Development

Expand Down
Loading