Skip to main content

Electron Desktop Delivery

Use when shipping Electron desktop changes securely.

Purpose​

Ship Electron changes as complete desktop behavior, not renderer-only code. Treat the renderer, preload bridge, main process, packaging manifest, operating-system integration, and platform-specific verification as one delivery path.

When to use​

  • Adding a renderer action that needs Electron or OS capabilities
  • Opening external documentation, files, folders, or URLs
  • Changing preload or IPC contracts
  • Adding resources that packaged users must be able to reach
  • Documenting or testing Windows, macOS, and Linux behavior
  • Reviewing a change that works in development but may fail after packaging

Trust boundaries​

  1. The renderer is untrusted. It must not receive Node or unrestricted Electron access.
  2. Preload exposes a narrow, typed allowlist through contextBridge.
  3. Main-process handlers validate all renderer-controlled values.
  4. Prefer zero-argument, purpose-specific actions when the destination is fixed.
  5. Keep contextIsolation: true, nodeIntegration: false, sandboxing, navigation guards, and a restrictive CSP.
  6. Do not weaken global navigation protections to make one link work.

Delivery workflow​

1. Trace the full user path​

Before editing, identify:

  • the renderer control;
  • its accessible role and label;
  • the preload method;
  • the shared request/response type;
  • the main-process handler;
  • the OS API it invokes;
  • whether the target exists in the packaged artifact;
  • the focused and end-to-end verification paths.

A visible URL or repository-relative path is not automatically usable in a packaged application.

2. Choose packaged content or an external destination​

Use packaged content when it must work offline or is version-locked to the installed build. Confirm the resource is included by the packager and resolve it correctly inside or beside asar.

Use an external destination when current hosted documentation is intentional. Open it through an Electron-mediated action rather than renderer navigation.

For a single fixed destination, use:

  • a fixed HTTPS constant in the main process;
  • a zero-argument typed IPC channel;
  • one explicit preload method;
  • shell.openExternal in the main process;
  • an accessible renderer link or button that prevents default navigation.

Never accept an arbitrary renderer URL merely to support one fixed help link.

See references/external-documentation-links.md for the tested pattern and review checklist.

3. Test before implementation​

Add focused tests that fail for the missing behavior:

  • renderer exposes an accessible action;
  • clicking invokes the intended typed bridge;
  • the main handler exists;
  • the handler opens exactly the allowlisted HTTPS destination;
  • no caller-supplied URL reaches the OS API.

Then implement the minimum bridge and make the focused tests pass.

4. Verify packaging assumptions​

Inspect the actual packager files and extraResources configuration. A file present in the repository is unavailable to packaged users unless it is bundled or intentionally hosted elsewhere.

Before producing a cross-platform human handoff, preflight every direct native runtime dependency against the target OS and architecture: published os/cpu/engines, prebuilt matrix, source-build support, Electron/Node compatibility, and clean-install behavior. Run the smallest target-native install probe first. If it fails, do not send the operator through build, package, or launch steps that cannot succeed.

Interpret failures as a prerequisite chain. A failed dependency install commonly causes missing local build CLIs, missing output directories, and absent installers. Report the first root failure and classify the rest as cascading symptoms; never suggest force-installing or ignoring platform checks for a runtime native module.

Run:

  • focused renderer and main-process tests;
  • typecheck;
  • lint;
  • full test suite;
  • production renderer/main/preload bundle;
  • packaged-app smoke test when behavior depends on OS integration.

5. Apply platform gates literally​

Static review is not execution. Commands or OS integrations documented for Windows, macOS, and Linux need target-platform execution before claiming full verification.

When an operator reports a runtime prerequisite has been repaired, probe the exact installed binary again and execute the preserved native gate immediately under the repository's shared gate lock. On Linux, ldd is a useful prerequisite probe, not the acceptance test itself. Historical handoff comments are not live prerequisite evidence. Do not reinstall or rebuild an addon merely because an old report says it was blocked. Record a successful run only for the actual host/runtime tested; Linux Electron compatibility is not Windows package acceptance. Supersede stale blocker receipts in both the authoritative task and persistent manager input, then advance acceptance inspection/review rather than replaying completed implementation.

See references/native-gate-recovery-evidence.md for the exercised recovery sequence, evidence boundaries, and delivery-manager handoff.

Record each platform independently:

  • command or action executed;
  • relevant runtime/tool version;
  • observed result;
  • packaged versus development build;
  • any platform still pending.

An approval of code structure does not waive a stated native-platform acceptance criterion. Use a HOLD rather than calling the change merge-ready when a required platform remains untested.

6. Produce an exact native-platform handoff​

For this user's operator handoffs, provide only the steps that are executable now. A warning above a long future build checklist is insufficient: the user may still copy the commands and hit the known blocker. If dependency installation cannot succeed on the named candidate, omit downstream build/install commands from the immediate instructions. Provide independently runnable checks separately, name the agent-owned prerequisite, and issue the build handoff only after the candidate is ready. Shell version and runtime must be checked explicitly; a terminal window's appearance does not establish either.

When the user says they need a working build, prioritize the delivery path, not repeated status commentary. Distinguish completed code, running implementation, review, integration, artifact production, and native-human acceptance. A launched worker or a passing prototype suite is not a delivered installer. If the user explicitly authorizes gated merges, persist the exact scope and conditions in the delivery manager's authoritative input, replace contradictory stale no-merge instructions for that scope, and read back the external authorization record. Such permission does not waive checks or native acceptance and does not extend to unrelated repositories.

When the remaining gate must be executed by a human on another operating system, do not answer only “test on Windows/macOS.” Give a bounded, copy-pasteable handoff that includes:

  1. Whether a physical machine is required or a genuine VM is sufficient. WSL or a compatibility shell does not satisfy a native Windows gate.
  2. Evidence that target-native dependency installation is supported and has passed the smallest clean-install preflight; otherwise stop and report the upstream blocker instead of issuing impossible downstream steps.
  3. Required runtime/tool versions and a command that records each version.
  4. An immutable PR-head checkout with an explicit expected-SHA assertion and clean-status check.
  5. The repository-derived build/package command and the expected artifact location.
  6. Exact installed-app actions and the observable OS result, distinguishing a packaged build from development mode.
  7. Safe synthetic test inputs instead of customer identifiers or production credentials.
  8. Expected non-secret outputs and a minimal result list for the operator to report back.
  9. Cleanup commands for generated keys, certificates, files, clipboard contents, test accounts, or other sensitive residue.
  10. A warning not to paste, screenshot, log, commit, or transmit generated private material.

If a fixed external help URL targets the default branch while its document exists only in the unmerged PR, separate two checks explicitly:

  • Pre-merge native integration: the packaged app invokes the system browser with the exact fixed URL; a temporary 404 can be expected because the document is not on the default branch yet.
  • Post-merge reachability: after merge, verify that the same URL returns the committed document.

Do not weaken the production URL to a feature-branch URL merely to avoid the pre-merge 404. Record the temporary condition and verify reachability after merge.

See references/native-platform-verification-handoff.md for a reusable handoff checklist.

Review checklist​

  • Renderer cannot choose an arbitrary destination when only one is required.
  • Preload exposes only the purpose-specific method.
  • Shared IPC types use void for a zero-argument request.
  • Main handler owns and fixes the HTTPS destination.
  • Link has an accessible name and prevents blocked in-app navigation.
  • Existing new-window, navigation, webview, sandbox, and CSP controls remain intact.
  • Tests assert the exact destination and bridge invocation.
  • Documentation is reachable in the packaged build, not only the source checkout.
  • Platform-specific steps are executed on every claimed target platform.
  • Exact-head review and final verification are repeated after remediation commits.

Common pitfalls​

  • Rendering a plain-text URL and calling it discoverable
  • Linking to docs/foo.md when docs are excluded from packaging
  • Using <a target="_blank"> while setWindowOpenHandler correctly denies new windows
  • Adding broad open-url(url) IPC instead of a purpose-specific fixed action
  • Testing only that link text renders, not that the OS action occurs
  • Claiming Windows instructions are verified after only Linux syntax review
  • Treating a successful development build as packaged-app proof
  • Sending a human a full native build checklist before checking that every direct native dependency actually supports that OS
  • Debugging command not found, missing release/, or absent installer errors separately when the dependency install already failed

Completion standard​

A desktop change is complete only when the user-visible action, typed boundary, main-process effect, packaging path, focused tests, full checks, and required native-platform gates all agree at the exact commit under review.


Supporting files: this skill's supporting files are held in the docsite at docs/15-skills/_support/engineering/electron-desktop-delivery/ — fetch them fresh from jknash/docsite main alongside this page. Source: jknash/hermes-shared-skills · branch hermes-jkdev001 @ 1d0d545c3970 · skills/engineering/electron-desktop-delivery/ · view source · Imported 2026-10-04. Supporting files (references, scripts) remain in the source repository.

version 1.0.0.

Published by Muse · 2026-10-04.