* test: read the download item inside will-download in api-session spec `will-download event > identifies the frame and origin that started the download` called preventDefault() in its will-download listener and only read item.getInitiatorOrigin() after awaiting the event. preventDefault() cancels the download, which destroys the item, and that can happen before the awaiting code runs, so the read threw "DownloadItem used after being destroyed". Read the origin inside the listener, while the item is alive. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS * test: wait for the page to see clearData() in api-session spec `ses.clearData() > clears all data when no options supplied` (and its "called twice in parallel" twin) read localStorage.length right after clearData() resolved. The page answers from its own cached copy of localStorage, which the storage backend updates over a separate pipe, so the page could still report the old item. Wait until the page sees the clear, as the clearStorageData() spec already does. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS * test: enable Network capture before navigating in debugger valid unicode spec "handles valid unicode characters in message" started loadURL() on a fresh window and only then attached the debugger and sent Network.enable without waiting for it. Network.enable reaches the renderer only once it exists, so when the tiny response won that race Network.responseReceived was never emitted and the test hung until its 30s timeout. Load about:blank first, attach, await Network.enable, then start listening and navigate, matching the neighbouring invalid unicode spec. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS * test: drop the 5s timeout on contentTracing recording specs startRecording() resolves only once every child process acks the start, or after the tracing service's 10s ack timeout, and stopRecording() then waits up to 5s for the stop acks. A child that is slow to get scheduled on a busy CI host therefore stretches a single record() past the 5s per-suite timeout whatever the trace categories are, and the test only passed on the in-suite retry. Use the default spec timeout instead. Stopping the network service for 25s while a recording runs makes the slowest record() take about 15s, which matches that bound and stays well inside the default. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS * test: listen for the PDF viewer download's done event before it can fire The asar PDF viewer download test attached its 'done' listener only after the click loop noticed that the download had started. When the click's executeJavaScript() round trip came back late, the small download could start and finish inside that window, and the test then waited for a 'done' event that had already fired until the spec timed out. Start listening for 'done' in the synchronous will-download handler that accepts the first download, so the event cannot be missed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS * test: isolate the custom protocol extension fixtures' profiles runFixture() started the custom-protocol fixture apps on the default profile (they have no package.json, so userData is the stock Electron directory other fixture apps use too) and never stopped them. When another browser process holds that profile, the fixture's MV3 service worker never answers the content script, the page title never changes and the app hangs until the test times out. Because the hung app was not killed it kept the profile open, so every in-job retry hung the same way. Give each run its own --user-data-dir, and kill the app and remove the directory when the test ends. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS * test: follow links without synthesized clicks in navigation ordering specs The "navigation events > ordering" specs for a second navigation, a redirect and an in-page navigation clicked a link in a window that was never shown, by sending CDP mouse events after a fixed 2s wait. On Wayland a hidden window presents no frames, and the click can be lost before it reaches the page: the browser forwards mouseDown and mouseUp, but the page sees no pointer, mouse or click event, so the navigation never starts and the test times out. These specs check the order of navigation events, not input delivery. Follow the link with a renderer-side click() once the page has loaded instead; it is the same renderer-initiated navigation, and it no longer depends on frames being presented or on the 2s wait. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LPMvJBQiyP6b7QjatACmnS --------- Co-authored-by: Claude <noreply@anthropic.com>
📝 Available Translations: 🇨🇳 🇧🇷 🇪🇸 🇯🇵 🇷🇺 🇫🇷 🇺🇸 🇩🇪. View these docs in other languages on our Crowdin project.
The Electron framework lets you write cross-platform desktop applications using JavaScript, HTML and CSS. It is based on Node.js and Chromium and is used by the Visual Studio Code and many other apps.
Follow @electronjs on Twitter for important announcements.
This project adheres to the Contributor Covenant code of conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to coc@electronjs.org.
Installation
To install prebuilt Electron binaries, use npm.
The preferred method is to install Electron as a development dependency in your
app:
npm install electron --save-dev
For more installation options and troubleshooting tips, see installation. For info on how to manage Electron versions in your apps, see Electron versioning.
Platform support
Each Electron release provides binaries for macOS, Windows, and Linux.
- macOS (Ventura and up): Electron provides 64-bit Intel and Apple Silicon / ARM binaries for macOS.
- Windows (Windows 10 and up): Electron provides
x64(amd64) andarm64binaries for Windows. - Linux: Electron provides
x64(amd64) andarm64binaries for Linux. Electron supports major Linux distributions (e.g., Ubuntu, Fedora, Debian) in versions that are still supported by both Chromium and the distro maker (without requiring a paid subscription). The prebuilt binaries are built on Ubuntu.
In general, Electron tries to align with Chromium on platform support.
Electron Fiddle
Use Electron Fiddle
to build, run, and package small Electron experiments, to see code examples for all of Electron's APIs, and
to try out different versions of Electron. It's designed to make the start of your journey with
Electron easier.
Resources for learning Electron
- electronjs.org/docs - All of Electron's documentation
- electron/fiddle - A tool to build, run, and package small Electron experiments
Programmatic usage
Most people use Electron from the command line, but if you require electron inside
your Node app (not your Electron app) it will return the file path to the
binary. Use this to spawn Electron from Node scripts:
const electron = require('electron')
const proc = require('node:child_process')
// will print something similar to /Users/maf/.../Electron
console.log(electron)
// spawn Electron
const child = proc.spawn(electron)
Mirrors
See the Advanced Installation Instructions to learn how to use a custom mirror.
Documentation translations
We crowdsource translations for our documentation via Crowdin. We currently accept translations for Chinese (Simplified), French, German, Japanese, Portuguese, Russian, and Spanish.
Contributing
If you are interested in reporting/fixing issues and contributing directly to the code base, please see CONTRIBUTING.md for more information on what we're looking for and how to get started.
Community
Info on reporting bugs, getting help, finding third-party tools and sample apps, and more can be found on the Community page.
License
When using Electron logos, make sure to follow OpenJS Foundation Trademark Policy.