Skip to content

fix(desktop): brand the install and updater cache directories - #266

Merged
quickbeard merged 2 commits into
mainfrom
brand-install-dirs
Aug 19, 2026
Merged

quickbeard merged 2 commits into
mainfrom
brand-install-dirs

Conversation

@quickbeard

@quickbeard quickbeard commented Aug 19, 2026 •

Copy link
Copy Markdown
Owner

@opencode-aidesktop was on screen. On Windows the app installed itself into %LOCALAPPDATA%\Programs\@opencode-aidesktop and kept downloaded updates in @opencode-aidesktop-updater beside it.

Neither name comes from productName. A one-click perMachine: false install takes appInfo.sanitizedName — getWindowsInstallationDirName(appInfo, !oneClick || isPerMachine) returns productFilename only when that flag is true, and for us both operands are false. updaterCacheDirName is the same string plus -updater, and it is baked into app-update.yml on every platform, so the leak was not Windows-only.

The fix

Override the derived name with extraMetadata.name instead of renaming the workspace package. DIVERGENCES keeps @opencode-ai/* package ids upstream on purpose, and that rule is still right — the package id stays @opencode-ai/desktop; only what the packager derives from it changes. extraMetadata merges into the metadata appInfo reads (packager.js:277), so this decouples the internal id from the user-visible one.

Per channel, like appId: the old value was channel-independent, so dev, beta and prod all installed over the same directory and shared one updater cache. Single-sourced with rpm.packageName — the same identity on Linux — as PACKAGE_NAMES, so the two cannot drift.

before after
install dir Programs\@opencode-aidesktop (all channels) Programs\codev / codev-beta / codev-dev
updater cache @opencode-aidesktop-updater (all channels) codev-updater / codev-beta-updater / codev-dev-updater

The .deb package name is not affected, despite also deriving from this name. An earlier revision of this description claimed it went CoDev → codev; that was wrong. FpmTarget passes appInfo.linuxPackageName straight to fpm, and fpm normalizes the name itself — it downcases with a warning and turns the space into a hyphen. Run against the cached fpm 1.17.0 directly:

input resulting Package:
CoDev codev
CoDev Beta codev-beta
CoDev Dev codev-dev

A prod .deb built from main before this branch confirms it: dpkg-deb -f reports Package: codev. So on the deb this change only silences an fpm warning. macOS derives nothing from the name either. Windows and the updater cache are the whole user-visible effect.

Verification

Confirmed against a real packaged build, not just by reading the source — both of these derive from sanitizedName:

  • dist/win-unpacked/resources/app-update.yml now reads updaterCacheDirName: codev-updater
  • the intermediate NSIS archive is codev-1.18.4-8-x64.nsis.7z, previously @opencode-aidesktop-…

Not directly observed: the install directory itself, which would mean running the installer. Its define is getWindowsInstallationDirName, a two-line pure function returning sanitizedName on this path, and the two artifacts above pin sanitizedName to codev.

electron-builder.config.test.ts covers the new name per channel. Full desktop suite: 136 pass, 1 fail — ships and re-signs the codev-vmm helper on macOS, which fails on main too (a toEndWith assertion using forward slashes against a path.join result on Windows). Untouched here.

Scope

Also updates DIVERGENCES per the fork's rule, including the Known rebrand gaps section, whose "Internal names" bullet justified keeping @opencode-ai/* as "names users never see" — no longer true for the desktop package, so the bullet now records the exception and the fix.

Rescanned the desktop package for the same shape of leak. The persisted store file names (opencode.settings, opencode.{draft,workspace,global,window,updater}.* under %APPDATA%\ai.codev.desktop) are equally visible but are not renamed here: unlike a derived name, renaming those orphans existing state and needs a migration. Deliberately untouched too, per the existing table row: the basic-auth username "opencode" (must match the server default), the Tauri app ids in migrate.ts, the ../opencode/dist build paths, and the WSL installer URL/CLI path, which are real external identifiers.

🤖 Generated with Claude Code

The Windows per-user install directory and the updater cache directory
both come from package.json `name`, not from productName: a one-click
perMachine:false install takes appInfo.sanitizedName
(getWindowsInstallationDirName), and updaterCacheDirName is that same
string plus "-updater". So the app installed itself into
%LOCALAPPDATA%\Programs\@opencode-aidesktop and cached updates in
@opencode-aidesktop-updater beside it.

Override the derived name with extraMetadata.name rather than renaming
the workspace package, which DIVERGENCES keeps upstream on purpose. Per
channel, like appId: one shared value installed every channel over the
same directory and shared one updater cache. Single-sourced with
rpm.packageName, which is the same identity on Linux, as PACKAGE_NAMES.

This also makes the Debian package name lowercase and space-free, as
Debian requires — it defaults to sanitizedProductName when
deb.packageName is unset, i.e. "CoDev Dev" on the dev channel.

Verified in a packaged build: app-update.yml reads
`updaterCacheDirName: codev-updater`, and the intermediate NSIS archive
is now codev-1.18.4-8-x64.nsis.7z rather than @opencode-aidesktop-…,
both of which derive from sanitizedName.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The PR said this change renames the Debian package from `CoDev` to
`codev`. It does not: `FpmTarget` hands `appInfo.linuxPackageName` to
fpm, and fpm normalizes the name itself — it downcases with a warning
and turns the space into a hyphen. Checked against the cached fpm 1.17.0
directly: `CoDev` -> `codev`, `CoDev Beta` -> `codev-beta`, `CoDev Dev`
-> `codev-dev`. A prod `.deb` built from main before this branch already
reported `Package: codev`.

So `extraMetadata.name` changes two user-visible things, not three: the
Windows per-user install directory and the updater cache directory. On
the deb it only silences an fpm warning.

Corrects the CHANGELOG entry, the DIVERGENCES row, and the config
comment that each restated it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@quickbeard
quickbeard merged commit 536bb24 into main Aug 19, 2026
0 of 5 checks passed
@quickbeard
quickbeard deleted the brand-install-dirs branch August 19, 2026 02:51
quickbeard added a commit that referenced this pull request Aug 19, 2026
The installer was one-click: no pages, no questions, and no way to put
the app anywhere but the default. Make it assisted and add the directory
page, so the user can take the default location or browse for their own.

allowToChangeInstallationDirectory is rejected outright when oneClick is
true, so both move together. perMachine stays false: the install-mode
page (all users / only for me) comes with any assisted installer and
cannot be suppressed without forcing per-machine, so it is there, but
only-for-me remains the default and nothing needs admin rights.

Updates install with /S. quitAndInstall() defaults to isSilent = false,
which for an assisted installer would walk every update through the full
wizard and re-ask for a location the user already chose; isForceRunAfter
is honoured only alongside isSilent, so both arguments are set.

Knock-on to #266, now corrected in the config comment, DIVERGENCES and
CHANGELOG: the Windows install directory no longer derives from
extraMetadata.name. getWindowsInstallationDirName falls back to
sanitizedName only for a one-click per-user install, so the default is
productFilename ("CoDev") instead of "codev". The override still names
the updater cache directory, which is what keeps it load-bearing.

Verified by packaging: electron-builder logs `oneClick=false
perMachine=false` and app-update.yml still reads
`updaterCacheDirName: codev-updater`.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant