{"owner":"electron","repo":"forge","hasSkills":true,"totalSkillsCount":30,"totalTokensCount":10165,"categories":["root-instruction","anthropic-skill","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md","docs/config/plugins/auto-unpack-natives.md","docs/config/plugins/electronegativity.md","docs/config/plugins/index.md","docs/config/plugins/local-electron.md","packages/api/core/README.md","packages/external/create-electron-app/README.md","packages/maker/appx/README.md","packages/maker/deb/README.md","packages/maker/dmg/README.md","packages/maker/flatpak/README.md","packages/maker/msix/README.md","packages/maker/pkg/README.md","packages/maker/rpm/README.md","packages/maker/snap/README.md","packages/maker/squirrel/README.md","packages/maker/wix/README.md","packages/maker/zip/README.md","packages/plugin/auto-unpack-natives/README.md","packages/plugin/fuses/README.md","packages/plugin/local-electron/README.md","packages/plugin/vite/README.md","packages/plugin/webpack/README.md","packages/publisher/bitbucket/README.md","packages/publisher/electron-release-server/README.md","packages/publisher/github/README.md","packages/publisher/nucleus/README.md","packages/publisher/s3/README.md","packages/publisher/snapcraft/README.md","packages/utils/multi-logger/README.md"],"skills":{"AGENTS.md":"# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Overview\n\nElectron Forge is a Yarn 4 + Lerna monorepo of TypeScript packages published as `@electron-forge/*` (plus `create-electron-app`). All packages share one version (`lerna.json`). Node version: `.nvmrc`.\n\nThis is Forge 8, and several things differ from Forge 7, which you may know better:\n\n- Packages are ESM-only.\n- `init`/`import` live in `create-electron-app`, not core.\n- `publish` is renamed `release` (the old name remains as a deprecated alias).\n- `make --skip-package` is now `--from-package`, and `release --from-dry-run` is now `--from-make`.\n- The bundler plugins emit main and preload bundles as `.cjs`.\n- PRs target `main`.\n\n## Commands\n\n```bash\nyarn                      # install; postinstall regenerates the gitignored per-package tsconfig.json files and packages/tsconfig.json\nyarn build                # ~5s; tsc -b packages, then tools/test-dist checks that every package's entry point exists and imports\nyarn build:watch\n\nyarn lint                 # oxfmt --check, oxlint, markdownlint, lint of code blocks in markdown, markdown link check\nyarn lint:fix             # oxfmt --write + oxlint --fix\nyarn constraints          # yarn.config.cjs: a dependency must use the same range in every workspace (--fix to apply)\nyarn knip                 # unused files/exports/deps\n\nyarn test:fast [file] [-t \"name\"]   # unit tests (*.spec.ts); the full suite takes ~25s\nyarn test:slow [file]               # *.slow.spec.ts: downloads Electron, real packaging/making, 240s timeouts\nyarn test:verdaccio [file]          # *.slow.verdaccio.spec.ts against a local registry holding the current build\nyarn test:clear                     # remove temp dirs left behind by tests\n```\n\n## Verifying changes\n\n- **Rebuild before testing across packages.** A spec imports its own package from `../src`. Every other `@electron-forge/*` import resolves through `package.json` `exports` to `dist/`. After editing package A, run `yarn build`, or keep `yarn build:watch` running, before testing anything that imports A.\n- **Default to `yarn test:fast <file>`.** Run the slow or Verdaccio specs only when touching packaging, making, `init` or templates.\n- **Don't run bare `yarn test`.** It includes the `slow-verdaccio` project without starting Verdaccio, so those specs install `@electron-forge/*` from the public registry and test the wrong code.\n- **`test:fast`, `test:slow` and `test:verdaccio` run through `xvfb-maybe`.** On headless Linux without xvfb they exit with \"Failed to find xvfb-run in PATH\". Call vitest directly instead: `yarn vitest run --project fast <file>`, or `yarn spawn-verdaccio yarn vitest run --project slow-verdaccio <file>`.\n- **Verdaccio specs need more setup.** They publish the current `dist/`, so build first. They also need network access, port 4873 free, `pnpm` on PATH, and npm >= 11.17 for install age-gating.\n- **Specs are not type-checked.** `tsconfig.base.json` excludes `spec/`, and vitest strips types. A green build doesn't prove spec types are right.\n- **Try a change in a real app:** `yarn build && LINK_FORGE_DEPENDENCIES_ON_INIT=1 node packages/external/create-electron-app/dist/index.js <dir> --package-manager pnpm`. Then check that `<dir>/node_modules/@electron-forge/cli` resolves into this repo.\n  - Only pnpm links reliably.\n  - With npm, the default when there's no TTY, linking reports success, but the install that follows replaces the links with published packages.\n  - Yarn works only if Corepack provides Yarn 4. Yarn 1's `yarn link` fails.\n- **Debug logging:** `DEBUG=electron-forge:*` traces CLI and core internals.\n- **Parts of `CONTRIBUTING.md` are stale.** Its \"Running Forge locally\" and test instructions mention `yarn link:prepare`, `yarn build:fast` and `yarn test`, and it says the website docs live in a separate repo. Follow this file instead where they conflict.\n\nThe pre-commit hook runs `lint-staged` (oxfmt + oxlint) and `yarn constraints`. CI runs build, then `yarn lint`, `yarn constraints` and `yarn knip`, then the test suites on Windows, macOS and Linux. Changes that only touch `docs/` skip the test jobs.\n\n## Architecture\n\nPackage groups under `packages/` (each is a Yarn workspace):\n\n- `api/core`: the programmatic API (`src/api/{start,package,make,release}.ts`) and shared internals in `src/util/`.\n- `api/cli`: a thin `commander` wrapper. It dispatches to one executable per subcommand (`electron-forge-<cmd>.ts`), and each of those calls the core API.\n- `external/create-electron-app`: project scaffolding (`init.ts`, `import.ts`, `init-scripts/`).\n- `maker/*`, `publisher/*`, `plugin/*`: implementations of `MakerBase`, `PublisherBase` and `PluginBase` from the matching `*/base` package.\n  - Most makers wrap a third-party installer module (`electron-installer-*`, `electron-winstaller`, …), usually declared in `optionalDependencies`. `yarn constraints` skips only the names hard-coded in `OPTIONAL_DEPS` in `yarn.config.cjs`, so add a new installer there.\n  - `publisher/base-static` is shared logic for object-storage publishers (S3, GCS).\n  - Plugins provide lifecycle hooks and can take over `start` (`startLogic`). `vite` and `webpack` are the bundler plugins.\n- `template/*`: templates used by `create-electron-app`. `template/base` has `BaseTemplate` and the shared `tmpl/` files, and the vite and webpack templates extend it.\n- `utils/*`:\n  - `shared-types` lives in `utils/types`. It defines `ForgeConfig`, the hook signatures and the maker/publisher/plugin interfaces that every package codes against.\n  - `core-utils` covers package manager detection, the `@electron/rebuild` wrapper and Electron version lookup.\n  - Also: `multi-logger`, `tracer`, `test-utils`.\n\nCross-cutting pieces in `api/core/src/util/`:\n\n- **`forge-config.ts` loads the config.**\n  - Precedence: a config registered with `registerForgeConfigForDirectory()` (used by tests), then a `package.json` `config.forge` object, then the first `forge.config.{js,mjs,cjs,ts,mts,cts}` found. A `config.forge` _path string_ is used only when no `forge.config.*` file exists.\n  - TS configs load through `jiti`, JS configs through `import()`.\n  - After the `resolveForgeConfig` hook runs, the config is wrapped in a `Proxy`. Missing keys fall back to `ELECTRON_FORGE_<KEY>` env vars, and `fromBuildIdentifier()` values resolve per `buildIdentifier`.\n- **`import-search.ts` resolves by name** the makers, publishers and plugins in the config, plus `packagerConfig` hooks given as strings. It tries the bare specifier, then a path relative to the project, then the project's `node_modules`, and uses only the module's default export.\n- **`plugin-interface.ts` + `hook.ts` run the plugin lifecycle.** There are three kinds of hook:\n  - simple hooks (`runHook`)\n  - mutating hooks that thread a value through each plugin (`runMutatingHook`)\n  - hooks that return `listr2` tasks (`getHookListrTasks`)\n\n  Commands are built as `listr2` task lists.\n\n- **The commands chain together.** `package` wraps `@electron/packager` and injects Forge hooks into its `afterCopy`/`afterPrune`/`afterExtract` callbacks. `make` runs package first unless given `--from-package`, and `release` runs make first unless given `--from-make`.\n\nTests live in each package's `spec/`, and the filename suffix picks the vitest project (see the test commands above). Spec files run serially (`fileParallelism: false`) because many write into shared on-disk fixtures. Each file gets fresh module state, but registered configs and mocks persist between tests in the same file, so unregister them in `afterEach`. Core's fixture apps and configs are in `packages/api/core/spec/fixture/`.\n\n## Gotchas\n\n- **Coupled changes.** A behavior change in a bundler plugin usually also needs updates to the templates' `tmpl/` files (what users actually get) and to `docs/config/plugins/`.\n- **Two sets of docs.** `docs/` is the user-facing docs site. New pages must be registered in `docs/sidebars.ts`. The site isn't built in this repo. Markdown lint and the link check cover only `*.md`, so `.mdx` pages (including `docs/config/plugins/vite.mdx` and `webpack.mdx`) aren't checked at all; review them by hand. Each package's `README.md` is separate, hand-written, and published to npm.\n- **Dependency install policy.** `.yarnrc.yml` rejects versions published less than 7 days ago (`npmMinimalAgeGate`), except for pre-approved scopes, and disables install scripts, except those allowed in `dependenciesMeta`. CI installs with `--immutable`, so commit `yarn.lock`.\n- **Generated project references.** Each package's `tsconfig.json` is generated from `tsconfig.base.json` and its workspace dependencies by `tools/gen-tsconfigs.ts`, so don't hand-edit it. After adding or removing an `@electron-forge/*` dependency, re-run `yarn`, or `tsc -b` fails.\n- **Adding a package.**\n  1. Put it under an existing `workspaces` glob.\n  2. Set its version to the one in `lerna.json`, and depend on sibling packages with `workspace:*`.\n  3. Run `yarn`.\n  4. Add a workspace entry to `knip.json`.\n  5. Check the `typedoc.jsonc` entry points.\n  6. Copy the `exports`, `typings` and `publishConfig` fields from a sibling package. `tools/test-dist` fails without the entry point and typings.\n- **Imports.** Relative imports in `src/` use `.js` extensions. Some type-only re-exports use `.ts`, but `.js` also works there. Specs import `../src/...` without an extension; don't copy that style into `src/`.\n- **Commit messages.** Commits and PR titles use Conventional Commits (the `semantic` workflow checks PR titles), for example `fix(core): ...` or `feat(plugin-vite)!: ...`. Lerna derives version bumps from them, so don't bump versions in PRs.\n- **TSDoc style.** Follow the rules in `CONTRIBUTING.md`: the first line is imperative, capitalized and ends with a period.\n","docs/config/plugins/auto-unpack-natives.md":"---\ndescription: >-\n  Reduce loading times and disk consumption by unpacking native Node modules\n  from your Forge app's ASAR archive.\n---\n\n# Auto Unpack Native Modules Plugin\n\nThis plugin will automatically add all native Node modules in your `node_modules` folder to the [`asar.unpack`](https://electron.github.io/packager/main/interfaces/Options.html#asar) config option in your [`packagerConfig`](../configuration.mdx#electron-packager-config). If your app uses native Node modules, you should probably use this to reduce loading times and disk consumption on your users' machines.\n\n## Installation\n\n```shell\nnpm install --save-dev @electron-forge/plugin-auto-unpack-natives\n```\n\n## Usage\n\nYou must add this plugin to your [`plugins`](../configuration.mdx#plugins) array in your Forge configuration. There are currently no configuration options available for this plugin.\n\n:::info\nAsar archives are disabled by default with Electron Packager. Make sure you set your `packagerConfig.asar` value accordingly. This option also supports advanced configuration if you pass it an object. See the [API documentation for this option](https://js.electronforge.io/modules/_electron_forge_shared_types.InternalOptions.html#CreateOptions) for more information.\n:::\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  packagerConfig: {\n    asar: true // or an object containing your asar options\n  },\n  plugins: [\n    {\n      name: '@electron-forge/plugin-auto-unpack-natives',\n      config: {}\n    }\n  ]\n};\n```\n","docs/config/plugins/electronegativity.md":"---\ndescription: >-\n  Check for misconfigurations and security anti-patterns with the\n  Electronegativity tool.\n---\n\n# Electronegativity Plugin\n\nThe Electronegativity plugin integrates Doyensec's [Electronegativity tool](https://github.com/doyensec/electronegativity#electronegativity) into the Electron Forge workflow. After packaging your Electron app, it identifies any known misconfigurations and security anti-patterns.\n\n## Installation\n\n```shell\nnpm install --save-dev @electron-forge/plugin-electronegativity\n```\n\n## Usage\n\nAdd this plugin to the [`plugins`](../configuration.mdx#plugins) array in your Forge configuration. All [programmatic options for Electronegativity](https://github.com/doyensec/electronegativity#programmatically), except for `input` and `electronVersion`.\n\n### Example\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      name: '@electron-forge/plugin-electronegativity',\n      config: {\n        isSarif: true\n      }\n    }\n  ]\n  // ...\n};\n```\n","docs/config/plugins/index.md":"---\ndescription: Modules to extend Forge's core functionality\n---\n\n# Plugins\n\nElectron Forge has a plugin system which allows you to extend its core functionality.\n\nBy default, Forge takes a vanilla JS application and packages, makes and publishes it (see the [Build Lifecycle](../../core-concepts/build-lifecycle.md) document for more details). Plugins can execute custom logic during any of the Forge [Hooks](../hooks.md) during the build process, and can also override the [Start](../../cli.md#start) command in development.\n\n:::info\nIf you want to write your own Forge plugin, check out the [Writing Plugins](../../advanced/extending-electron-forge/writing-plugins.md) guide.\n:::\n\n## Bundler plugins\n\n- [Webpack Plugin](webpack.mdx) - Build your Electron app with webpack\n- [Vite Plugin](vite.mdx) - Build your Electron app with Vite\n\n## Utility plugins\n\n- [Auto Unpack Native Modules Plugin](auto-unpack-natives.md) - Unpack native Node.js modules from your Forge app's ASAR archive.\n- [Local Electron Plugin](local-electron.md) - Integrate a local build of Electron into your Forge app.\n- [Fuses Plugin](fuses.mdx) - Toggle Electron functionality at package-time with Electron Fuses.\n- [Electronegativity Plugin](electronegativity.md) - Check for misconfigurations and security anti-patterns with the Electronegativity tool.\n","docs/config/plugins/local-electron.md":"---\ndescription: Integrate a local build of Electron into your Forge app.\n---\n\n# Local Electron Plugin\n\n:::info\nThis plugin should only be used by people who are building Electron locally themselves. If you want to use a fork of Electron, check out the [environment variables](https://github.com/electron/get#usage) you can use to configure `@electron/get`.\n:::\n\nThis plugin allows you to both run and build your app using a **local** build of Electron. This can be incredibly useful if you want to test a feature or a bug fix in your app before making a PR up to the Electron repository.\n\nIf you want to set up a local build of Electron, you should check out [Electron Build Tools](https://github.com/electron/build-tools).\n\n### Installation\n\n```bash\nnpm install --save-dev @electron-forge/plugin-local-electron\n```\n\n### Usage\n\nOnce you have a working build of Electron, point the plugin's `electronPath` config option to the folder containing the built Electron binary.\n\nAll possible configuration options are documented in [`LocalElectronPluginConfig`](https://js.electronforge.io/interfaces/\\_electron\\_forge\\_plugin\\_local\\_electron.LocalElectronPluginConfig.html).\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-local-electron',\n      config: {\n        electronPath: '/Users/me/projects/electron/out/Testing'\n      }\n    }\n  ]\n};\n```\n\n:::info\nPlease note that the plugin only accepts **absolute paths**. You should use Node's [`path.resolve()`](https://nodejs.org/api/path.html#pathresolvepaths) to make things deterministic.\n:::\n","packages/api/core/README.md":"# Electron Forge Core\n\nThis module contains the core logic of Electron Forge and exposes the base\nAPI as a number of simple JS functions.\n\n## Basic Usage\n\n```javascript\nimport { api } from '@electron-forge/core';\n\n// Package the current directory as an Electron app\napi.package(import.meta.dirname);\n```\n\nThe named export `api` has it's methods documented over at [ForgeAPI](https://js.electronforge.io/classes/_electron-forge_core.ForgeAPI.html).\nAll the methods are async and expose the core forge methods, please note that all\nuser-side configuration is still done through your forge config file or the \"config.forge\"\nsection of your package.json. This API simply let's you call the methods in\nnode land without using the CLI.\n\n## Error Handling\n\nAs all methods return a promise you should handle all rejections, you should note\nthat rejections will **not** always be errors, in fact we commonly reject our\npromises with just strings so do not assume that properties such as `stack` or\n`message` will exist on thrown errors.\n","packages/external/create-electron-app/README.md":"## create-electron-app\n\nCreate Electron App allows you to quickly bootstrap a new Electron app using\n[Electron Forge](https://electronforge.io).\n\n### Usage\n\nInitialize a new project by running the following:\n\n```sh\nnpx create-electron-app@latest my-app\n```\n\nYou should now have a directory called my-app with an ultra-minimal Electron app boilerplate inside.\nIf you head into that directory and start up the app, you'll be all set to start developing!\n\n```sh\ncd my-app\nnpm start\n```\n","packages/maker/appx/README.md":"## maker-appx\n\n> **Deprecated:** use [`@electron-forge/maker-msix`](https://www.electronforge.io/config/makers/msix) instead.\n\n`@electron-forge/maker-appx` is a legacy compatibility layer over the MSIX maker. It maps its `MakerAppXConfig` onto `electron-windows-msix` and builds a `.msix` package, which is designed to target the Windows Store.\n\nYou can only build the AppX target on Windows machines with the Windows 10 SDK installed.\n\nWhen `devCert` is not set, `electron-windows-msix` signs the package with a self-signed development certificate, which the maker saves next to the `.msix` as `dev_cert.cer` and `dev_cert.pfx` so it can be trusted on a test device. The `.pfx` password is `WINDOWS_CERTIFICATE_PASSWORD` when that environment variable is set, otherwise a random one.\n\nConfiguration options are documented in [`MakerAppXConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-appx.MakerAppXConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-appx',\n      config: {\n        publisher: 'CN=developmentca',\n        devCert: 'C:\\\\devcert.pfx',\n        certPass: 'abcd'\n      }\n    }\n  ]\n};\n```\n","packages/maker/deb/README.md":"## maker-deb\n\n`@electron-forge/maker-deb` builds .deb packages, which are the standard package format for Debian-based Linux distributions such as Ubuntu. You can only build the deb target on Linux or macOS machines with the dpkg package installed.\n\nConfiguration options are documented in [`MakerDebConfigOptions`](https://js.electronforge.io/interfaces/_electron-forge_maker-deb.MakerDebConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-deb',\n      config: {\n        options: {\n          maintainer: 'The Forgers',\n          homepage: 'https://example.com',\n          icon: 'path/to/icon.svg'\n        }\n      }\n    }\n  ]\n};\n```\n","packages/maker/dmg/README.md":"## maker-dmg\n\n`@electron-forge/maker-dmg` builds `.dmg` files, which are the standard format for sharing macOS apps. You can only build the DMG target on macOS machines.\n\nConfiguration options are documented in [`MakerDMGConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-dmg.MakerDMGConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-dmg',\n      config: {\n        background: './assets/dmg-background.png',\n        format: 'ULFO'\n      }\n    }\n  ]\n};\n```\n","packages/maker/flatpak/README.md":"## maker-flatpak\n\n`@electron-forge/maker-flatpak` [`.flatpak` files](http://flatpak.org/), which is a packaging format for Linux distributions that allows for sandboxed installation of applications in isolation from the rest of their system.\n\nYou can only build the Flatpak target if you have `flatpak`, `flatpak-builder`, and `eu-strip` _\\(usually part of the `elfutils` package\\)_ installed on your system.\n\nConfiguration options are documented in [`MakerFlatpakOptionsConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-flatpak.MakerFlatpakConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-flatpak',\n      config: {\n        options: {\n          categories: ['Video'],\n          mimeType: ['video/h264']\n        }\n      }\n    }\n  ]\n};\n```\n","packages/maker/msix/README.md":"## maker-msix\n\n> [!IMPORTANT]\n> This module is _experimental_ and is subject to breaking changes between releases.\n> See GitHub Releases change notes for migration instructions.\n\n`@electron-forge/maker-msix` builds `.msix` packages, which can be distributed directly or via the Windows Store.\n\nYou can only build the MSIX target on Windows machines with the Windows 10 SDK installed.\n\nConfiguration options are documented in [`MakerMSIXConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-msix.MakerMSIXConfig.html).\n\nmaker-msix utilizes @electron/windows-sign via the `windowsSignOptions` property. See the [windows-sign documentation](https://github.com/electron/windows-sign/blob/main/README.md) for details.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-msix',\n      config: {\n        manifestVariables: {\n          publisher: 'Electron Dev'\n        },\n        windowsSignOptions: {\n          certificatePassword: '12345'\n        }\n      }\n    }\n  ]\n};\n```\n","packages/maker/pkg/README.md":"## maker-pkg\n\n`@electron-forge/maker-pkg` builds `.pkg` files for macOS. These are used to upload your application to the Mac App Store or just as an alternate distribution method for macOS users.  You can only build the Pkg target on macOS machines while targeting the `darwin`  or `mas` platforms.\n\nConfiguration options are documented in [`MakerPkgConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-pkg.MakerPKGConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-pkg',\n      config: {\n        keychain: 'my-secret-ci-keychain'\n      }\n    }\n  ]\n};\n```\n","packages/maker/rpm/README.md":"## maker-rpm\n\n`@electron-forge/maker-rpm` builds `.rpm` files, which is the standard package format for RedHat-based Linux distributions such as Fedora.\n\nYou can only build the RPM target on Linux machines with the `rpm` or `rpm-build` packages installed.\n\nConfiguration options are documented in [`MakerRpmConfigOptions`](https://js.electronforge.io/interfaces/_electron-forge_maker-rpm.MakerRpmConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-rpm',\n      config: {\n        options: {\n          name: 'QuickEdit',\n          homepage: 'http://example.com'\n        }\n      }\n    }\n  ]\n};\n```\n","packages/maker/snap/README.md":"## maker-snap\n\n`@electron-forge/maker-snap` builds `.snap` files, which is the packaging format created and sponsored by Canonical, the company behind Ubuntu. It is a sandboxed package format that lets users of various Linux distributions install your application in an isolated environment on their machine.\n\nYou can only build the Snapcraft target on Linux systems with the `snapcraft` package installed.\n\nConfiguration options are documented in [`MakerSnapConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-snap.MakerSnapConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-snap',\n      config: {\n        version: '1.1.0',\n        features: {\n          audio: true,\n          mpris: 'com.example.mpris',\n          webgl: true\n        },\n        summary: 'My application'\n      }\n    }\n  ]\n};\n```\n","packages/maker/squirrel/README.md":"## maker-squirrel\n\n`@electron-forge/maker-squirrel` builds a number of files required to distribute apps using the Squirrel.Windows framework. It generates a `{appName} Setup.exe` file which is the main installer for your application, `{appName}-full.nupkg` and a `RELEASES` file which you use to issue updates to your application.\n\nPre-requisites:\n\n* Windows machine\n* Linux machine with `mono` and `wine` installed.\n\nConfiguration options are documented in [`MakerSquirrelConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-squirrel.MakerSquirrelConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-squirrel',\n      config: {\n        certificateFile: './cert.pfx',\n        certificatePassword: 'this-is-a-secret'\n      }\n    }\n  ]\n};\n```\n","packages/maker/wix/README.md":"\n## maker-wix-msi\n\nThe WiX MSI target builds `.msi` files, which are \"traditional\" Windows installer files.\n\nPre-requisites:\n\n* `light` and `candle` installed from [the WiX toolkit](https://github.com/felixrieseberg/electron-wix-msi#prerequisites).\n\nConfiguration options are documented in [`MakerWixConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-wix.MakerWixConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-wix',\n      config: {\n        language: 1033,\n        manufacturer: 'My Awesome Company'\n      }\n    }\n  ]\n};\n```\n","packages/maker/zip/README.md":"## maker-zip\n\n`@electron-forge/maker-zip` builds basic `.zip` files containing your packaged application. There are no platform specific dependencies for using this maker and it will run on any platform.\n\nConfiguration options are documented in [`MakerZIPConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-zip.MakerZIPConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-zip'\n    }\n  ]\n};\n```\n","packages/plugin/auto-unpack-natives/README.md":"## plugin-auto-unpack-natives\n\nThis plugin will automatically add all native Node modules in your node_modules folder to the `asar.unpack` config option in your `packagerConfig`. If your app uses native Node modules, you should probably use this to reduce loading times and disk consumption on your users' machines.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-auto-unpack-natives',\n      config: {}\n    }\n  ]\n};\n```\n","packages/plugin/fuses/README.md":"## @electron-forge/plugin-fuses\n\nThis plugin allows flipping [Electron Fuses](https://github.com/electron/fuses) when packaging your app with Electron Forge.\n\n### Usage\n\nInstall `@electron-forge/plugin-fuses` and `@electron/fuses` as dev dependencies and add this plugin to the `plugins` array in your Forge configuration:\n\n```shell\n# Yarn\nyarn add --dev @electron-forge/plugin-fuses @electron/fuses\n\n# npm\nnpm i -D @electron-forge/plugin-fuses @electron/fuses\n```\n\n```js\n// forge.config.js\n\nconst { FusesPlugin } = require('@electron-forge/plugin-fuses');\nconst { FuseV1Options, FuseVersion } = require('@electron/fuses');\n\nconst forgeConfig = {\n  plugins: [\n    new FusesPlugin({\n      version: FuseVersion.V1,\n      [FuseV1Options.RunAsNode]: false\n      // ...any other options supported by @electron/fuses\n    })\n  ]\n};\n\nmodule.exports = forgeConfig;\n```\n","packages/plugin/local-electron/README.md":"## plugin-local-electron\n\nThis plugin allows you to both run and build your app using a local build of Electron. This can be incredibly useful if you want to test a feature or a bug fix in your app before making a PR up to the Electron repository.\n\n_Note: This plugin should only be used by people who are building Electron locally themselves. If you want to set up a local build of Electron, you should check out [Electron Build Tools](https://github.com/electron/build-tools)._\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-local-electron',\n      config: {\n        electronPath: '/Users/me/projects/electron/out/Testing'\n      }\n    }\n  ]\n};\n```\n","packages/plugin/vite/README.md":"## plugin-vite\n\nThis plugin makes it easy to set up standard vite tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-vite',\n      config: {\n        // `build` can specify multiple entry builds, which can be Main process, Preload scripts, Worker process, etc.\n        // If you are familiar with Vite configuration, it will look really familiar.\n        build: [\n          {\n            // `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`.\n            entry: 'src/main.js',\n            config: 'vite.main.config.mjs'\n          },\n          {\n            entry: 'src/preload.js',\n            config: 'vite.preload.config.mjs'\n          }\n        ],\n        renderer: [\n          {\n            name: 'main_window',\n            config: 'vite.renderer.config.mjs'\n          }\n        ]\n      }\n    }\n  ]\n};\n```\n\n### Main process hot restart\n\nRenderer code is hot-reloaded by Vite out of the box, but main process code is\nnot: the app has to be relaunched to pick it up. Set `hotRestart` to have\n`electron-forge start` do that for you whenever a main process bundle rebuilds:\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-vite',\n      config: {\n        hotRestart: true,\n        build: [\n          {\n            entry: 'src/main.js',\n            config: 'vite.main.config.mjs'\n          }\n        ],\n        renderer: []\n      }\n    }\n  ]\n};\n```\n\nThis is off by default, so main process changes otherwise only take effect when\nyou type `rs` in the terminal or restart `electron-forge start`. The option has\nno effect when packaging.\n","packages/plugin/webpack/README.md":"## plugin-webpack\n\nThis plugin makes it easy to set up standard webpack tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-webpack',\n      config: {\n        mainConfig: './webpack.main.config.js',\n        renderer: {\n          config: './webpack.renderer.config.js',\n          entryPoints: [{\n            name: 'main_window',\n            html: './src/renderer/index.html',\n            js: './src/renderer/index.js',\n            preload: {\n              js: './src/preload.js'\n            }\n          }]\n        }\n      }\n    }\n  ]\n};\n```\n","packages/publisher/bitbucket/README.md":"## Electron Forge: publisher-bitbucket\n\n`@electron-forge/publisher-bitbucket` publishes your artifacts to Bitbucket where users will be able to download them.\n\nThis publish target is for Bitbucket Cloud only and will not work with self hosted Bitbucket Server instances.\n\nConfiguration options are documented in [`PublisherBitbucketConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-bitbucket.PublisherBitbucketConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-bitbucket',\n      config: {\n        repository: {\n          owner: 'myusername',\n          name: 'myreponame'\n        },\n        auth: {\n          username: 'myusername',\n          appPassword: 'mysecretapppassword'\n        }\n      }\n    }\n  ]\n};\n```\n\nAlternatively you can (and should) use environment variables for the authentication\n\n```sh\n# env.sh\nBITBUCKET_USERNAME=\"myusername\"\nBITBUCKET_APP_PASSWORD=\"mysecretapppassword\"\n```\n\n```sh\nsource env.sh\n```\n","packages/publisher/electron-release-server/README.md":"## publisher-electron-release-server\n\n`@electron-forge/publisher-electron-release-server` publishes all your artifacts to a hosted instance of [Electron Release Server](https://github.com/ArekSredzki/electron-release-server) where users will be able to download them.\n\nPlease note that Electron Release Server is a community powered project and is not associated with Electron Forge or the Electron project directly.\n\nConfiguration options are documented in [`PublisherERSConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-electron-release-server.PublisherERSConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-electron-release-server',\n      config: {\n        baseUrl: 'https://update.server.com',\n        username: 'admin',\n        password: 'admin'\n      }\n    }\n  ]\n};\n```\n","packages/publisher/github/README.md":"## publisher-github\n\n`@electron-forge/publisher-github` publishes all your artifacts to GitHub releases, this allows your users to download the files straight from your repository or if your repository is open source you can use [update.electronjs.org](https://github.com/electron/update.electronjs.org) and get a free hosted update service.\n\nConfiguration options are documented in [`PublisherGitHubConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-github.PublisherGitHubConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-github',\n      config: {\n        repository: {\n          owner: 'me',\n          name: 'awesome-thing'\n        },\n        prerelease: true\n      }\n    }\n  ]\n};\n```\n","packages/publisher/nucleus/README.md":"## publisher-nucleus\n\n`@electron-forge/publisher-nucleus` publishes all your artifacts to an instance of Nucleus Update Server where users will be able to download them. This update service supports all three platforms.\n\nCheck out the README at [`atlassian/nucleus`](https://github.com/atlassian/nucleus) for more information on this project.\n\nConfiguration options are documented in [`Publisher\nNucleusConfig](https://js.electronforge.io/interfaces/_electron-forge_publisher-nucleus.PublisherNucleusConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-nucleus',\n      config: {\n        host: 'https://my-nucleus.mysite.com',\n        appId: 1,\n        channelId: 'abcdefg',\n        token: 'my-token'\n      }\n    }\n  ]\n};\n```\n\nWe recommend you set the `token`option using an environment variable, don't hard code into in your config.\n","packages/publisher/s3/README.md":"## publisher-s3\n\n`@electron-forge/publisher-s3` publishes all your artifacts to an Amazon S3 bucket where users will be able to download them.\n\nBy default, all files are positioned at the following key:\n\n```text\n${config.folder || appVersion}/${artifactName}\n```\n\nConfiguration options are documented in [PublisherS3Config](https://js.electronforge.io/interfaces/_electron-forge_publisher-s3.PublisherS3Config.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-s3',\n      config: {\n        bucket: 'my-bucket',\n        public: true\n      }\n    }\n  ]\n};\n```\n\nIf you run publish twice with the same version on the same platform, it is possible for your old artifacts to get overwritten in S3. It is your responsibility to ensure that you don't overwrite your own releases.\n\n### Authentication\n\nIt is recommended to follow the [Amazon AWS guide](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html) and set either a shared credentials guide or the proper environment variables. However, if that is not possible, the publisher config allows the setting of the accessKeyId and secretAccessKey configuration options.\n","packages/publisher/snapcraft/README.md":"## publisher-snapcraft\n\nThe Snapcraft target publishes your .snap artifacts to the Snap Store. All configuration of your package is done via the Snapcraft maker.\n\nThis target requires that the system has the snapcraft utility installed.\n\nConfiguration options are documented in [PublisherSnapConfig](https://js.electronforge.io/interfaces/_electron-forge_publisher-snapcraft.PublisherSnapcraftConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-snapcraft',\n      config: {\n        release: 'latest/edge, insider/stable'\n      }\n    }\n  ]\n};\n```\n","packages/utils/multi-logger/README.md":"# Multi Logger\n\n> Display multiple streams of logs as tabs in the terminal\n\nThis module collects multiple logically separated streams of logs (\"tabs\") and\nrenders them in the terminal the process is already running in. When attached\nto an interactive terminal it draws a full-screen tabbed UI with\n[ink](https://github.com/vadimdemedes/ink); otherwise (CI, piped output) it\nfalls back to append-only lines prefixed with a colored tag. Lines may contain\nANSI styling, so anything that would render in a terminal can be piped in.\n\n## Usage\n\n```javascript\nimport Logger from '@electron-forge/multi-logger';\n\nconst logger = new Logger({ title: 'My tool' });\n\nconst serverTab = logger.createTab('Server');\nconst frontEndTab = logger.createTab('Front End');\n\n// Everything logged before start() is buffered and shown once rendering begins.\nserverTab.setStatus({ state: 'building' });\nserverTab.log('listening on :3000');\nserverTab.setStatus({ state: 'success', durationMs: 1200 });\n\n// Pipe a child process's stdout/stderr into a tab of its own.\nlogger.attachProcess(spawn('node', ['server.js']), 'Server');\n\nawait logger.start();\n\n// Later: restore the terminal. Safe to call more than once, and it also runs\n// on process exit so a crash never leaves the terminal in the alternate screen.\nlogger.stop();\n```\n\n## API\n\n### `new Logger(options?)`\n\n| Option                  | Description                                                                                      |\n| ----------------------- | ------------------------------------------------------------------------------------------------ |\n| `stdout`                | Stream to render to. Defaults to `process.stdout`.                                               |\n| `stdin`                 | Stream to read keys from. Defaults to `process.stdin`.                                           |\n| `interactive`           | Whether the tabbed UI may be used. Defaults to `stdout.isTTY && stdin.isTTY && !process.env.CI`. |\n| `forceMode`             | `'ink'` or `'plain'` to bypass detection.                                                        |\n| `title`                 | Text shown at the left of the tab bar.                                                           |\n| `keys`                  | Extra hotkeys, `{ key, label, onPress }`, listed in the footer.                                  |\n| `maxLines`              | Lines kept per tab (and for the merged view). Defaults to 5000.                                  |\n| `initialTab`            | Name of the tab shown first, or `'all'` for the merged view. Defaults to the first tab.          |\n| `errorSwitchDebounceMs` | Minimum gap between automatic switches to a tab that failed. Defaults to 15000.                  |\n\n* `logger.createTab(name)` returns a `Tab`.\n* `logger.getTab(name)` / `logger.getTabs()`.\n* `logger.attachProcess(child, name = 'App')` pipes the child's `stdout` and\n  `stderr` into a tab line by line and marks the tab as exited when it ends.\n  A tab with the same name is reused, so a restarted process keeps its tab.\n  When the child exits, stdin is put back into raw mode in case the child\n  inherited the terminal and reset it on the way out (Node embedders such as\n  Electron do); `logger.reassertRawMode()` does the same on demand.\n* `logger.start()` begins rendering. Before this everything is buffered.\n* `logger.stop()` unmounts the UI and restores the terminal. If the UI never\n  rendered, the buffered lines are written out as plain text instead so\n  nothing is lost.\n* `logger.extendOptions({ keys?, title?, initialTab? })` adds to the options\n  the logger was created with: extra `keys` (already bound keys are left\n  alone) and `title` / `initialTab` when none is set yet. It has no effect on\n  the UI once `start()` has been called.\n\n### Sharing one logger across packages\n\nA process can only sensibly draw one UI, so a host and the plugins running\ninside it should share a logger instead of each creating their own:\n\n```javascript\nimport { ensureSharedLogger } from '@electron-forge/multi-logger';\n\n// The host creates it. The first caller decides how it is set up…\nconst logger = ensureSharedLogger({ title: 'My tool', initialTab: 'App' });\n\n// …and a plugin, later, just adds a tab to it.\nconst tab = ensureSharedLogger().createTab('Bundler');\n```\n\n* `ensureSharedLogger(options?)` returns the process-wide logger, creating it\n  on the first call. On later calls `options` are merged additively via\n  `extendOptions()`: extra `keys` are added, `title` / `initialTab` are taken\n  only if none is set yet, and everything else is ignored.\n* `getSharedLogger()` returns it, or `undefined` if none has been created.\n* `resetSharedLogger()` forgets it without stopping it; meant for tests.\n\nThe instance is registered under `Symbol.for('@electron-forge/multi-logger')`\non `globalThis`, so even two copies of this package in one `node_modules` tree\nend up sharing it.\n\n### `Tab`\n\n* `tab.log(text)` appends text, which may contain many lines and ANSI colors.\n* `tab.setStatus({ state, errors?, warnings?, durationMs?, detail? })` where\n  `state` is one of `idle`, `building`, `success`, `warning`, `error` or\n  `exited`. The status is shown next to the tab name.\n* `tab.clear()` empties the tab's buffer.\n\n## Interactive UI\n\n```text\nElectron Forge · webpack  1 Main Process ✔ 1.2s  2 Renderer (web) ⠹  3 Preload (electron-preload) ✖ 2  4 App ●  a All\n────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n… the active tab's most recent lines, wrapped to the terminal width …\n←/→ 1-9 tabs · a all · r restart electron · c clear · f follow · ↑/↓ scroll · q quit\n```\n\n| Key                            | Action                                                    |\n| ------------------------------ | --------------------------------------------------------- |\n| `←` / `→`, `Tab` / `Shift+Tab` | Cycle through the tabs                                    |\n| `1` to `9`                     | Jump to a tab                                             |\n| `a`                            | Merged view of every tab, in arrival order, tagged by tab |\n| `↑` / `↓`, `PgUp` / `PgDn`     | Scroll back through the buffer (stops following)          |\n| `Home` / `End`                 | Jump to the oldest line / back to the tail                |\n| `f`                            | Toggle following the tail                                 |\n| `c`                            | Clear the current tab (or every tab in the merged view)   |\n| `q`, `Ctrl+C`                  | Restore the terminal and re-raise `SIGINT`                |\n| custom `keys`                  | Whatever the host registered, e.g. `r` to restart         |\n\nThe tab bar always fits the terminal: when it gets tight the durations and\ncounts go first, then the title, and finally the chips wrap onto more rows.\nWhen a tab's status turns to `error` the view switches to it, at most once per\n`errorSwitchDebounceMs`, so a cascade of failures does not fight the user.\n\nThe UI uses the terminal's alternate screen, so whatever was printed before\n`start()` is still in the scrollback when it exits, and it prints a one-line\nstatus per tab (plus the tail of any tab that ended in an error) on the way\nout.\n\nBecause ink puts stdin into raw mode, line-based input such as typing `rs`\nis not seen by the host process while the UI is up; hosts should register an\nequivalent hotkey via `keys` instead.\n\n## Plain mode\n\nWhen stdout or stdin is not a TTY, `CI` is set, or the `interactive` option is\nset to `false`, lines are written as they arrive:\n\n```text\n[Main Process]   asset index.js 1.2 KiB [emitted] (name: main)\n[Main Process]   ✔ compiled in 1.2s\n[Renderer (web)] ✖ failed with 1 error in 2.1s\n```\n"},"files":{"AGENTS.md":"# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Overview\n\nElectron Forge is a Yarn 4 + Lerna monorepo of TypeScript packages published as `@electron-forge/*` (plus `create-electron-app`). All packages share one version (`lerna.json`). Node version: `.nvmrc`.\n\nThis is Forge 8, and several things differ from Forge 7, which you may know better:\n\n- Packages are ESM-only.\n- `init`/`import` live in `create-electron-app`, not core.\n- `publish` is renamed `release` (the old name remains as a deprecated alias).\n- `make --skip-package` is now `--from-package`, and `release --from-dry-run` is now `--from-make`.\n- The bundler plugins emit main and preload bundles as `.cjs`.\n- PRs target `main`.\n\n## Commands\n\n```bash\nyarn                      # install; postinstall regenerates the gitignored per-package tsconfig.json files and packages/tsconfig.json\nyarn build                # ~5s; tsc -b packages, then tools/test-dist checks that every package's entry point exists and imports\nyarn build:watch\n\nyarn lint                 # oxfmt --check, oxlint, markdownlint, lint of code blocks in markdown, markdown link check\nyarn lint:fix             # oxfmt --write + oxlint --fix\nyarn constraints          # yarn.config.cjs: a dependency must use the same range in every workspace (--fix to apply)\nyarn knip                 # unused files/exports/deps\n\nyarn test:fast [file] [-t \"name\"]   # unit tests (*.spec.ts); the full suite takes ~25s\nyarn test:slow [file]               # *.slow.spec.ts: downloads Electron, real packaging/making, 240s timeouts\nyarn test:verdaccio [file]          # *.slow.verdaccio.spec.ts against a local registry holding the current build\nyarn test:clear                     # remove temp dirs left behind by tests\n```\n\n## Verifying changes\n\n- **Rebuild before testing across packages.** A spec imports its own package from `../src`. Every other `@electron-forge/*` import resolves through `package.json` `exports` to `dist/`. After editing package A, run `yarn build`, or keep `yarn build:watch` running, before testing anything that imports A.\n- **Default to `yarn test:fast <file>`.** Run the slow or Verdaccio specs only when touching packaging, making, `init` or templates.\n- **Don't run bare `yarn test`.** It includes the `slow-verdaccio` project without starting Verdaccio, so those specs install `@electron-forge/*` from the public registry and test the wrong code.\n- **`test:fast`, `test:slow` and `test:verdaccio` run through `xvfb-maybe`.** On headless Linux without xvfb they exit with \"Failed to find xvfb-run in PATH\". Call vitest directly instead: `yarn vitest run --project fast <file>`, or `yarn spawn-verdaccio yarn vitest run --project slow-verdaccio <file>`.\n- **Verdaccio specs need more setup.** They publish the current `dist/`, so build first. They also need network access, port 4873 free, `pnpm` on PATH, and npm >= 11.17 for install age-gating.\n- **Specs are not type-checked.** `tsconfig.base.json` excludes `spec/`, and vitest strips types. A green build doesn't prove spec types are right.\n- **Try a change in a real app:** `yarn build && LINK_FORGE_DEPENDENCIES_ON_INIT=1 node packages/external/create-electron-app/dist/index.js <dir> --package-manager pnpm`. Then check that `<dir>/node_modules/@electron-forge/cli` resolves into this repo.\n  - Only pnpm links reliably.\n  - With npm, the default when there's no TTY, linking reports success, but the install that follows replaces the links with published packages.\n  - Yarn works only if Corepack provides Yarn 4. Yarn 1's `yarn link` fails.\n- **Debug logging:** `DEBUG=electron-forge:*` traces CLI and core internals.\n- **Parts of `CONTRIBUTING.md` are stale.** Its \"Running Forge locally\" and test instructions mention `yarn link:prepare`, `yarn build:fast` and `yarn test`, and it says the website docs live in a separate repo. Follow this file instead where they conflict.\n\nThe pre-commit hook runs `lint-staged` (oxfmt + oxlint) and `yarn constraints`. CI runs build, then `yarn lint`, `yarn constraints` and `yarn knip`, then the test suites on Windows, macOS and Linux. Changes that only touch `docs/` skip the test jobs.\n\n## Architecture\n\nPackage groups under `packages/` (each is a Yarn workspace):\n\n- `api/core`: the programmatic API (`src/api/{start,package,make,release}.ts`) and shared internals in `src/util/`.\n- `api/cli`: a thin `commander` wrapper. It dispatches to one executable per subcommand (`electron-forge-<cmd>.ts`), and each of those calls the core API.\n- `external/create-electron-app`: project scaffolding (`init.ts`, `import.ts`, `init-scripts/`).\n- `maker/*`, `publisher/*`, `plugin/*`: implementations of `MakerBase`, `PublisherBase` and `PluginBase` from the matching `*/base` package.\n  - Most makers wrap a third-party installer module (`electron-installer-*`, `electron-winstaller`, …), usually declared in `optionalDependencies`. `yarn constraints` skips only the names hard-coded in `OPTIONAL_DEPS` in `yarn.config.cjs`, so add a new installer there.\n  - `publisher/base-static` is shared logic for object-storage publishers (S3, GCS).\n  - Plugins provide lifecycle hooks and can take over `start` (`startLogic`). `vite` and `webpack` are the bundler plugins.\n- `template/*`: templates used by `create-electron-app`. `template/base` has `BaseTemplate` and the shared `tmpl/` files, and the vite and webpack templates extend it.\n- `utils/*`:\n  - `shared-types` lives in `utils/types`. It defines `ForgeConfig`, the hook signatures and the maker/publisher/plugin interfaces that every package codes against.\n  - `core-utils` covers package manager detection, the `@electron/rebuild` wrapper and Electron version lookup.\n  - Also: `multi-logger`, `tracer`, `test-utils`.\n\nCross-cutting pieces in `api/core/src/util/`:\n\n- **`forge-config.ts` loads the config.**\n  - Precedence: a config registered with `registerForgeConfigForDirectory()` (used by tests), then a `package.json` `config.forge` object, then the first `forge.config.{js,mjs,cjs,ts,mts,cts}` found. A `config.forge` _path string_ is used only when no `forge.config.*` file exists.\n  - TS configs load through `jiti`, JS configs through `import()`.\n  - After the `resolveForgeConfig` hook runs, the config is wrapped in a `Proxy`. Missing keys fall back to `ELECTRON_FORGE_<KEY>` env vars, and `fromBuildIdentifier()` values resolve per `buildIdentifier`.\n- **`import-search.ts` resolves by name** the makers, publishers and plugins in the config, plus `packagerConfig` hooks given as strings. It tries the bare specifier, then a path relative to the project, then the project's `node_modules`, and uses only the module's default export.\n- **`plugin-interface.ts` + `hook.ts` run the plugin lifecycle.** There are three kinds of hook:\n  - simple hooks (`runHook`)\n  - mutating hooks that thread a value through each plugin (`runMutatingHook`)\n  - hooks that return `listr2` tasks (`getHookListrTasks`)\n\n  Commands are built as `listr2` task lists.\n\n- **The commands chain together.** `package` wraps `@electron/packager` and injects Forge hooks into its `afterCopy`/`afterPrune`/`afterExtract` callbacks. `make` runs package first unless given `--from-package`, and `release` runs make first unless given `--from-make`.\n\nTests live in each package's `spec/`, and the filename suffix picks the vitest project (see the test commands above). Spec files run serially (`fileParallelism: false`) because many write into shared on-disk fixtures. Each file gets fresh module state, but registered configs and mocks persist between tests in the same file, so unregister them in `afterEach`. Core's fixture apps and configs are in `packages/api/core/spec/fixture/`.\n\n## Gotchas\n\n- **Coupled changes.** A behavior change in a bundler plugin usually also needs updates to the templates' `tmpl/` files (what users actually get) and to `docs/config/plugins/`.\n- **Two sets of docs.** `docs/` is the user-facing docs site. New pages must be registered in `docs/sidebars.ts`. The site isn't built in this repo. Markdown lint and the link check cover only `*.md`, so `.mdx` pages (including `docs/config/plugins/vite.mdx` and `webpack.mdx`) aren't checked at all; review them by hand. Each package's `README.md` is separate, hand-written, and published to npm.\n- **Dependency install policy.** `.yarnrc.yml` rejects versions published less than 7 days ago (`npmMinimalAgeGate`), except for pre-approved scopes, and disables install scripts, except those allowed in `dependenciesMeta`. CI installs with `--immutable`, so commit `yarn.lock`.\n- **Generated project references.** Each package's `tsconfig.json` is generated from `tsconfig.base.json` and its workspace dependencies by `tools/gen-tsconfigs.ts`, so don't hand-edit it. After adding or removing an `@electron-forge/*` dependency, re-run `yarn`, or `tsc -b` fails.\n- **Adding a package.**\n  1. Put it under an existing `workspaces` glob.\n  2. Set its version to the one in `lerna.json`, and depend on sibling packages with `workspace:*`.\n  3. Run `yarn`.\n  4. Add a workspace entry to `knip.json`.\n  5. Check the `typedoc.jsonc` entry points.\n  6. Copy the `exports`, `typings` and `publishConfig` fields from a sibling package. `tools/test-dist` fails without the entry point and typings.\n- **Imports.** Relative imports in `src/` use `.js` extensions. Some type-only re-exports use `.ts`, but `.js` also works there. Specs import `../src/...` without an extension; don't copy that style into `src/`.\n- **Commit messages.** Commits and PR titles use Conventional Commits (the `semantic` workflow checks PR titles), for example `fix(core): ...` or `feat(plugin-vite)!: ...`. Lerna derives version bumps from them, so don't bump versions in PRs.\n- **TSDoc style.** Follow the rules in `CONTRIBUTING.md`: the first line is imperative, capitalized and ends with a period.\n","docs/config/plugins/auto-unpack-natives.md":"---\ndescription: >-\n  Reduce loading times and disk consumption by unpacking native Node modules\n  from your Forge app's ASAR archive.\n---\n\n# Auto Unpack Native Modules Plugin\n\nThis plugin will automatically add all native Node modules in your `node_modules` folder to the [`asar.unpack`](https://electron.github.io/packager/main/interfaces/Options.html#asar) config option in your [`packagerConfig`](../configuration.mdx#electron-packager-config). If your app uses native Node modules, you should probably use this to reduce loading times and disk consumption on your users' machines.\n\n## Installation\n\n```shell\nnpm install --save-dev @electron-forge/plugin-auto-unpack-natives\n```\n\n## Usage\n\nYou must add this plugin to your [`plugins`](../configuration.mdx#plugins) array in your Forge configuration. There are currently no configuration options available for this plugin.\n\n:::info\nAsar archives are disabled by default with Electron Packager. Make sure you set your `packagerConfig.asar` value accordingly. This option also supports advanced configuration if you pass it an object. See the [API documentation for this option](https://js.electronforge.io/modules/_electron_forge_shared_types.InternalOptions.html#CreateOptions) for more information.\n:::\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  packagerConfig: {\n    asar: true // or an object containing your asar options\n  },\n  plugins: [\n    {\n      name: '@electron-forge/plugin-auto-unpack-natives',\n      config: {}\n    }\n  ]\n};\n```\n","docs/config/plugins/electronegativity.md":"---\ndescription: >-\n  Check for misconfigurations and security anti-patterns with the\n  Electronegativity tool.\n---\n\n# Electronegativity Plugin\n\nThe Electronegativity plugin integrates Doyensec's [Electronegativity tool](https://github.com/doyensec/electronegativity#electronegativity) into the Electron Forge workflow. After packaging your Electron app, it identifies any known misconfigurations and security anti-patterns.\n\n## Installation\n\n```shell\nnpm install --save-dev @electron-forge/plugin-electronegativity\n```\n\n## Usage\n\nAdd this plugin to the [`plugins`](../configuration.mdx#plugins) array in your Forge configuration. All [programmatic options for Electronegativity](https://github.com/doyensec/electronegativity#programmatically), except for `input` and `electronVersion`.\n\n### Example\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      name: '@electron-forge/plugin-electronegativity',\n      config: {\n        isSarif: true\n      }\n    }\n  ]\n  // ...\n};\n```\n","docs/config/plugins/index.md":"---\ndescription: Modules to extend Forge's core functionality\n---\n\n# Plugins\n\nElectron Forge has a plugin system which allows you to extend its core functionality.\n\nBy default, Forge takes a vanilla JS application and packages, makes and publishes it (see the [Build Lifecycle](../../core-concepts/build-lifecycle.md) document for more details). Plugins can execute custom logic during any of the Forge [Hooks](../hooks.md) during the build process, and can also override the [Start](../../cli.md#start) command in development.\n\n:::info\nIf you want to write your own Forge plugin, check out the [Writing Plugins](../../advanced/extending-electron-forge/writing-plugins.md) guide.\n:::\n\n## Bundler plugins\n\n- [Webpack Plugin](webpack.mdx) - Build your Electron app with webpack\n- [Vite Plugin](vite.mdx) - Build your Electron app with Vite\n\n## Utility plugins\n\n- [Auto Unpack Native Modules Plugin](auto-unpack-natives.md) - Unpack native Node.js modules from your Forge app's ASAR archive.\n- [Local Electron Plugin](local-electron.md) - Integrate a local build of Electron into your Forge app.\n- [Fuses Plugin](fuses.mdx) - Toggle Electron functionality at package-time with Electron Fuses.\n- [Electronegativity Plugin](electronegativity.md) - Check for misconfigurations and security anti-patterns with the Electronegativity tool.\n","docs/config/plugins/local-electron.md":"---\ndescription: Integrate a local build of Electron into your Forge app.\n---\n\n# Local Electron Plugin\n\n:::info\nThis plugin should only be used by people who are building Electron locally themselves. If you want to use a fork of Electron, check out the [environment variables](https://github.com/electron/get#usage) you can use to configure `@electron/get`.\n:::\n\nThis plugin allows you to both run and build your app using a **local** build of Electron. This can be incredibly useful if you want to test a feature or a bug fix in your app before making a PR up to the Electron repository.\n\nIf you want to set up a local build of Electron, you should check out [Electron Build Tools](https://github.com/electron/build-tools).\n\n### Installation\n\n```bash\nnpm install --save-dev @electron-forge/plugin-local-electron\n```\n\n### Usage\n\nOnce you have a working build of Electron, point the plugin's `electronPath` config option to the folder containing the built Electron binary.\n\nAll possible configuration options are documented in [`LocalElectronPluginConfig`](https://js.electronforge.io/interfaces/\\_electron\\_forge\\_plugin\\_local\\_electron.LocalElectronPluginConfig.html).\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-local-electron',\n      config: {\n        electronPath: '/Users/me/projects/electron/out/Testing'\n      }\n    }\n  ]\n};\n```\n\n:::info\nPlease note that the plugin only accepts **absolute paths**. You should use Node's [`path.resolve()`](https://nodejs.org/api/path.html#pathresolvepaths) to make things deterministic.\n:::\n","packages/api/core/README.md":"# Electron Forge Core\n\nThis module contains the core logic of Electron Forge and exposes the base\nAPI as a number of simple JS functions.\n\n## Basic Usage\n\n```javascript\nimport { api } from '@electron-forge/core';\n\n// Package the current directory as an Electron app\napi.package(import.meta.dirname);\n```\n\nThe named export `api` has it's methods documented over at [ForgeAPI](https://js.electronforge.io/classes/_electron-forge_core.ForgeAPI.html).\nAll the methods are async and expose the core forge methods, please note that all\nuser-side configuration is still done through your forge config file or the \"config.forge\"\nsection of your package.json. This API simply let's you call the methods in\nnode land without using the CLI.\n\n## Error Handling\n\nAs all methods return a promise you should handle all rejections, you should note\nthat rejections will **not** always be errors, in fact we commonly reject our\npromises with just strings so do not assume that properties such as `stack` or\n`message` will exist on thrown errors.\n","packages/external/create-electron-app/README.md":"## create-electron-app\n\nCreate Electron App allows you to quickly bootstrap a new Electron app using\n[Electron Forge](https://electronforge.io).\n\n### Usage\n\nInitialize a new project by running the following:\n\n```sh\nnpx create-electron-app@latest my-app\n```\n\nYou should now have a directory called my-app with an ultra-minimal Electron app boilerplate inside.\nIf you head into that directory and start up the app, you'll be all set to start developing!\n\n```sh\ncd my-app\nnpm start\n```\n","packages/maker/appx/README.md":"## maker-appx\n\n> **Deprecated:** use [`@electron-forge/maker-msix`](https://www.electronforge.io/config/makers/msix) instead.\n\n`@electron-forge/maker-appx` is a legacy compatibility layer over the MSIX maker. It maps its `MakerAppXConfig` onto `electron-windows-msix` and builds a `.msix` package, which is designed to target the Windows Store.\n\nYou can only build the AppX target on Windows machines with the Windows 10 SDK installed.\n\nWhen `devCert` is not set, `electron-windows-msix` signs the package with a self-signed development certificate, which the maker saves next to the `.msix` as `dev_cert.cer` and `dev_cert.pfx` so it can be trusted on a test device. The `.pfx` password is `WINDOWS_CERTIFICATE_PASSWORD` when that environment variable is set, otherwise a random one.\n\nConfiguration options are documented in [`MakerAppXConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-appx.MakerAppXConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-appx',\n      config: {\n        publisher: 'CN=developmentca',\n        devCert: 'C:\\\\devcert.pfx',\n        certPass: 'abcd'\n      }\n    }\n  ]\n};\n```\n","packages/maker/deb/README.md":"## maker-deb\n\n`@electron-forge/maker-deb` builds .deb packages, which are the standard package format for Debian-based Linux distributions such as Ubuntu. You can only build the deb target on Linux or macOS machines with the dpkg package installed.\n\nConfiguration options are documented in [`MakerDebConfigOptions`](https://js.electronforge.io/interfaces/_electron-forge_maker-deb.MakerDebConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-deb',\n      config: {\n        options: {\n          maintainer: 'The Forgers',\n          homepage: 'https://example.com',\n          icon: 'path/to/icon.svg'\n        }\n      }\n    }\n  ]\n};\n```\n","packages/maker/dmg/README.md":"## maker-dmg\n\n`@electron-forge/maker-dmg` builds `.dmg` files, which are the standard format for sharing macOS apps. You can only build the DMG target on macOS machines.\n\nConfiguration options are documented in [`MakerDMGConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-dmg.MakerDMGConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-dmg',\n      config: {\n        background: './assets/dmg-background.png',\n        format: 'ULFO'\n      }\n    }\n  ]\n};\n```\n","packages/maker/flatpak/README.md":"## maker-flatpak\n\n`@electron-forge/maker-flatpak` [`.flatpak` files](http://flatpak.org/), which is a packaging format for Linux distributions that allows for sandboxed installation of applications in isolation from the rest of their system.\n\nYou can only build the Flatpak target if you have `flatpak`, `flatpak-builder`, and `eu-strip` _\\(usually part of the `elfutils` package\\)_ installed on your system.\n\nConfiguration options are documented in [`MakerFlatpakOptionsConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-flatpak.MakerFlatpakConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-flatpak',\n      config: {\n        options: {\n          categories: ['Video'],\n          mimeType: ['video/h264']\n        }\n      }\n    }\n  ]\n};\n```\n","packages/maker/msix/README.md":"## maker-msix\n\n> [!IMPORTANT]\n> This module is _experimental_ and is subject to breaking changes between releases.\n> See GitHub Releases change notes for migration instructions.\n\n`@electron-forge/maker-msix` builds `.msix` packages, which can be distributed directly or via the Windows Store.\n\nYou can only build the MSIX target on Windows machines with the Windows 10 SDK installed.\n\nConfiguration options are documented in [`MakerMSIXConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-msix.MakerMSIXConfig.html).\n\nmaker-msix utilizes @electron/windows-sign via the `windowsSignOptions` property. See the [windows-sign documentation](https://github.com/electron/windows-sign/blob/main/README.md) for details.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-msix',\n      config: {\n        manifestVariables: {\n          publisher: 'Electron Dev'\n        },\n        windowsSignOptions: {\n          certificatePassword: '12345'\n        }\n      }\n    }\n  ]\n};\n```\n","packages/maker/pkg/README.md":"## maker-pkg\n\n`@electron-forge/maker-pkg` builds `.pkg` files for macOS. These are used to upload your application to the Mac App Store or just as an alternate distribution method for macOS users.  You can only build the Pkg target on macOS machines while targeting the `darwin`  or `mas` platforms.\n\nConfiguration options are documented in [`MakerPkgConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-pkg.MakerPKGConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-pkg',\n      config: {\n        keychain: 'my-secret-ci-keychain'\n      }\n    }\n  ]\n};\n```\n","packages/maker/rpm/README.md":"## maker-rpm\n\n`@electron-forge/maker-rpm` builds `.rpm` files, which is the standard package format for RedHat-based Linux distributions such as Fedora.\n\nYou can only build the RPM target on Linux machines with the `rpm` or `rpm-build` packages installed.\n\nConfiguration options are documented in [`MakerRpmConfigOptions`](https://js.electronforge.io/interfaces/_electron-forge_maker-rpm.MakerRpmConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-rpm',\n      config: {\n        options: {\n          name: 'QuickEdit',\n          homepage: 'http://example.com'\n        }\n      }\n    }\n  ]\n};\n```\n","packages/maker/snap/README.md":"## maker-snap\n\n`@electron-forge/maker-snap` builds `.snap` files, which is the packaging format created and sponsored by Canonical, the company behind Ubuntu. It is a sandboxed package format that lets users of various Linux distributions install your application in an isolated environment on their machine.\n\nYou can only build the Snapcraft target on Linux systems with the `snapcraft` package installed.\n\nConfiguration options are documented in [`MakerSnapConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-snap.MakerSnapConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-snap',\n      config: {\n        version: '1.1.0',\n        features: {\n          audio: true,\n          mpris: 'com.example.mpris',\n          webgl: true\n        },\n        summary: 'My application'\n      }\n    }\n  ]\n};\n```\n","packages/maker/squirrel/README.md":"## maker-squirrel\n\n`@electron-forge/maker-squirrel` builds a number of files required to distribute apps using the Squirrel.Windows framework. It generates a `{appName} Setup.exe` file which is the main installer for your application, `{appName}-full.nupkg` and a `RELEASES` file which you use to issue updates to your application.\n\nPre-requisites:\n\n* Windows machine\n* Linux machine with `mono` and `wine` installed.\n\nConfiguration options are documented in [`MakerSquirrelConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-squirrel.MakerSquirrelConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-squirrel',\n      config: {\n        certificateFile: './cert.pfx',\n        certificatePassword: 'this-is-a-secret'\n      }\n    }\n  ]\n};\n```\n","packages/maker/wix/README.md":"\n## maker-wix-msi\n\nThe WiX MSI target builds `.msi` files, which are \"traditional\" Windows installer files.\n\nPre-requisites:\n\n* `light` and `candle` installed from [the WiX toolkit](https://github.com/felixrieseberg/electron-wix-msi#prerequisites).\n\nConfiguration options are documented in [`MakerWixConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-wix.MakerWixConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-wix',\n      config: {\n        language: 1033,\n        manufacturer: 'My Awesome Company'\n      }\n    }\n  ]\n};\n```\n","packages/maker/zip/README.md":"## maker-zip\n\n`@electron-forge/maker-zip` builds basic `.zip` files containing your packaged application. There are no platform specific dependencies for using this maker and it will run on any platform.\n\nConfiguration options are documented in [`MakerZIPConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-zip.MakerZIPConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-zip'\n    }\n  ]\n};\n```\n","packages/plugin/auto-unpack-natives/README.md":"## plugin-auto-unpack-natives\n\nThis plugin will automatically add all native Node modules in your node_modules folder to the `asar.unpack` config option in your `packagerConfig`. If your app uses native Node modules, you should probably use this to reduce loading times and disk consumption on your users' machines.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-auto-unpack-natives',\n      config: {}\n    }\n  ]\n};\n```\n","packages/plugin/fuses/README.md":"## @electron-forge/plugin-fuses\n\nThis plugin allows flipping [Electron Fuses](https://github.com/electron/fuses) when packaging your app with Electron Forge.\n\n### Usage\n\nInstall `@electron-forge/plugin-fuses` and `@electron/fuses` as dev dependencies and add this plugin to the `plugins` array in your Forge configuration:\n\n```shell\n# Yarn\nyarn add --dev @electron-forge/plugin-fuses @electron/fuses\n\n# npm\nnpm i -D @electron-forge/plugin-fuses @electron/fuses\n```\n\n```js\n// forge.config.js\n\nconst { FusesPlugin } = require('@electron-forge/plugin-fuses');\nconst { FuseV1Options, FuseVersion } = require('@electron/fuses');\n\nconst forgeConfig = {\n  plugins: [\n    new FusesPlugin({\n      version: FuseVersion.V1,\n      [FuseV1Options.RunAsNode]: false\n      // ...any other options supported by @electron/fuses\n    })\n  ]\n};\n\nmodule.exports = forgeConfig;\n```\n","packages/plugin/local-electron/README.md":"## plugin-local-electron\n\nThis plugin allows you to both run and build your app using a local build of Electron. This can be incredibly useful if you want to test a feature or a bug fix in your app before making a PR up to the Electron repository.\n\n_Note: This plugin should only be used by people who are building Electron locally themselves. If you want to set up a local build of Electron, you should check out [Electron Build Tools](https://github.com/electron/build-tools)._\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-local-electron',\n      config: {\n        electronPath: '/Users/me/projects/electron/out/Testing'\n      }\n    }\n  ]\n};\n```\n","packages/plugin/vite/README.md":"## plugin-vite\n\nThis plugin makes it easy to set up standard vite tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-vite',\n      config: {\n        // `build` can specify multiple entry builds, which can be Main process, Preload scripts, Worker process, etc.\n        // If you are familiar with Vite configuration, it will look really familiar.\n        build: [\n          {\n            // `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`.\n            entry: 'src/main.js',\n            config: 'vite.main.config.mjs'\n          },\n          {\n            entry: 'src/preload.js',\n            config: 'vite.preload.config.mjs'\n          }\n        ],\n        renderer: [\n          {\n            name: 'main_window',\n            config: 'vite.renderer.config.mjs'\n          }\n        ]\n      }\n    }\n  ]\n};\n```\n\n### Main process hot restart\n\nRenderer code is hot-reloaded by Vite out of the box, but main process code is\nnot: the app has to be relaunched to pick it up. Set `hotRestart` to have\n`electron-forge start` do that for you whenever a main process bundle rebuilds:\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-vite',\n      config: {\n        hotRestart: true,\n        build: [\n          {\n            entry: 'src/main.js',\n            config: 'vite.main.config.mjs'\n          }\n        ],\n        renderer: []\n      }\n    }\n  ]\n};\n```\n\nThis is off by default, so main process changes otherwise only take effect when\nyou type `rs` in the terminal or restart `electron-forge start`. The option has\nno effect when packaging.\n","packages/plugin/webpack/README.md":"## plugin-webpack\n\nThis plugin makes it easy to set up standard webpack tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-webpack',\n      config: {\n        mainConfig: './webpack.main.config.js',\n        renderer: {\n          config: './webpack.renderer.config.js',\n          entryPoints: [{\n            name: 'main_window',\n            html: './src/renderer/index.html',\n            js: './src/renderer/index.js',\n            preload: {\n              js: './src/preload.js'\n            }\n          }]\n        }\n      }\n    }\n  ]\n};\n```\n","packages/publisher/bitbucket/README.md":"## Electron Forge: publisher-bitbucket\n\n`@electron-forge/publisher-bitbucket` publishes your artifacts to Bitbucket where users will be able to download them.\n\nThis publish target is for Bitbucket Cloud only and will not work with self hosted Bitbucket Server instances.\n\nConfiguration options are documented in [`PublisherBitbucketConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-bitbucket.PublisherBitbucketConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-bitbucket',\n      config: {\n        repository: {\n          owner: 'myusername',\n          name: 'myreponame'\n        },\n        auth: {\n          username: 'myusername',\n          appPassword: 'mysecretapppassword'\n        }\n      }\n    }\n  ]\n};\n```\n\nAlternatively you can (and should) use environment variables for the authentication\n\n```sh\n# env.sh\nBITBUCKET_USERNAME=\"myusername\"\nBITBUCKET_APP_PASSWORD=\"mysecretapppassword\"\n```\n\n```sh\nsource env.sh\n```\n","packages/publisher/electron-release-server/README.md":"## publisher-electron-release-server\n\n`@electron-forge/publisher-electron-release-server` publishes all your artifacts to a hosted instance of [Electron Release Server](https://github.com/ArekSredzki/electron-release-server) where users will be able to download them.\n\nPlease note that Electron Release Server is a community powered project and is not associated with Electron Forge or the Electron project directly.\n\nConfiguration options are documented in [`PublisherERSConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-electron-release-server.PublisherERSConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-electron-release-server',\n      config: {\n        baseUrl: 'https://update.server.com',\n        username: 'admin',\n        password: 'admin'\n      }\n    }\n  ]\n};\n```\n","packages/publisher/github/README.md":"## publisher-github\n\n`@electron-forge/publisher-github` publishes all your artifacts to GitHub releases, this allows your users to download the files straight from your repository or if your repository is open source you can use [update.electronjs.org](https://github.com/electron/update.electronjs.org) and get a free hosted update service.\n\nConfiguration options are documented in [`PublisherGitHubConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-github.PublisherGitHubConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-github',\n      config: {\n        repository: {\n          owner: 'me',\n          name: 'awesome-thing'\n        },\n        prerelease: true\n      }\n    }\n  ]\n};\n```\n","packages/publisher/nucleus/README.md":"## publisher-nucleus\n\n`@electron-forge/publisher-nucleus` publishes all your artifacts to an instance of Nucleus Update Server where users will be able to download them. This update service supports all three platforms.\n\nCheck out the README at [`atlassian/nucleus`](https://github.com/atlassian/nucleus) for more information on this project.\n\nConfiguration options are documented in [`Publisher\nNucleusConfig](https://js.electronforge.io/interfaces/_electron-forge_publisher-nucleus.PublisherNucleusConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-nucleus',\n      config: {\n        host: 'https://my-nucleus.mysite.com',\n        appId: 1,\n        channelId: 'abcdefg',\n        token: 'my-token'\n      }\n    }\n  ]\n};\n```\n\nWe recommend you set the `token`option using an environment variable, don't hard code into in your config.\n","packages/publisher/s3/README.md":"## publisher-s3\n\n`@electron-forge/publisher-s3` publishes all your artifacts to an Amazon S3 bucket where users will be able to download them.\n\nBy default, all files are positioned at the following key:\n\n```text\n${config.folder || appVersion}/${artifactName}\n```\n\nConfiguration options are documented in [PublisherS3Config](https://js.electronforge.io/interfaces/_electron-forge_publisher-s3.PublisherS3Config.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-s3',\n      config: {\n        bucket: 'my-bucket',\n        public: true\n      }\n    }\n  ]\n};\n```\n\nIf you run publish twice with the same version on the same platform, it is possible for your old artifacts to get overwritten in S3. It is your responsibility to ensure that you don't overwrite your own releases.\n\n### Authentication\n\nIt is recommended to follow the [Amazon AWS guide](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html) and set either a shared credentials guide or the proper environment variables. However, if that is not possible, the publisher config allows the setting of the accessKeyId and secretAccessKey configuration options.\n","packages/publisher/snapcraft/README.md":"## publisher-snapcraft\n\nThe Snapcraft target publishes your .snap artifacts to the Snap Store. All configuration of your package is done via the Snapcraft maker.\n\nThis target requires that the system has the snapcraft utility installed.\n\nConfiguration options are documented in [PublisherSnapConfig](https://js.electronforge.io/interfaces/_electron-forge_publisher-snapcraft.PublisherSnapcraftConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-snapcraft',\n      config: {\n        release: 'latest/edge, insider/stable'\n      }\n    }\n  ]\n};\n```\n","packages/utils/multi-logger/README.md":"# Multi Logger\n\n> Display multiple streams of logs as tabs in the terminal\n\nThis module collects multiple logically separated streams of logs (\"tabs\") and\nrenders them in the terminal the process is already running in. When attached\nto an interactive terminal it draws a full-screen tabbed UI with\n[ink](https://github.com/vadimdemedes/ink); otherwise (CI, piped output) it\nfalls back to append-only lines prefixed with a colored tag. Lines may contain\nANSI styling, so anything that would render in a terminal can be piped in.\n\n## Usage\n\n```javascript\nimport Logger from '@electron-forge/multi-logger';\n\nconst logger = new Logger({ title: 'My tool' });\n\nconst serverTab = logger.createTab('Server');\nconst frontEndTab = logger.createTab('Front End');\n\n// Everything logged before start() is buffered and shown once rendering begins.\nserverTab.setStatus({ state: 'building' });\nserverTab.log('listening on :3000');\nserverTab.setStatus({ state: 'success', durationMs: 1200 });\n\n// Pipe a child process's stdout/stderr into a tab of its own.\nlogger.attachProcess(spawn('node', ['server.js']), 'Server');\n\nawait logger.start();\n\n// Later: restore the terminal. Safe to call more than once, and it also runs\n// on process exit so a crash never leaves the terminal in the alternate screen.\nlogger.stop();\n```\n\n## API\n\n### `new Logger(options?)`\n\n| Option                  | Description                                                                                      |\n| ----------------------- | ------------------------------------------------------------------------------------------------ |\n| `stdout`                | Stream to render to. Defaults to `process.stdout`.                                               |\n| `stdin`                 | Stream to read keys from. Defaults to `process.stdin`.                                           |\n| `interactive`           | Whether the tabbed UI may be used. Defaults to `stdout.isTTY && stdin.isTTY && !process.env.CI`. |\n| `forceMode`             | `'ink'` or `'plain'` to bypass detection.                                                        |\n| `title`                 | Text shown at the left of the tab bar.                                                           |\n| `keys`                  | Extra hotkeys, `{ key, label, onPress }`, listed in the footer.                                  |\n| `maxLines`              | Lines kept per tab (and for the merged view). Defaults to 5000.                                  |\n| `initialTab`            | Name of the tab shown first, or `'all'` for the merged view. Defaults to the first tab.          |\n| `errorSwitchDebounceMs` | Minimum gap between automatic switches to a tab that failed. Defaults to 15000.                  |\n\n* `logger.createTab(name)` returns a `Tab`.\n* `logger.getTab(name)` / `logger.getTabs()`.\n* `logger.attachProcess(child, name = 'App')` pipes the child's `stdout` and\n  `stderr` into a tab line by line and marks the tab as exited when it ends.\n  A tab with the same name is reused, so a restarted process keeps its tab.\n  When the child exits, stdin is put back into raw mode in case the child\n  inherited the terminal and reset it on the way out (Node embedders such as\n  Electron do); `logger.reassertRawMode()` does the same on demand.\n* `logger.start()` begins rendering. Before this everything is buffered.\n* `logger.stop()` unmounts the UI and restores the terminal. If the UI never\n  rendered, the buffered lines are written out as plain text instead so\n  nothing is lost.\n* `logger.extendOptions({ keys?, title?, initialTab? })` adds to the options\n  the logger was created with: extra `keys` (already bound keys are left\n  alone) and `title` / `initialTab` when none is set yet. It has no effect on\n  the UI once `start()` has been called.\n\n### Sharing one logger across packages\n\nA process can only sensibly draw one UI, so a host and the plugins running\ninside it should share a logger instead of each creating their own:\n\n```javascript\nimport { ensureSharedLogger } from '@electron-forge/multi-logger';\n\n// The host creates it. The first caller decides how it is set up…\nconst logger = ensureSharedLogger({ title: 'My tool', initialTab: 'App' });\n\n// …and a plugin, later, just adds a tab to it.\nconst tab = ensureSharedLogger().createTab('Bundler');\n```\n\n* `ensureSharedLogger(options?)` returns the process-wide logger, creating it\n  on the first call. On later calls `options` are merged additively via\n  `extendOptions()`: extra `keys` are added, `title` / `initialTab` are taken\n  only if none is set yet, and everything else is ignored.\n* `getSharedLogger()` returns it, or `undefined` if none has been created.\n* `resetSharedLogger()` forgets it without stopping it; meant for tests.\n\nThe instance is registered under `Symbol.for('@electron-forge/multi-logger')`\non `globalThis`, so even two copies of this package in one `node_modules` tree\nend up sharing it.\n\n### `Tab`\n\n* `tab.log(text)` appends text, which may contain many lines and ANSI colors.\n* `tab.setStatus({ state, errors?, warnings?, durationMs?, detail? })` where\n  `state` is one of `idle`, `building`, `success`, `warning`, `error` or\n  `exited`. The status is shown next to the tab name.\n* `tab.clear()` empties the tab's buffer.\n\n## Interactive UI\n\n```text\nElectron Forge · webpack  1 Main Process ✔ 1.2s  2 Renderer (web) ⠹  3 Preload (electron-preload) ✖ 2  4 App ●  a All\n────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n… the active tab's most recent lines, wrapped to the terminal width …\n←/→ 1-9 tabs · a all · r restart electron · c clear · f follow · ↑/↓ scroll · q quit\n```\n\n| Key                            | Action                                                    |\n| ------------------------------ | --------------------------------------------------------- |\n| `←` / `→`, `Tab` / `Shift+Tab` | Cycle through the tabs                                    |\n| `1` to `9`                     | Jump to a tab                                             |\n| `a`                            | Merged view of every tab, in arrival order, tagged by tab |\n| `↑` / `↓`, `PgUp` / `PgDn`     | Scroll back through the buffer (stops following)          |\n| `Home` / `End`                 | Jump to the oldest line / back to the tail                |\n| `f`                            | Toggle following the tail                                 |\n| `c`                            | Clear the current tab (or every tab in the merged view)   |\n| `q`, `Ctrl+C`                  | Restore the terminal and re-raise `SIGINT`                |\n| custom `keys`                  | Whatever the host registered, e.g. `r` to restart         |\n\nThe tab bar always fits the terminal: when it gets tight the durations and\ncounts go first, then the title, and finally the chips wrap onto more rows.\nWhen a tab's status turns to `error` the view switches to it, at most once per\n`errorSwitchDebounceMs`, so a cascade of failures does not fight the user.\n\nThe UI uses the terminal's alternate screen, so whatever was printed before\n`start()` is still in the scrollback when it exits, and it prints a one-line\nstatus per tab (plus the tail of any tab that ended in an error) on the way\nout.\n\nBecause ink puts stdin into raw mode, line-based input such as typing `rs`\nis not seen by the host process while the UI is up; hosts should register an\nequivalent hotkey via `keys` instead.\n\n## Plain mode\n\nWhen stdout or stdin is not a TTY, `CI` is set, or the `interactive` option is\nset to `false`, lines are written as they arrive:\n\n```text\n[Main Process]   asset index.js 1.2 KiB [emitted] (name: main)\n[Main Process]   ✔ compiled in 1.2s\n[Renderer (web)] ✖ failed with 1 error in 2.1s\n```\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Overview\n\nElectron Forge is a Yarn 4 + Lerna monorepo of TypeScript packages published as `@electron-forge/*` (plus `create-electron-app`). All packages share one version (`lerna.json`). Node version: `.nvmrc`.\n\nThis is Forge 8, and several things differ from Forge 7, which you may know better:\n\n- Packages are ESM-only.\n- `init`/`import` live in `create-electron-app`, not core.\n- `publish` is renamed `release` (the old name remains as a deprecated alias).\n- `make --skip-package` is now `--from-package`, and `release --from-dry-run` is now `--from-make`.\n- The bundler plugins emit main and preload bundles as `.cjs`.\n- PRs target `main`.\n\n## Commands\n\n```bash\nyarn                      # install; postinstall regenerates the gitignored per-package tsconfig.json files and packages/tsconfig.json\nyarn build                # ~5s; tsc -b packages, then tools/test-dist checks that every package's entry point exists and imports\nyarn build:watch\n\nyarn lint                 # oxfmt --check, oxlint, markdownlint, lint of code blocks in markdown, markdown link check\nyarn lint:fix             # oxfmt --write + oxlint --fix\nyarn constraints          # yarn.config.cjs: a dependency must use the same range in every workspace (--fix to apply)\nyarn knip                 # unused files/exports/deps\n\nyarn test:fast [file] [-t \"name\"]   # unit tests (*.spec.ts); the full suite takes ~25s\nyarn test:slow [file]               # *.slow.spec.ts: downloads Electron, real packaging/making, 240s timeouts\nyarn test:verdaccio [file]          # *.slow.verdaccio.spec.ts against a local registry holding the current build\nyarn test:clear                     # remove temp dirs left behind by tests\n```\n\n## Verifying changes\n\n- **Rebuild before testing across packages.** A spec imports its own package from `../src`. Every other `@electron-forge/*` import resolves through `package.json` `exports` to `dist/`. After editing package A, run `yarn build`, or keep `yarn build:watch` running, before testing anything that imports A.\n- **Default to `yarn test:fast <file>`.** Run the slow or Verdaccio specs only when touching packaging, making, `init` or templates.\n- **Don't run bare `yarn test`.** It includes the `slow-verdaccio` project without starting Verdaccio, so those specs install `@electron-forge/*` from the public registry and test the wrong code.\n- **`test:fast`, `test:slow` and `test:verdaccio` run through `xvfb-maybe`.** On headless Linux without xvfb they exit with \"Failed to find xvfb-run in PATH\". Call vitest directly instead: `yarn vitest run --project fast <file>`, or `yarn spawn-verdaccio yarn vitest run --project slow-verdaccio <file>`.\n- **Verdaccio specs need more setup.** They publish the current `dist/`, so build first. They also need network access, port 4873 free, `pnpm` on PATH, and npm >= 11.17 for install age-gating.\n- **Specs are not type-checked.** `tsconfig.base.json` excludes `spec/`, and vitest strips types. A green build doesn't prove spec types are right.\n- **Try a change in a real app:** `yarn build && LINK_FORGE_DEPENDENCIES_ON_INIT=1 node packages/external/create-electron-app/dist/index.js <dir> --package-manager pnpm`. Then check that `<dir>/node_modules/@electron-forge/cli` resolves into this repo.\n  - Only pnpm links reliably.\n  - With npm, the default when there's no TTY, linking reports success, but the install that follows replaces the links with published packages.\n  - Yarn works only if Corepack provides Yarn 4. Yarn 1's `yarn link` fails.\n- **Debug logging:** `DEBUG=electron-forge:*` traces CLI and core internals.\n- **Parts of `CONTRIBUTING.md` are stale.** Its \"Running Forge locally\" and test instructions mention `yarn link:prepare`, `yarn build:fast` and `yarn test`, and it says the website docs live in a separate repo. Follow this file instead where they conflict.\n\nThe pre-commit hook runs `lint-staged` (oxfmt + oxlint) and `yarn constraints`. CI runs build, then `yarn lint`, `yarn constraints` and `yarn knip`, then the test suites on Windows, macOS and Linux. Changes that only touch `docs/` skip the test jobs.\n\n## Architecture\n\nPackage groups under `packages/` (each is a Yarn workspace):\n\n- `api/core`: the programmatic API (`src/api/{start,package,make,release}.ts`) and shared internals in `src/util/`.\n- `api/cli`: a thin `commander` wrapper. It dispatches to one executable per subcommand (`electron-forge-<cmd>.ts`), and each of those calls the core API.\n- `external/create-electron-app`: project scaffolding (`init.ts`, `import.ts`, `init-scripts/`).\n- `maker/*`, `publisher/*`, `plugin/*`: implementations of `MakerBase`, `PublisherBase` and `PluginBase` from the matching `*/base` package.\n  - Most makers wrap a third-party installer module (`electron-installer-*`, `electron-winstaller`, …), usually declared in `optionalDependencies`. `yarn constraints` skips only the names hard-coded in `OPTIONAL_DEPS` in `yarn.config.cjs`, so add a new installer there.\n  - `publisher/base-static` is shared logic for object-storage publishers (S3, GCS).\n  - Plugins provide lifecycle hooks and can take over `start` (`startLogic`). `vite` and `webpack` are the bundler plugins.\n- `template/*`: templates used by `create-electron-app`. `template/base` has `BaseTemplate` and the shared `tmpl/` files, and the vite and webpack templates extend it.\n- `utils/*`:\n  - `shared-types` lives in `utils/types`. It defines `ForgeConfig`, the hook signatures and the maker/publisher/plugin interfaces that every package codes against.\n  - `core-utils` covers package manager detection, the `@electron/rebuild` wrapper and Electron version lookup.\n  - Also: `multi-logger`, `tracer`, `test-utils`.\n\nCross-cutting pieces in `api/core/src/util/`:\n\n- **`forge-config.ts` loads the config.**\n  - Precedence: a config registered with `registerForgeConfigForDirectory()` (used by tests), then a `package.json` `config.forge` object, then the first `forge.config.{js,mjs,cjs,ts,mts,cts}` found. A `config.forge` _path string_ is used only when no `forge.config.*` file exists.\n  - TS configs load through `jiti`, JS configs through `import()`.\n  - After the `resolveForgeConfig` hook runs, the config is wrapped in a `Proxy`. Missing keys fall back to `ELECTRON_FORGE_<KEY>` env vars, and `fromBuildIdentifier()` values resolve per `buildIdentifier`.\n- **`import-search.ts` resolves by name** the makers, publishers and plugins in the config, plus `packagerConfig` hooks given as strings. It tries the bare specifier, then a path relative to the project, then the project's `node_modules`, and uses only the module's default export.\n- **`plugin-interface.ts` + `hook.ts` run the plugin lifecycle.** There are three kinds of hook:\n  - simple hooks (`runHook`)\n  - mutating hooks that thread a value through each plugin (`runMutatingHook`)\n  - hooks that return `listr2` tasks (`getHookListrTasks`)\n\n  Commands are built as `listr2` task lists.\n\n- **The commands chain together.** `package` wraps `@electron/packager` and injects Forge hooks into its `afterCopy`/`afterPrune`/`afterExtract` callbacks. `make` runs package first unless given `--from-package`, and `release` runs make first unless given `--from-make`.\n\nTests live in each package's `spec/`, and the filename suffix picks the vitest project (see the test commands above). Spec files run serially (`fileParallelism: false`) because many write into shared on-disk fixtures. Each file gets fresh module state, but registered configs and mocks persist between tests in the same file, so unregister them in `afterEach`. Core's fixture apps and configs are in `packages/api/core/spec/fixture/`.\n\n## Gotchas\n\n- **Coupled changes.** A behavior change in a bundler plugin usually also needs updates to the templates' `tmpl/` files (what users actually get) and to `docs/config/plugins/`.\n- **Two sets of docs.** `docs/` is the user-facing docs site. New pages must be registered in `docs/sidebars.ts`. The site isn't built in this repo. Markdown lint and the link check cover only `*.md`, so `.mdx` pages (including `docs/config/plugins/vite.mdx` and `webpack.mdx`) aren't checked at all; review them by hand. Each package's `README.md` is separate, hand-written, and published to npm.\n- **Dependency install policy.** `.yarnrc.yml` rejects versions published less than 7 days ago (`npmMinimalAgeGate`), except for pre-approved scopes, and disables install scripts, except those allowed in `dependenciesMeta`. CI installs with `--immutable`, so commit `yarn.lock`.\n- **Generated project references.** Each package's `tsconfig.json` is generated from `tsconfig.base.json` and its workspace dependencies by `tools/gen-tsconfigs.ts`, so don't hand-edit it. After adding or removing an `@electron-forge/*` dependency, re-run `yarn`, or `tsc -b` fails.\n- **Adding a package.**\n  1. Put it under an existing `workspaces` glob.\n  2. Set its version to the one in `lerna.json`, and depend on sibling packages with `workspace:*`.\n  3. Run `yarn`.\n  4. Add a workspace entry to `knip.json`.\n  5. Check the `typedoc.jsonc` entry points.\n  6. Copy the `exports`, `typings` and `publishConfig` fields from a sibling package. `tools/test-dist` fails without the entry point and typings.\n- **Imports.** Relative imports in `src/` use `.js` extensions. Some type-only re-exports use `.ts`, but `.js` also works there. Specs import `../src/...` without an extension; don't copy that style into `src/`.\n- **Commit messages.** Commits and PR titles use Conventional Commits (the `semantic` workflow checks PR titles), for example `fix(core): ...` or `feat(plugin-vite)!: ...`. Lerna derives version bumps from them, so don't bump versions in PRs.\n- **TSDoc style.** Follow the rules in `CONTRIBUTING.md`: the first line is imperative, capitalized and ends with a period.\n","isInternal":false,"tokens":2508,"sizeBytes":9837},{"name":"auto-unpack-natives.md","path":"docs/config/plugins/auto-unpack-natives.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/docs/config/plugins/auto-unpack-natives.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"---\ndescription: >-\n  Reduce loading times and disk consumption by unpacking native Node modules\n  from your Forge app's ASAR archive.\n---\n\n# Auto Unpack Native Modules Plugin\n\nThis plugin will automatically add all native Node modules in your `node_modules` folder to the [`asar.unpack`](https://electron.github.io/packager/main/interfaces/Options.html#asar) config option in your [`packagerConfig`](../configuration.mdx#electron-packager-config). If your app uses native Node modules, you should probably use this to reduce loading times and disk consumption on your users' machines.\n\n## Installation\n\n```shell\nnpm install --save-dev @electron-forge/plugin-auto-unpack-natives\n```\n\n## Usage\n\nYou must add this plugin to your [`plugins`](../configuration.mdx#plugins) array in your Forge configuration. There are currently no configuration options available for this plugin.\n\n:::info\nAsar archives are disabled by default with Electron Packager. Make sure you set your `packagerConfig.asar` value accordingly. This option also supports advanced configuration if you pass it an object. See the [API documentation for this option](https://js.electronforge.io/modules/_electron_forge_shared_types.InternalOptions.html#CreateOptions) for more information.\n:::\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  packagerConfig: {\n    asar: true // or an object containing your asar options\n  },\n  plugins: [\n    {\n      name: '@electron-forge/plugin-auto-unpack-natives',\n      config: {}\n    }\n  ]\n};\n```\n","frontmatter":{"description":"Reduce loading times and disk consumption by unpacking native Node modules from your Forge app's ASAR archive."},"isInternal":false,"tokens":328,"sizeBytes":1511},{"name":"electronegativity.md","path":"docs/config/plugins/electronegativity.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/docs/config/plugins/electronegativity.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"---\ndescription: >-\n  Check for misconfigurations and security anti-patterns with the\n  Electronegativity tool.\n---\n\n# Electronegativity Plugin\n\nThe Electronegativity plugin integrates Doyensec's [Electronegativity tool](https://github.com/doyensec/electronegativity#electronegativity) into the Electron Forge workflow. After packaging your Electron app, it identifies any known misconfigurations and security anti-patterns.\n\n## Installation\n\n```shell\nnpm install --save-dev @electron-forge/plugin-electronegativity\n```\n\n## Usage\n\nAdd this plugin to the [`plugins`](../configuration.mdx#plugins) array in your Forge configuration. All [programmatic options for Electronegativity](https://github.com/doyensec/electronegativity#programmatically), except for `input` and `electronVersion`.\n\n### Example\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      name: '@electron-forge/plugin-electronegativity',\n      config: {\n        isSarif: true\n      }\n    }\n  ]\n  // ...\n};\n```\n","frontmatter":{"description":"Check for misconfigurations and security anti-patterns with the Electronegativity tool."},"isInternal":false,"tokens":244,"sizeBytes":1014},{"name":"index.md","path":"docs/config/plugins/index.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/docs/config/plugins/index.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"---\ndescription: Modules to extend Forge's core functionality\n---\n\n# Plugins\n\nElectron Forge has a plugin system which allows you to extend its core functionality.\n\nBy default, Forge takes a vanilla JS application and packages, makes and publishes it (see the [Build Lifecycle](../../core-concepts/build-lifecycle.md) document for more details). Plugins can execute custom logic during any of the Forge [Hooks](../hooks.md) during the build process, and can also override the [Start](../../cli.md#start) command in development.\n\n:::info\nIf you want to write your own Forge plugin, check out the [Writing Plugins](../../advanced/extending-electron-forge/writing-plugins.md) guide.\n:::\n\n## Bundler plugins\n\n- [Webpack Plugin](webpack.mdx) - Build your Electron app with webpack\n- [Vite Plugin](vite.mdx) - Build your Electron app with Vite\n\n## Utility plugins\n\n- [Auto Unpack Native Modules Plugin](auto-unpack-natives.md) - Unpack native Node.js modules from your Forge app's ASAR archive.\n- [Local Electron Plugin](local-electron.md) - Integrate a local build of Electron into your Forge app.\n- [Fuses Plugin](fuses.mdx) - Toggle Electron functionality at package-time with Electron Fuses.\n- [Electronegativity Plugin](electronegativity.md) - Check for misconfigurations and security anti-patterns with the Electronegativity tool.\n","frontmatter":{"description":"Modules to extend Forge's core functionality"},"isInternal":false,"tokens":304,"sizeBytes":1331},{"name":"local-electron.md","path":"docs/config/plugins/local-electron.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/docs/config/plugins/local-electron.md","title":"Plugins Skill","category":"anthropic-skill","format":"markdown","content":"---\ndescription: Integrate a local build of Electron into your Forge app.\n---\n\n# Local Electron Plugin\n\n:::info\nThis plugin should only be used by people who are building Electron locally themselves. If you want to use a fork of Electron, check out the [environment variables](https://github.com/electron/get#usage) you can use to configure `@electron/get`.\n:::\n\nThis plugin allows you to both run and build your app using a **local** build of Electron. This can be incredibly useful if you want to test a feature or a bug fix in your app before making a PR up to the Electron repository.\n\nIf you want to set up a local build of Electron, you should check out [Electron Build Tools](https://github.com/electron/build-tools).\n\n### Installation\n\n```bash\nnpm install --save-dev @electron-forge/plugin-local-electron\n```\n\n### Usage\n\nOnce you have a working build of Electron, point the plugin's `electronPath` config option to the folder containing the built Electron binary.\n\nAll possible configuration options are documented in [`LocalElectronPluginConfig`](https://js.electronforge.io/interfaces/\\_electron\\_forge\\_plugin\\_local\\_electron.LocalElectronPluginConfig.html).\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-local-electron',\n      config: {\n        electronPath: '/Users/me/projects/electron/out/Testing'\n      }\n    }\n  ]\n};\n```\n\n:::info\nPlease note that the plugin only accepts **absolute paths**. You should use Node's [`path.resolve()`](https://nodejs.org/api/path.html#pathresolvepaths) to make things deterministic.\n:::\n","frontmatter":{"description":"Integrate a local build of Electron into your Forge app."},"isInternal":false,"tokens":355,"sizeBytes":1602},{"name":"README.md","path":"packages/api/core/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/api/core/README.md","title":"core Documentation","category":"plugin-manifest","format":"markdown","content":"# Electron Forge Core\n\nThis module contains the core logic of Electron Forge and exposes the base\nAPI as a number of simple JS functions.\n\n## Basic Usage\n\n```javascript\nimport { api } from '@electron-forge/core';\n\n// Package the current directory as an Electron app\napi.package(import.meta.dirname);\n```\n\nThe named export `api` has it's methods documented over at [ForgeAPI](https://js.electronforge.io/classes/_electron-forge_core.ForgeAPI.html).\nAll the methods are async and expose the core forge methods, please note that all\nuser-side configuration is still done through your forge config file or the \"config.forge\"\nsection of your package.json. This API simply let's you call the methods in\nnode land without using the CLI.\n\n## Error Handling\n\nAs all methods return a promise you should handle all rejections, you should note\nthat rejections will **not** always be errors, in fact we commonly reject our\npromises with just strings so do not assume that properties such as `stack` or\n`message` will exist on thrown errors.\n","isInternal":false,"tokens":224,"sizeBytes":1028},{"name":"README.md","path":"packages/external/create-electron-app/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/external/create-electron-app/README.md","title":"create-electron-app Documentation","category":"plugin-manifest","format":"markdown","content":"## create-electron-app\n\nCreate Electron App allows you to quickly bootstrap a new Electron app using\n[Electron Forge](https://electronforge.io).\n\n### Usage\n\nInitialize a new project by running the following:\n\n```sh\nnpx create-electron-app@latest my-app\n```\n\nYou should now have a directory called my-app with an ultra-minimal Electron app boilerplate inside.\nIf you head into that directory and start up the app, you'll be all set to start developing!\n\n```sh\ncd my-app\nnpm start\n```\n","isInternal":false,"tokens":112,"sizeBytes":483},{"name":"README.md","path":"packages/maker/appx/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/appx/README.md","title":"appx Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-appx\n\n> **Deprecated:** use [`@electron-forge/maker-msix`](https://www.electronforge.io/config/makers/msix) instead.\n\n`@electron-forge/maker-appx` is a legacy compatibility layer over the MSIX maker. It maps its `MakerAppXConfig` onto `electron-windows-msix` and builds a `.msix` package, which is designed to target the Windows Store.\n\nYou can only build the AppX target on Windows machines with the Windows 10 SDK installed.\n\nWhen `devCert` is not set, `electron-windows-msix` signs the package with a self-signed development certificate, which the maker saves next to the `.msix` as `dev_cert.cer` and `dev_cert.pfx` so it can be trusted on a test device. The `.pfx` password is `WINDOWS_CERTIFICATE_PASSWORD` when that environment variable is set, otherwise a random one.\n\nConfiguration options are documented in [`MakerAppXConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-appx.MakerAppXConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-appx',\n      config: {\n        publisher: 'CN=developmentca',\n        devCert: 'C:\\\\devcert.pfx',\n        certPass: 'abcd'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":298,"sizeBytes":1190},{"name":"README.md","path":"packages/maker/deb/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/deb/README.md","title":"deb Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-deb\n\n`@electron-forge/maker-deb` builds .deb packages, which are the standard package format for Debian-based Linux distributions such as Ubuntu. You can only build the deb target on Linux or macOS machines with the dpkg package installed.\n\nConfiguration options are documented in [`MakerDebConfigOptions`](https://js.electronforge.io/interfaces/_electron-forge_maker-deb.MakerDebConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-deb',\n      config: {\n        options: {\n          maintainer: 'The Forgers',\n          homepage: 'https://example.com',\n          icon: 'path/to/icon.svg'\n        }\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":165,"sizeBytes":708},{"name":"README.md","path":"packages/maker/dmg/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/dmg/README.md","title":"dmg Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-dmg\n\n`@electron-forge/maker-dmg` builds `.dmg` files, which are the standard format for sharing macOS apps. You can only build the DMG target on macOS machines.\n\nConfiguration options are documented in [`MakerDMGConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-dmg.MakerDMGConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-dmg',\n      config: {\n        background: './assets/dmg-background.png',\n        format: 'ULFO'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":137,"sizeBytes":545},{"name":"README.md","path":"packages/maker/flatpak/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/flatpak/README.md","title":"flatpak Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-flatpak\n\n`@electron-forge/maker-flatpak` [`.flatpak` files](http://flatpak.org/), which is a packaging format for Linux distributions that allows for sandboxed installation of applications in isolation from the rest of their system.\n\nYou can only build the Flatpak target if you have `flatpak`, `flatpak-builder`, and `eu-strip` _\\(usually part of the `elfutils` package\\)_ installed on your system.\n\nConfiguration options are documented in [`MakerFlatpakOptionsConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-flatpak.MakerFlatpakConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-flatpak',\n      config: {\n        options: {\n          categories: ['Video'],\n          mimeType: ['video/h264']\n        }\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":195,"sizeBytes":837},{"name":"README.md","path":"packages/maker/msix/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/msix/README.md","title":"msix Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-msix\n\n> [!IMPORTANT]\n> This module is _experimental_ and is subject to breaking changes between releases.\n> See GitHub Releases change notes for migration instructions.\n\n`@electron-forge/maker-msix` builds `.msix` packages, which can be distributed directly or via the Windows Store.\n\nYou can only build the MSIX target on Windows machines with the Windows 10 SDK installed.\n\nConfiguration options are documented in [`MakerMSIXConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-msix.MakerMSIXConfig.html).\n\nmaker-msix utilizes @electron/windows-sign via the `windowsSignOptions` property. See the [windows-sign documentation](https://github.com/electron/windows-sign/blob/main/README.md) for details.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-msix',\n      config: {\n        manifestVariables: {\n          publisher: 'Electron Dev'\n        },\n        windowsSignOptions: {\n          certificatePassword: '12345'\n        }\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":231,"sizeBytes":1039},{"name":"README.md","path":"packages/maker/pkg/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/pkg/README.md","title":"pkg Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-pkg\n\n`@electron-forge/maker-pkg` builds `.pkg` files for macOS. These are used to upload your application to the Mac App Store or just as an alternate distribution method for macOS users.  You can only build the Pkg target on macOS machines while targeting the `darwin`  or `mas` platforms.\n\nConfiguration options are documented in [`MakerPkgConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-pkg.MakerPKGConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-pkg',\n      config: {\n        keychain: 'my-secret-ci-keychain'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":157,"sizeBytes":643},{"name":"README.md","path":"packages/maker/rpm/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/rpm/README.md","title":"rpm Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-rpm\n\n`@electron-forge/maker-rpm` builds `.rpm` files, which is the standard package format for RedHat-based Linux distributions such as Fedora.\n\nYou can only build the RPM target on Linux machines with the `rpm` or `rpm-build` packages installed.\n\nConfiguration options are documented in [`MakerRpmConfigOptions`](https://js.electronforge.io/interfaces/_electron-forge_maker-rpm.MakerRpmConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-rpm',\n      config: {\n        options: {\n          name: 'QuickEdit',\n          homepage: 'http://example.com'\n        }\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":160,"sizeBytes":670},{"name":"README.md","path":"packages/maker/snap/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/snap/README.md","title":"snap Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-snap\n\n`@electron-forge/maker-snap` builds `.snap` files, which is the packaging format created and sponsored by Canonical, the company behind Ubuntu. It is a sandboxed package format that lets users of various Linux distributions install your application in an isolated environment on their machine.\n\nYou can only build the Snapcraft target on Linux systems with the `snapcraft` package installed.\n\nConfiguration options are documented in [`MakerSnapConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-snap.MakerSnapConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-snap',\n      config: {\n        version: '1.1.0',\n        features: {\n          audio: true,\n          mpris: 'com.example.mpris',\n          webgl: true\n        },\n        summary: 'My application'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":202,"sizeBytes":886},{"name":"README.md","path":"packages/maker/squirrel/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/squirrel/README.md","title":"squirrel Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-squirrel\n\n`@electron-forge/maker-squirrel` builds a number of files required to distribute apps using the Squirrel.Windows framework. It generates a `{appName} Setup.exe` file which is the main installer for your application, `{appName}-full.nupkg` and a `RELEASES` file which you use to issue updates to your application.\n\nPre-requisites:\n\n* Windows machine\n* Linux machine with `mono` and `wine` installed.\n\nConfiguration options are documented in [`MakerSquirrelConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-squirrel.MakerSquirrelConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-squirrel',\n      config: {\n        certificateFile: './cert.pfx',\n        certificatePassword: 'this-is-a-secret'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":191,"sizeBytes":826},{"name":"README.md","path":"packages/maker/wix/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/wix/README.md","title":"wix Documentation","category":"plugin-manifest","format":"markdown","content":"\n## maker-wix-msi\n\nThe WiX MSI target builds `.msi` files, which are \"traditional\" Windows installer files.\n\nPre-requisites:\n\n* `light` and `candle` installed from [the WiX toolkit](https://github.com/felixrieseberg/electron-wix-msi#prerequisites).\n\nConfiguration options are documented in [`MakerWixConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-wix.MakerWixConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-wix',\n      config: {\n        language: 1033,\n        manufacturer: 'My Awesome Company'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":160,"sizeBytes":617},{"name":"README.md","path":"packages/maker/zip/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/maker/zip/README.md","title":"zip Documentation","category":"plugin-manifest","format":"markdown","content":"## maker-zip\n\n`@electron-forge/maker-zip` builds basic `.zip` files containing your packaged application. There are no platform specific dependencies for using this maker and it will run on any platform.\n\nConfiguration options are documented in [`MakerZIPConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-zip.MakerZIPConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-zip'\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":112,"sizeBytes":480},{"name":"README.md","path":"packages/plugin/auto-unpack-natives/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/plugin/auto-unpack-natives/README.md","title":"auto-unpack-natives Documentation","category":"plugin-manifest","format":"markdown","content":"## plugin-auto-unpack-natives\n\nThis plugin will automatically add all native Node modules in your node_modules folder to the `asar.unpack` config option in your `packagerConfig`. If your app uses native Node modules, you should probably use this to reduce loading times and disk consumption on your users' machines.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-auto-unpack-natives',\n      config: {}\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":106,"sizeBytes":481},{"name":"README.md","path":"packages/plugin/fuses/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/plugin/fuses/README.md","title":"fuses Documentation","category":"plugin-manifest","format":"markdown","content":"## @electron-forge/plugin-fuses\n\nThis plugin allows flipping [Electron Fuses](https://github.com/electron/fuses) when packaging your app with Electron Forge.\n\n### Usage\n\nInstall `@electron-forge/plugin-fuses` and `@electron/fuses` as dev dependencies and add this plugin to the `plugins` array in your Forge configuration:\n\n```shell\n# Yarn\nyarn add --dev @electron-forge/plugin-fuses @electron/fuses\n\n# npm\nnpm i -D @electron-forge/plugin-fuses @electron/fuses\n```\n\n```js\n// forge.config.js\n\nconst { FusesPlugin } = require('@electron-forge/plugin-fuses');\nconst { FuseV1Options, FuseVersion } = require('@electron/fuses');\n\nconst forgeConfig = {\n  plugins: [\n    new FusesPlugin({\n      version: FuseVersion.V1,\n      [FuseV1Options.RunAsNode]: false\n      // ...any other options supported by @electron/fuses\n    })\n  ]\n};\n\nmodule.exports = forgeConfig;\n```\n","isInternal":false,"tokens":221,"sizeBytes":860},{"name":"README.md","path":"packages/plugin/local-electron/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/plugin/local-electron/README.md","title":"local-electron Documentation","category":"plugin-manifest","format":"markdown","content":"## plugin-local-electron\n\nThis plugin allows you to both run and build your app using a local build of Electron. This can be incredibly useful if you want to test a feature or a bug fix in your app before making a PR up to the Electron repository.\n\n_Note: This plugin should only be used by people who are building Electron locally themselves. If you want to set up a local build of Electron, you should check out [Electron Build Tools](https://github.com/electron/build-tools)._\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-local-electron',\n      config: {\n        electronPath: '/Users/me/projects/electron/out/Testing'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":160,"sizeBytes":711},{"name":"README.md","path":"packages/plugin/vite/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/plugin/vite/README.md","title":"vite Documentation","category":"plugin-manifest","format":"markdown","content":"## plugin-vite\n\nThis plugin makes it easy to set up standard vite tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-vite',\n      config: {\n        // `build` can specify multiple entry builds, which can be Main process, Preload scripts, Worker process, etc.\n        // If you are familiar with Vite configuration, it will look really familiar.\n        build: [\n          {\n            // `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`.\n            entry: 'src/main.js',\n            config: 'vite.main.config.mjs'\n          },\n          {\n            entry: 'src/preload.js',\n            config: 'vite.preload.config.mjs'\n          }\n        ],\n        renderer: [\n          {\n            name: 'main_window',\n            config: 'vite.renderer.config.mjs'\n          }\n        ]\n      }\n    }\n  ]\n};\n```\n\n### Main process hot restart\n\nRenderer code is hot-reloaded by Vite out of the box, but main process code is\nnot: the app has to be relaunched to pick it up. Set `hotRestart` to have\n`electron-forge start` do that for you whenever a main process bundle rebuilds:\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-vite',\n      config: {\n        hotRestart: true,\n        build: [\n          {\n            entry: 'src/main.js',\n            config: 'vite.main.config.mjs'\n          }\n        ],\n        renderer: []\n      }\n    }\n  ]\n};\n```\n\nThis is off by default, so main process changes otherwise only take effect when\nyou type `rs` in the terminal or restart `electron-forge start`. The option has\nno effect when packaging.\n","isInternal":false,"tokens":432,"sizeBytes":1878},{"name":"README.md","path":"packages/plugin/webpack/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/plugin/webpack/README.md","title":"webpack Documentation","category":"plugin-manifest","format":"markdown","content":"## plugin-webpack\n\nThis plugin makes it easy to set up standard webpack tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-webpack',\n      config: {\n        mainConfig: './webpack.main.config.js',\n        renderer: {\n          config: './webpack.renderer.config.js',\n          entryPoints: [{\n            name: 'main_window',\n            html: './src/renderer/index.html',\n            js: './src/renderer/index.js',\n            preload: {\n              js: './src/preload.js'\n            }\n          }]\n        }\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":165,"sizeBytes":790},{"name":"README.md","path":"packages/publisher/bitbucket/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/publisher/bitbucket/README.md","title":"bitbucket Documentation","category":"plugin-manifest","format":"markdown","content":"## Electron Forge: publisher-bitbucket\n\n`@electron-forge/publisher-bitbucket` publishes your artifacts to Bitbucket where users will be able to download them.\n\nThis publish target is for Bitbucket Cloud only and will not work with self hosted Bitbucket Server instances.\n\nConfiguration options are documented in [`PublisherBitbucketConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-bitbucket.PublisherBitbucketConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-bitbucket',\n      config: {\n        repository: {\n          owner: 'myusername',\n          name: 'myreponame'\n        },\n        auth: {\n          username: 'myusername',\n          appPassword: 'mysecretapppassword'\n        }\n      }\n    }\n  ]\n};\n```\n\nAlternatively you can (and should) use environment variables for the authentication\n\n```sh\n# env.sh\nBITBUCKET_USERNAME=\"myusername\"\nBITBUCKET_APP_PASSWORD=\"mysecretapppassword\"\n```\n\n```sh\nsource env.sh\n```\n","isInternal":false,"tokens":231,"sizeBytes":1032},{"name":"README.md","path":"packages/publisher/electron-release-server/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/publisher/electron-release-server/README.md","title":"electron-release-server Documentation","category":"plugin-manifest","format":"markdown","content":"## publisher-electron-release-server\n\n`@electron-forge/publisher-electron-release-server` publishes all your artifacts to a hosted instance of [Electron Release Server](https://github.com/ArekSredzki/electron-release-server) where users will be able to download them.\n\nPlease note that Electron Release Server is a community powered project and is not associated with Electron Forge or the Electron project directly.\n\nConfiguration options are documented in [`PublisherERSConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-electron-release-server.PublisherERSConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-electron-release-server',\n      config: {\n        baseUrl: 'https://update.server.com',\n        username: 'admin',\n        password: 'admin'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":185,"sizeBytes":888},{"name":"README.md","path":"packages/publisher/github/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/publisher/github/README.md","title":"github Documentation","category":"plugin-manifest","format":"markdown","content":"## publisher-github\n\n`@electron-forge/publisher-github` publishes all your artifacts to GitHub releases, this allows your users to download the files straight from your repository or if your repository is open source you can use [update.electronjs.org](https://github.com/electron/update.electronjs.org) and get a free hosted update service.\n\nConfiguration options are documented in [`PublisherGitHubConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-github.PublisherGitHubConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-github',\n      config: {\n        repository: {\n          owner: 'me',\n          name: 'awesome-thing'\n        },\n        prerelease: true\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":175,"sizeBytes":799},{"name":"README.md","path":"packages/publisher/nucleus/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/publisher/nucleus/README.md","title":"nucleus Documentation","category":"plugin-manifest","format":"markdown","content":"## publisher-nucleus\n\n`@electron-forge/publisher-nucleus` publishes all your artifacts to an instance of Nucleus Update Server where users will be able to download them. This update service supports all three platforms.\n\nCheck out the README at [`atlassian/nucleus`](https://github.com/atlassian/nucleus) for more information on this project.\n\nConfiguration options are documented in [`Publisher\nNucleusConfig](https://js.electronforge.io/interfaces/_electron-forge_publisher-nucleus.PublisherNucleusConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-nucleus',\n      config: {\n        host: 'https://my-nucleus.mysite.com',\n        appId: 1,\n        channelId: 'abcdefg',\n        token: 'my-token'\n      }\n    }\n  ]\n};\n```\n\nWe recommend you set the `token`option using an environment variable, don't hard code into in your config.\n","isInternal":false,"tokens":218,"sizeBytes":920},{"name":"README.md","path":"packages/publisher/s3/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/publisher/s3/README.md","title":"s3 Documentation","category":"plugin-manifest","format":"markdown","content":"## publisher-s3\n\n`@electron-forge/publisher-s3` publishes all your artifacts to an Amazon S3 bucket where users will be able to download them.\n\nBy default, all files are positioned at the following key:\n\n```text\n${config.folder || appVersion}/${artifactName}\n```\n\nConfiguration options are documented in [PublisherS3Config](https://js.electronforge.io/interfaces/_electron-forge_publisher-s3.PublisherS3Config.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-s3',\n      config: {\n        bucket: 'my-bucket',\n        public: true\n      }\n    }\n  ]\n};\n```\n\nIf you run publish twice with the same version on the same platform, it is possible for your old artifacts to get overwritten in S3. It is your responsibility to ensure that you don't overwrite your own releases.\n\n### Authentication\n\nIt is recommended to follow the [Amazon AWS guide](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html) and set either a shared credentials guide or the proper environment variables. However, if that is not possible, the publisher config allows the setting of the accessKeyId and secretAccessKey configuration options.\n","isInternal":false,"tokens":270,"sizeBytes":1237},{"name":"README.md","path":"packages/publisher/snapcraft/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/publisher/snapcraft/README.md","title":"snapcraft Documentation","category":"plugin-manifest","format":"markdown","content":"## publisher-snapcraft\n\nThe Snapcraft target publishes your .snap artifacts to the Snap Store. All configuration of your package is done via the Snapcraft maker.\n\nThis target requires that the system has the snapcraft utility installed.\n\nConfiguration options are documented in [PublisherSnapConfig](https://js.electronforge.io/interfaces/_electron-forge_publisher-snapcraft.PublisherSnapcraftConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-snapcraft',\n      config: {\n        release: 'latest/edge, insider/stable'\n      }\n    }\n  ]\n};\n```\n","isInternal":false,"tokens":138,"sizeBytes":633},{"name":"README.md","path":"packages/utils/multi-logger/README.md","rawUrl":"https://raw.githubusercontent.com/electron/forge/HEAD/packages/utils/multi-logger/README.md","title":"multi-logger Documentation","category":"plugin-manifest","format":"markdown","content":"# Multi Logger\n\n> Display multiple streams of logs as tabs in the terminal\n\nThis module collects multiple logically separated streams of logs (\"tabs\") and\nrenders them in the terminal the process is already running in. When attached\nto an interactive terminal it draws a full-screen tabbed UI with\n[ink](https://github.com/vadimdemedes/ink); otherwise (CI, piped output) it\nfalls back to append-only lines prefixed with a colored tag. Lines may contain\nANSI styling, so anything that would render in a terminal can be piped in.\n\n## Usage\n\n```javascript\nimport Logger from '@electron-forge/multi-logger';\n\nconst logger = new Logger({ title: 'My tool' });\n\nconst serverTab = logger.createTab('Server');\nconst frontEndTab = logger.createTab('Front End');\n\n// Everything logged before start() is buffered and shown once rendering begins.\nserverTab.setStatus({ state: 'building' });\nserverTab.log('listening on :3000');\nserverTab.setStatus({ state: 'success', durationMs: 1200 });\n\n// Pipe a child process's stdout/stderr into a tab of its own.\nlogger.attachProcess(spawn('node', ['server.js']), 'Server');\n\nawait logger.start();\n\n// Later: restore the terminal. Safe to call more than once, and it also runs\n// on process exit so a crash never leaves the terminal in the alternate screen.\nlogger.stop();\n```\n\n## API\n\n### `new Logger(options?)`\n\n| Option                  | Description                                                                                      |\n| ----------------------- | ------------------------------------------------------------------------------------------------ |\n| `stdout`                | Stream to render to. Defaults to `process.stdout`.                                               |\n| `stdin`                 | Stream to read keys from. Defaults to `process.stdin`.                                           |\n| `interactive`           | Whether the tabbed UI may be used. Defaults to `stdout.isTTY && stdin.isTTY && !process.env.CI`. |\n| `forceMode`             | `'ink'` or `'plain'` to bypass detection.                                                        |\n| `title`                 | Text shown at the left of the tab bar.                                                           |\n| `keys`                  | Extra hotkeys, `{ key, label, onPress }`, listed in the footer.                                  |\n| `maxLines`              | Lines kept per tab (and for the merged view). Defaults to 5000.                                  |\n| `initialTab`            | Name of the tab shown first, or `'all'` for the merged view. Defaults to the first tab.          |\n| `errorSwitchDebounceMs` | Minimum gap between automatic switches to a tab that failed. Defaults to 15000.                  |\n\n* `logger.createTab(name)` returns a `Tab`.\n* `logger.getTab(name)` / `logger.getTabs()`.\n* `logger.attachProcess(child, name = 'App')` pipes the child's `stdout` and\n  `stderr` into a tab line by line and marks the tab as exited when it ends.\n  A tab with the same name is reused, so a restarted process keeps its tab.\n  When the child exits, stdin is put back into raw mode in case the child\n  inherited the terminal and reset it on the way out (Node embedders such as\n  Electron do); `logger.reassertRawMode()` does the same on demand.\n* `logger.start()` begins rendering. Before this everything is buffered.\n* `logger.stop()` unmounts the UI and restores the terminal. If the UI never\n  rendered, the buffered lines are written out as plain text instead so\n  nothing is lost.\n* `logger.extendOptions({ keys?, title?, initialTab? })` adds to the options\n  the logger was created with: extra `keys` (already bound keys are left\n  alone) and `title` / `initialTab` when none is set yet. It has no effect on\n  the UI once `start()` has been called.\n\n### Sharing one logger across packages\n\nA process can only sensibly draw one UI, so a host and the plugins running\ninside it should share a logger instead of each creating their own:\n\n```javascript\nimport { ensureSharedLogger } from '@electron-forge/multi-logger';\n\n// The host creates it. The first caller decides how it is set up…\nconst logger = ensureSharedLogger({ title: 'My tool', initialTab: 'App' });\n\n// …and a plugin, later, just adds a tab to it.\nconst tab = ensureSharedLogger().createTab('Bundler');\n```\n\n* `ensureSharedLogger(options?)` returns the process-wide logger, creating it\n  on the first call. On later calls `options` are merged additively via\n  `extendOptions()`: extra `keys` are added, `title` / `initialTab` are taken\n  only if none is set yet, and everything else is ignored.\n* `getSharedLogger()` returns it, or `undefined` if none has been created.\n* `resetSharedLogger()` forgets it without stopping it; meant for tests.\n\nThe instance is registered under `Symbol.for('@electron-forge/multi-logger')`\non `globalThis`, so even two copies of this package in one `node_modules` tree\nend up sharing it.\n\n### `Tab`\n\n* `tab.log(text)` appends text, which may contain many lines and ANSI colors.\n* `tab.setStatus({ state, errors?, warnings?, durationMs?, detail? })` where\n  `state` is one of `idle`, `building`, `success`, `warning`, `error` or\n  `exited`. The status is shown next to the tab name.\n* `tab.clear()` empties the tab's buffer.\n\n## Interactive UI\n\n```text\nElectron Forge · webpack  1 Main Process ✔ 1.2s  2 Renderer (web) ⠹  3 Preload (electron-preload) ✖ 2  4 App ●  a All\n────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n… the active tab's most recent lines, wrapped to the terminal width …\n←/→ 1-9 tabs · a all · r restart electron · c clear · f follow · ↑/↓ scroll · q quit\n```\n\n| Key                            | Action                                                    |\n| ------------------------------ | --------------------------------------------------------- |\n| `←` / `→`, `Tab` / `Shift+Tab` | Cycle through the tabs                                    |\n| `1` to `9`                     | Jump to a tab                                             |\n| `a`                            | Merged view of every tab, in arrival order, tagged by tab |\n| `↑` / `↓`, `PgUp` / `PgDn`     | Scroll back through the buffer (stops following)          |\n| `Home` / `End`                 | Jump to the oldest line / back to the tail                |\n| `f`                            | Toggle following the tail                                 |\n| `c`                            | Clear the current tab (or every tab in the merged view)   |\n| `q`, `Ctrl+C`                  | Restore the terminal and re-raise `SIGINT`                |\n| custom `keys`                  | Whatever the host registered, e.g. `r` to restart         |\n\nThe tab bar always fits the terminal: when it gets tight the durations and\ncounts go first, then the title, and finally the chips wrap onto more rows.\nWhen a tab's status turns to `error` the view switches to it, at most once per\n`errorSwitchDebounceMs`, so a cascade of failures does not fight the user.\n\nThe UI uses the terminal's alternate screen, so whatever was printed before\n`start()` is still in the scrollback when it exits, and it prints a one-line\nstatus per tab (plus the tail of any tab that ended in an error) on the way\nout.\n\nBecause ink puts stdin into raw mode, line-based input such as typing `rs`\nis not seen by the host process while the UI is up; hosts should register an\nequivalent hotkey via `keys` instead.\n\n## Plain mode\n\nWhen stdout or stdin is not a TTY, `CI` is set, or the `interactive` option is\nset to `false`, lines are written as they arrive:\n\n```text\n[Main Process]   asset index.js 1.2 KiB [emitted] (name: main)\n[Main Process]   ✔ compiled in 1.2s\n[Renderer (web)] ✖ failed with 1 error in 2.1s\n```\n","isInternal":false,"tokens":1781,"sizeBytes":8058}],"systemPromptSnippet":"<yakaai_skills repo=\"electron/forge\">\n<!-- File: AGENTS.md (Tokens: ~2508 | Category: root-instruction) -->\n# AGENTS.md\n\nGuidance for AI coding agents working in this repository.\n\n## Overview\n\nElectron Forge is a Yarn 4 + Lerna monorepo of TypeScript packages published as `@electron-forge/*` (plus `create-electron-app`). All packages share one version (`lerna.json`). Node version: `.nvmrc`.\n\nThis is Forge 8, and several things differ from Forge 7, which you may know better:\n\n- Packages are ESM-only.\n- `init`/`import` live in `create-electron-app`, not core.\n- `publish` is renamed `release` (the old name remains as a deprecated alias).\n- `make --skip-package` is now `--from-package`, and `release --from-dry-run` is now `--from-make`.\n- The bundler plugins emit main and preload bundles as `.cjs`.\n- PRs target `main`.\n\n## Commands\n\n```bash\nyarn                      # install; postinstall regenerates the gitignored per-package tsconfig.json files and packages/tsconfig.json\nyarn build                # ~5s; tsc -b packages, then tools/test-dist checks that every package's entry point exists and imports\nyarn build:watch\n\nyarn lint                 # oxfmt --check, oxlint, markdownlint, lint of code blocks in markdown, markdown link check\nyarn lint:fix             # oxfmt --write + oxlint --fix\nyarn constraints          # yarn.config.cjs: a dependency must use the same range in every workspace (--fix to apply)\nyarn knip                 # unused files/exports/deps\n\nyarn test:fast [file] [-t \"name\"]   # unit tests (*.spec.ts); the full suite takes ~25s\nyarn test:slow [file]               # *.slow.spec.ts: downloads Electron, real packaging/making, 240s timeouts\nyarn test:verdaccio [file]          # *.slow.verdaccio.spec.ts against a local registry holding the current build\nyarn test:clear                     # remove temp dirs left behind by tests\n```\n\n## Verifying changes\n\n- **Rebuild before testing across packages.** A spec imports its own package from `../src`. Every other `@electron-forge/*` import resolves through `package.json` `exports` to `dist/`. After editing package A, run `yarn build`, or keep `yarn build:watch` running, before testing anything that imports A.\n- **Default to `yarn test:fast <file>`.** Run the slow or Verdaccio specs only when touching packaging, making, `init` or templates.\n- **Don't run bare `yarn test`.** It includes the `slow-verdaccio` project without starting Verdaccio, so those specs install `@electron-forge/*` from the public registry and test the wrong code.\n- **`test:fast`, `test:slow` and `test:verdaccio` run through `xvfb-maybe`.** On headless Linux without xvfb they exit with \"Failed to find xvfb-run in PATH\". Call vitest directly instead: `yarn vitest run --project fast <file>`, or `yarn spawn-verdaccio yarn vitest run --project slow-verdaccio <file>`.\n- **Verdaccio specs need more setup.** They publish the current `dist/`, so build first. They also need network access, port 4873 free, `pnpm` on PATH, and npm >= 11.17 for install age-gating.\n- **Specs are not type-checked.** `tsconfig.base.json` excludes `spec/`, and vitest strips types. A green build doesn't prove spec types are right.\n- **Try a change in a real app:** `yarn build && LINK_FORGE_DEPENDENCIES_ON_INIT=1 node packages/external/create-electron-app/dist/index.js <dir> --package-manager pnpm`. Then check that `<dir>/node_modules/@electron-forge/cli` resolves into this repo.\n  - Only pnpm links reliably.\n  - With npm, the default when there's no TTY, linking reports success, but the install that follows replaces the links with published packages.\n  - Yarn works only if Corepack provides Yarn 4. Yarn 1's `yarn link` fails.\n- **Debug logging:** `DEBUG=electron-forge:*` traces CLI and core internals.\n- **Parts of `CONTRIBUTING.md` are stale.** Its \"Running Forge locally\" and test instructions mention `yarn link:prepare`, `yarn build:fast` and `yarn test`, and it says the website docs live in a separate repo. Follow this file instead where they conflict.\n\nThe pre-commit hook runs `lint-staged` (oxfmt + oxlint) and `yarn constraints`. CI runs build, then `yarn lint`, `yarn constraints` and `yarn knip`, then the test suites on Windows, macOS and Linux. Changes that only touch `docs/` skip the test jobs.\n\n## Architecture\n\nPackage groups under `packages/` (each is a Yarn workspace):\n\n- `api/core`: the programmatic API (`src/api/{start,package,make,release}.ts`) and shared internals in `src/util/`.\n- `api/cli`: a thin `commander` wrapper. It dispatches to one executable per subcommand (`electron-forge-<cmd>.ts`), and each of those calls the core API.\n- `external/create-electron-app`: project scaffolding (`init.ts`, `import.ts`, `init-scripts/`).\n- `maker/*`, `publisher/*`, `plugin/*`: implementations of `MakerBase`, `PublisherBase` and `PluginBase` from the matching `*/base` package.\n  - Most makers wrap a third-party installer module (`electron-installer-*`, `electron-winstaller`, …), usually declared in `optionalDependencies`. `yarn constraints` skips only the names hard-coded in `OPTIONAL_DEPS` in `yarn.config.cjs`, so add a new installer there.\n  - `publisher/base-static` is shared logic for object-storage publishers (S3, GCS).\n  - Plugins provide lifecycle hooks and can take over `start` (`startLogic`). `vite` and `webpack` are the bundler plugins.\n- `template/*`: templates used by `create-electron-app`. `template/base` has `BaseTemplate` and the shared `tmpl/` files, and the vite and webpack templates extend it.\n- `utils/*`:\n  - `shared-types` lives in `utils/types`. It defines `ForgeConfig`, the hook signatures and the maker/publisher/plugin interfaces that every package codes against.\n  - `core-utils` covers package manager detection, the `@electron/rebuild` wrapper and Electron version lookup.\n  - Also: `multi-logger`, `tracer`, `test-utils`.\n\nCross-cutting pieces in `api/core/src/util/`:\n\n- **`forge-config.ts` loads the config.**\n  - Precedence: a config registered with `registerForgeConfigForDirectory()` (used by tests), then a `package.json` `config.forge` object, then the first `forge.config.{js,mjs,cjs,ts,mts,cts}` found. A `config.forge` _path string_ is used only when no `forge.config.*` file exists.\n  - TS configs load through `jiti`, JS configs through `import()`.\n  - After the `resolveForgeConfig` hook runs, the config is wrapped in a `Proxy`. Missing keys fall back to `ELECTRON_FORGE_<KEY>` env vars, and `fromBuildIdentifier()` values resolve per `buildIdentifier`.\n- **`import-search.ts` resolves by name** the makers, publishers and plugins in the config, plus `packagerConfig` hooks given as strings. It tries the bare specifier, then a path relative to the project, then the project's `node_modules`, and uses only the module's default export.\n- **`plugin-interface.ts` + `hook.ts` run the plugin lifecycle.** There are three kinds of hook:\n  - simple hooks (`runHook`)\n  - mutating hooks that thread a value through each plugin (`runMutatingHook`)\n  - hooks that return `listr2` tasks (`getHookListrTasks`)\n\n  Commands are built as `listr2` task lists.\n\n- **The commands chain together.** `package` wraps `@electron/packager` and injects Forge hooks into its `afterCopy`/`afterPrune`/`afterExtract` callbacks. `make` runs package first unless given `--from-package`, and `release` runs make first unless given `--from-make`.\n\nTests live in each package's `spec/`, and the filename suffix picks the vitest project (see the test commands above). Spec files run serially (`fileParallelism: false`) because many write into shared on-disk fixtures. Each file gets fresh module state, but registered configs and mocks persist between tests in the same file, so unregister them in `afterEach`. Core's fixture apps and configs are in `packages/api/core/spec/fixture/`.\n\n## Gotchas\n\n- **Coupled changes.** A behavior change in a bundler plugin usually also needs updates to the templates' `tmpl/` files (what users actually get) and to `docs/config/plugins/`.\n- **Two sets of docs.** `docs/` is the user-facing docs site. New pages must be registered in `docs/sidebars.ts`. The site isn't built in this repo. Markdown lint and the link check cover only `*.md`, so `.mdx` pages (including `docs/config/plugins/vite.mdx` and `webpack.mdx`) aren't checked at all; review them by hand. Each package's `README.md` is separate, hand-written, and published to npm.\n- **Dependency install policy.** `.yarnrc.yml` rejects versions published less than 7 days ago (`npmMinimalAgeGate`), except for pre-approved scopes, and disables install scripts, except those allowed in `dependenciesMeta`. CI installs with `--immutable`, so commit `yarn.lock`.\n- **Generated project references.** Each package's `tsconfig.json` is generated from `tsconfig.base.json` and its workspace dependencies by `tools/gen-tsconfigs.ts`, so don't hand-edit it. After adding or removing an `@electron-forge/*` dependency, re-run `yarn`, or `tsc -b` fails.\n- **Adding a package.**\n  1. Put it under an existing `workspaces` glob.\n  2. Set its version to the one in `lerna.json`, and depend on sibling packages with `workspace:*`.\n  3. Run `yarn`.\n  4. Add a workspace entry to `knip.json`.\n  5. Check the `typedoc.jsonc` entry points.\n  6. Copy the `exports`, `typings` and `publishConfig` fields from a sibling package. `tools/test-dist` fails without the entry point and typings.\n- **Imports.** Relative imports in `src/` use `.js` extensions. Some type-only re-exports use `.ts`, but `.js` also works there. Specs import `../src/...` without an extension; don't copy that style into `src/`.\n- **Commit messages.** Commits and PR titles use Conventional Commits (the `semantic` workflow checks PR titles), for example `fix(core): ...` or `feat(plugin-vite)!: ...`. Lerna derives version bumps from them, so don't bump versions in PRs.\n- **TSDoc style.** Follow the rules in `CONTRIBUTING.md`: the first line is imperative, capitalized and ends with a period.\n\n<!-- File: docs/config/plugins/auto-unpack-natives.md (Tokens: ~328 | Category: anthropic-skill) -->\n---\ndescription: >-\n  Reduce loading times and disk consumption by unpacking native Node modules\n  from your Forge app's ASAR archive.\n---\n\n# Auto Unpack Native Modules Plugin\n\nThis plugin will automatically add all native Node modules in your `node_modules` folder to the [`asar.unpack`](https://electron.github.io/packager/main/interfaces/Options.html#asar) config option in your [`packagerConfig`](../configuration.mdx#electron-packager-config). If your app uses native Node modules, you should probably use this to reduce loading times and disk consumption on your users' machines.\n\n## Installation\n\n```shell\nnpm install --save-dev @electron-forge/plugin-auto-unpack-natives\n```\n\n## Usage\n\nYou must add this plugin to your [`plugins`](../configuration.mdx#plugins) array in your Forge configuration. There are currently no configuration options available for this plugin.\n\n:::info\nAsar archives are disabled by default with Electron Packager. Make sure you set your `packagerConfig.asar` value accordingly. This option also supports advanced configuration if you pass it an object. See the [API documentation for this option](https://js.electronforge.io/modules/_electron_forge_shared_types.InternalOptions.html#CreateOptions) for more information.\n:::\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  packagerConfig: {\n    asar: true // or an object containing your asar options\n  },\n  plugins: [\n    {\n      name: '@electron-forge/plugin-auto-unpack-natives',\n      config: {}\n    }\n  ]\n};\n```\n\n<!-- File: docs/config/plugins/electronegativity.md (Tokens: ~244 | Category: anthropic-skill) -->\n---\ndescription: >-\n  Check for misconfigurations and security anti-patterns with the\n  Electronegativity tool.\n---\n\n# Electronegativity Plugin\n\nThe Electronegativity plugin integrates Doyensec's [Electronegativity tool](https://github.com/doyensec/electronegativity#electronegativity) into the Electron Forge workflow. After packaging your Electron app, it identifies any known misconfigurations and security anti-patterns.\n\n## Installation\n\n```shell\nnpm install --save-dev @electron-forge/plugin-electronegativity\n```\n\n## Usage\n\nAdd this plugin to the [`plugins`](../configuration.mdx#plugins) array in your Forge configuration. All [programmatic options for Electronegativity](https://github.com/doyensec/electronegativity#programmatically), except for `input` and `electronVersion`.\n\n### Example\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  // ...\n  plugins: [\n    {\n      name: '@electron-forge/plugin-electronegativity',\n      config: {\n        isSarif: true\n      }\n    }\n  ]\n  // ...\n};\n```\n\n<!-- File: docs/config/plugins/index.md (Tokens: ~304 | Category: anthropic-skill) -->\n---\ndescription: Modules to extend Forge's core functionality\n---\n\n# Plugins\n\nElectron Forge has a plugin system which allows you to extend its core functionality.\n\nBy default, Forge takes a vanilla JS application and packages, makes and publishes it (see the [Build Lifecycle](../../core-concepts/build-lifecycle.md) document for more details). Plugins can execute custom logic during any of the Forge [Hooks](../hooks.md) during the build process, and can also override the [Start](../../cli.md#start) command in development.\n\n:::info\nIf you want to write your own Forge plugin, check out the [Writing Plugins](../../advanced/extending-electron-forge/writing-plugins.md) guide.\n:::\n\n## Bundler plugins\n\n- [Webpack Plugin](webpack.mdx) - Build your Electron app with webpack\n- [Vite Plugin](vite.mdx) - Build your Electron app with Vite\n\n## Utility plugins\n\n- [Auto Unpack Native Modules Plugin](auto-unpack-natives.md) - Unpack native Node.js modules from your Forge app's ASAR archive.\n- [Local Electron Plugin](local-electron.md) - Integrate a local build of Electron into your Forge app.\n- [Fuses Plugin](fuses.mdx) - Toggle Electron functionality at package-time with Electron Fuses.\n- [Electronegativity Plugin](electronegativity.md) - Check for misconfigurations and security anti-patterns with the Electronegativity tool.\n\n<!-- File: docs/config/plugins/local-electron.md (Tokens: ~355 | Category: anthropic-skill) -->\n---\ndescription: Integrate a local build of Electron into your Forge app.\n---\n\n# Local Electron Plugin\n\n:::info\nThis plugin should only be used by people who are building Electron locally themselves. If you want to use a fork of Electron, check out the [environment variables](https://github.com/electron/get#usage) you can use to configure `@electron/get`.\n:::\n\nThis plugin allows you to both run and build your app using a **local** build of Electron. This can be incredibly useful if you want to test a feature or a bug fix in your app before making a PR up to the Electron repository.\n\nIf you want to set up a local build of Electron, you should check out [Electron Build Tools](https://github.com/electron/build-tools).\n\n### Installation\n\n```bash\nnpm install --save-dev @electron-forge/plugin-local-electron\n```\n\n### Usage\n\nOnce you have a working build of Electron, point the plugin's `electronPath` config option to the folder containing the built Electron binary.\n\nAll possible configuration options are documented in [`LocalElectronPluginConfig`](https://js.electronforge.io/interfaces/\\_electron\\_forge\\_plugin\\_local\\_electron.LocalElectronPluginConfig.html).\n\n```javascript title=\"forge.config.js\"\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-local-electron',\n      config: {\n        electronPath: '/Users/me/projects/electron/out/Testing'\n      }\n    }\n  ]\n};\n```\n\n:::info\nPlease note that the plugin only accepts **absolute paths**. You should use Node's [`path.resolve()`](https://nodejs.org/api/path.html#pathresolvepaths) to make things deterministic.\n:::\n\n<!-- File: packages/api/core/README.md (Tokens: ~224 | Category: plugin-manifest) -->\n# Electron Forge Core\n\nThis module contains the core logic of Electron Forge and exposes the base\nAPI as a number of simple JS functions.\n\n## Basic Usage\n\n```javascript\nimport { api } from '@electron-forge/core';\n\n// Package the current directory as an Electron app\napi.package(import.meta.dirname);\n```\n\nThe named export `api` has it's methods documented over at [ForgeAPI](https://js.electronforge.io/classes/_electron-forge_core.ForgeAPI.html).\nAll the methods are async and expose the core forge methods, please note that all\nuser-side configuration is still done through your forge config file or the \"config.forge\"\nsection of your package.json. This API simply let's you call the methods in\nnode land without using the CLI.\n\n## Error Handling\n\nAs all methods return a promise you should handle all rejections, you should note\nthat rejections will **not** always be errors, in fact we commonly reject our\npromises with just strings so do not assume that properties such as `stack` or\n`message` will exist on thrown errors.\n\n<!-- File: packages/external/create-electron-app/README.md (Tokens: ~112 | Category: plugin-manifest) -->\n## create-electron-app\n\nCreate Electron App allows you to quickly bootstrap a new Electron app using\n[Electron Forge](https://electronforge.io).\n\n### Usage\n\nInitialize a new project by running the following:\n\n```sh\nnpx create-electron-app@latest my-app\n```\n\nYou should now have a directory called my-app with an ultra-minimal Electron app boilerplate inside.\nIf you head into that directory and start up the app, you'll be all set to start developing!\n\n```sh\ncd my-app\nnpm start\n```\n\n<!-- File: packages/maker/appx/README.md (Tokens: ~298 | Category: plugin-manifest) -->\n## maker-appx\n\n> **Deprecated:** use [`@electron-forge/maker-msix`](https://www.electronforge.io/config/makers/msix) instead.\n\n`@electron-forge/maker-appx` is a legacy compatibility layer over the MSIX maker. It maps its `MakerAppXConfig` onto `electron-windows-msix` and builds a `.msix` package, which is designed to target the Windows Store.\n\nYou can only build the AppX target on Windows machines with the Windows 10 SDK installed.\n\nWhen `devCert` is not set, `electron-windows-msix` signs the package with a self-signed development certificate, which the maker saves next to the `.msix` as `dev_cert.cer` and `dev_cert.pfx` so it can be trusted on a test device. The `.pfx` password is `WINDOWS_CERTIFICATE_PASSWORD` when that environment variable is set, otherwise a random one.\n\nConfiguration options are documented in [`MakerAppXConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-appx.MakerAppXConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-appx',\n      config: {\n        publisher: 'CN=developmentca',\n        devCert: 'C:\\\\devcert.pfx',\n        certPass: 'abcd'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/deb/README.md (Tokens: ~165 | Category: plugin-manifest) -->\n## maker-deb\n\n`@electron-forge/maker-deb` builds .deb packages, which are the standard package format for Debian-based Linux distributions such as Ubuntu. You can only build the deb target on Linux or macOS machines with the dpkg package installed.\n\nConfiguration options are documented in [`MakerDebConfigOptions`](https://js.electronforge.io/interfaces/_electron-forge_maker-deb.MakerDebConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-deb',\n      config: {\n        options: {\n          maintainer: 'The Forgers',\n          homepage: 'https://example.com',\n          icon: 'path/to/icon.svg'\n        }\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/dmg/README.md (Tokens: ~137 | Category: plugin-manifest) -->\n## maker-dmg\n\n`@electron-forge/maker-dmg` builds `.dmg` files, which are the standard format for sharing macOS apps. You can only build the DMG target on macOS machines.\n\nConfiguration options are documented in [`MakerDMGConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-dmg.MakerDMGConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-dmg',\n      config: {\n        background: './assets/dmg-background.png',\n        format: 'ULFO'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/flatpak/README.md (Tokens: ~195 | Category: plugin-manifest) -->\n## maker-flatpak\n\n`@electron-forge/maker-flatpak` [`.flatpak` files](http://flatpak.org/), which is a packaging format for Linux distributions that allows for sandboxed installation of applications in isolation from the rest of their system.\n\nYou can only build the Flatpak target if you have `flatpak`, `flatpak-builder`, and `eu-strip` _\\(usually part of the `elfutils` package\\)_ installed on your system.\n\nConfiguration options are documented in [`MakerFlatpakOptionsConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-flatpak.MakerFlatpakConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-flatpak',\n      config: {\n        options: {\n          categories: ['Video'],\n          mimeType: ['video/h264']\n        }\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/msix/README.md (Tokens: ~231 | Category: plugin-manifest) -->\n## maker-msix\n\n> [!IMPORTANT]\n> This module is _experimental_ and is subject to breaking changes between releases.\n> See GitHub Releases change notes for migration instructions.\n\n`@electron-forge/maker-msix` builds `.msix` packages, which can be distributed directly or via the Windows Store.\n\nYou can only build the MSIX target on Windows machines with the Windows 10 SDK installed.\n\nConfiguration options are documented in [`MakerMSIXConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-msix.MakerMSIXConfig.html).\n\nmaker-msix utilizes @electron/windows-sign via the `windowsSignOptions` property. See the [windows-sign documentation](https://github.com/electron/windows-sign/blob/main/README.md) for details.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-msix',\n      config: {\n        manifestVariables: {\n          publisher: 'Electron Dev'\n        },\n        windowsSignOptions: {\n          certificatePassword: '12345'\n        }\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/pkg/README.md (Tokens: ~157 | Category: plugin-manifest) -->\n## maker-pkg\n\n`@electron-forge/maker-pkg` builds `.pkg` files for macOS. These are used to upload your application to the Mac App Store or just as an alternate distribution method for macOS users.  You can only build the Pkg target on macOS machines while targeting the `darwin`  or `mas` platforms.\n\nConfiguration options are documented in [`MakerPkgConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-pkg.MakerPKGConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-pkg',\n      config: {\n        keychain: 'my-secret-ci-keychain'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/rpm/README.md (Tokens: ~160 | Category: plugin-manifest) -->\n## maker-rpm\n\n`@electron-forge/maker-rpm` builds `.rpm` files, which is the standard package format for RedHat-based Linux distributions such as Fedora.\n\nYou can only build the RPM target on Linux machines with the `rpm` or `rpm-build` packages installed.\n\nConfiguration options are documented in [`MakerRpmConfigOptions`](https://js.electronforge.io/interfaces/_electron-forge_maker-rpm.MakerRpmConfigOptions.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-rpm',\n      config: {\n        options: {\n          name: 'QuickEdit',\n          homepage: 'http://example.com'\n        }\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/snap/README.md (Tokens: ~202 | Category: plugin-manifest) -->\n## maker-snap\n\n`@electron-forge/maker-snap` builds `.snap` files, which is the packaging format created and sponsored by Canonical, the company behind Ubuntu. It is a sandboxed package format that lets users of various Linux distributions install your application in an isolated environment on their machine.\n\nYou can only build the Snapcraft target on Linux systems with the `snapcraft` package installed.\n\nConfiguration options are documented in [`MakerSnapConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-snap.MakerSnapConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-snap',\n      config: {\n        version: '1.1.0',\n        features: {\n          audio: true,\n          mpris: 'com.example.mpris',\n          webgl: true\n        },\n        summary: 'My application'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/squirrel/README.md (Tokens: ~191 | Category: plugin-manifest) -->\n## maker-squirrel\n\n`@electron-forge/maker-squirrel` builds a number of files required to distribute apps using the Squirrel.Windows framework. It generates a `{appName} Setup.exe` file which is the main installer for your application, `{appName}-full.nupkg` and a `RELEASES` file which you use to issue updates to your application.\n\nPre-requisites:\n\n* Windows machine\n* Linux machine with `mono` and `wine` installed.\n\nConfiguration options are documented in [`MakerSquirrelConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-squirrel.MakerSquirrelConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-squirrel',\n      config: {\n        certificateFile: './cert.pfx',\n        certificatePassword: 'this-is-a-secret'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/wix/README.md (Tokens: ~160 | Category: plugin-manifest) -->\n## maker-wix-msi\n\nThe WiX MSI target builds `.msi` files, which are \"traditional\" Windows installer files.\n\nPre-requisites:\n\n* `light` and `candle` installed from [the WiX toolkit](https://github.com/felixrieseberg/electron-wix-msi#prerequisites).\n\nConfiguration options are documented in [`MakerWixConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-wix.MakerWixConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-wix',\n      config: {\n        language: 1033,\n        manufacturer: 'My Awesome Company'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/maker/zip/README.md (Tokens: ~112 | Category: plugin-manifest) -->\n## maker-zip\n\n`@electron-forge/maker-zip` builds basic `.zip` files containing your packaged application. There are no platform specific dependencies for using this maker and it will run on any platform.\n\nConfiguration options are documented in [`MakerZIPConfig`](https://js.electronforge.io/interfaces/_electron-forge_maker-zip.MakerZIPConfig.html).\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  makers: [\n    {\n      name: '@electron-forge/maker-zip'\n    }\n  ]\n};\n```\n\n<!-- File: packages/plugin/auto-unpack-natives/README.md (Tokens: ~106 | Category: plugin-manifest) -->\n## plugin-auto-unpack-natives\n\nThis plugin will automatically add all native Node modules in your node_modules folder to the `asar.unpack` config option in your `packagerConfig`. If your app uses native Node modules, you should probably use this to reduce loading times and disk consumption on your users' machines.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-auto-unpack-natives',\n      config: {}\n    }\n  ]\n};\n```\n\n<!-- File: packages/plugin/fuses/README.md (Tokens: ~221 | Category: plugin-manifest) -->\n## @electron-forge/plugin-fuses\n\nThis plugin allows flipping [Electron Fuses](https://github.com/electron/fuses) when packaging your app with Electron Forge.\n\n### Usage\n\nInstall `@electron-forge/plugin-fuses` and `@electron/fuses` as dev dependencies and add this plugin to the `plugins` array in your Forge configuration:\n\n```shell\n# Yarn\nyarn add --dev @electron-forge/plugin-fuses @electron/fuses\n\n# npm\nnpm i -D @electron-forge/plugin-fuses @electron/fuses\n```\n\n```js\n// forge.config.js\n\nconst { FusesPlugin } = require('@electron-forge/plugin-fuses');\nconst { FuseV1Options, FuseVersion } = require('@electron/fuses');\n\nconst forgeConfig = {\n  plugins: [\n    new FusesPlugin({\n      version: FuseVersion.V1,\n      [FuseV1Options.RunAsNode]: false\n      // ...any other options supported by @electron/fuses\n    })\n  ]\n};\n\nmodule.exports = forgeConfig;\n```\n\n<!-- File: packages/plugin/local-electron/README.md (Tokens: ~160 | Category: plugin-manifest) -->\n## plugin-local-electron\n\nThis plugin allows you to both run and build your app using a local build of Electron. This can be incredibly useful if you want to test a feature or a bug fix in your app before making a PR up to the Electron repository.\n\n_Note: This plugin should only be used by people who are building Electron locally themselves. If you want to set up a local build of Electron, you should check out [Electron Build Tools](https://github.com/electron/build-tools)._\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-local-electron',\n      config: {\n        electronPath: '/Users/me/projects/electron/out/Testing'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/plugin/vite/README.md (Tokens: ~432 | Category: plugin-manifest) -->\n## plugin-vite\n\nThis plugin makes it easy to set up standard vite tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-vite',\n      config: {\n        // `build` can specify multiple entry builds, which can be Main process, Preload scripts, Worker process, etc.\n        // If you are familiar with Vite configuration, it will look really familiar.\n        build: [\n          {\n            // `entry` is just an alias for `build.lib.entry` in the corresponding file of `config`.\n            entry: 'src/main.js',\n            config: 'vite.main.config.mjs'\n          },\n          {\n            entry: 'src/preload.js',\n            config: 'vite.preload.config.mjs'\n          }\n        ],\n        renderer: [\n          {\n            name: 'main_window',\n            config: 'vite.renderer.config.mjs'\n          }\n        ]\n      }\n    }\n  ]\n};\n```\n\n### Main process hot restart\n\nRenderer code is hot-reloaded by Vite out of the box, but main process code is\nnot: the app has to be relaunched to pick it up. Set `hotRestart` to have\n`electron-forge start` do that for you whenever a main process bundle rebuilds:\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-vite',\n      config: {\n        hotRestart: true,\n        build: [\n          {\n            entry: 'src/main.js',\n            config: 'vite.main.config.mjs'\n          }\n        ],\n        renderer: []\n      }\n    }\n  ]\n};\n```\n\nThis is off by default, so main process changes otherwise only take effect when\nyou type `rs` in the terminal or restart `electron-forge start`. The option has\nno effect when packaging.\n\n<!-- File: packages/plugin/webpack/README.md (Tokens: ~165 | Category: plugin-manifest) -->\n## plugin-webpack\n\nThis plugin makes it easy to set up standard webpack tooling to compile both your main process code and your renderer process code, with built-in support for Hot Module Replacement (HMR) in the renderer process and support for multiple renderers.\n\n```javascript\n// forge.config.js\n\nmodule.exports = {\n  plugins: [\n    {\n      name: '@electron-forge/plugin-webpack',\n      config: {\n        mainConfig: './webpack.main.config.js',\n        renderer: {\n          config: './webpack.renderer.config.js',\n          entryPoints: [{\n            name: 'main_window',\n            html: './src/renderer/index.html',\n            js: './src/renderer/index.js',\n            preload: {\n              js: './src/preload.js'\n            }\n          }]\n        }\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/publisher/bitbucket/README.md (Tokens: ~231 | Category: plugin-manifest) -->\n## Electron Forge: publisher-bitbucket\n\n`@electron-forge/publisher-bitbucket` publishes your artifacts to Bitbucket where users will be able to download them.\n\nThis publish target is for Bitbucket Cloud only and will not work with self hosted Bitbucket Server instances.\n\nConfiguration options are documented in [`PublisherBitbucketConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-bitbucket.PublisherBitbucketConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-bitbucket',\n      config: {\n        repository: {\n          owner: 'myusername',\n          name: 'myreponame'\n        },\n        auth: {\n          username: 'myusername',\n          appPassword: 'mysecretapppassword'\n        }\n      }\n    }\n  ]\n};\n```\n\nAlternatively you can (and should) use environment variables for the authentication\n\n```sh\n# env.sh\nBITBUCKET_USERNAME=\"myusername\"\nBITBUCKET_APP_PASSWORD=\"mysecretapppassword\"\n```\n\n```sh\nsource env.sh\n```\n\n<!-- File: packages/publisher/electron-release-server/README.md (Tokens: ~185 | Category: plugin-manifest) -->\n## publisher-electron-release-server\n\n`@electron-forge/publisher-electron-release-server` publishes all your artifacts to a hosted instance of [Electron Release Server](https://github.com/ArekSredzki/electron-release-server) where users will be able to download them.\n\nPlease note that Electron Release Server is a community powered project and is not associated with Electron Forge or the Electron project directly.\n\nConfiguration options are documented in [`PublisherERSConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-electron-release-server.PublisherERSConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-electron-release-server',\n      config: {\n        baseUrl: 'https://update.server.com',\n        username: 'admin',\n        password: 'admin'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/publisher/github/README.md (Tokens: ~175 | Category: plugin-manifest) -->\n## publisher-github\n\n`@electron-forge/publisher-github` publishes all your artifacts to GitHub releases, this allows your users to download the files straight from your repository or if your repository is open source you can use [update.electronjs.org](https://github.com/electron/update.electronjs.org) and get a free hosted update service.\n\nConfiguration options are documented in [`PublisherGitHubConfig`](https://js.electronforge.io/interfaces/_electron-forge_publisher-github.PublisherGitHubConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-github',\n      config: {\n        repository: {\n          owner: 'me',\n          name: 'awesome-thing'\n        },\n        prerelease: true\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/publisher/nucleus/README.md (Tokens: ~218 | Category: plugin-manifest) -->\n## publisher-nucleus\n\n`@electron-forge/publisher-nucleus` publishes all your artifacts to an instance of Nucleus Update Server where users will be able to download them. This update service supports all three platforms.\n\nCheck out the README at [`atlassian/nucleus`](https://github.com/atlassian/nucleus) for more information on this project.\n\nConfiguration options are documented in [`Publisher\nNucleusConfig](https://js.electronforge.io/interfaces/_electron-forge_publisher-nucleus.PublisherNucleusConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-nucleus',\n      config: {\n        host: 'https://my-nucleus.mysite.com',\n        appId: 1,\n        channelId: 'abcdefg',\n        token: 'my-token'\n      }\n    }\n  ]\n};\n```\n\nWe recommend you set the `token`option using an environment variable, don't hard code into in your config.\n\n<!-- File: packages/publisher/s3/README.md (Tokens: ~270 | Category: plugin-manifest) -->\n## publisher-s3\n\n`@electron-forge/publisher-s3` publishes all your artifacts to an Amazon S3 bucket where users will be able to download them.\n\nBy default, all files are positioned at the following key:\n\n```text\n${config.folder || appVersion}/${artifactName}\n```\n\nConfiguration options are documented in [PublisherS3Config](https://js.electronforge.io/interfaces/_electron-forge_publisher-s3.PublisherS3Config.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-s3',\n      config: {\n        bucket: 'my-bucket',\n        public: true\n      }\n    }\n  ]\n};\n```\n\nIf you run publish twice with the same version on the same platform, it is possible for your old artifacts to get overwritten in S3. It is your responsibility to ensure that you don't overwrite your own releases.\n\n### Authentication\n\nIt is recommended to follow the [Amazon AWS guide](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html) and set either a shared credentials guide or the proper environment variables. However, if that is not possible, the publisher config allows the setting of the accessKeyId and secretAccessKey configuration options.\n\n<!-- File: packages/publisher/snapcraft/README.md (Tokens: ~138 | Category: plugin-manifest) -->\n## publisher-snapcraft\n\nThe Snapcraft target publishes your .snap artifacts to the Snap Store. All configuration of your package is done via the Snapcraft maker.\n\nThis target requires that the system has the snapcraft utility installed.\n\nConfiguration options are documented in [PublisherSnapConfig](https://js.electronforge.io/interfaces/_electron-forge_publisher-snapcraft.PublisherSnapcraftConfig.html).\n\n```javascript title=forge.config.js\nmodule.exports = {\n  // ...\n  publishers: [\n    {\n      name: '@electron-forge/publisher-snapcraft',\n      config: {\n        release: 'latest/edge, insider/stable'\n      }\n    }\n  ]\n};\n```\n\n<!-- File: packages/utils/multi-logger/README.md (Tokens: ~1781 | Category: plugin-manifest) -->\n# Multi Logger\n\n> Display multiple streams of logs as tabs in the terminal\n\nThis module collects multiple logically separated streams of logs (\"tabs\") and\nrenders them in the terminal the process is already running in. When attached\nto an interactive terminal it draws a full-screen tabbed UI with\n[ink](https://github.com/vadimdemedes/ink); otherwise (CI, piped output) it\nfalls back to append-only lines prefixed with a colored tag. Lines may contain\nANSI styling, so anything that would render in a terminal can be piped in.\n\n## Usage\n\n```javascript\nimport Logger from '@electron-forge/multi-logger';\n\nconst logger = new Logger({ title: 'My tool' });\n\nconst serverTab = logger.createTab('Server');\nconst frontEndTab = logger.createTab('Front End');\n\n// Everything logged before start() is buffered and shown once rendering begins.\nserverTab.setStatus({ state: 'building' });\nserverTab.log('listening on :3000');\nserverTab.setStatus({ state: 'success', durationMs: 1200 });\n\n// Pipe a child process's stdout/stderr into a tab of its own.\nlogger.attachProcess(spawn('node', ['server.js']), 'Server');\n\nawait logger.start();\n\n// Later: restore the terminal. Safe to call more than once, and it also runs\n// on process exit so a crash never leaves the terminal in the alternate screen.\nlogger.stop();\n```\n\n## API\n\n### `new Logger(options?)`\n\n| Option                  | Description                                                                                      |\n| ----------------------- | ------------------------------------------------------------------------------------------------ |\n| `stdout`                | Stream to render to. Defaults to `process.stdout`.                                               |\n| `stdin`                 | Stream to read keys from. Defaults to `process.stdin`.                                           |\n| `interactive`           | Whether the tabbed UI may be used. Defaults to `stdout.isTTY && stdin.isTTY && !process.env.CI`. |\n| `forceMode`             | `'ink'` or `'plain'` to bypass detection.                                                        |\n| `title`                 | Text shown at the left of the tab bar.                                                           |\n| `keys`                  | Extra hotkeys, `{ key, label, onPress }`, listed in the footer.                                  |\n| `maxLines`              | Lines kept per tab (and for the merged view). Defaults to 5000.                                  |\n| `initialTab`            | Name of the tab shown first, or `'all'` for the merged view. Defaults to the first tab.          |\n| `errorSwitchDebounceMs` | Minimum gap between automatic switches to a tab that failed. Defaults to 15000.                  |\n\n* `logger.createTab(name)` returns a `Tab`.\n* `logger.getTab(name)` / `logger.getTabs()`.\n* `logger.attachProcess(child, name = 'App')` pipes the child's `stdout` and\n  `stderr` into a tab line by line and marks the tab as exited when it ends.\n  A tab with the same name is reused, so a restarted process keeps its tab.\n  When the child exits, stdin is put back into raw mode in case the child\n  inherited the terminal and reset it on the way out (Node embedders such as\n  Electron do); `logger.reassertRawMode()` does the same on demand.\n* `logger.start()` begins rendering. Before this everything is buffered.\n* `logger.stop()` unmounts the UI and restores the terminal. If the UI never\n  rendered, the buffered lines are written out as plain text instead so\n  nothing is lost.\n* `logger.extendOptions({ keys?, title?, initialTab? })` adds to the options\n  the logger was created with: extra `keys` (already bound keys are left\n  alone) and `title` / `initialTab` when none is set yet. It has no effect on\n  the UI once `start()` has been called.\n\n### Sharing one logger across packages\n\nA process can only sensibly draw one UI, so a host and the plugins running\ninside it should share a logger instead of each creating their own:\n\n```javascript\nimport { ensureSharedLogger } from '@electron-forge/multi-logger';\n\n// The host creates it. The first caller decides how it is set up…\nconst logger = ensureSharedLogger({ title: 'My tool', initialTab: 'App' });\n\n// …and a plugin, later, just adds a tab to it.\nconst tab = ensureSharedLogger().createTab('Bundler');\n```\n\n* `ensureSharedLogger(options?)` returns the process-wide logger, creating it\n  on the first call. On later calls `options` are merged additively via\n  `extendOptions()`: extra `keys` are added, `title` / `initialTab` are taken\n  only if none is set yet, and everything else is ignored.\n* `getSharedLogger()` returns it, or `undefined` if none has been created.\n* `resetSharedLogger()` forgets it without stopping it; meant for tests.\n\nThe instance is registered under `Symbol.for('@electron-forge/multi-logger')`\non `globalThis`, so even two copies of this package in one `node_modules` tree\nend up sharing it.\n\n### `Tab`\n\n* `tab.log(text)` appends text, which may contain many lines and ANSI colors.\n* `tab.setStatus({ state, errors?, warnings?, durationMs?, detail? })` where\n  `state` is one of `idle`, `building`, `success`, `warning`, `error` or\n  `exited`. The status is shown next to the tab name.\n* `tab.clear()` empties the tab's buffer.\n\n## Interactive UI\n\n```text\nElectron Forge · webpack  1 Main Process ✔ 1.2s  2 Renderer (web) ⠹  3 Preload (electron-preload) ✖ 2  4 App ●  a All\n────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n… the active tab's most recent lines, wrapped to the terminal width …\n←/→ 1-9 tabs · a all · r restart electron · c clear · f follow · ↑/↓ scroll · q quit\n```\n\n| Key                            | Action                                                    |\n| ------------------------------ | --------------------------------------------------------- |\n| `←` / `→`, `Tab` / `Shift+Tab` | Cycle through the tabs                                    |\n| `1` to `9`                     | Jump to a tab                                             |\n| `a`                            | Merged view of every tab, in arrival order, tagged by tab |\n| `↑` / `↓`, `PgUp` / `PgDn`     | Scroll back through the buffer (stops following)          |\n| `Home` / `End`                 | Jump to the oldest line / back to the tail                |\n| `f`                            | Toggle following the tail                                 |\n| `c`                            | Clear the current tab (or every tab in the merged view)   |\n| `q`, `Ctrl+C`                  | Restore the terminal and re-raise `SIGINT`                |\n| custom `keys`                  | Whatever the host registered, e.g. `r` to restart         |\n\nThe tab bar always fits the terminal: when it gets tight the durations and\ncounts go first, then the title, and finally the chips wrap onto more rows.\nWhen a tab's status turns to `error` the view switches to it, at most once per\n`errorSwitchDebounceMs`, so a cascade of failures does not fight the user.\n\nThe UI uses the terminal's alternate screen, so whatever was printed before\n`start()` is still in the scrollback when it exits, and it prints a one-line\nstatus per tab (plus the tail of any tab that ended in an error) on the way\nout.\n\nBecause ink puts stdin into raw mode, line-based input such as typing `rs`\nis not seen by the host process while the UI is up; hosts should register an\nequivalent hotkey via `keys` instead.\n\n## Plain mode\n\nWhen stdout or stdin is not a TTY, `CI` is set, or the `interactive` option is\nset to `false`, lines are written as they arrive:\n\n```text\n[Main Process]   asset index.js 1.2 KiB [emitted] (name: main)\n[Main Process]   ✔ compiled in 1.2s\n[Renderer (web)] ✖ failed with 1 error in 2.1s\n```\n</yakaai_skills>"}