Jesse A. Green / notebook

Pake User 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.

Pake turns any webpage into a lightweight desktop application with a single command. It wraps the site in a native window built on Rust and Tauri, so the result is roughly 20× smaller than the equivalent Electron app (typically around 5 MB) while starting faster and using less memory. Pake works on macOS, Windows, and Linux.

This guide covers everything you do as a user: installing the pake command, packaging your first app, customizing the window and behavior with options, living with the app day to day (keyboard shortcuts, system tray, menus), and fixing the problems people hit most often.

Note

Pake ships two things in one project: the Pake CLI (the pake command you run to build apps) and the Pake container (the Rust/Tauri desktop shell that your packaged app runs inside). This guide is about using both — building apps with the CLI and using the apps you build.


1. Quick Start

If you already have Node.js installed, you can build a desktop app in two commands.

# 1. Install the Pake CLI globally
pnpm install -g pake-cli

# 2. Package any website into a desktop app
pake https://github.com --name "GitHub"

When the build finishes, the installer (a .dmg, .msi, .deb, or .AppImage depending on your operating system) appears in your current working directory. Open it to install your new app.

Important

The first build downloads and compiles the Rust toolchain and Tauri dependencies. Expect 5–15 minutes the first time. Every build after that is much faster because the dependencies are cached.

If you don't want to install anything locally, skip ahead to Building Online with GitHub Actions — you can build apps entirely in the cloud.


2. Installation

2.1 Requirements

Requirement Version Notes
Node.js ≥ 22.0.0 recommended (≥ 18.0.0 may work) Runs the Pake CLI itself
Rust ≥ 1.85.0 Compiles the desktop app; installed automatically if missing
macOS / Linux tools curl, wget, file, tar Used during dependency setup

Important

Rust 1.85.0 or newer is mandatory. Pake's dependency chain requires the Rust 2024 edition, which only became stable in 1.85.0. An older toolchain fails the build with feature 'edition2024' is required — see Troubleshooting.

2.2 Install the CLI

Pake is published to npm as pake-cli. The binary it installs is named pake.

pnpm (recommended)

pnpm install -g pake-cli

npm

npm install -g pake-cli

npx (no install)

npx pake-cli https://github.com --name GitHub

Tip

pnpm is the recommended package manager — Pake is pinned to a specific pnpm version internally. If you only have npm, that works too; the CLI automatically falls back to npm when a compatible pnpm isn't found.

2.3 Verify the install

pake --version
3.11.7
pake --help
 ____       _
|  _ \ __ _| | _____
| |_) / _` | |/ / _ \
|  __/ (_| |   <  __/   https://github.com/tw93/pake
|_|   \__,_|_|\_\___|  can turn any webpage into a desktop app with Rust.

Usage: pake [url] [options]
...

Note

If you hit a permission error during global install, see Permission Denied When Installing Globally. The short answer is to use npx, switch to pnpm, or move npm's global prefix into your home directory.

2.4 Platform build tools

Because Pake compiles a real Rust binary, your machine needs the standard native build toolchain. These are one-time setup steps; the CLI prompts you to install Rust automatically, but the platform compilers are on you.

macOS

xcode-select --install

Windows

Install Visual Studio Build Tools 2022 with the Desktop development with C++ workload, plus the Windows 10 SDK (10.0.19041.0). For ARM64 builds, also add MSVC v143 – VS 2022 C++ ARM64 build tools.

Linux (Ubuntu/Debian)

sudo apt install libdbus-1-dev libsoup-3.0-dev \
  libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev \
  build-essential curl wget file libxdo-dev libssl-dev \
  libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev \
  gnome-video-effects libglib2.0-dev pkg-config

3. Packaging Your First App

The command shape is always the same:

pake [url] [options]

[url] is the website you want to wrap (or the path to a local HTML file). Everything else is optional.

pake https://github.com --name "GitHub"
✺ Using pnpm for package management.
✺ First-time setup may take 5-10 minutes (installing dependencies)...
✔ Package installed!
✸ Building app...
✔ Build success!
✔ App installer located in /Users/you/GitHub.dmg

A few things worth knowing about that first run:

  • The icon is automatic. If you don't pass --icon, Pake fetches the website's favicon and converts it to the right format for your platform.
  • You'll be asked for a name if you omit one. Pake prompts you interactively; the default is derived from the domain.
  • The output lands in your current directory. Move to the folder where you want the installer before running pake.

Tip

Always give your app a clear --name. On Windows and macOS the name preserves spaces and case (--name "Google Translate"). On Linux it's automatically lowercased and hyphenated (google-translate).

3.1 A richer example

pake https://weekly.tw93.fun \
  --name "Weekly" \
  --icon https://cdn.tw93.fun/pake/weekly.icns \
  --width 1200 \
  --height 800 \
  --hide-title-bar

This builds an app named Weekly with a custom icon, a 1200×800 window, and the immersive (hidden) title bar on macOS.

Pake's maintainers publish pre-built installers for popular sites so you don't have to build them yourself. WeChat, Twitter/X, Grok, DeepSeek, ChatGPT, Gemini, YouTube, YouTube Music, Excalidraw, XiaoHongShu, WeRead, and more are available directly from the project Releases page. Download the installer for your platform and you're done — no CLI required.


4. Everyday Packaging Options

Below are the options you'll reach for most often, grouped by what they do. For the complete alphabetical reference, see Section 11: Full Option Reference.

4.1 Naming and identity

Option What it does Example
--name <string> Sets the application name --name "Weekly"
--title <string> Sets the window title-bar text --title "My App"
--icon <path> Custom icon (local or remote); auto-fetched if omitted --icon ./app.png
--app-version <string> Version stamped into the app (default 1.0.0) --app-version 2.1.0

Tip

Provide the icon in the native format for the cleanest result: .icns for macOS, .ico for Windows, .png for Linux. Pake can convert other formats, but the native one is most reliable.

4.2 Window size and appearance

Option What it does Default
--width <number> Window width in pixels 1200
--height <number> Window height in pixels 780
--min-width <number> Minimum resizable width 0 (no limit)
--min-height <number> Minimum resizable height 0 (no limit)
--zoom <number> Initial page zoom, 50–200 100
--hide-title-bar Immersive header (macOS only) off
--fullscreen Launch full screen off
--maximize Launch maximized off
--always-on-top Keep the window above others off
--dark-mode Force dark mode (macOS) off
pake https://excalidraw.com --name Excalidraw --width 1400 --height 900 --zoom 110

4.3 System tray and close behavior

Option What it does Default
--show-system-tray Show a tray/menu-bar icon off on macOS, on for Windows/Linux
--system-tray-icon <path> Custom tray icon (.ico/.png, 32–256 px) app icon
--start-to-tray Start hidden in the tray (needs --show-system-tray) off
--hide-on-close Hide instead of quit when closing true on macOS, false elsewhere
pake https://github.com --name GitHub --show-system-tray --start-to-tray

Note

Double-click the tray icon to show or hide the window. --start-to-tray is ignored unless --show-system-tray is also set.

4.4 Activation shortcut

Bind a global hotkey that shows/hides the app from anywhere:

pake https://chatgpt.com --name ChatGPT --activation-shortcut "CmdOrControl+Shift+P"

Pressing the shortcut toggles the window. The accelerator syntax follows the common Electron accelerator format (e.g. CmdOrControl, Shift, Alt, letter keys).


5. Common Recipes

5.1 Package a chat app that needs sign-in

Some sites authenticate through popup windows. Allow them:

pake https://chat.example.com --name ChatApp --new-window

Warning

--new-window and --multi-window help popup-based sign-in flows, but they cannot override provider policy. Google in particular blocks sign-in inside embedded webviews. If a site relies on Google OAuth, you may still be unable to log in from a Pake app — that's the provider's restriction, not a Pake bug. Use a real browser for those sign-ins.

5.2 Package WeChat (web)

WeChat detects the webview and blocks repeat logins. Build with incognito mode:

pake https://wx.qq.com --name WeChat --incognito

The trade-off: incognito means cookies aren't stored, so you'll scan a QR code on every launch.

5.3 Strip ads or restyle a page

Inject your own CSS/JS into the wrapped page. Write the customization once and apply it at build time:

# Comma-separated
pake https://news.ycombinator.com --name HackerNews --inject ./style.css,./tweaks.js

# Or repeat the flag
pake https://news.ycombinator.com --name HackerNews --inject ./style.css --inject ./tweaks.js

A minimal ad-hiding CSS file:

.ads-banner { display: none !important; }
.header { background: #1a1a1a !important; }

5.4 Package a local web app

Point Pake at a local HTML file and copy its assets into the bundle:

pake ./my-app/index.html --name "My App" --use-local-file

--use-local-file recursively copies the folder containing the HTML file (and all sub-files) into the app so it runs offline.

5.5 Package a Flutter Web / WebAssembly app

Apps that use SharedArrayBuffer or WebAssembly (Flutter Web, sqlite3.wasm, canvaskit.wasm) need cross-origin isolation headers:

pake https://flutter.dev --name FlutterApp --wasm

5.6 Two apps for the same site

Need separate logins for the same site (e.g. work and personal Gmail)? Build with different names — Pake generates a distinct app identity per URL + name pair:

pake https://gmail.com --name "Gmail Work"
pake https://gmail.com --name "Gmail Personal"

5.7 Build for a specific architecture or format

# macOS universal binary (Intel + Apple Silicon)
pake https://github.com --name GitHub --multi-arch
pake https://github.com --name GitHub --targets universal

# Windows ARM64
pake https://github.com --name GitHub --targets arm64

# Linux RPM instead of the default deb/appimage
pake https://github.com --name GitHub --targets rpm

Note

Linux ARM64 cross-compilation needs extra setup (gcc-aarch64-linux-gnu and cross-compile environment variables). ARM64 builds let Pake apps run on Raspberry Pi, Linux phones, and other ARM64 systems.


6. Using Your Packaged App

Once installed, a Pake app behaves like a native window around the website. It ships with a full set of keyboard shortcuts, a navigation menu, and (optionally) a tray icon.

6.1 Keyboard shortcuts

macOS Windows / Linux Action
⌘ + [ Ctrl + ← Back to previous page
⌘ + ] Ctrl + → Forward to next page
⌘ + ↑ Ctrl + ↑ Scroll to top of page
⌘ + ↓ Ctrl + ↓ Scroll to bottom of page
⌘ + R Ctrl + R Refresh the page
⌘ + W Ctrl + W Hide window (does not quit)
⌘ + - Ctrl + - Zoom out
⌘ + = Ctrl + = Zoom in
⌘ + 0 Ctrl + 0 Reset zoom to 100%
⌘ + L Ctrl + L Copy current page URL
⌘ + ⇧ + ⌥ + V Ctrl + Shift + V Paste and match style
⌘ + ⇧ + H Ctrl + Shift + H Go to the app's home page
⌘ + ⌥ + I Ctrl + Shift + I Toggle developer tools (debug builds only)
⌘ + ⇧ + ⌫ Ctrl + Shift + Del Clear cache and restart

Tip

Double-click the title bar to toggle full screen. On macOS you can also drag the title bar to move the window and use trackpad gestures for back/forward navigation.

6.2 In-page Find

If the app was built with --enable-find, you get an in-page search box:

Shortcut Action
Cmd/Ctrl + F Open Find
Cmd/Ctrl + G Jump to next match
Cmd/Ctrl + Shift + G Jump to previous match

6.3 The menu bar (macOS)

macOS builds get a full native menu: Pake (about/hide/quit), File (new window, clear cache & restart), Edit (undo/redo/cut/copy/paste, paste-and-match-style, find), View (reload, zoom, full screen, dev tools), Navigation (back/forward/home), Window, and Help (a link back to the Pake project).

6.4 Downloads

Pake captures downloads triggered inside the page — including blob, data-URI, and dynamically generated files — and saves them to your operating system's Downloads folder. You'll see a toast notification when a download starts, succeeds, or fails, in English or Chinese depending on your system language. If a file with the same name already exists, Pake appends -1, -2, and so on rather than overwriting.

6.5 System tray

If the tray is enabled, left-click the tray icon to show/hide the window. Right-click for a menu with Show, Hide, Quit, and (in multi-window apps) New Window.


7. Building Online with GitHub Actions

You can build Pake apps entirely in the cloud — no local Node, Rust, or compiler needed.

  • [ ] Fork the Pake repository
  • [ ] Open the Actions tab in your fork
  • [ ] Select the Build App With Pake CLI workflow
  • [ ] Fill in the form (the fields mirror the CLI options)
  • [ ] Click Run Workflow
  • [ ] When the run finishes with a green check, download your app from the Artifacts section

Build times: roughly 10–15 minutes on the first run (the cache is being built) and about 5 minutes afterward.

Tip

Pake can also be used as a reusable GitHub Action inside your own repository's workflows. See the project's pake-action.md documentation for the uses: syntax.


8. Running Pake in Docker

If you'd rather not install build tools at all, run the CLI from the official container image. AppImage builds need FUSE access, so the container runs privileged:

docker run --rm --privileged \
    --device /dev/fuse \
    --security-opt apparmor=unconfined \
    -v ./packages:/output \
    ghcr.io/tw93/pake \
    https://example.com --name myapp --icon ./icon.png --targets appimage

The finished installer is written to the mounted /output directory.

Note

The generated file may be owned by root. Fix ownership afterward with sudo chown $(id -nu):$(id -ng) ./packages/*.


9. How It Works (Concepts)

You don't need this section to use Pake, but it helps explain why some options behave the way they do.

When you run pake, the CLI:

  1. Ensures Rust is installed (offering to install it if not) and installs the project's Node and Cargo dependencies.
  2. Merges your options into a Tauri configuration and writes it to a temporary build directory.
  3. Compiles a small Rust application — the Pake container — that opens a native window and loads your URL.
  4. Copies the finished installer into your current directory.

The container is what gives every Pake app its consistent behavior: the keyboard shortcuts, the menu, download handling, the tray, and the ability to inject your custom CSS/JS into the page. The website itself runs in the operating system's built-in webview (WebKit on macOS/Linux, WebView2 on Windows), which is why Pake apps are so much smaller than Electron apps — they don't bundle a whole browser engine.

Note

Because the page runs in a system webview rather than a full browser, a small number of sites behave differently than they would in Chrome or Safari. Most differences are solved with --user-agent or --inject. See Website Features Not Working below.


10. Troubleshooting

10.1 Rust version error: "feature 'edition2024' is required"

Cause: Your Rust toolchain is older than 1.85.0. Pake's dependencies require the Rust 2024 edition.

Solution:

rustup update stable
rustc --version   # must report 1.85.0 or higher

Prevention: Run rustup update stable before your first Pake build.

10.2 Linux: "Can't detect any appindicator library" on Ubuntu 24.04

Cause: Ubuntu 24.04 replaced libappindicator3-dev with the Ayatana fork.

Solution:

sudo apt-get update
sudo apt-get install -y libayatana-appindicator3-dev

10.3 Linux: AppImage build fails with "failed to run linuxdeploy"

Cause: The bundled linuxdeploy strip tool doesn't recognize the .relr.dyn section introduced in glibc 2.38+.

Solution: Pake automatically retries with NO_STRIP=1. To skip stripping from the start:

NO_STRIP=1 pake https://example.com --name MyApp --targets appimage

If that still fails, build a deb instead (--targets deb) or use the Docker image, or install the full set of Linux system dependencies listed in Section 2.4.

10.4 Linux: "cargo: command not found" after installing Rust

Solution: Reload the Rust environment in your shell, then rebuild:

source ~/.cargo/env

10.5 Windows: installation timeout during first build

Cause: First-time setup compiles native modules and downloads large dependencies; antivirus scanning slows it further.

Solutions:

  • Be patient — the first build can take 10–15 minutes on Windows.

  • If downloads are slow in China, opt in to mirrors:

    $env:PAKE_USE_CN_MIRROR="1"; pake https://github.com --name GitHub
    
  • Temporarily disable real-time antivirus scanning during the build.

10.6 Windows: missing Visual Studio Build Tools

Solution: Install Visual Studio Build Tools and select the Desktop development with C++ workload. For ARM64, add the C++ ARM64 build-tools component.

10.7 macOS: build fails with module compilation errors

Cause: macOS 26 beta SDKs can break Rust module compilation.

Solution: Pin a compatible SDK:

cat > src-tauri/.cargo/config.toml << 'EOF'
[env]
MACOSX_DEPLOYMENT_TARGET = "15.0"
SDKROOT = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"
EOF

10.8 App window is too small or too large

Solution: Set explicit dimensions at build time:

pake https://example.com --name Example --width 1200 --height 800

10.9 App icon not showing correctly

Solution: Supply the icon in the platform-native format — .icns (macOS), .ico (Windows), .png (Linux):

pake https://example.com --name Example --icon ./icon.icns   # macOS

10.9.3 Website features (login, upload) not working

Cause: Most often a webview compatibility difference, not a bug.

Solutions, in order:

  1. Set a desktop browser user agent:

    pake https://example.com --name Example \
      --user-agent "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
    
  2. Inject a fix script with --inject ./fix.js.

  3. For embedded-webview sign-in limits (especially Google), use a real browser — this is provider policy.

  4. For WeChat, add --incognito.

10.4 Permission denied when installing globally

Solutions:

# Use npx (no install)
npx pake-cli https://example.com

# Or fix npm's global prefix
npm config set prefix ~/.npm-global
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# Or use pnpm
pnpm install -g pake-cli

11. Full Option Reference

All options are passed after the URL: pake [url] [options].

11.1 Window and appearance

Option Type Default Description
--name <string> string prompted Application name
--title <string> string — Window title-bar text
--icon <path> path/URL auto-fetched Application icon
--width <number> number 1200 Window width (px)
--height <number> number 780 Window height (px)
--min-width <number> number 0 Minimum window width
--min-height <number> number 0 Minimum window height
--zoom <number> number (50–200) 100 Initial page zoom
--hide-title-bar flag off Immersive header (macOS)
--fullscreen flag off Launch full screen
--maximize flag off Launch maximized
--always-on-top flag off Keep window on top
--dark-mode flag off Force dark mode (macOS)

11.2 Behavior

Option Type Default Description
--activation-shortcut <string> string empty Global show/hide hotkey
--show-system-tray flag platform Show tray icon
--system-tray-icon <path> path app icon Custom tray icon
--start-to-tray flag off Start minimized to tray
--hide-on-close [bool] bool macOS true Hide instead of quit on close
--enable-find flag off In-page Find (Cmd/Ctrl+F)
--incognito flag off Private mode (no cookies/history)
--enable-drag-drop flag off Native drag-and-drop in page
--multi-instance flag off Allow multiple app processes
--multi-window flag off Multiple windows in one process
--new-window flag off Allow site-opened popup windows
--force-internal-navigation flag off Keep all links inside the window
--internal-url-regex <pattern> regex empty Treat matching URLs as internal
--disabled-web-shortcuts flag off Disable built-in web shortcuts

11.3 Web compatibility

Option Type Default Description
--user-agent <string> string empty Custom User-Agent
--inject <files> path(s) — Inject local CSS/JS (comma-separated or repeated)
--wasm flag off Enable WebAssembly / cross-origin isolation
--proxy-url <url> url empty Route requests through HTTP/HTTPS/SOCKS5 proxy
--ignore-certificate-errors flag off Skip TLS validation (self-signed certs)
--use-local-file flag off Copy local HTML + assets into the app

11.4 Build and output

Option Type Default Description
--targets <string> string platform default Build format/architecture (see below)
--multi-arch flag off macOS universal (Intel + Apple Silicon)
--app-version <string> string 1.0.0 App version number
--keep-binary flag off Also output a standalone executable
--iterative-build flag off Fast app-only build (no installer)
--install flag off Install to /Applications after build (macOS)
--installer-language <lang> string en-US Windows installer language
--debug flag off Developer tools + verbose logging

--targets values:

  • Linux: deb, appimage, rpm, deb-arm64, appimage-arm64, rpm-arm64 (default: deb, appimage)
  • Windows: x64, arm64 (auto-detected)
  • macOS: intel, apple, universal (auto-detected)

11.5 macOS media permissions (advanced)

By default Pake apps do not request camera or microphone access. Add these only for sites that need them:

pake https://meet.google.com --name GoogleMeet --camera --microphone
Option Grants
--camera Camera access (com.apple.security.device.camera)
--microphone Microphone access (com.apple.security.device.audio-input)

11.6 Environment variables

Variable Effect
PAKE_USE_CN_MIRROR=1 Use China mirrors (npmmirror + rsproxy.cn) for downloads
NO_STRIP=1 Skip the AppImage strip step (Linux glibc 2.38+ workaround)
PAKE_CREATE_APP=1 Build a macOS .app bundle instead of a .dmg

12. FAQ

Q: How big is a Pake app? About 5 MB on average — roughly 20× smaller than the equivalent Electron app, because Pake reuses the operating system's webview instead of bundling a browser engine.

Q: Do I need to know Rust to use Pake? No. The CLI handles all compilation for you and installs Rust automatically if it's missing. Rust knowledge only matters if you want to customize the container's source code.

Q: Why does my first build take so long? The first build downloads and compiles the entire Rust/Tauri dependency tree. Subsequent builds reuse the cache and are much faster.

Q: Can I build a Windows app on macOS (or vice versa)? Pake builds for the platform you run it on. To build for all three platforms without juggling machines, use the GitHub Actions online build.

Q: Where does the installer go? Into your current working directory. cd to the folder you want before running pake.

Q: Can I change the icon after building? Rebuild with --icon <path>. There's no post-build icon editor.

Q: My app can't sign in with Google. Is that a bug? No. Google blocks sign-in inside embedded webviews as a matter of policy. --new-window and --multi-window can help some flows, but Google OAuth specifically may still be blocked. Use a regular browser for those sign-ins.

Q: How do I remove ads or restyle a site? Write a CSS or JS file and pass it with --inject ./style.css. See Recipe 5.3.

Q: Can I run two copies of the same app? For separate identities (e.g. two accounts), build with different --name values. To allow multiple processes of the same app, use --multi-instance. To open multiple windows within one process, use --multi-window.

Q: Does Pake store my browsing data? Each app keeps its own webview data (cookies, local storage) unless you build with --incognito, which disables persistence. Use Clear Cache & Restart (Cmd/Ctrl+Shift+Backspace) to wipe it.

Q: How do I package a site that uses WebAssembly or Flutter Web? Add --wasm to enable the required cross-origin isolation headers.

Q: Can I build apps in the cloud without installing anything? Yes — fork the repo and use the GitHub Actions workflow, or run the official Docker image.

Q: How do I update the CLI? Re-run your package manager's global install: pnpm install -g pake-cli (or npm). Pake also notifies you when a new version is available.

Q: Is there a configuration file, or only CLI flags? For day-to-day use, CLI flags are all you need. Deeper customization (editing the container's injected scripts and config) is covered in the Admin Guide.