Help us improve
Share bugs, ideas, or general feedback.
From agency-slack
Electron Forge packaging in slack-desktop — platform-specific makers, code signing, notarization, webpack production builds, and security fuses.
npx claudepluginhub autisticaf/agency-slackHow this skill is triggered — by the user, by Claude, or both
Slash command
/agency-slack:desktop-packagingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
slack-desktop uses Electron Forge for packaging, with platform-specific makers and a multi-stage code signing pipeline.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Share bugs, ideas, or general feedback.
slack-desktop uses Electron Forge for packaging, with platform-specific makers and a multi-stage code signing pipeline.
# Development build + launch
yarn start
# Package for current platform
yarn package
# Package with options
yarn package --override-arch=arm64
yarn package --dmg=true
yarn package --msi=true
yarn package --appx=true
yarn package --installers=false # output folder only, no installers
forge.config.ts)The config is an async function returning ForgeConfig:
getPackagerOpts() in build/make-package.ts{ disablePreGypCopy: true, mode: 'parallel' }@electron-forge/maker-dmg, @electron-forge/maker-zipgenerateAssets hook)generateAssets, postPackage, postMakeMakers: DMG (UDBZ format, 600x440 window, custom background) + ZIP (for darwin and mas)
App bundle:
appBundleId: com.tinyspeck.slackmacgapElectronTeamID: BQR82RBBHLLSMinimumSystemVersion: 12.0slack://Icons: slack.icns (prod), slack-dogfood.icns (dogfood), slack-prototype.icns (prototype branches)
MAS builds: Set SLACK_DARWIN_PLATFORM=mas env var.
x64 makers (4):
electron-wix-msi.exe + .msi + .nupkg + RELEASES)arm64 makers (2): Only the two MSIX makers (no Squirrel or standalone MSI)
No Forge makers. Custom createDistroPackage() from build/linux-packaging.ts.
Signing is done after Forge's package step (not via osxSign). This is intentional — post-package hooks add binaries that need signing.
Flow:
codesign --deep for M1 compatibility (after fuse flipping invalidates Electron's signature)npm run codesign runs:
codesignMacApp() via @electron/osx-signcodesignNodeFiles() — signs all .node files individually--notarize triggers notarizeApp() via @electron/notarizeSigning identities:
Developer ID Application: SLACK TECHNOLOGIES L.L.C. (BQR82RBBHL)3rd Party Mac Developer Application: SLACK TECHNOLOGIES L.L.C. (BQR82RBBHL)Apple Development: Desktop Release (44TN467826)DDL builds: Hardened runtime enabled, custom designated requirements. MAS builds: Per-entitlements signing (separate entitlement files for Plugin, GPU, Renderer, inherit).
Tool: Jsign (Java-based) with AWS KMS as keystore.
KMS_REGION: us-east-1KMS_ALIAS: alias/code-signinghttp://timestamp.digicert.comWhen signing happens:
postPackage hook — scans and signs all unsigned .dll, .node, .exevendor/signtool.exe for Squirrel releasifywindows-sign-hook.js calls Jsign.msiSkip condition: Prototype builds (version ending .65535) skip signing unless on support-build/ branch.
Triggered by Forge's generateAssets hook calling createCompiledResources().
Architecture:
jest-worker threadssrc/common pre-bundled with esbuild before webpack runsesbuild-loader (target: esnext, JSX factory: h for Preact)EsbuildPlugin (ES2022 target, replaces Terser)Build targets (webpack/configs/):
| Target | Config | Process |
|---|---|---|
| Boot | boot/boot.ts | Startup |
| Browser | browser/main.ts | Main process |
| Preload (default) | preload/preload.default.ts | Preload |
| Preload (main) | preload/preload.main.ts | Main window preload |
| Renderer (default) | renderer/renderer.default.ts | Renderer |
| Window Chrome | renderer/windowchrome.ts | Window chrome renderer |
| Utility | utility/utility.default.ts | Utility process |
| Vendor DLL | vendor/vendor.dll.ts | Pre-built vendor bundle |
Post-build: .map files moved from dist/ to dist_sourcemap/ (uploaded to S3 separately, not shipped).
Set in build/hooks/common/flip-fuses.ts via @electron/fuses after Electron binary extraction:
| Fuse | Value | Purpose |
|---|---|---|
RunAsNode | false | Prevents using the app as a Node.js runtime |
EnableCookieEncryption | true | Encrypts cookies at rest |
EnableNodeCliInspectArguments | false | Disables --inspect in production |
EnableNodeOptionsEnvironmentVariable | false | Ignores NODE_OPTIONS env var |
EnableEmbeddedAsarIntegrityValidation | true (except Linux) | Validates ASAR integrity |
OnlyLoadAppFromAsar | true | Prevents loading app from plain directories |
GrantFileProtocolExtraPrivileges | false | Restricts file:// protocol |
WasmTrapHandlers | true | Enables Wasm trap handlers |
afterCopy (after app source copied):
stripSourcemapUrlsHook — strips sourcemap referencesdeleteStrayFilesHook — removes unnecessary filescopyInLicenseFilesHook — copies license filescopyInSoundFilesHook — copies sound assetscopyInCRTFilesHook — (Windows) C runtime filescopyInVisualElementsFilesHook — (Windows) visual elements manifestdeleteUnsupportedLanguageFilesHook — (Darwin) removes unsupported .lproj dirsresetUtimeHook — (Darwin) resets timestamps for reproducible buildsafterExtract: flipFusesHook (see Security Fuses above)
postPackage: signWindowsLibrariesHook (signs unsigned binaries)
postMake: copyOutArtifacts + maybeNotarize (DMG only)
| Variable | Purpose |
|---|---|
SLACK_OVERRIDE_ARCH | Target architecture (arm64 / x64) |
SLACK_DARWIN_PLATFORM | Set to mas for Mac App Store builds |
BUILD_TYPE | dogfood or release — changes icons and behavior |
BUILD_ONLY | Skip notarization |
SLACK_ELECTRON_ZIP_DIR | Custom local Electron zip |
WEBPACK_BUNDLE_ANALYZE | Generate bundle analysis .stats.json |
| File | Purpose |
|---|---|
forge.config.ts | Top-level Forge config |
build/package-cli.ts | Packaging CLI entry point |
build/make-package.ts | Packager options, hooks, createInitialPackages() |
build/makers/win/index.ts | Windows maker orchestration |
build/mac-code-signing.ts | macOS codesign logic |
build/windows-code-signing.ts | Windows Jsign + AWS KMS |
build/utils/apple-notarize.ts | Apple notarization |
build/hooks/common/flip-fuses.ts | Electron fuse configuration |
webpack/runner.ts | Webpack build orchestrator |
webpack/constants/base-config.ts | Shared webpack base config |