Skip to content

Commit e2fa95d

Browse files
authored
Show "Ness" instead of "harness" in the macOS app menu (#300)
## Problem The macOS app menu's items read **"About harness"**, **"Hide harness"**, and **"Quit harness"**. The menu bar *title* is already correct ("Ness") because macOS takes that from `CFBundleName`, which electron-builder sets from `build.productName`. But the submenu items come from `app.name`, which Electron derives from `package.json`'s top-level `"name"` — still `"harness"`. ## Why not just rename the package `package.json`'s `"name": "harness"` is load-bearing, and CLAUDE.md documents it. `app.getName()` keys **both**: - the userData directory (`~/Library/Application Support/harness`), and - the macOS Safe Storage keychain item (service `harness Safe Storage`, account `harness Key`). The filesystem is case-insensitive but **the keychain is not**, so renaming the package — or calling `app.setName('Ness')` at boot — would break `safeStorage` decryption of `secrets.enc` (GitHub PAT, backend tokens) with *"A keychain can not be found to store …"*. Same reasoning that keeps `build.appId` at `org.mikelyons.harness`. So the fix is explicit labels, not a rename. ## The change All in `src/main/desktop-shell.ts`: - New module-level `APP_DISPLAY_NAME = 'Ness'` constant, with a "why" comment noting it is deliberately **not** `app.name`. - `buildMenu()`: explicit labels on `about`, `hide`, and `Quit` (and the app-menu `label`, which macOS ignores in favor of `CFBundleName` but is kept consistent). `hideOthers` / `unhide` need no change — they render "Hide Others" / "Show All" with no app name. - `app.setAboutPanelOptions({ applicationName, applicationVersion })` on darwin at ready, so the About *dialog* behind the menu item stops showing "harness" too. No behavior outside the menu changes; `app.name` is untouched everywhere it matters (paths, keychain). ## Verification - `npm run typecheck` — clean - `npx electron-vite build` — clean - `npx vitest run` — 2987 tests / 227 files pass - Menu confirmed visually by @blindpirate in a dev build One note for reviewers: this machine's C++ toolchain can't build `node-pty` (a bare `#include <functional>` fails system-wide), so the dev app runs but PTY spawns fail with `posix_spawnp failed`. That's a pre-existing local environment issue, unrelated to this change, and it doesn't affect the menu. _PR opened on behalf of @blindpirate by Claude via [Ness](https://github.com/ness-dev/ness)._
1 parent ebc3079 commit e2fa95d

1 file changed

Lines changed: 16 additions & 4 deletions

File tree

src/main/desktop-shell.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ export interface DesktopShellEarlyHandle {
6868
transport: ElectronServerTransport
6969
}
7070

71+
/** User-facing product name. Deliberately NOT `app.name` — package.json's
72+
* `name` stays "harness" because it keys the userData directory and the
73+
* macOS Safe Storage keychain item (see CLAUDE.md), so renaming it or
74+
* calling `app.setName()` would break secrets.enc decryption. */
75+
const APP_DISPLAY_NAME = 'Ness'
76+
7177
/** Where the web-client bundle lives at runtime. Differs between
7278
* packaged builds (asar-relative) and dev / unpacked (sibling of the
7379
* main bundle output). Lives here so index.ts doesn't need to call
@@ -411,17 +417,17 @@ export function startDesktopShell(deps: DesktopShellStartDeps): DesktopShellStar
411417
function buildMenu(): void {
412418
const template: Electron.MenuItemConstructorOptions[] = [
413419
{
414-
label: app.name,
420+
label: APP_DISPLAY_NAME,
415421
submenu: [
416-
{ role: 'about' },
422+
{ role: 'about', label: `About ${APP_DISPLAY_NAME}` },
417423
{ type: 'separator' },
418424
{
419425
label: 'Settings…',
420426
accelerator: 'CmdOrCtrl+,',
421427
click: () => transport.sendSignal('app:openSettings')
422428
},
423429
{ type: 'separator' },
424-
{ role: 'hide' },
430+
{ role: 'hide', label: `Hide ${APP_DISPLAY_NAME}` },
425431
{ role: 'hideOthers' },
426432
{ role: 'unhide' },
427433
{ type: 'separator' },
@@ -444,7 +450,7 @@ export function startDesktopShell(deps: DesktopShellStartDeps): DesktopShellStar
444450
// AND keyup) flows to our handlers, where the hold gesture lives.
445451
// Menu click still quits immediately.
446452
{
447-
label: `Quit ${app.name}`,
453+
label: `Quit ${APP_DISPLAY_NAME}`,
448454
click: () => app.quit()
449455
}
450456
]
@@ -802,6 +808,12 @@ export function startDesktopShell(deps: DesktopShellStartDeps): DesktopShellStar
802808
log('app', 'failed to set dock icon', err instanceof Error ? err.message : err)
803809
}
804810
}
811+
if (process.platform === 'darwin') {
812+
app.setAboutPanelOptions({
813+
applicationName: APP_DISPLAY_NAME,
814+
applicationVersion: app.getVersion()
815+
})
816+
}
805817
buildMenu()
806818
void runBoot()
807819
createWindow()

0 commit comments

Comments
 (0)