From c3254ca00ccc1ba7c92a98adcbfd1e5f11ec545a Mon Sep 17 00:00:00 2001 From: Carl <3e3d196dd9859e7da50eb419bfc7e219beb702c8730adc23dfec69f30d5064df@buzz.block.builderlab.xyz> Date: Mon, 21 Sep 2026 15:46:28 -0700 Subject: [PATCH 1/2] Label macOS worktree Dock icons through the shared launcher Signed-off-by: Carl <3e3d196dd9859e7da50eb419bfc7e219beb702c8730adc23dfec69f30d5064df@buzz.block.builderlab.xyz> --- docs/contributing.md | 18 ++ scripts/desktop-dev.mjs | 22 ++- scripts/generate-dev-icon.swift | 216 +++++++++++++++++++++++ scripts/worktree-icon.mjs | 70 ++++++++ tests/integration/dev-commands.test.mjs | 4 + tests/integration/worktree-icon.test.mjs | 185 +++++++++++++++++++ 6 files changed, 506 insertions(+), 9 deletions(-) create mode 100644 scripts/generate-dev-icon.swift create mode 100644 scripts/worktree-icon.mjs create mode 100644 tests/integration/worktree-icon.test.mjs diff --git a/docs/contributing.md b/docs/contributing.md index 9ede80cdd..17f1b3da8 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -106,6 +106,24 @@ do not copy private keys, `node_modules`, build output, `.npmrc`, or other ignor files. Install hooks separately as described below so existing custom hooks are never silently replaced. +### Worktree Dock labels (macOS) + +`just desktop` adds the current branch suffix to the Dock icon in linked Git +worktrees (for example, `person/my-feature` shows `my-feature`). Detached +worktrees use the checkout directory name. Restart the desktop command after +switching or renaming a branch; no Cargo clean is needed. + +The launcher reuses the existing badge design and generates an icon under the +ignored `src-tauri/target/dev-icons/` directory. The generated bytes determine its +filename, so changed labels, source artwork, or rendering update Tauri's embedded +icon even with a warm build. Generation requires macOS Swift/AppKit and `iconutil`; +if it fails, startup warns and continues with the ordinary icon. Explicit Tauri +`--config` arguments still take precedence over the generated icon and port. + +Ordinary checkouts, non-macOS launches, and `pnpm tauri build` keep their existing +icons. This does not change the app identifier, credentials, profiles, ports, or +notification settings. + ## Interactive product iteration While shaping the first version, default to **edit → human tries the running app diff --git a/scripts/desktop-dev.mjs b/scripts/desktop-dev.mjs index c0131ad3d..e541ff66e 100644 --- a/scripts/desktop-dev.mjs +++ b/scripts/desktop-dev.mjs @@ -1,4 +1,6 @@ import { spawnSync } from "node:child_process"; +import { fileURLToPath } from "node:url"; +import { worktreeIcon } from "./worktree-icon.mjs"; const args = process.argv.slice(2); const forwarded = []; @@ -23,18 +25,20 @@ for (; index < args.length && args[index] !== "--"; index++) { } } +const config = {}; +const icon = worktreeIcon(fileURLToPath(new URL("../", import.meta.url))); +if (icon) config.bundle = { icon: [icon] }; if (port !== undefined) { // Tauri's own --port controls its static-file server, not our Vite server. + config.build = { + devUrl: `http://localhost:${port}`, + beforeDevCommand: `pnpm dev:desktop --port ${port}`, + }; +} +if (Object.keys(config).length) { // Prepend: Tauri treats everything after a bare positional as runner args. - forwarded.unshift( - "--config", - JSON.stringify({ - build: { - devUrl: `http://localhost:${port}`, - beforeDevCommand: `pnpm dev:desktop --port ${port}`, - }, - }), - ); + // Explicit user configs merge afterward and retain precedence. + forwarded.unshift("--config", JSON.stringify(config)); } // Runner/application arguments after -- belong to Tauri, including any --port. forwarded.push(...args.slice(index)); diff --git a/scripts/generate-dev-icon.swift b/scripts/generate-dev-icon.swift new file mode 100644 index 000000000..b324478cc --- /dev/null +++ b/scripts/generate-dev-icon.swift @@ -0,0 +1,216 @@ +#!/usr/bin/env swift + +import AppKit +import Foundation + +// Ported from block/buzz scripts/generate-dev-icon.swift. +// Generate a dev icon with worktree name badge +// Usage: generate-dev-icon.swift