references/electron.md
# Electron Platform Reference
Package: [`@capawesome/capacitor-electron`](https://github.com/capawesome-team/capacitor-electron) (MIT). Maximum plugin compatibility and web-bundle update support, at the cost of larger binaries (bundled Chromium).
## Compatibility
Supports **Capacitor 6+** and **Electron 28+** (no upper Electron bound — update Electron in `electron/package.json` and run `npm install` there). On Capacitor 6 and 7, the Capacitor CLI ignores the exit code of platform hooks, so a failing `npx cap sync` still reports success — check the log output for `[capacitor-electron]` errors. Capacitor 8 fails the command properly.
## Scaffold Layout
`npx cap add @capawesome/capacitor-electron` creates an `electron/` directory containing only user-owned files:
| File | Purpose |
| --- | --- |
| `main.ts` | ~5 lines: imports the runtime and starts the app |
| `capacitor.electron.config.ts` | Typed platform options (window, CSP, deep links, hooks) |
| `electron-builder.config.js` | Packaging configuration |
| `package.json` | Electron/electron-builder/TypeScript devDependencies and the `build`/`start`/`pack` scripts |
| `tsconfig.json` | TypeScript configuration for `main.ts` and the platform config |
| `assets/` | App icons |
All runtime logic lives in the npm package and updates via `npm update`.
After `cap add`, install the Electron dependencies once (`cd electron && npm install && cd ..`) and add a `postinstall` script to the app's root `package.json` so they stay in sync with the main app dependencies:
```json
{
"scripts": {
"postinstall": "cd electron && npm ci && cd .."
}
}
```
## Configuration
Typed options in `electron/capacitor.electron.config.ts`:
```typescript
import { defineConfig } from '@capawesome/capacitor-electron/config';
export default defineConfig({
window: {
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
},
deepLinks: {
scheme: 'myapp',
},
});
```
Available top-level options: `scheme` (default `'capacitor-electron'`), `hostname` (default `'localhost'`), `window` (size/min/max, `backgroundColor`, `fullscreen`, `statePersistence`, `titleBarStyle`), `csp` (`policy` and `devPolicy` overrides), `deepLinks` (`scheme`), `singleInstance` (default `true`), and `hooks`.
Extension happens through typed options and the hooks nested under the `hooks` key (`beforeReady`, `windowFactory`, `onWindowCreated`) — never by owning runtime code. The security defaults (sandboxed renderer, context isolation, validated IPC) are not configurable; `windowFactory` must not weaken the mandatory security window options.
## Live Reload
Set `server.url` in the Capacitor config to the dev server and run the platform:
```typescript
// capacitor.config.ts
const config: CapacitorConfig = {
server: {
url: 'http://localhost:5173',
},
};
```
```bash
npx vite &
npx cap run @capawesome/capacitor-electron
```
Dev mode applies a documented, dev-only CSP relaxation (inline scripts, eval, websockets) and reconnects automatically when the dev server restarts. Remove `server.url` to serve built web assets again.
## Deep Links
Declare the scheme in the platform configuration (see above) and listen with the standard `@capacitor/app` plugin:
```typescript
import { App } from '@capacitor/app';
await App.addListener('appUrlOpen', ({ url }) => {
console.log('App opened with URL:', url);
});
```
Deep links opened while the app runs are routed to the running instance (single instance is enforced by default); the launch URL is available via `App.getLaunchUrl()`.
## Plugin Support
- Plugins with a **web implementation** work unchanged via automatic fallback.
- Plugins with a dedicated **electron implementation** get native (Node) capability.
Plugins declare their electron implementation via `package.json`:
```json
{
"capacitor": {
"electron": { "src": "electron" }
}
}
```
The implementation is an ES module at `<src>/dist/plugin.mjs` exporting plugin classes with a static `__capacitorElectronPlugin` property (`{ name: string; methods: string[] }`). The static property is the contract, so plugins need no build-time dependency on the platform package (an optional `defineElectronPlugin` helper is exported from `@capawesome/capacitor-electron/plugin`). A declared method missing on the class fails loudly at boot. Implementations written for the old `@capacitor-community/electron` platform are **not** loaded.
## Packaging
```bash
cd electron && npm run pack
```
The `pack` script runs compile (`tsc`), **vendor** (`capacitor-electron vendor` — copies the platform runtime, every plugin's electron implementation, and their dependency closure into `electron/vendor/`, mapped to `node_modules` inside the packaged app), and `electron-builder`. Code signing, notarization, and targets (dmg/msi/nsis/AppImage/deb) are standard electron-builder configuration in the user-owned `electron-builder.config.js`. Electron Forge is a supported alternative: run `capacitor-electron vendor` before packaging and include `vendor/node_modules` as the app's `node_modules`.
Native Node addons are **not** rebuilt automatically — the vendor step detects and reports them, but they must be rebuilt against Electron's ABI (e.g. with `@electron/rebuild`).
## App Updates
Two independent layers:
- **Binary updates** (Electron, runtime, native modules): use [`electron-updater`](https://www.electron.build/auto-update), wired in the user-owned `main.ts`.
- **Web-bundle updates (Live Updates)**: supported via Capawesome Cloud and `@capawesome/capacitor-live-update` **>= 8.5.0** on **Capacitor 8** with platform version **>= 0.2.0**. The plugin uses the same app, `appId`, and `LiveUpdate` config as Android/iOS; sync with `npx cap sync @capawesome/capacitor-electron` registers its Electron implementation automatically. Electron specifics: the app version is `version` in `electron/package.json` (bump it per release), only `zip` bundles are delivered, the default channel for versioned channels is set under `plugins.LiveUpdate.defaultChannel` in `electron/capacitor.electron.config.ts`, and the CLI takes `--electron-min`/`--electron-max`/`--electron-eq` constraints. Read the `capawesome-cloud` skill (`references/live-updates-capacitor.md`, section "Enable Live Updates on Electron") for the setup procedure.
- **Bundle-serving primitive**: plugin implementations can access `services.bundles` (`getActiveBundlePath()`, `setActiveBundle(dir | null)`), an in-memory switch of the served directory that reloads the app windows. The platform persists nothing and never rolls back; download, persistence, rollback, channels, and verification are provided by the Live Update plugin.
## Migration from `@capacitor-community/electron`
The platform replaces `@capacitor-community/electron`. Key differences: the scaffold is minimal and user-owned (no runtime code to maintain), and plugin implementations use the contract above — old-platform implementations are not loaded, but web implementations keep working via the fallback. Follow the Migration section of the [README](https://github.com/capawesome-team/capacitor-electron) for the step-by-step procedure.
references/tauri.md
# Tauri Platform Reference
Package: [`@capawesome/capacitor-tauri`](https://github.com/capawesome-team/capacitor-tauri) (MIT) + the [`capacitor-tauri`](https://crates.io/crates/capacitor-tauri) Rust crate (version-locked to the npm package). Lean, secure desktop apps with tiny system-webview binaries and a deny-by-default Rust core, with a deliberately scoped plugin story.
## Prerequisites
Tauri requires the **Rust toolchain** (1.77.2+) and platform system dependencies (WebKitGTK dev packages on Linux, MSVC Build Tools on Windows, Xcode Command Line Tools on macOS). Verify with `rustc --version`; if missing, follow the [Tauri prerequisites guide](https://v2.tauri.app/start/prerequisites/) before installing.
## Scaffold Layout
`npx cap add @capawesome/capacitor-tauri` creates a `src-tauri/` directory containing only user-owned files:
| File | Purpose |
| --- | --- |
| `src/main.rs` | ~3 lines: starts the app via the platform crate |
| `src/generated.rs` | Generated plugin registrations (regenerated at sync, gitignored) |
| `tauri.conf.json` | App configuration (window, CSP, deep links, bundle) |
| `capabilities/` | Permission grants (regenerated at sync) |
| `Cargo.toml` | Crate dependencies (curated plugin crates added at sync) |
| `build.rs` | Standard Tauri build script |
| `icons/` | App icons |
All runtime logic lives in the `capacitor-tauri` crate and updates via `cargo update`.
## Sync-Time Codegen
`npx cap sync @capawesome/capacitor-tauri` copies web assets (skipped when `server.url` is set) and then statically scans the app's Capacitor plugin dependencies to generate:
- a **deny-by-default capability file** (`capabilities/capacitor.json`) containing only the permissions the enabled curated plugins need,
- the matching `tauri-plugin-*` crate dependencies in the managed block of `Cargo.toml`,
- the Rust plugin registrations in `src/generated.rs`.
Detection scans the app `package.json` `dependencies` only — a curated plugin listed under `devDependencies` is **not** detected. Rerun sync after adding or removing Capacitor plugins.
## Plugin Tiers
| Tier | What | Examples |
| --- | --- | --- |
| Built-in | Implemented by the platform crate | `@capacitor/app` (commands + lifecycle/deep-link events) |
| Curated | Shims calling official `tauri-plugin-*` crates | Filesystem → `fs`, Preferences → `store`, Dialog → `dialog`, Local Notifications → `notification` |
| Web fallback | Any plugin with a web implementation, automatically | e.g. `@capacitor/device` |
Plugins needing native functionality beyond this require a bespoke Rust implementation (Tier 3). Before recommending Tauri, list the app's plugins and verify coverage; if a required plugin is uncovered, recommend the [Electron platform](https://github.com/capawesome-team/capacitor-electron) instead. Requests for new curated plugins go to the [issue tracker](https://github.com/capawesome-team/capacitor-tauri/issues).
`Capacitor.getPlatform()` returns `'tauri'` and `Capacitor.isNativePlatform()` returns `true`.
## Configuration Notes
- The scaffold ships a default CSP in `tauri.conf.json` (`default-src 'self'; img-src 'self' data: blob:; style-src 'self' 'unsafe-inline'`) — apps loading remote resources must extend it.
- The default window is labeled `main` and the generated capability file grants permissions to `["main"]` only — renaming or adding windows requires updating `capabilities/` manually.
## Live Reload
Set `server.url` in the Capacitor config to the dev server, then `npx cap run @capawesome/capacitor-tauri` — it launches `tauri dev` pointing at the dev server with full HMR.
## Deep Links
Declare the scheme in `src-tauri/tauri.conf.json` under `plugins.deep-link.desktop.schemes` and listen with the standard `@capacitor/app` plugin:
```typescript
import { App } from '@capacitor/app';
await App.addListener('appUrlOpen', ({ url }) => {
console.log('App opened with URL:', url);
});
```
OS URL-scheme handlers are registered for packaged apps; single instance is enforced so links route to the running app.
## Packaging
```bash
npx cap sync @capawesome/capacitor-tauri
npx tauri build
```
Tauri's bundler produces native installers for the current OS (`.dmg`/`.app`, `.msi`/`.exe`, `.deb`/`.AppImage`). Signing, updater, and target configuration live in `src-tauri/tauri.conf.json` — see the [Tauri distribution guide](https://v2.tauri.app/distribute/).
## Honest Limitations
Inherent trade-offs, not bugs — communicate them before the user commits:
1. **No plugin-ecosystem reuse.** No Node runtime; only web implementations, curated shims, and bespoke Rust plugins work.
2. **Three webview engines.** WKWebView (macOS), WebView2 (Windows), WebKitGTK (Linux) behave differently — a real cross-engine testing burden, worst on Linux.
3. **No web-bundle OTA.** Web assets are compiled into the binary; only full signed binary updates (via `tauri-plugin-updater`) are possible.
4. **Rust toolchain required** for developers and CI, with longer first builds and large `target/` directories.
SKILL.md
---
name: capacitor-platforms
description: "Guides the agent through adding, configuring, and using the Capawesome desktop platforms for Capacitor — @capawesome/capacitor-electron and @capawesome/capacitor-tauri. Covers choosing between Electron and Tauri, installation and scaffolding, sync/run workflows, live reload, deep links, plugin compatibility (Electron plugin implementations and web fallback; Tauri plugin tiers), packaging, and app updates. Do not use for the Android or iOS platforms, installing individual Capacitor plugins, migrating Capacitor apps or plugins to newer versions, or non-Capacitor desktop frameworks."
license: MIT
compatibility: "Requires Node.js 18+ and npm. Tauri additionally requires the Rust toolchain and its system dependencies."
metadata:
author: capawesome-team
source: https://github.com/capawesome-team/skills/tree/main/skills/capacitor-platforms
---
# Capacitor Platforms (Desktop)
Bring a Capacitor app to macOS, Windows, and Linux with the Capawesome desktop platforms: [`@capawesome/capacitor-electron`](https://github.com/capawesome-team/capacitor-electron) and [`@capawesome/capacitor-tauri`](https://github.com/capawesome-team/capacitor-tauri). Both use the standard Capacitor workflow (`cap add` / `cap sync` / `cap run`), report `Capacitor.isNativePlatform()` as `true`, and deliver deep links through the standard `@capacitor/app` events.
## Prerequisites
| Requirement | Electron | Tauri |
| --- | --- | --- |
| Node.js | LTS (18+) | LTS (18+) |
| Capacitor | 6+ | 8+ |
| Electron | >= 28 (installed by the scaffold) | — |
| Rust toolchain + system dependencies | — | Required — see the [Tauri prerequisites guide](https://v2.tauri.app/start/prerequisites/) |
On Capacitor 6 and 7, the Capacitor CLI ignores the exit code of platform hooks — a failing `npx cap sync` still reports success. Check the log output for `[capacitor-electron]` errors. Capacitor 8 fails the command properly.
## Agent Behavior
- **Auto-detect before asking.** Read `package.json` and the Capacitor config to determine installed platforms and plugins before prompting the user.
- **Help choose the platform first.** If the user has not committed to Electron or Tauri, apply Step 1 — plugin requirements usually decide it.
- **Always use the full package name** with Capacitor CLI commands (e.g. `npx cap sync @capawesome/capacitor-electron`). A bare `npx cap sync electron` or `npx cap sync tauri` silently does nothing.
- **Check plugin compatibility early.** On Tauri, list the app's Capacitor plugins and verify each is covered by a web implementation or a curated shim (see `references/tauri.md`) before recommending it.
## MCP Servers
Two hosted MCP servers serve the current documentation, so both are always ahead of the guidance bundled with this skill:
- **[Capawesome MCP server](https://capawesome.io/docs/ai/mcp/capawesome/)** — the Capawesome plugins, the Capawesome CLI, and Capawesome Cloud.
- **[Capacitor MCP server](https://capawesome.io/docs/ai/mcp/capacitor/)** (unofficial) — Capacitor itself: the CLI, the `capacitor.config` file, the native Android and iOS projects, and the official plugin APIs.
Both expose `search_docs` and `get_doc_page`, so pick the server by topic before calling either.
- **If the MCP tools are available**, call `search_docs` on the server that owns the topic and read the matching page with `get_doc_page` before applying the guidance below. Where the two disagree, follow the documentation.
- **If they are not available**, mention once that the servers can be added with the commands below, then continue with this skill. Never block on it.
```bash
claude mcp add --transport http capawesome "https://mcp.capawesome.io/mcp"
claude mcp add --transport http capacitor "https://capacitor-mcp.capawesome.io/mcp"
```
Neither server needs an account or a token for documentation. See the `capawesome-mcp` and `capacitor-mcp` skills for full setup, including the Capawesome Cloud tools.
## Procedures
### Step 1: Choose a Platform
| The app needs… | Choose |
| --- | --- |
| Reuse of Capacitor plugins with native (Node) desktop implementations | **Electron** |
| Web-bundle over-the-air updates | **Electron** (Capawesome Cloud Live Updates via `@capawesome/capacitor-live-update` >= 8.5.0, requires Capacitor 8 — see `references/electron.md`; Tauri compiles web assets into the binary — only full signed binary updates) |
| A single, predictable bundled Chromium across all OSes | **Electron** |
| Smallest binaries (~3–10 MB vs ~85–120 MB) and lowest memory use | **Tauri** |
| A deny-by-default security model with a Rust core | **Tauri** |
| No Rust toolchain in dev/CI | **Electron** |
Tauri's trade-offs are inherent, not bugs: no Node runtime (so no arbitrary Capacitor plugin reuse), three different system webviews (WKWebView/WebView2/WebKitGTK), no web-bundle OTA, and a required Rust toolchain. If in doubt, read the Honest Limitations section of the [Tauri platform README](https://github.com/capawesome-team/capacitor-tauri).
### Step 2: Install and Add the Platform
Electron:
```bash
npm install @capawesome/capacitor-electron
npx cap add @capawesome/capacitor-electron
cd electron && npm install && cd ..
```
Then add a `postinstall` script to the app's root `package.json` so the Electron dependencies are always installed together with the main app dependencies:
```json
{
"scripts": {
"postinstall": "cd electron && npm ci && cd .."
}
}
```
Tauri (verify `rustc --version` works first; if not, stop and walk the user through the [Tauri prerequisites](https://v2.tauri.app/start/prerequisites/)):
```bash
npm install @capawesome/capacitor-tauri
npx cap add @capawesome/capacitor-tauri
```
Both scaffolds contain only files the user owns (config, icons, a few-line entry point); all runtime logic lives in the versioned package/crate and updates via `npm update` / `cargo update`.
### Step 3: Sync and Run
```bash
npx cap sync @capawesome/capacitor-electron # or @capawesome/capacitor-tauri
npx cap run @capawesome/capacitor-electron # or @capawesome/capacitor-tauri
```
Electron sync copies web assets and regenerates the plugin manifest. Tauri sync additionally scans the app's Capacitor plugin dependencies and generates a deny-by-default capability file, the curated `tauri-plugin-*` crate dependencies, and the Rust plugin registrations.
For live reload on either platform, set `server.url` in the Capacitor config to the local dev server and run the platform — see the platform reference for details.
### Step 4: Configure
- Electron: typed options in `electron/capacitor.electron.config.ts` (window, CSP, deep links, hooks) — see `references/electron.md`.
- Tauri: `src-tauri/tauri.conf.json` (window, CSP, deep links via `plugins.deep-link.desktop.schemes`, bundle) — see `references/tauri.md`.
### Step 5: Package for Distribution
- Electron: `cd electron && npm run pack` (electron-builder; vendors the runtime and plugin implementations automatically) — see `references/electron.md`.
- Tauri: `npx cap sync @capawesome/capacitor-tauri && npx tauri build` (native installers per OS) — see `references/tauri.md`.
## References
- `references/electron.md` — scaffold layout, configuration, live reload, deep links, plugin support and plugin development contract, packaging and vendoring, app updates (binary updates and Live Updates), migration from `@capacitor-community/electron`.
- `references/tauri.md` — Rust prerequisites, scaffold layout, sync-time codegen, the plugin tier model (built-in / curated / web fallback), configuration, live reload, deep links, packaging, honest limitations.
## Related Skills
- **`capacitor-app-creation`** — Create a new Capacitor app before adding a desktop platform.
- **`capacitor-app-development`** — General Capacitor development topics, configuration, and troubleshooting.
- **`capacitor-plugins`** — Install and configure Capacitor plugins, including checking desktop platform support.
- **`capawesome-cloud`** — Set up Capawesome Cloud Live Updates for the Electron platform (same app and config as Android/iOS).
- **`capawesome-mcp`** — Connect an MCP client to the hosted Capawesome MCP server for always-current documentation and Capawesome Cloud management.