Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
8de254a
Use client-side fallbacks for missing project favicons (#3959)
juliusmarminge Jul 14, 2026
735240f
Skip stale working-task notifications (#3961)
juliusmarminge Jul 14, 2026
3513fa0
Prepare Android beta branding and review diff UI (#3967)
juliusmarminge Jul 14, 2026
2fdc704
perf(web): duty-cycle status animations and remove fixed noise overla…
t3dotgg Jul 15, 2026
7b928d5
fix(docs): correct CI task-runner commands in ci.md (#3990)
kridaydave Jul 15, 2026
c69120f
fix(docs): repair broken source links in architecture overview (#3991)
kridaydave Jul 15, 2026
4624426
fix(docs): replace stale codething-mvp absolute paths with repo-relat…
kridaydave Jul 15, 2026
d359789
docs: Add T3 Code Legal Docs (#3972)
juliusmarminge Jul 15, 2026
ecb35f7
Fix Legal modal header crash (#4000)
juliusmarminge Jul 15, 2026
b982337
[codex] Fix onboarding connection status (#4001)
juliusmarminge Jul 16, 2026
5e8b2c8
Isolate native diff highlight grammar state (#4029)
juliusmarminge Jul 16, 2026
0418301
Fix macOS fullscreen titlebar spacing (#4019)
D3OXY Jul 16, 2026
d114e27
Prevent duplicate project workspace roots (#3829)
juliusmarminge Jul 16, 2026
54f167e
Normalize over-indented markdown list items (#4020)
juliusmarminge Jul 16, 2026
bde0a4c
Resolve localhost preview URLs for remote environments (#4011)
juliusmarminge Jul 16, 2026
2a33a18
fix(mobile): Send composer images in upload wire format (#4035)
juliusmarminge Jul 16, 2026
5d68fca
Fix iOS terminal Enter input encoding (#4043)
juliusmarminge Jul 16, 2026
fdca154
Add native mobile share target support (#4021)
juliusmarminge Jul 16, 2026
8a02c71
[codex] Expand real-route app store screenshot harness (#4014)
juliusmarminge Jul 17, 2026
eb733c1
fix(server): use CLAUDE_CONFIG_DIR instead of HOME for Claude instanc…
dmstoykov Jul 17, 2026
c14a5ca
Fix dropped events during initial thread snapshot (#4079)
D3OXY Jul 17, 2026
1f27973
feat: show nightly update changelog tooltip (#3832)
HugoVizcainoSantana Jul 17, 2026
58302b2
fix(git): treat selected commit paths literally (#3998)
EricTsai83 Jul 17, 2026
8b54698
fix(server): stabilize non-repository Git diagnostics (#4077)
EricTsai83 Jul 17, 2026
6e9987c
Refresh app icons across release variants (#4080)
juliusmarminge Jul 17, 2026
0748134
Update marketing GitHub star count (#4088)
AmoonPod Jul 17, 2026
4804a98
fix(marketing): correct Cursor icon color (#4090)
AmoonPod Jul 17, 2026
c49d424
Normalize protocol-relative remote host input as https (#3971)
kridaydave Jul 17, 2026
7f1cb61
fix(cursor): default binary path to cursor-agent (avoid path conflict…
BunnyGamezsc Jul 17, 2026
f9a4f59
Fix documented task-runner commands (bun run -> vp) (#3965)
kridaydave Jul 17, 2026
a7f6d97
Allow preview panel to grow on wide displays (#4044)
olivoil Jul 17, 2026
e057e2e
fix: prevent initial right-click from selecting a context menu item (…
Fazalkadivar21 Jul 17, 2026
7dc7512
Fix duplicate keybinding rule when replacing with an existing rule (#…
kridaydave Jul 17, 2026
ed81c15
fix(server): image upload crashed dispatchCommand with a stack overfl…
t3dotgg Jul 17, 2026
b49a2e6
Remove unused code parameter from describePreviewError (#3970)
kridaydave Jul 17, 2026
bcd640b
[codex] prevent ACP assistant ID collisions after restarts (#3932)
maxwellyoung Jul 17, 2026
7b8d126
fix(web): inset Windows desktop scrollbars from resize edge (#4097)
nateEc Jul 17, 2026
6a17629
[codex] fix mobile composer Enter behavior (#3930)
maxwellyoung Jul 17, 2026
cf58cad
feat(server): include runtime model and effort in Codex developer ins…
t3dotgg Jul 17, 2026
143b9c9
fix(ux): spamming cmd + , no longer stack opening settings (#2757)
jamesx0416 Jul 17, 2026
1047dac
fix(terminal): strip AppImage runtime env from spawned terminals (#3108)
leorivastech Jul 17, 2026
4e3f2f0
fix(server): thread cwd through Claude capability probe (#2048) (#2124)
mvanhorn Jul 17, 2026
b655a9f
[codex] fix: guard invalid web timestamps (#3515)
StiensWout Jul 17, 2026
43e2aea
[codex] fix: tolerate invalid latest user message timestamps (#3521)
StiensWout Jul 17, 2026
73bf127
[codex] Fix provider update checks restore defaults (#3531)
StiensWout Jul 17, 2026
31ca9e5
fix(server): skip undecodable provider runtime rows when listing sess…
t3dotgg Jul 17, 2026
24f9c2a
Share MCP OAuth locks across Codex shadow homes (#4104)
juliusmarminge Jul 17, 2026
8b33799
Preserve T3 Code identity in macOS development launcher (#4102)
juliusmarminge Jul 17, 2026
5ca3266
fix(web): increase contrast of question option descriptions (#3867)
xxashxx-svg Jul 17, 2026
1bd2fa2
feat: draft hero landing on the index route (#4055)
yordis Jul 18, 2026
4cfec8c
feat: file explorer mention actions and zoom-aware context menus (#4054)
yordis Jul 18, 2026
2318e00
fix(web): avoid duplicate mention text on paste
juliusmarminge Jul 18, 2026
03e20c8
fix(mobile): restore iOS home screen branding (#4025)
PixPMusic Jul 18, 2026
765e1b5
perf(client): defer active thread cache writes (#4006)
Chrrxs Jul 18, 2026
38e0bb0
Default diffs to working changes (#3974)
jakeleventhal Jul 18, 2026
e350c0a
Add Grok to marketing site provider list (#3484)
Aditya190803 Jul 18, 2026
31caa56
Fix reopening existing Diff tab (#3973)
jakeleventhal Jul 18, 2026
d8b12ae
Fix sending messages during active turns (#3919)
jakeleventhal Jul 18, 2026
d0b9f8d
[codex] Route OpenCode missing-session errors through Effect (#3608)
StiensWout Jul 18, 2026
c0e161a
[fix/feat:ui] Show default option badge (#3232)
sandersonstabo Jul 18, 2026
e63403f
[fix/feat:ui] Preserve open-in editor brand colors (#3225)
sandersonstabo Jul 18, 2026
b859a57
fix(web): handle macOS Home and End in composer (#2508)
GuilhermeVieiraDev Jul 18, 2026
0506508
Allow failed remote environments to be removed (#4084)
zepi2509 Jul 18, 2026
da3c203
[codex] canonicalize client timestamps (#4112)
maxwellyoung Jul 18, 2026
5c66110
[fix/feat:ui] Make selected menu checks blue (#3234)
sandersonstabo Jul 18, 2026
bf76535
fix(desktop): Validate WSL node version against engine range after pr…
UtkarshUsername Jul 18, 2026
ebe8afb
Refresh splash screen and favicon branding (#4120)
juliusmarminge Jul 18, 2026
1735e27
Add terminal selection copy action (#2904)
tarik02 Jul 18, 2026
4f11740
Add isolated app testing workflow (#4121)
juliusmarminge Jul 19, 2026
53e3c98
feat(web): themed sidebar header art for nightly and dev builds (#4130)
maria-rcks Jul 19, 2026
48a3f2c
Merge remote-tracking branch 'upstream/main' into t3code/upstream-syn…
Jul 19, 2026
9566a3e
docs(upstream-sync): 20 — cadence pull v0.0.29-nightly.20260712.791 →…
Jul 19, 2026
f306dd4
fix(web): adopt upstream draft-hero index, retire loom goal overview
Jul 20, 2026
d77df9c
Merge remote-tracking branch 'origin/main' into t3code/upstream-sync-…
Jul 20, 2026
932258e
docs(upstream-sync): record loom PR #115 shell catch-up integration i…
Jul 20, 2026
5b5456e
Merge remote-tracking branch 'origin/main' into t3code/upstream-sync-…
Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
69 changes: 69 additions & 0 deletions .agents/skills/test-t3-app/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: test-t3-app
description: Launch and test the T3 Code web app in isolated development environments, including first-try browser authentication with one-time pairing URLs, pairing-token recovery, worktree-safe state directories, dev server lifecycle, and direct SQLite inspection or fixture seeding. Use when an agent needs to run T3 locally, test UI behavior in a browser, recover from an expired or consumed pairing token, isolate dev state, or prepare test data in state.sqlite.
---

# Test T3 App

## Start an isolated web environment

1. Run commands from the repository root.
2. Choose a base directory that belongs only to the current worktree or test:
- Use the repository's ignored `.t3` directory for reusable worktree-local state.
- Use `mktemp -d /tmp/t3code-test.XXXXXX` for disposable state and retain the printed absolute path.
3. Start the full web stack with `vp run dev --home-dir <base-dir>`.
4. Keep the terminal session alive and read the selected server port, web port, base directory, and pairing URL from its output.

Treat a base directory as disposable only when it was created or deliberately selected for the current test. Never delete or directly seed the shared `~/.t3` directory. Prefer starting with a new temporary base directory over clearing state of uncertain ownership.

The dev runner disables browser auto-open by default. Do not pass `--browser` during automated testing: an automatically opened page can consume the one-time bootstrap token before the controlled browser uses it.

## Authenticate the browser on the first navigation

1. Wait for the server log that says authentication is required and includes a URL ending in `/pair#token=...`.
2. Use the controlled in-app browser or browser-automation surface available to the agent. Do not use a system-browser launch command during automated testing.
3. Open that complete URL exactly once as the controlled browser's first navigation. Preserve the fragment and token verbatim.
4. Wait for the pairing exchange and redirect to finish before navigating elsewhere.
5. Continue in the same browser context so its stored bearer session remains available.

Treat pairing URLs as secrets. Do not copy them into final responses, screenshots, committed files, or durable logs. A pairing token is short-lived and single-use; opening the URL in another browser or opening it twice can consume it.

## Recover a consumed or expired pairing token

Create another token against the same database and web URL as the running dev server:

```bash
T3CODE_PORT=<server-port> node apps/server/src/bin.ts auth pairing create \
--base-dir <base-dir> \
--dev-url <web-url> \
--base-url <web-url> \
--ttl 15m \
--label agent-ui-test
```

Use the `Pair URL` from this command once. Derive `<server-port>` and `<web-url>` from the current dev-runner output, including any automatically selected port offset. Setting `T3CODE_PORT` keeps the administrative CLI from probing for an unrelated free port.

Always pass `--dev-url` for a dev-runner environment so the generated pairing URL uses the current web origin. An explicit base directory stores runtime state in `<base-dir>/userdata`; the `<base-dir>/dev` fallback is only used by an implicit dev home. Use `auth pairing list` to inspect active token metadata; it intentionally cannot reveal token secrets.

## Inspect or seed SQLite state

Read [references/sqlite-fixtures.md](references/sqlite-fixtures.md) before changing the database.

- Use `node apps/server/scripts/t3-sqlite-state.ts query` for schema discovery and read-only checks.
- Stop the dev server before using `node apps/server/scripts/t3-sqlite-state.ts exec`, then restart it with the same base directory.
- Seed projection tables only for disposable UI fixtures. Use application commands and APIs when testing business behavior or projection correctness.
- Use the auth CLI, not direct `auth_*` table edits, for pairing and sessions.

The helper refuses to write to the shared `~/.t3` directory by default and creates a database backup before each mutation.

## Finish the test

Stop the dev process with its terminal interrupt. Preserve the isolated base directory when it contains useful reproduction evidence; otherwise remove only a path that was created for this test after resolving and verifying the exact target. A fresh isolated base directory is the safest reset when authentication, migrations, or fixture state becomes ambiguous.

## Troubleshoot predictably

- If the browser shows an unauthenticated pairing screen, issue a new token instead of retrying the consumed URL.
- If the pairing URL is no longer visible, create a replacement token with both `--dev-url` and `--base-url`.
- If the replacement token is rejected, verify that the CLI and server use the identical absolute base directory and web URL.
- If the UI shows unexpected data, verify that every command uses the identical explicit base directory before editing anything.
- If ports move because another instance is running, trust the current dev-runner output rather than assuming ports `13773` and `5733`.
4 changes: 4 additions & 0 deletions .agents/skills/test-t3-app/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "T3 App Testing"
short_description: "Launch and seed isolated T3 test environments"
default_prompt: "Use $test-t3-app to launch an isolated T3 development environment and test it in the browser."
58 changes: 58 additions & 0 deletions .agents/skills/test-t3-app/references/sqlite-fixtures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# SQLite fixtures

Load this reference only when inspecting or seeding local T3 state directly.

## Select the correct database

When `--base-dir` or `--home-dir` is explicit, runtime state lives under `<base-dir>/userdata` and the database path is `<base-dir>/userdata/state.sqlite`. The `<base-dir>/dev` state directory is only the fallback for an implicit development home, preventing an ordinary `vp run dev` from touching production state.

Start the target runtime once before seeding so all migrations have run. Use an isolated base directory. Stop the server before writes to avoid racing application state or an active projection.

## Use the helper

List tables:

```bash
node apps/server/scripts/t3-sqlite-state.ts query \
--base-dir <base-dir> \
--sql "SELECT name FROM sqlite_schema WHERE type = 'table' ORDER BY name"
```

Inspect current columns before writing a fixture:

```bash
node apps/server/scripts/t3-sqlite-state.ts query \
--base-dir <base-dir> \
--sql "PRAGMA table_info(projection_threads)"
```

Apply a SQL fixture from a file:

```bash
node apps/server/scripts/t3-sqlite-state.ts exec \
--base-dir <base-dir> \
--file /tmp/t3-seed.sql
```

Use one statement per invocation for both `query` and `exec`; the helper wraps writes in a transaction and prints the backup path after a successful mutation. Use a single insert with multiple value rows when a fixture needs several records.

## Seed projection data carefully

The web UI primarily reads these projection tables:

- `projection_projects`
- `projection_threads`
- `projection_thread_messages`
- `projection_thread_activities`
- `projection_thread_sessions`
- `projection_turns`
- `projection_pending_approvals`
- `projection_thread_proposed_plans`

Inspect `PRAGMA table_info(<table>)` and the current migrations under `apps/server/src/persistence/Migrations/` before constructing inserts. Keep identifiers unique, timestamps as ISO strings, JSON columns valid, and related project/thread/turn IDs consistent.

For a substantial current example, inspect `seedDatabase` in `scripts/mobile-showcase-environment.ts`. Adapt its column set to the target database instead of assuming copied SQL remains current.

Direct projection writes are appropriate for ephemeral visual states, edge-case counts, long titles, activity lists, and similar UI fixtures. They do not create a coherent orchestration event history. Do not modify `orchestration_events` unless the test specifically exercises projector internals, and do not use direct projection writes to claim backend business behavior works.

Use the app's commands or APIs for behavior tests. Use `node apps/server/src/bin.ts auth ...` for auth state rather than editing `auth_pairing_links` or `auth_sessions`.
134 changes: 134 additions & 0 deletions .github/workflows/mobile-showcase-screenshots.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: Mobile Showcase Screenshots

on:
workflow_dispatch:
inputs:
platform:
description: Device platforms to capture
required: true
default: all
type: choice
options:
- all
- ios
- android
appearance:
description: System appearances to capture
required: true
default: both
type: choice
options:
- both
- dark
- light

permissions:
contents: read

env:
NODE_OPTIONS: --max-old-space-size=8192

jobs:
ios:
name: iPhone 6.9, iPhone 6.5, and iPad 13
if: inputs.platform == 'all' || inputs.platform == 'ios'
runs-on: blacksmith-12vcpu-macos-26
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Vite+
uses: voidzero-dev/setup-vp@v1
with:
node-version-file: package.json
cache: true
run-install: true

- name: Expose pnpm
run: |
pnpm_version="$(node --print "require('./package.json').packageManager.split('@').pop()")"
vp_pnpm_bin="$HOME/.vite-plus/package_manager/pnpm/$pnpm_version/pnpm/bin"
echo "$vp_pnpm_bin" >> "$GITHUB_PATH"
"$vp_pnpm_bin/pnpm" --version

- name: Capture iOS showcase
run: pnpm screenshots:mobile --platform ios --appearance "${{ inputs.appearance }}"

- name: Validate App Store Connect assets
run: pnpm screenshots:mobile --platform ios --appearance "${{ inputs.appearance }}" --validate-only

- name: Upload iOS screenshots
if: always()
uses: actions/upload-artifact@v7
with:
name: app-store-connect-screenshots
path: artifacts/app-store/screenshots/apple/
if-no-files-found: warn
retention-days: 14

android:
name: Android phone, 7-inch tablet, and 10-inch tablet
if: inputs.platform == 'all' || inputs.platform == 'android'
runs-on: blacksmith-16vcpu-ubuntu-2404
timeout-minutes: 60
env:
T3_SHOWCASE_ANDROID_ABI: x86_64
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Vite+
uses: voidzero-dev/setup-vp@v1
with:
node-version-file: package.json
cache: true
run-install: true

- name: Expose pnpm
run: |
pnpm_version="$(node --print "require('./package.json').packageManager.split('@').pop()")"
vp_pnpm_bin="$HOME/.vite-plus/package_manager/pnpm/$pnpm_version/pnpm/bin"
echo "$vp_pnpm_bin" >> "$GITHUB_PATH"
"$vp_pnpm_bin/pnpm" --version

- name: Setup Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 17

- name: Setup Gradle cache
uses: gradle/actions/setup-gradle@v5

- name: Enable KVM
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS="static_node=kvm"' \
| sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

- name: Capture Android showcase
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 36
target: google_apis
arch: x86_64
profile: pixel_7_pro
avd-name: Pixel_10_Pro
cores: 8
ram-size: 4096M
disable-animations: false
script: pnpm screenshots:mobile --platform android --appearance "${{ inputs.appearance }}"

- name: Validate Google Play assets
run: pnpm screenshots:mobile --platform android --appearance "${{ inputs.appearance }}" --validate-only

- name: Upload Android screenshots
if: always()
uses: actions/upload-artifact@v7
with:
name: google-play-screenshots
path: artifacts/app-store/screenshots/google-play/
if-no-files-found: warn
retention-days: 14
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ squashfs-root/
.gstack/
dist-electron/
.electron-runtime/
.showcase/
apps/mobile/.showcase/
artifacts/app-store/screenshots/
node_modules/
.alchemy/
*.log
Expand Down
4 changes: 1 addition & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ UI-affecting changes should be verified live in the browser, not just by static
## Reference Repos

- Open-source Codex repo: https://github.com/openai/codex
- Codex-Monitor (Tauri, feature-complete, strong reference implementation): https://github.com/Dimillian/CodexMonitor

Use these as implementation references when designing protocol handling, UX flows, and operational safeguards.

Expand All @@ -70,8 +69,7 @@ agents.
- Prefer examples and patterns from the vendored source code over generated guesses or web search results.
- Do not edit files under `.repos/` unless explicitly asked.
- Do not import from `.repos/`; application code must continue importing from normal package dependencies.
- Manage vendored subtrees with `bun run sync:repos`; use `bun run sync:repos --repo <id>` to sync one
configured repository.
- Manage vendored subtrees with `vpr sync:repos`; use `vpr sync:repos --repo <id>` to sync one configured repository.
- When updating a dependency with a configured vendored subtree, sync that subtree in the same change so
`.repos/` matches the installed dependency version.
- When writing Effect code, read `.repos/effect-smol/LLMS.md` first and inspect `.repos/effect-smol/` for
Expand Down
43 changes: 34 additions & 9 deletions apps/desktop/scripts/electron-launcher.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const APP_BUNDLE_ID = isDevelopment
? `com.t3tools.t3code.dev.${devBundleIdSuffix || "local"}`
: "com.t3tools.t3code";
const APP_PROTOCOL_SCHEMES = isDevelopment ? ["t3code-dev"] : ["t3code"];
const LAUNCHER_VERSION = 12;
const LAUNCHER_VERSION = 14;
const defaultIconPath = NodePath.join(desktopDir, "resources", "icon.icns");
const developmentMacIconPngPath = NodePath.join(
repoRoot,
Expand Down Expand Up @@ -220,11 +220,12 @@ function ensureDevelopmentIconIcns(runtimeDir) {
}
}

function patchMainBundleInfoPlist(appBundlePath, iconPath) {
function patchMainBundleInfoPlist(appBundlePath, iconPath, executableName) {
const infoPlistPath = NodePath.join(appBundlePath, "Contents", "Info.plist");
setPlistString(infoPlistPath, "CFBundleDisplayName", APP_DISPLAY_NAME);
setPlistString(infoPlistPath, "CFBundleName", APP_DISPLAY_NAME);
setPlistString(infoPlistPath, "CFBundleIdentifier", APP_BUNDLE_ID);
setPlistString(infoPlistPath, "CFBundleExecutable", executableName);
setPlistString(infoPlistPath, "CFBundleIconFile", "icon.icns");
setPlistJson(infoPlistPath, "CFBundleURLTypes", [
{
Expand Down Expand Up @@ -277,11 +278,25 @@ function readJson(path) {
}
}

export function resolveMacLauncherPaths(appBundlePath, displayName = APP_DISPLAY_NAME) {
const executableDir = NodePath.join(appBundlePath, "Contents", "MacOS");
const launcherExecutableName = `${displayName} Launcher`;
return {
launcherExecutableName,
launcherBinaryPath: NodePath.join(executableDir, launcherExecutableName),
runtimeElectronBinaryPath: NodePath.join(executableDir, "Electron"),
};
}

function buildMacLauncher(electronBinaryPath) {
const sourceAppBundlePath = NodePath.resolve(NodePath.dirname(electronBinaryPath), "../..");
const runtimeDir = NodePath.join(desktopDir, ".electron-runtime");
const targetAppBundlePath = NodePath.join(runtimeDir, `${APP_DISPLAY_NAME}.app`);
const targetBinaryPath = NodePath.join(targetAppBundlePath, "Contents", "MacOS", "Electron");
const developmentPaths = resolveMacLauncherPaths(targetAppBundlePath);
const runtimeElectronBinaryPath = developmentPaths.runtimeElectronBinaryPath;
const launcherBinaryPath = isDevelopment
? developmentPaths.launcherBinaryPath
: runtimeElectronBinaryPath;
const iconPath = isDevelopment ? ensureDevelopmentIconIcns(runtimeDir) : defaultIconPath;
const metadataPath = NodePath.join(runtimeDir, "metadata.json");

Expand All @@ -298,18 +313,19 @@ function buildMacLauncher(electronBinaryPath) {

const currentMetadata = readJson(metadataPath);
if (
NodeFS.existsSync(targetBinaryPath) &&
NodeFS.existsSync(launcherBinaryPath) &&
(!isDevelopment || NodeFS.existsSync(runtimeElectronBinaryPath)) &&
currentMetadata &&
JSON.stringify(currentMetadata) === JSON.stringify(expectedMetadata)
) {
if (isDevelopment) {
// The launcher also handles protocol activations outside the dev runner,
// so refresh its fallback environment on every launch. Never let a value
// captured by an older parent app override the live dev-runner environment.
writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath);
writeDevelopmentLauncherScript(launcherBinaryPath, runtimeElectronBinaryPath);
}
registerMacLauncherBundle(targetAppBundlePath);
return targetBinaryPath;
return launcherBinaryPath;
}

NodeFS.rmSync(targetAppBundlePath, { recursive: true, force: true });
Expand All @@ -321,15 +337,24 @@ function buildMacLauncher(electronBinaryPath) {
recursive: true,
verbatimSymlinks: true,
});
patchMainBundleInfoPlist(targetAppBundlePath, iconPath);
patchMainBundleInfoPlist(
targetAppBundlePath,
iconPath,
isDevelopment ? developmentPaths.launcherExecutableName : "Electron",
);
patchHelperBundleInfoPlists(targetAppBundlePath);
if (isDevelopment) {
writeDevelopmentLauncherScript(targetBinaryPath, electronBinaryPath);
// Keep Electron's native executable inside the branded bundle. Launching the
// node_modules copy makes macOS associate the process (and Dock label) with
// Electron.app even though this bundle's Info.plist has the T3 Code name.
// Its conventional executable name also keeps Electron's default-app runtime
// in development mode instead of making app.isPackaged report true.
writeDevelopmentLauncherScript(launcherBinaryPath, runtimeElectronBinaryPath);
}
NodeFS.writeFileSync(metadataPath, `${JSON.stringify(expectedMetadata, null, 2)}\n`);
registerMacLauncherBundle(targetAppBundlePath);

return targetBinaryPath;
return launcherBinaryPath;
}

function isLinuxSetuidSandboxConfigured(electronBinaryPath) {
Expand Down
Loading
Loading