Skip to content
CAI
Software that uses CAICheck a score

balena-io/etcher

44.0

Weak · 20 September 2026

9.4k

lines of production code

TypeScript

primary language

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

This system is a cross-platform desktop application for writing disk images to flash drives, now known as Resin Etcher. It provides a graphical interface for selecting source images and target drives, managing the flashing process with real-time progress and error reporting, and handling system-level permissions for low-level disk access. The application supports multiple operating systems, internationalization, and advanced features like URL-based image sources and multi-drive selection.

How it got here

2015 — Rebranding and build system migration

14 changes.

The project underwent a major architectural overhaul, migrating from a legacy Gulp and Angular-based pipeline to Electron Forge, Webpack, and a React/Redux frontend. This period also saw the rebranding from Herostratus to Resin Etcher, the removal of obsolete legacy code and styling, and the adoption of a new Apache 2.0 license.

2017–2024 — GUI modernization and TypeScript migration

33 changes.

This period focused on rewriting the graphical user interface from Angular to React and TypeScript, alongside migrating the entire codebase to strict typing. The work included restructuring the build pipeline with Electron Forge, implementing internationalization, and replacing legacy inter-process communication with a WebSocket-based architecture for improved reliability and security.

Features

Add EtcherPro utility and TypeScript conversion for text truncation

The application now includes a new \etcher-pro-specific.ts\ utility that provides an \EtcherPro\ class and \etcherProInfo()\ factory to interact with the Balena Supervisor API, specifically enabling the retrieval of device tags and serial numbers when running in a Balena environment. Additionally, the \middle-ellipsis\ text truncation utility has been converted from JavaScript to TypeScript to improve type safety.

lib/gui/app/utils · high confidence

Initial i18n structure and English, Simplified Chinese, and Traditional Chinese translations

The application now uses the i18next library for internationalization, introducing a structured translation system. This change adds initial translation files for English (en), Simplified Chinese (zh-CN), and Traditional Chinese (zh-TW), covering UI strings for flashing, settings, and error messages. A README is also included to guide contributors on adding new languages.

lib/gui/app/i18n · high confidence

New Drive Selector Component with Enhanced Drive Handling

A new DriveSelector component has been introduced to manage drive selection, featuring support for multiple drive types including standard drives, driverless drives, and USB boot drives. The component implements specific logic for handling system and large drives, improves user feedback with better hover messages for drives that are too small, and utilizes a table-based interface for displaying flash errors. It also integrates internationalization (i18n) with Chinese language support and allows for the selection of locked SD cards as source drives.

lib/gui/app/components/drive-selector · high confidence

Settings modal now displays system information for EtcherPro and version details

The Settings modal has been updated to include a dedicated System Information section for EtcherPro devices, displaying either the device's serial number or UUID. Additionally, the modal now shows the application version number alongside a link to the changelog, and the list of available settings is dynamically filtered to only show the auto-update option on supported platforms (AppImage, NSIS, DMG).

lib/gui/app/components/settings · high confidence

Source selector now supports flashing from URLs with basic authentication

The source selector component has been updated to allow users to select an image source via a URL. This includes a new modal interface where users can enter a valid HTTP/HTTPS URL, view recent URLs, and optionally provide basic authentication credentials (username and password) if required by the server. The component manages local storage of recent URLs and handles the selection flow, integrating with the existing selection state and analytics modules.

lib/gui/app/components/source-selector · high confidence

Removals

Removal of legacy Herostratus application entry point

The \lib/browser/app.js\ file, which served as the main entry point for the legacy 'Herostratus' application, has been removed. This file previously initialized the core Angular module, registered essential services (SelectionState, DriveScanner, ImageWriter), and defined the AppController responsible for image selection, drive selection, and the burning process. Its deletion indicates that the application's architecture has been refactored, likely moving these responsibilities to new modules or a different entry structure as part of the broader transition to 'Etcher'.

lib/browser · high confidence

Removal of legacy Polymer web components

The legacy Polymer-based web components (hero-badge, hero-button, hero-caption, hero-icon, and hero-progress-button) have been removed from the codebase. These files, which relied on the Polymer library and Shadow DOM v0 conventions, are no longer present, indicating a migration away from this framework for these specific UI elements.

lib/components · high confidence

Removal of legacy browser module files

The \drive-scanner\, \image-writer\, \path\, and \selection-state\ Angular modules have been removed from the browser codebase. This cleanup eliminates the legacy \herostratus\-named services and filters that previously handled drive scanning, image writing, path formatting, and selection state management, indicating a shift in how these core functionalities are implemented or exposed in the application.

lib/browser/modules · high confidence

Removal of main.css build artifact

The compiled CSS file \build/css/main.css\ has been deleted from the repository. This file previously contained the bundled styles for the application, including Bootstrap v3.3.5 and normalize.css. Its removal indicates a change in the build process or asset management strategy, meaning this specific output file is no longer generated or distributed as part of the standard build.

build/css · high confidence

Architecture

Migration to Electron Forge and modern build tooling

The project has replaced the legacy Gulp and Browserify build pipeline with Electron Forge and Webpack, introducing a new \forge.config.ts\ and \webpack.config.ts\ for bundling. This change includes migrating CI from Travis CI and Appveyor to GitHub Actions (Flowzone), removing the Bower dependency, and switching the license from MIT to Apache 2.0. macOS builds are now hardened with specific entitlements defined in \entitlements.mac.plist\, and the application now uses a TypeScript-based sidecar plugin (\forge.sidecar.ts\) to manage the privileged \etcher-util\ binary.

(repo-wide) · high confidence

Behavioural changes

4 commits (0 fixes) modifying assets

A change to existing behaviour in assets — 4 commits, 3 files.

assets · medium confidence · unverified

4 commits (1 fix) modifying assets/dmg

A change to existing behaviour in assets/dmg — 4 commits (1 fix), 3 files.

assets/dmg · medium confidence · unverified

Add main CSS styles and font definitions

The application now includes a main CSS file that defines global styles for the HTML and body elements, sets the background color to prevent white flashes, disables text selection, and removes focus outlines for interactive elements. It also registers the SourceSansPro font family for use in tooltips and other UI components.

lib/gui/app/css · high confidence

Added TypeScript declarations for external modules and SVG imports

TypeScript type declarations have been added for the 'omit-deep-lodash', 'path-is-inside', and '@balena/sudo-prompt' packages to resolve missing type information. Additionally, a declaration for '\*.svg' files has been introduced, enabling SVGs to be imported as React functional components with appropriate props.

typings · high confidence

Analytics now anonymizes user paths and error reporting uses Sentry

The application now replaces the previous analytics system with Sentry for error reporting. To protect user privacy, all file paths included in error reports and analytics data are automatically anonymized, ensuring personal directory structures are not sent to the server. Additionally, the exception reporter module has been updated to integrate with this new Sentry-based logging, ensuring that errors are captured and reported consistently while maintaining user anonymity.

lib/gui/app/modules · high confidence

Application renamed from Herostratus to Resin Etcher

The application's internal module name and branding have been updated from 'Herostratus' to 'Resin Etcher'. This change is visible in the Angular module definition and associated service names within the browser build artifacts, reflecting the product's rebranding.

build/browser · high confidence

Drive selection and sorting behavior updated

The application now sorts available drives to show system drives last and respects a new 'drivesOrder' setting for custom ordering on Linux. Additionally, the 'autoSelectAllDrives' setting has replaced the removed 'disableExplicitDriveSelection' setting, changing how drives are automatically selected when plugged in.

lib/gui/app/models · high confidence

Finish page reworked with React and configurable success banner

The finish page has been rewritten in TypeScript using React, replacing the previous Angular implementation. This change introduces a configurable success banner that loads from a URL defined in settings (defaulting to efp.balena.io), displayed alongside the flash results. The UI now uses the 'rendition' Flex component for layout and includes a 'Flash Another' button that resets the flashing workflow UUID and navigates back to the main screen.

lib/gui/app/components/finish · high confidence

Flash results screen displays effective speed and detailed error information

The FlashResults component now calculates and displays the effective flashing speed, accounting for compressed images by using block-mapped size rather than just the average flashing speed. It also presents a detailed error table for failed devices, showing the target, device location, and specific error codes or messages, with a link to view full error details in a modal.

lib/gui/app/components/flash-results · high confidence

FlashAnother component converted to TypeScript with i18n support

The FlashAnother button component in the GUI has been rewritten in TypeScript and now utilizes i18next for internationalization, displaying the 'flash.another' translation key instead of hardcoded text. This change ensures type safety for the component's props and allows the button label to be localized for different languages.

lib/gui/app/components/flash-another · high confidence

GUI application restructured with TypeScript, Webpack, and i18n support

The lib/gui/app entry point has been rewritten in TypeScript and integrated with a Webpack build pipeline, replacing the previous Angular-based architecture. This change introduces internationalization support for Simplified and Traditional Chinese alongside English, updates the UI theme to use the SourceSansPro font, and modernizes the application structure by migrating to React components and the rendition library for styling.

lib/gui/app · high confidence

Main interface and flashing workflow rewritten in React/TypeScript

The main application page and the core flashing step have been converted from Angular to React components written in TypeScript. This change introduces a new UI structure using the 'rendition' library for layout and styling, replacing the previous Angular-based implementation. Users will see the same core functionality—selecting an image, choosing a target drive, and initiating the flash—but the underlying component architecture is now modernized, improving maintainability and type safety without altering the visible user experience.

lib/gui/app/pages · high confidence

Migrate GUI to Electron Forge and TypeScript with updated dependencies

The lib/gui entry point has been rewritten in TypeScript and restructured to use the Electron Forge build pipeline, replacing the previous setup. This change upgrades the application to Electron 25 (as indicated by the commit history context for this migration) and integrates @electron/remote for main-renderer communication. The main process now initializes Sentry for error reporting with data anonymization, registers the custom 'etcher://' protocol for opening images from external links, and configures the main window with contextIsolation disabled and nodeIntegration enabled. The menu system has been converted to TypeScript and fully internationalized using i18next, while a new webapi module exposes IPC-based utilities to the renderer process.

lib/gui · high confidence

Migrate OS abstraction layer to TypeScript and Electron Remote

The OS abstraction layer in lib/gui/app/os has been converted from JavaScript to TypeScript, introducing type safety for core UI interactions. This change replaces the deprecated electron.remote with @electron/remote for accessing main-process APIs in dialog, notification, and window-progress modules. Additionally, the Windows network drive handling now uses withTmpFile from etcher-sdk for secure temporary file management, and the image selection dialog now supports opening any file type alongside supported image formats.

lib/gui/app/os · high confidence

Progress button component converted to TypeScript with i18n support

The ProgressButton component has been rewritten in TypeScript and now supports internationalization for its labels. It displays a progress bar with specific colors for decompressing, flashing, and verifying states, and includes a cancel button that dynamically shows 'Cancel' or 'Skip' based on the current operation type.

lib/gui/app/components/progress-button · high confidence

Redesigned target drive selection with warning modals and multi-drive support

The target drive selection interface has been restructured to support selecting multiple drives simultaneously and to provide clearer feedback on drive compatibility. A new warning modal now appears when system or large drives are selected, displaying specific status messages and drive sizes formatted with the pretty-bytes library. The main selector button has been updated to list all selected targets, show compatibility warnings via icons, and allow users to change their selection without closing the main flow.

lib/gui/app/components/target-selector · high confidence

Refactored backend communication to use WebSockets and extracted child-process logic

The \lib/util\ module has been restructured to replace the previous inter-process communication mechanism with a WebSocket-based API (\lib/util/api.ts\), enabling the main process to control a dedicated child writer process. This change introduces new files to handle specific responsibilities: \child-writer.ts\ manages the actual disk writing and validation using \etcher-sdk\, \scanner.ts\ and \drive-scanner.ts\ handle drive detection and state updates, and \source-metadata.ts\ retrieves image information. This separation allows the GUI to offload heavy I/O operations to a separate process while maintaining real-time progress and error reporting via the new WebSocket interface.

lib/util · high confidence

Refactored reduced flashing info component to TypeScript

The reduced flashing info component, which displays the selected image and target drive details during the flashing process, has been converted from JavaScript to TypeScript. This change introduces strict type definitions for component props (such as image name, size, and drive label) and integrates with the existing SVG icon and text utility components, ensuring better type safety and maintainability for this specific UI element without altering its visual behavior.

lib/gui/app/components/reduced-flashing-infos · high confidence

Removal of legacy SCSS styling files

The application has removed the \lib/scss\ directory, specifically deleting \\_angular.scss\, \\_desktop.scss\, and \main.scss\. This eliminates the previous SCSS-based styling for Angular directives, desktop-specific layout constraints (such as preventing text selection and WebView bounce effects), and global theme variables. Users will no longer have these specific SCSS styles applied, indicating a shift away from this styling architecture.

lib/scss · high confidence

Removal of legacy source modules

The \lib/src\ directory has been cleaned up by deleting the \dialog.js\, \drives.js\, and \writer.js\ files. This removes the previous implementations for image selection dialogs, drive listing, and the image writing process, indicating these capabilities have been moved, refactored, or replaced in other parts of the application.

lib/src · high confidence

Removal of legacy spacing module

The legacy spacing module (\_space.scss) has been removed from the codebase. This file previously defined specific spacing variables and utility classes for vertical and horizontal margins; its removal indicates a shift in how spacing is handled, likely relying on a different system or global styles instead of these specific utility classes.

lib/scss/modules · high confidence

Remove legacy elevation and app entry-point modules

The \lib/elevate.js\ and \lib/herostratus.js\ files have been removed, eliminating the previous implementation that handled privilege escalation via \sudo-prompt\ on macOS and \windosu\ on Windows, as well as the original Electron app initialization logic. This change removes the code responsible for detecting admin rights and spawning the elevated process, indicating a shift in how the application manages system permissions or its startup sequence.

lib · high confidence

Replaced sudo-prompt with native platform-specific privilege elevation

The shared sudo module now implements its own privilege-escalation logic for macOS, Linux, and Windows, removing the dependency on the external sudo-prompt library. On macOS, it uses a custom AppleScript-based askpass script to handle password prompts; on Linux, it detects and utilizes pkexec or kdesudo; and on Windows, it invokes PowerShell with the 'runAs' verb to trigger the UAC prompt. This change modernizes the permission code and simplifies the underlying implementation while maintaining the same user-facing behavior of requesting elevated privileges for disk flashing.

lib/shared/sudo · high confidence

SVG icon component now supports inline SVG content with fallback

The SVG icon component has been rewritten in TypeScript and now accepts raw SVG string content via a new \contents\ prop, rendering it as a data URI image. If the provided content is invalid or missing, the component automatically falls back to rendering a specified \fallback\ React component, ensuring robust icon display without external file dependencies.

lib/gui/app/components/svg-icon · high confidence

SafeWebView component rewritten in TypeScript with Electron session management

The SafeWebView component has been converted from JavaScript to TypeScript, introducing strict typing for its props and state. It now manages a persistent Electron session via \@electron/remote\ to handle webview content, automatically appending version and API parameters to URLs, and controlling visibility based on HTTP response codes and load failures.

lib/gui/app/components/safe-webview · high confidence

Shared logic and utilities converted to TypeScript

The core shared library modules—including drive constraints, error handling, exit codes, user-facing messages, permission elevation, supported file formats, and utility functions—have been rewritten in TypeScript. This migration introduces strict type definitions for drive metadata, source selection, and error objects, improving code reliability and maintainability without altering the external user-facing behavior.

lib/shared · high confidence

The open-external service has been rewritten in TypeScript, introducing a new \open\ function that respects the \disableExternalLinks\ setting before invoking Electron's shell API. This change ensures that external URL handling is strictly governed by user configuration, preventing unintended navigation when the setting is enabled.

lib/gui/app/os/open-external · high confidence

Test coverage

Added E2E test infrastructure and configuration; Added GUI tests for Electron remote module configuration; Added TypeScript tests for GUI models; Added TypeScript tests for shared utility modules; Added TypeScript tests for the middleEllipsis utility; Added TypeScript unit tests for window progress and Windows network drive utilities; Added unit tests for image writer and progress status modules; Removal of legacy unit tests for dialog, drives, and writer modules; Removal of obsolete browser unit tests.

Dependencies

Major dependency overhaul and build system migration

The project has been completely re-architected, migrating from an Angular-based application to a React and Redux frontend, and switching the build pipeline from Gulp to Electron Forge with Webpack. This update upgrades the core runtime to Electron 37.2.4 and requires Node.js 20, while significantly updating key libraries such as etcher-sdk to 10.0.0, drivelist to 12.0.2, and rendition to 35.2.0. The package metadata has also been updated to reflect the new 'balena-etcher' identity and Apache-2.0 license.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Baseline

  • First survey — no prior run to compare against. CAI 44.

Lenses

  • Code Health 83
  • Architecture 59
  • Maturity 61
  • Readiness 30
  • Security 50

Changes since last survey

  • 300 commits — 250 feature/other, 50 fixes

By area

  • (root) — 139 commits
  • (repo) — 76 commits
  • lib/gui — 44 commits
  • .github/workflows — 14 commits
  • .github/actions — 12 commits
  • docs/PUBLISHING.md — 3 commits
  • lib/shared — 3 commits
  • docs/CONTRIBUTING.md — 2 commits
  • docs/FAQ.md — 2 commits
  • docs/USER-DOCUMENTATION.md — 2 commits
  • .gitsecret/keys — 1 commit
  • docs/COMMIT-GUIDELINES.md — 1 commit
  • tests/gui — 1 commit

Notable commits

  • fix: Add libgdk-pixbuf dependency alternatives to fix Ubuntu 26.04 installation
  • fix: Fix MacOS x86 build by switching to the macos-14-large GH runner
  • fix: Fix Publish action on Windows
  • fix: Fix lint issues
  • fix: Fix opening links from within SafeWebView
  • fix: Merge pull request #3948 from balena-io/fix-i18n-settings
  • fix: Merge pull request #3964 from balena-io/fix-winget-releaser
  • fix: Merge pull request #3978 from balena-io/aethernet/fix-screensaver
  • fix: Merge pull request #3995 from balena-io/fix-build
  • fix: Merge pull request #4019 from balena-io/fix-accept-encoding-gzip
  • fix: Merge pull request #4086 from balena-io/fix-opening-links-in-safe-webview
  • fix: Merge pull request #4167 from balena-io/aethernet/fix-screensaver-error
  • fix: Merge pull request #4193 from balena-io/fix-windows-signature
  • fix: Merge pull request #4209 from balena-io/fix-win-install
  • fix: Merge pull request #4211 from balena-io/fix-url-loading
  • fix: Merge pull request #4212 from balena-io/fix-race
  • fix: Merge pull request #4221 from balena-io/fix-analytics-imports
  • fix: Merge pull request #4237 from balena-io/fix-win
  • fix: Merge pull request #4238 from balena-io/fix-win-2
  • fix: Merge pull request #4333 from balena-io/rglidden/rpm-fix-etcher-util
  • …and 280 more

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

balena-io/etcher was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 20 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit bfcfafd32e3628fccf924c8d17fcdb56e4ade989 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-b51f968c9b10.