Jesse A. Green / notebook

Pake Administrator & Developer Guide

Generated June 2026 from tw93/Pake at 35fc57d

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

This guide is the deep reference for engineers, packagers, and contributors who need to understand how Pake works internally — how the CLI compiles apps, how the Rust container behaves at runtime, the configuration surface, the security model, and how to extend or contribute to the project. If you only want to package a website, the User Guide is the right document; this one assumes you want to see the machinery.

Pake is a two-part system: a TypeScript CLI (bin/) that orchestrates builds, and a Rust/Tauri container (src-tauri/) that becomes the desktop app. Both live in one repository and ship together as the pake-cli npm package.


1. Executive Summary

Attribute Value
Project Pake — turn any webpage into a desktop app
License MIT
CLI package pake-cli v3.11.7 (binary: pake)
Container crate pake v3.11.7 (lib name: app_lib)
Frameworks Tauri 2.x (Rust), Commander 14 (CLI), Rollup (CLI bundling)
Languages TypeScript (CLI), Rust 2021 edition (container)
Min toolchain Node ≥ 18 (22 recommended), Rust ≥ 1.85.0
Platforms macOS, Windows, Linux (incl. ARM64)
Webview WebKit (macOS/Linux), WebView2 (Windows)

What Pake actually is, architecturally: it is a code generator and compiler driver, not a runtime. The CLI takes a URL plus options, synthesizes a Tauri configuration, compiles a purpose-built Rust binary that wraps the URL in a system webview, and emits a platform installer. The compiled container is deliberately small and uniform — every Pake app shares the same shortcuts, menu, tray, download handling, and JavaScript-injection behavior.

Important

The Pake container does not bundle a browser engine. The wrapped site runs in the OS-provided webview. This is the source of Pake's headline advantage (≈5 MB vs ≈100 MB for Electron) and also the source of its main caveat: site behavior is subject to the host webview's capabilities and quirks.


2. Architecture

2.1 Two-stage pipeline

 ┌─────────────────────────── Build time (your machine / CI) ───────────────────────────┐
 │                                                                                        │
 │   pake [url] [options]                                                                 │
 │        │                                                                               │
 │        ▼                                                                               │
 │   bin/cli.ts  ──► getCliProgram() (Commander parses flags)                             │
 │        │                                                                               │
 │        ▼                                                                               │
 │   options/index.ts  ──► resolve name, identifier, icon  (handleIcon, resolveIdentifier)│
 │        │                                                                               │
 │        ▼                                                                               │
 │   BuilderProvider.create()  ──► MacBuilder | WinBuilder | LinuxBuilder                 │
 │        │                                                                               │
 │        ▼                                                                               │
 │   BaseBuilder.prepare()  ──► ensure Rust, install deps (pnpm/npm), CN-mirror toggle    │
 │        │                                                                               │
 │        ▼                                                                               │
 │   BaseBuilder.buildAndCopy()  ──► mergeConfig() writes src-tauri/.pake/tauri.conf.json │
 │        │                          then `tauri build -c .pake/tauri.conf.json`          │
 │        ▼                                                                               │
 │   Rust/Tauri compiles src-tauri/  ──► installer copied to CWD as <name>.<type>         │
 │                                                                                        │
 └────────────────────────────────────────────────────────────────────────────────────────┘
                                          │ produces
                                          ▼
 ┌─────────────────────────── Run time (end user's machine) ────────────────────────────┐
 │                                                                                        │
 │   app_lib::run()  (src-tauri/src/lib.rs)                                               │
 │        │  reads embedded pake.json + tauri.conf.json (include_str!)                    │
 │        ▼                                                                               │
 │   tauri::Builder ──► plugins ──► invoke_handler (8 IPC commands) ──► setup():          │
 │        ├─ set_window()        build the "pake" webview, inject 8 JS scripts            │
 │        ├─ set_system_tray()   optional tray icon + menu                                │
 │        ├─ set_global_shortcut() optional activation hotkey                             │
 │        └─ set_app_menu()      native menu (macOS only)                                 │
 │                                                                                        │
 └────────────────────────────────────────────────────────────────────────────────────────┘

2.2 Component inventory

Layer Path Responsibility
CLI entry bin/cli.ts Parse args, run the builder, handle errors
CLI program bin/helpers/cli-program.ts Commander option definitions (authoritative flag list)
Option processing bin/options/index.ts, bin/options/icon.ts Resolve name/identifier/icon
Builders bin/builders/* Platform-specific build orchestration
Build environment bin/builders/env.ts Package-manager detection, timeouts, CN-mirror, NO_STRIP logic
Config merge bin/helpers/merge.ts, bin/helpers/tauriConfig.ts Translate CLI options → Tauri config
Rust toolchain bin/helpers/rust.ts Detect/install Rust, set up environment
Utilities bin/utils/* URL parsing, name normalization, icon conversion, shell exec
Container entry src-tauri/src/main.rs, lib.rs Tauri app bootstrap
Window src-tauri/src/app/window.rs Build the webview window, proxy, downloads, multi-window
Setup src-tauri/src/app/setup.rs Tray, global shortcut
Menu src-tauri/src/app/menu.rs Native menu + handlers (macOS)
IPC commands src-tauri/src/app/invoke.rs The 8 backend commands
Config types src-tauri/src/app/config.rs PakeConfig / WindowConfig structs
Utilities src-tauri/src/util.rs Config loading, data dir, toast, download-message i18n, filename collision
Injected scripts src-tauri/src/inject/*.js Behavior injected into the wrapped page
Capabilities src-tauri/capabilities/default.json Tauri permission grants

2.3 CLI build flow in detail

BaseBuilder.prepare() (bin/builders/BaseBuilder.ts) runs before any compilation:

  1. ensureRustEnv() / checkRustInstalled() — if Rust is missing, prompt and installRust(). Non-interactive CI failures exit with code 1.
  2. configureCargoRegistry() — when PAKE_USE_CN_MIRROR=1, copy src-tauri/rust_proxy.toml to src-tauri/.cargo/config.toml (rsproxy.cn); otherwise remove the auto-generated mirror config.
  3. detectPackageManager() — prefer pnpm; fall back to npm if pnpm is absent or its major version doesn't match the pinned packageManager field in package.json.
  4. getInstallCommand() — install dependencies (--registry=https://registry.npmmirror.com under CN mirror; --legacy-peer-deps for npm).

BaseBuilder.buildAndCopy() then:

  1. mergeConfig(url, options, tauriConfig) — writes the merged Tauri configuration into src-tauri/.pake/tauri.conf.json (the build never mutates the tracked source config).
  2. getBuildCommand() — runs pnpm run build -c .pake/tauri.conf.json (or build:debug in debug mode) with the cli-build Cargo feature, adding macos-proxy on macOS 14+ (Darwin ≥ 23).
  3. Copies the resulting installer to <name>.<type> in the working directory, optionally copies a standalone binary (--keep-binary), and on macOS optionally installs to /Applications (--install).

Note

The cli-build Cargo feature changes which config the container embeds. In src-tauri/src/util.rs, get_pake_config() uses include_str!("../.pake/pake.json") under cli-build, versus include_str!("../pake.json") for a plain source build. This is why CLI builds read from .pake/ and developer builds (pnpm run dev) read the tracked root config.

2.4 Architecture-to-target mapping

BaseBuilder.ARCH_MAPPINGS resolves logical targets to Rust triples:

Platform arm64 x64 universal
macOS (darwin) aarch64-apple-darwin x86_64-apple-darwin universal-apple-darwin
Windows (win32) aarch64-pc-windows-msvc x86_64-pc-windows-msvc —
Linux aarch64-unknown-linux-gnu x86_64-unknown-linux-gnu —

3. The Pake Container (Runtime Internals)

3.1 Bootstrap (lib.rs::run_app)

On launch the container:

  1. On Linux, sets WEBKIT_DISABLE_DMABUF_RENDERER=1 and WEBKIT_DISABLE_COMPOSITING_MODE=1 (unless already set) to avoid common WebKitGTK rendering failures (white-screen bugs).
  2. Loads the embedded PakeConfig and Tauri Config via get_pake_config().
  3. Registers plugins: window-state, oauth, http, shell, notification, opener. Adds single-instance only when multi_instance is false.
  4. Registers the IPC invoke_handler (see §3.2).
  5. In setup(): builds the main window, the tray, the global shortcut, and (macOS) the menu.
  6. Handles window close: when hide_on_close is set, CloseRequested is intercepted and the window is hidden instead of the app quitting.

3.2 IPC command surface

Tauri commands are neither CLI nor HTTP endpoints — they are IPC calls dispatched from page JavaScript (window.__TAURI__.invoke('name', args)) to Rust. The complete, authoritative surface is the tauri::generate_handler! macro in lib.rs. There are 8 commands, all defined in src-tauri/src/app/invoke.rs:

Command Signature Purpose
download_file (params: { url, filename, language? }) Download a URL to the OS Downloads folder, with localized toast notifications
send_notification (params: { title, body, icon }) Show a native OS notification
set_dock_badge (count: Option<i64>) Set the macOS dock badge to a count (1–99999), or clear
increment_dock_badge () Increment the dock badge by 1 (clamped to 99999)
set_dock_badge_label (label: Option<String>) Set a text badge (≤ 16 chars)
clear_dock_badge () Clear the dock badge
update_theme_mode (mode: String) Set window theme to dark/light (macOS)
clear_cache_and_restart () Clear all browsing data and restart the app

Note

Dock-badge commands are macOS-native (via objc2/NSDockTile) on macOS and fall back to set_badge_count on the main window for other platforms. update_theme_mode is a no-op off macOS.

3.3 Window construction (window.rs::build_window)

This is the heart of the container. Each window is built from the first entry in PakeConfig.windows plus platform branches:

  • URL type — url_type: "web" parses the URL as a remote address; "local" treats it as a bundled file path. Any other value is a hard error.
  • Sizing — on Windows the configured pixel size is divided by the monitor scale factor (HiDPI correctness); other platforms use the raw size. min_width/min_height apply a minimum if set.
  • Title — macOS prefers an empty title; Windows/Linux fall back to the product name.
  • Injection scripts — eight scripts are injected in a fixed order (see §3.5). window.pakeConfig is injected first so later scripts can read it.
  • Browser args — Windows/Linux receive --disable-blink-features=AutomationControlled (and Windows also disables several Edge OOUI features). --ignore-certificate-errors and WASM flags (SharedArrayBuffer, --enable-unsafe-webgpu) are appended conditionally.
  • Proxy — proxy_url is parsed and applied via proxy_url(); on Windows an explicit --proxy-server= arg is also emitted for http/socks5.
  • Downloads — an on_download handler redirects webview-initiated downloads (blob/data-URI/Content-Disposition) into the OS Downloads folder, independent of page CSP and the IPC channel. Filename collisions are resolved by check_file_or_append.
  • New windows — when new_window is enabled, an on_new_window handler opens popups as additional Pake windows (used for auth flows).

Caution

On macOS 26+, sharing the opener's WKWebViewConfiguration triggers duplicate WKScriptMessageHandler registrations and crashes the app (issue #1194). build_window therefore reuses only the opener's position/size on macOS, never the full feature set. Preserve this branch if you modify popup handling.

3.4 Tray, shortcut, and menu

  • set_system_tray (setup.rs) — builds a tray icon with a Show/Hide/Quit (and New Window in multi-window) menu. Left-click toggles window visibility. On Linux, fullscreen is re-applied on show to work around WM focus bugs.
  • set_global_shortcut (setup.rs) — registers the activation hotkey via tauri-plugin-global-shortcut, with a 300 ms debounce. Invalid shortcuts log a warning and are skipped rather than failing the launch.
  • set_app_menu (menu.rs, macOS only) — constructs the full native menu. handle_menu_click dispatches menu items, most of which call window.eval(...) into the injected JavaScript (zoomIn(), zoomOut(), setZoom(), window.pakeFind?.open(), triggerPasteAsPlainText(), etc.).

3.5 The injection system

Eight scripts under src-tauri/src/inject/ are compiled into the binary with include_str! and injected into every wrapped page in this order (order matters):

Order Script Role
1 (generated) window.pakeConfig Exposes the window config to the page
2 find.js In-page Find UI (window.pakeFind)
3 toast.js Toast notifications (window.pakeToast) — must register before Rust calls show_toast
4 fullscreen.js Fullscreen polyfill / opt-out handling
5 event.js Keyboard shortcuts and page events
6 style.js CSS customizations (ad removal, theming)
7 theme_refresh.js Dark/light theme synchronization
8 auth.js Authentication-flow helpers
9 custom.js User-supplied customizations

User --inject files are layered on top of these built-in scripts. This is the supported mechanism for per-site customization (see §7.2).


4. Configuration Reference

4.1 Configuration model

Two JSON documents drive the container, both embedded at compile time:

  • pake.json — Pake-specific window and behavior config (deserialized into PakeConfig).
  • tauri.conf.json (+ platform variants tauri.{macos,linux,windows}.conf.json) — standard Tauri bundle/app config.

Important

The pake.json and tauri.conf.json tracked in the repo are the default "Weekly" template, not user configuration. When you run the CLI, mergeConfig() synthesizes a fresh config from your options into src-tauri/.pake/. Editing the root files only affects pnpm run dev builds.

4.2 PakeConfig (src-tauri/src/app/config.rs)

Field Type Meaning
windows Vec<WindowConfig> Window definitions (first is the main window)
user_agent PlatformSpecific<String> Per-platform UA string
system_tray PlatformSpecific<bool> Per-platform tray default (macOS off, Win/Linux on)
system_tray_path String Tray icon path (default icons/icon.png)
proxy_url String Proxy for all requests
multi_instance bool Allow multiple processes
multi_window bool Allow multiple windows per process

4.3 WindowConfig fields

Field Type Default CLI flag
url / url_type String — positional URL
width / height f64 1200 / 780 --width / --height
min_width / min_height f64 0 --min-width / --min-height
zoom u32 100 --zoom
resizable bool true —
fullscreen bool false --fullscreen
maximize bool false --maximize
hide_title_bar bool false --hide-title-bar
always_on_top bool false --always-on-top
dark_mode bool false --dark-mode
disabled_web_shortcuts bool false --disabled-web-shortcuts
activation_shortcut String empty --activation-shortcut
hide_on_close bool macOS true --hide-on-close
incognito bool false --incognito
enable_wasm bool false --wasm
enable_drag_drop bool false --enable-drag-drop
new_window bool false --new-window
start_to_tray bool false --start-to-tray
force_internal_navigation bool false --force-internal-navigation
internal_url_regex String empty --internal-url-regex
enable_find bool false --enable-find
ignore_certificate_errors bool false --ignore-certificate-errors
title Option<String> — --title

4.4 Tauri config highlights (tauri.conf.json)

{
  "productName": "Weekly",
  "identifier": "com.pake.weekly",
  "version": "3.11.7",
  "app": {
    "withGlobalTauri": true,
    "trayIcon": { "iconPath": "png/weekly_512.png", "id": "pake-tray" },
    "security": { "headers": {}, "csp": null }
  },
  "build": { "frontendDist": "../dist" }
}
Cargo feature Effect
cli-build Read config from .pake/ (CLI builds) instead of tracked root files
custom-protocol (default) Production asset protocol
macos-proxy Enable proxy support on macOS 14+

The release profile (Cargo.toml) is tuned for size: panic = "abort", codegen-units = 1, lto = "thin", opt-level = "z", strip = true.

4.5 Build environment variables

Variable Where Effect
PAKE_USE_CN_MIRROR=1 CLI prepare npmmirror registry + rsproxy.cn Cargo registry
NO_STRIP=1 Linux AppImage build Skip the linuxdeploy strip step (glibc 2.38+ fix; auto-retried)
PAKE_CREATE_APP=1 macOS build/tests Produce a .app bundle instead of a .dmg
MACOSX_DEPLOYMENT_TARGET macOS build Set by getBuildEnvironment() to 14.0; overridable for SDK pinning
GITHUB_ACTIONS CLI Switches name validation to non-interactive defaults

5. Security Analysis

5.1 The trust boundary

Pake's most important security property is the relationship between the wrapped remote site and the Tauri backend.

// src-tauri/capabilities/default.json
{
  "identifier": "pake-capability",
  "webviews": ["pake"],
  "remote": { "urls": ["https://*.*"] },
  "permissions": [ "shell:allow-open", "notification:allow-notify", ... ]
}

Combined with "withGlobalTauri": true in tauri.conf.json, this means any HTTPS page loaded in the webview can reach window.__TAURI__ and invoke the 8 backend commands. The capability grant is deliberately broad (https://*.*) because Pake wraps arbitrary user-chosen sites.

Caution

Because the remote-site ACL is wide open to all HTTPS origins, a malicious or compromised page inside a Pake app can call download_file, send_notification, theme/badge commands, and clear_cache_and_restart. Pake mitigates the blast radius by exposing a small, narrow command set (no arbitrary filesystem, no shell command execution beyond shell:allow-open), but operators packaging untrusted sites should understand this boundary. Only package sites you trust, and review the granted permissions before widening them.

5.2 Command-level safeguards

  • download_file writes only into the OS Downloads directory; filenames are collision-checked (check_file_or_append), and a u32::MAX overflow guard prevents an infinite-loop DoS on pathological filenames (regression guard for issue #1183).
  • Badge commands clamp counts to 1–99999 and labels to 16 characters.
  • shell:allow-open permits opening URLs/files via the OS handler but not arbitrary command execution.
  • DevTools (core:webview:allow-internal-toggle-devtools) are only functional in debug builds (cfg!(debug_assertions)).

5.3 Network and TLS

  • --proxy-url routes all traffic through an HTTP/HTTPS/SOCKS5 proxy.
  • --ignore-certificate-errors disables TLS validation — intended for intranet/dev servers with self-signed certificates only. Never ship a production app with this flag against a public site.
  • Automation-detection blink features are disabled by default to reduce bot-detection friction, not as a security feature.

5.4 macOS entitlements and permissions

By default the app requests no camera or microphone entitlement. --camera and --microphone add com.apple.security.device.camera / audio-input respectively. Grant these only for sites that need them; macOS prompts the user on first use.

5.5 Data isolation

Each app stores webview data under a per-app config directory (get_data_dir in util.rs, keyed by product name). --incognito disables persistence entirely. Distinct URL + name pairs produce distinct bundle identifiers, so two apps for the same site keep separate cookie jars.


6. Operations

6.1 Building for distribution

# Standard release build (current platform)
pake https://example.com --name Example

# macOS universal binary
pake https://example.com --name Example --multi-arch

# Linux deb + appimage (default), or specific format
pake https://example.com --name Example --targets rpm

# Keep a standalone binary alongside the installer
pake https://example.com --name Example --keep-binary

6.2 CI/CD via GitHub Actions

The repository ships a Build App With Pake CLI workflow and a reusable action (action.yml). Fork the repo, run the workflow with the same parameters as CLI options, and download artifacts. First runs take 10–15 min (cache warm-up); subsequent runs ≈5 min with a 400–600 MB cache.

6.3 Containerized builds

docker run --rm --privileged \
  --device /dev/fuse --security-opt apparmor=unconfined \
  -v $(pwd)/output:/output \
  ghcr.io/tw93/pake:latest \
  https://example.com --name MyApp --targets appimage

Warning

AppImage tooling requires /dev/fuse; the container must run privileged (or be granted FUSE explicitly). Output files may be root-owned — chown them afterward.

6.4 First-build timing and tuning

Platform First build Subsequent
macOS/Linux 5–10 min fast
Windows 10–15 min fast

Install timeout is 900 s on Windows, 600 s elsewhere; build timeout is 900 s (bin/builders/env.ts). For slow networks in China, PAKE_USE_CN_MIRROR=1 switches to domestic mirrors.


7. Developer Internals

7.1 Repository structure

├── bin/                    # CLI source (TypeScript, bundled by Rollup → dist/cli.js)
│   ├── builders/           # BaseBuilder + Mac/Win/Linux builders + env.ts
│   ├── helpers/            # cli-program, merge, rust, tauriConfig
│   ├── options/            # option/icon/logger processing
│   └── utils/              # url, name, icon, shell, validate, mirror, platform
├── src-tauri/              # Rust container
│   ├── src/
│   │   ├── app/            # config, invoke, menu, setup, window
│   │   ├── inject/         # 8 injected JS scripts
│   │   ├── lib.rs          # app bootstrap (run_app)
│   │   ├── main.rs         # thin entry → app_lib::run()
│   │   └── util.rs         # config load, data dir, toast, i18n, filename guard
│   ├── capabilities/       # Tauri permission grants
│   ├── icons/  png/        # per-app icon assets
│   ├── pake.json           # default PakeConfig template
│   └── tauri.*.conf.json   # Tauri config (+ platform variants)
├── default_app_list.json   # preset popular-app definitions
├── docs/                   # cli-usage, advanced-usage, faq, github-actions (EN + CN)
├── scripts/                # release helpers
└── tests/                  # Vitest unit/integration + build/release smoke tests

7.2 Customizing the container

Per the project's advanced-usage guidance:

  • Restyle / remove ads: edit src-tauri/src/inject/style.js, or pass a CSS file with --inject.
  • Add shortcuts / behavior: edit src-tauri/src/inject/event.js, or inject a JS file.
  • Add a backend command: add a #[tauri::command] in invoke.rs and register it in the generate_handler! macro in lib.rs; call it from the page via window.__TAURI__.invoke('name', args).

7.3 Development workflow

git clone https://github.com/tw93/Pake.git && cd Pake
pnpm install
pnpm run dev          # hot-reload container dev build
pnpm run build        # release build
pnpm run build:debug  # debug build (devtools enabled)
pnpm run cli:build    # bundle the CLI (rollup) → dist/cli.js

For CLI hot-reload development, edit DEFAULT_DEV_PAKE_OPTIONS in bin/defaults.ts and run pnpm run cli:dev.

7.4 Testing

pnpm test                 # build CLI + Vitest + real build smoke + release smoke
pnpm test -- --no-build   # skip the heavy real-build phase
npx vitest run            # fast unit/integration suite only
node ./tests/release.js   # release-workflow smoke test only

Test runner flags (tests/index.js): --no-unit, --no-integration, --no-builder, --no-build, --e2e, --pake-cli. The Vitest suite under tests/unit/ covers builders, CLI options, icon handling, name normalization, window-option merging, and identifier generation.

7.5 Code patterns worth knowing

  • Platform abstraction via generics — PlatformSpecific<T> with a cfg-gated get() selects the right value at compile time, avoiding runtime branching for per-OS config.
  • Atomic state — the dock badge uses AtomicI64; multi-window indices use AtomicU32.
  • Graceful degradation — invalid shortcuts, missing tray icons, and download-dir resolution failures log and continue rather than aborting launch.
  • i18n by locale sniffing — get_download_message_with_lang picks Chinese vs English from the params language or LANG/LC_ALL/LC_MESSAGES/LANGUAGE env vars.

8. Troubleshooting (Operational)

Error: feature 'edition2024' is required

Cause: Rust toolchain older than 1.85.0. Solution: rustup update stable. Prevention: Pin rust-toolchain.toml (already in repo: 1.85.0).

Error: Can't detect any appindicator library

Cause: Ubuntu 24.04 dropped libappindicator3-dev. Solution: sudo apt-get install -y libayatana-appindicator3-dev.

Error: failed to run linuxdeploy / strip: Unable to recognise the format

Cause: linuxdeploy's strip tool can't parse the .relr.dyn section (glibc 2.38+). Solution: Pake auto-retries with NO_STRIP=1; set it manually to skip from the start, or build --targets deb, or use Docker.

Error: Command timed out after 900000ms

Cause: First Windows build exceeded the install timeout (native compilation + AV scanning). Solution: Retry; pre-warm with PAKE_USE_CN_MIRROR=1 in China; disable real-time AV temporarily.

Error: Panic in check_file_or_append

Cause: Historical crash (#1183) when a filename had no extension or a huge numeric suffix. Status: Fixed — check_file_or_append handles extensionless files and guards against u32 overflow. Covered by unit tests in util.rs.

Error: macOS CoreFoundation / _Builtin_float module errors

Cause: macOS 26 beta SDK incompatibility. Solution: Create src-tauri/.cargo/config.toml pinning MACOSX_DEPLOYMENT_TARGET and SDKROOT (see User Guide §10.7).

Linux white screen (Ubuntu 24.04 / GNOME)

Cause: WebKitGTK DMABUF/compositing issues; GNOME map-event focus timing (#1122). Status: Mitigated — the container forces WEBKIT_DISABLE_DMABUF_RENDERER/WEBKIT_DISABLE_COMPOSITING_MODE and delays focus after map.


9. Known Limitations & Improvement Opportunities

Observed from the source and the community issue tracker:

  • Embedded-webview sign-in. Google (and some providers) block OAuth inside embedded webviews regardless of --new-window/--multi-window. This is provider policy and cannot be fixed in Pake; document it for users rather than attempting workarounds (#907, #1188).
  • Broad remote-site ACL. remote.urls: ["https://*.*"] plus withGlobalTauri is convenient but maximally permissive. A future hardening option could let packagers scope the ACL to the wrapped site's origin (the lencx/ChatGPT pattern uses a single-origin ACL).
  • Linux AppImage fragility. The glibc-2.38 strip incompatibility is handled by auto-retry, but AppImage remains the least reliable Linux target; deb is more stable.
  • pnpm version pinning. The CLI falls back to npm when the local pnpm major version differs from the pinned one — surfacing as a warning. Users on the wrong pnpm major silently get npm behavior; worth a clearer message (partially addressed via #1202).
  • Single-window config model. build_window only ever reads windows.first(); the Vec<WindowConfig> is effectively single-entry today. Multi-distinct-window apps would need this generalized.
  • CSP is null by default. No content security policy is enforced on the wrapped site, relying entirely on the remote site's own headers. Acceptable for a generic wrapper, but worth flagging for security-sensitive packaging.

10. Quick Reference

Need Command / file
Authoritative CLI flag list bin/helpers/cli-program.ts
CLI defaults bin/defaults.ts
IPC command list tauri::generate_handler! in src-tauri/src/lib.rs
Window behavior src-tauri/src/app/window.rs
Permission grants src-tauri/capabilities/default.json
Per-app config (CLI build) src-tauri/.pake/{pake,tauri.conf}.json
Default config template src-tauri/{pake,tauri.conf}.json
Dev build pnpm run dev
Release build pnpm run build
CLI bundle pnpm run cli:build
Full test suite pnpm test
CN mirror PAKE_USE_CN_MIRROR=1
AppImage strip fix NO_STRIP=1