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: 1 addition & 1 deletion DIVERGENCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ from the squash message first, or use a plain merge.
| `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. Auto-update `publish` targets repointed to the fork: beta `anomalyco/opencode-beta` and prod `anomalyco/opencode` both → `quickbeard/codev-code` (upstream has no fork-side beta repo, so the two channels share one). | Installer/product branding, and a packaged build must not offer upstream OpenCode releases as CoDev updates. 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. `rpm.packageName` (`opencode`/`opencode-beta`/`opencode-dev`) also stays — it names the installed Linux package, not a publish target. | Keep our names and publish targets; take upstream's other config. Two known follow-ups, both moot while the fork ships no desktop build: beta and prod now write the same `latest.yml` in one repo (splitting them needs `publish.channel` plus the hardcoded `autoUpdater.channel = "latest"` in `src/main/updater.ts`), and `codev-code` is private, which electron-updater cannot read without a token. |
| `packages/desktop/src/renderer/index.tsx` | Desktop notification icon `https://opencode.ai/favicon-96x96-v3.png` → the relative `./favicon-96x96-v3.png`. The renderer's `publicDir` is `packages/app/public`, whose `favicon-96x96-v3.png` symlinks to the rebranded `packages/ui/src/assets/favicon/` mark, so the file is emitted next to `index.html` and resolves against the renderer origin (`oc://renderer/` packaged, the vite dev server otherwise) — the same asset and the same relative form `src/renderer/index.html` already uses for `<link rel="icon">`. | A desktop app should not reach out to a remote host to draw its own notification icon (it fails offline and leaks a request per notification), and the remote file is upstream-branded while the bundled one is the codev mark. | Keep our relative path. If upstream changes the URL, re-point it at the bundled asset rather than taking a new remote host. `packages/app/src/entry.tsx` and `pages/layout/helpers.ts` keep their remote `opencode.ai/favicon*` sources — same bug class, not yet fixed. |
| `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). |
| `packages/ui/src/assets/favicon/` (favicon-v3.svg, favicon-v3.ico, site.webmanifest, favicon-96x96-v3.png, apple-touch-icon-v3.png, web-app-manifest-192/512.png) | New codev mark: the blocky "C" in brand red `#ee0033` on a white tile, generated from the same geometry as the app icon by `packages/desktop/scripts/generate-icons.ts` (4x5 grid, one-unit stroke, unit = 120/1024, corner radius 229/1024); `favicon-v3.svg` is the hand-written 512-unit source of that geometry. The tab and `.ico` icons keep the rounded tile so they read as an app icon; `apple-touch-icon-v3.png` and the two maskable `web-app-manifest-*` icons are square and full-bleed, because iOS and PWA launchers apply their own mask and a pre-rounded icon leaves transparent corners that render black. Manifest name "CoDev Code"/"codev"; its `theme_color`/`background_color` stay `#080808` — those describe the PWA's chrome and splash, not the icon. **Was `#00cdcd` on a dark tile** until this row was rewritten: PR #10 pinned the favicon to the then-cyan TUI banner accent, that banner later moved to the navy/red wordmark, and the favicon was left behind as the only cyan in the tree — visibly so on desktop, where the dock icon was red while the window and notification icons were cyan. | Every surface that draws the mark should draw the same mark: the dock icon, the tab, notifications, the `codev --mini` badge and the landing page icon are now one geometry in one red. Cyan on `#131010` was the higher-contrast tile at 16px (~9.4:1 versus red's ~4.2:1) — a real cost, accepted so the brand reads consistently. | Keep our assets (binary: take ours wholesale). Regenerate with the script rather than hand-editing, and edit `icons/icon.svg` + `favicon-v3.svg` together if the geometry ever changes. |
| `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. |
Expand Down
13 changes: 11 additions & 2 deletions packages/desktop/icons/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,18 @@ The three channels are currently identical — the same red C on white ships as
dev, beta and prod icon. `generate-icons.ts` still writes each channel separately,
so giving a channel its own treatment later is a change to that script alone.

The same run also regenerates the web and PWA favicon set in
`packages/ui/src/assets/favicon/`, whose `favicon-v3.svg` is the hand-written 512-unit
copy of this geometry. One generator for both sets is deliberate: the dock icon and the
favicon drew different marks in different colors for a while, which is the drift a
shared source prevents. The tab and `.ico` icons keep the rounded tile; the
apple-touch and maskable manifest icons are square, because those platforms apply
their own mask and a pre-rounded icon leaves transparent corners that render black.

The generator rasterizes, encodes the PNGs and builds the `.ico` itself, so the only
external tool it needs is `iconutil` for `.icns` — which means it has to run on macOS.
This replaces the old Tauri-CLI + [Image2Icon](https://img2icnsapp.com/) workflow;
external tool it needs is `iconutil` for `.icns`. That one is macOS-only, so off macOS
the script skips `.icns` (leaving the committed file alone) and regenerates everything
else. This replaces the old Tauri-CLI + [Image2Icon](https://img2icnsapp.com/) workflow;
the Big Sur inset and drop shadow that step used to add are now applied directly to
the `.icns` members and to `dock.png` (824/1024 rounded square), while the Windows,
Linux and Store assets stay full-bleed.
Expand Down
55 changes: 44 additions & 11 deletions packages/desktop/scripts/generate-icons.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
// Fork: regenerates every app icon in icons/{dev,beta,prod}/ from the geometry
// in icons/icon.svg — the brand-red CoDev "C" on a white tile.
// Fork: regenerates every app icon in icons/{dev,beta,prod}/ — and the web/PWA
// favicon set in packages/ui/src/assets/favicon/ — from the geometry in
// icons/icon.svg: the brand-red CoDev "C" on a white tile.
//
// Both sets come from this one script on purpose. They drew different marks in
// different colors for a while (dock icon red, favicon cyan), which is exactly
// the drift a shared generator prevents.
//
// Replaces the manual Tauri-CLI + Image2Icon workflow the old icons/README.md
// described. Everything here is self-contained (raw rasterizer, PNG encoder, ICO
Expand All @@ -21,14 +26,17 @@ const CORNER = 229 / 1024
// shadow; anything full-bleed reads as oversized next to native icons.
const MACOS_TILE = 824 / 1024

type Style = "flat" | "macos"
// "square" is full-bleed with no corner radius: iOS rounds apple-touch-icon
// itself and a pre-rounded one leaves transparent corners that render black,
// and maskable PWA icons are cropped by the launcher for the same reason.
type Style = "flat" | "macos" | "square"

// Coverage of the rounded rect and of the "C" for one pixel, supersampled.
function coverage(size: number, style: Style) {
const samples = size <= 256 ? 8 : 4
const tile = size * (style === "macos" ? MACOS_TILE : 1)
const origin = (size - tile) / 2
const radius = tile * CORNER
const radius = style === "square" ? 0 : tile * CORNER
const unit = tile * UNIT
const mark = {
x: origin + (tile - unit * 4) / 2,
Expand Down Expand Up @@ -227,6 +235,19 @@ const FLAT_PNGS = [

const ICO_SIZES = [16, 24, 32, 48, 64, 128, 256]

// The web + PWA favicon set, served out of packages/app/public through symlinks.
// favicon-v3.svg next to these is the hand-written source of the same geometry.
// The tab/`.ico` icons keep the rounded tile so they read as an app icon; the
// apple-touch and maskable manifest icons are square, since their platforms
// apply their own mask.
const FAVICON_DIR = "../ui/src/assets/favicon"
const FAVICON_PNGS: ReadonlyArray<readonly [string, number, Style]> = [
["favicon-96x96-v3.png", 96, "flat"],
["apple-touch-icon-v3.png", 180, "square"],
["web-app-manifest-192x192.png", 192, "square"],
["web-app-manifest-512x512.png", 512, "square"],
]

// Apple's required iconset members: {logical size, @2x?}.
const ICONSET = [16, 32, 128, 256, 512].flatMap((n) => [
{ name: `icon_${n}x${n}.png`, size: n },
Expand All @@ -250,12 +271,24 @@ for (const channel of ["dev", "beta", "prod"]) {
await Bun.write(`${dir}/icon.ico`, ico(ICO_SIZES.map((size) => ({ size, data: flat.get(size)! }))))
await Bun.write(`${dir}/dock.png`, macos.get(256)!)

const iconset = `${dir}/icon.iconset`
await rm(iconset, { recursive: true, force: true })
await mkdir(iconset, { recursive: true })
await Promise.all(ICONSET.map((entry) => Bun.write(`${iconset}/${entry.name}`, macos.get(entry.size)!)))
await $`iconutil -c icns -o ${dir}/icon.icns ${iconset}`
await rm(iconset, { recursive: true, force: true })
// iconutil ships with macOS only, so everything else regenerates on any
// platform and the committed .icns is left as is.
if (process.platform === "darwin") {
const iconset = `${dir}/icon.iconset`
await rm(iconset, { recursive: true, force: true })
await mkdir(iconset, { recursive: true })
await Promise.all(ICONSET.map((entry) => Bun.write(`${iconset}/${entry.name}`, macos.get(entry.size)!)))
await $`iconutil -c icns -o ${dir}/icon.icns ${iconset}`
await rm(iconset, { recursive: true, force: true })
}

console.log(`Generated ${channel} icons in ${dir}`)
console.log(
`Generated ${channel} icons in ${dir}${process.platform === "darwin" ? "" : " (icon.icns skipped, needs macOS)"}`,
)
}

await Promise.all(
FAVICON_PNGS.map(([name, size, style]) => Bun.write(`${FAVICON_DIR}/${name}`, png(render(size, style), size))),
)
await Bun.write(`${FAVICON_DIR}/favicon-v3.ico`, ico(ICO_SIZES.map((size) => ({ size, data: flat.get(size)! }))))
console.log(`Generated favicons in ${FAVICON_DIR}`)
Binary file modified packages/ui/src/assets/favicon/apple-touch-icon-v3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/ui/src/assets/favicon/favicon-96x96-v3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/ui/src/assets/favicon/favicon-v3.ico
Binary file not shown.
22 changes: 17 additions & 5 deletions packages/ui/src/assets/favicon/favicon-v3.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/ui/src/assets/favicon/web-app-manifest-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified packages/ui/src/assets/favicon/web-app-manifest-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading