# @suaveplan/electrobun - Electrobun desktop-app generator + orchestrator: scaffolds projects, generates icons, drives dev/build/package/sign commands via an injectable runner. Typed ELECTROBUN_CODES, Zod-validated options, OTel self-telemetry. Electrobun desktop-app generator and orchestrator for the SuavePlan ecosystem. Scaffolds a fresh Electrobun project from a layered config + prompt flow, drives the upstream `electrobun` binary for dev / build / package / sign, and emits structured reports + OpenTelemetry metrics for every operation. ## Documentation tree - [bin](./src/bin/suaveplan-electrobun.md) — Single-file binary that wires `process.argv` into the pure `runCli` dispatcher and translates the resolved exit code in… - [suaveplan-electrobun](./src/bin/suaveplan-electrobun.md) — Single-file binary that wires `process.argv` into the pure `runCli` dispatcher and translates the resolved exit code in… - [cli](./src/cli/cli.md) — Owns the five command surfaces — `createCommand`, `devCommand`, `buildCommand`, `packageCommand`, `signCommand` — plus… - [cli](./src/cli/cli.md) — Owns the five command surfaces — `createCommand`, `devCommand`, `buildCommand`, `packageCommand`, `signCommand` — plus… - [config](./src/config/config.md) — `loadConfig(cliArgs, deps?)` builds an `ElectrobunConfig` by layering hard-coded defaults, an optional on-disk `.suavep… - [config](./src/config/config.md) — `loadConfig(cliArgs, deps?)` builds an `ElectrobunConfig` by layering hard-coded defaults, an optional on-disk `.suavep… - [error-codes](./src/error-codes/error-codes.md) — Owns the stable `ELECTROBUN.*` error-code namespace and the `ElectrobunError` class that every public entry point throw… - [error-codes](./src/error-codes/error-codes.md) — Owns the stable `ELECTROBUN.*` error-code namespace and the `ElectrobunError` class that every public entry point throw… - [fs](./src/fs/fs.md) — Owns the `FsAdapter` seam and the synchronous `ConfigDiscoveryAdapter` used by the layered-config loader. Every IO-touc… - [fs](./src/fs/fs.md) — Owns the `FsAdapter` seam and the synchronous `ConfigDiscoveryAdapter` used by the layered-config loader. Every IO-touc… - [generator](./src/generator/generator.md) — Owns the two-call surface that scaffolds an Electrobun project on disk. `collectFiles(options, overrides?)` is pure — i… - [generator](./src/generator/generator.md) — Owns the two-call surface that scaffolds an Electrobun project on disk. `collectFiles(options, overrides?)` is pure — i… - [icons](./src/icons/icons.md) — Wraps the upstream `iconz` library behind an `IconRendererAdapter` seam so the generator can run the icon-generation pi… - [icons](./src/icons/icons.md) — Wraps the upstream `iconz` library behind an `IconRendererAdapter` seam so the generator can run the icon-generation pi… - [prompts](./src/prompts/prompts.md) — Owns the interactive scaffolder that backs the CLI's `create` command. `runPrompts(config, outputDir, prompter)` walks… - [prompts](./src/prompts/prompts.md) — Owns the interactive scaffolder that backs the CLI's `create` command. `runPrompts(config, outputDir, prompter)` walks… - [runner](./src/runner/runner.md) — Owns the `CommandRunner` seam that every electrobun shell-out flows through, plus the `probeElectrobun` and `invokeElec… - [runner](./src/runner/runner.md) — Owns the `CommandRunner` seam that every electrobun shell-out flows through, plus the `probeElectrobun` and `invokeElec… - [schemas](./src/schemas/schemas.md) — Owns the Zod schemas that gate every public boundary of `@suaveplan/electrobun`. Each interface in `src/types/electrobu… - [schemas](./src/schemas/schemas.md) — Owns the Zod schemas that gate every public boundary of `@suaveplan/electrobun`. Each interface in `src/types/electrobu… - [telemetry](./src/telemetry/telemetry.md) — Owns the OpenTelemetry surface for `@suaveplan/electrobun`. Every public entry point that does observable work (project… - [telemetry](./src/telemetry/telemetry.md) — Owns the OpenTelemetry surface for `@suaveplan/electrobun`. Every public entry point that does observable work (project… - [templates](./src/templates/templates.md) — Owns every renderer that produces a project-level file in the scaffolded output: `electrobun.config.ts`, `package.json`… - [features](./src/templates/features.md) — Owns every renderer that produces a per-feature file in the scaffolded output: `i18n`, `networking` (basic + full), `ap… - [templates](./src/templates/templates.md) — Owns every renderer that produces a project-level file in the scaffolded output: `electrobun.config.ts`, `package.json`… ## Features - **Five-command CLI**: `create`, `dev`, `build`, `package`, `sign`. - **Layered config**: defaults + `.suaveplan-electrobun.json` + CLI args via `@suaveplan/config`. - **Injectable seams**: `FsAdapter`, `CommandRunner`, `IconRendererAdapter`, `Prompter` — every IO path is testable without `vi.mock`. - **Zod-validated options** at every public boundary; bad input fails as `ELECTROBUN.INVALID_OPTIONS`. - **Eleven typed error codes** under the `ELECTROBUN.*` namespace. - **OpenTelemetry**: five counters + two histograms on the `@suaveplan/electrobun` meter. - **iconz integration** for `.icns` / `.ico` / `.png` icon generation. - **Auto-update bundling** via the `--update` flag on `build`. - **Code-signing pipeline** via `sign --identity --entitlements --notarize` (the wrapper shapes argv; signing certificates remain in the user's keychain). - **Eight feature renderers** (`i18n`, `networking` × basic/full, `api`, `api-schemas`, `storage`, `auth`, `form-builder`, `r3f` with five modules). ## Installation ```bash bun add @suaveplan/electrobun ``` The package ships a `suaveplan-electrobun` binary: ```bash suaveplan-electrobun --help ``` ## Usage ### Scaffold a new project ```bash suaveplan-electrobun create my-app --skip-prompts \ --name my-app --id com.example.my-app --icon ./assets/icon.png ``` ### Interactive scaffold ```bash suaveplan-electrobun create ./my-app ``` ### Dev / build / package / sign ```bash suaveplan-electrobun dev --cwd ./my-app suaveplan-electrobun build --cwd ./my-app --target mac --update suaveplan-electrobun package --cwd ./my-app --target mac suaveplan-electrobun sign --cwd ./my-app \ --identity "Developer ID Application: ..." \ --entitlements ./entitlements.plist --notarize ``` ### Programmatic use ```ts import { buildCommand, createCommand, generate, runCli, } from "@suaveplan/electrobun"; const report = await generate({ name: "my-app", identifier: "com.example.my-app", description: "A demo", version: "0.1.0", outputDir: "./my-app", features: ["i18n", "api"], networkingComplexity: "basic", r3fModules: [], }); ``` ## Subpath exports | Subpath | Surface | |---|---| | `@suaveplan/electrobun` | Full barrel | | `@suaveplan/electrobun/cli` | Five command functions + `runCli` | | `@suaveplan/electrobun/config` | `loadConfig`, defaults | | `@suaveplan/electrobun/error-codes` | `ELECTROBUN_CODES`, `ElectrobunError` | | `@suaveplan/electrobun/fs` | `FsAdapter`, `nodeFsAdapter`, file helpers | | `@suaveplan/electrobun/generator` | `collectFiles`, `generate` | | `@suaveplan/electrobun/icons` | `generateIcons`, `iconzRendererAdapter` | | `@suaveplan/electrobun/prompts` | `runPrompts` | | `@suaveplan/electrobun/runner` | `CommandRunner`, `probeElectrobun`, `invokeElectrobun` | | `@suaveplan/electrobun/schemas` | Zod schemas + `parseOrThrow` | | `@suaveplan/electrobun/telemetry` | OTel counters + histograms | | `@suaveplan/electrobun/templates` | Project + feature renderers | | `@suaveplan/electrobun/types` | Shared types + `FEATURE_ORDER` | ## Error codes The full `ELECTROBUN.*` registry: `INVALID_OPTIONS`, `OUTPUT_NOT_EMPTY`, `CONFIG_PARSE_FAILED`, `ICON_SOURCE_MISSING`, `ICON_RENDER_FAILED`, `TEMPLATE_RENDER_FAILED`, `FS_WRITE_FAILED`, `BINARY_UNAVAILABLE`, `RUNNER_FAILED`, `PROMPT_ABORTED`, `UNKNOWN_FLAG`. ## License MIT — see the repository root.