# Tauri 2.0 Agent Prompts — Part 2: Advanced Prompts, Checklist & Migration Map > **Purpose**: Copy-paste ready prompts for instructing AI agents to build Tauri 2.0 applications. > **Constraint**: These prompts are designed for sandbox environments where code compilation is NOT available. Agents must verify correctness using logic, API references, and pattern matching. --- ## Table of Contents 8. [Prompt: Build a WebSocket Server in Rust](#8-prompt-build-a-websocket-server-in-rust) 9. [Prompt: Implement Script Injection](#9-prompt-implement-script-injection) 10. [Prompt: Set Up Capabilities & Permissions](#10-prompt-set-up-capabilities--permissions) 11. [Prompt: Migrate a v1 App to v2](#11-prompt-migrate-a-v1-app-to-v2) 12. [Prompt: Full App Build (End-to-End)](#12-prompt-full-app-build-end-to-end) 13. [Verification Checklist for Agents](#13-verification-checklist-for-agents) 14. [Quick Reference: v1 vs v2 API Map](#14-quick-reference-v1-vs-v2-api-map) 15. [Prompt: Debug a Tauri 2.0 Build/Compile Error](#15-prompt-debug-a-tauri-20-buildcompile-error) **See also**: [Part 1: System Prompt & Common Task Prompts](./01-system-prompt-and-common-prompts.md) --- ## 8. Prompt: Build a WebSocket Server in Rust ``` Build a native WebSocket server that runs inside a Tauri 2.0 application using the Tokio async runtime. Requirements: Dependencies (Cargo.toml): - `tokio = { version = "1", features = ["net", "rt", "sync", "macros"] }` - `tokio-tungstenite = "0.24"` - `futures-util = "0.3"` Server implementation (`src-tauri/src/server.rs`): - Bind a TcpListener to `127.0.0.1:[PORT]` - Use `tokio::sync::broadcast` channel for message fan-out to all connected clients - Accept WebSocket connections using `tokio_tungstenite::accept_async` - Use `tokio::select!` to handle both incoming messages from clients AND broadcast messages from other clients - Handle disconnections gracefully - Spawn the server in `src-tauri/src/lib.rs` using `tauri::async_runtime::spawn(server::start_websocket_server())` inside the `.setup()` closure Frontend client: - Connect using standard `new WebSocket('ws://127.0.0.1:[PORT]')` - Show send and receive handlers Key pattern: Each client connection gets its own broadcast receiver via `tx.subscribe()`, enabling fan-out to all connected clients. ``` --- ## 9. Prompt: Implement Script Injection ``` Implement JavaScript injection into a Tauri 2.0 WebviewWindow. Requirements: 1. Create a JavaScript file (e.g., `src-tauri/inject.js`) that will be injected into webview windows 2. The injected script should: - Connect to a local WebSocket server (ws://127.0.0.1:[PORT]) - Send data from the webview page (e.g., localStorage contents) back to the server - Receive data from the server and process it - Expose the socket connection on `window.localAppSocket` for the page's own code to use 3. Use `include_str!("../inject.js")` to load the script at compile time 4. Inject it using `WebviewWindowBuilder::initialization_script(script_content)` 5. Show a complete working example of creating a window with an external URL and injecting the script IMPORTANT: Set `"csp": null` in the app security config if injecting scripts into external URLs, otherwise CSP may block the injection. Show both the Rust window creation code with injection and the JavaScript injection script. ``` --- ## 10. Prompt: Set Up Capabilities & Permissions ``` Set up the Tauri 2.0 Capabilities and Permissions system for an application. The application needs access to: - [LIST REQUIRED FEATURES: file system, dialogs, HTTP requests, clipboard, notifications, etc.] Requirements: 1. Create `src-tauri/capabilities/default.json` with proper v2 structure 2. Include the `$schema` pointing to `../gen/schemas/desktop-schema.json` 3. Set the `identifier`, `description`, `windows` (list of window labels), and `platforms` fields 4. Add the correct permission identifiers for each required feature: - File system: `fs:default` or specific `fs:allow-*` - Dialogs: `dialog:default` or specific `dialog:allow-*` - HTTP: `http:default` or specific `http:allow-*` - Events: `core:event:default` - Window management: `core:window:default` 5. If fine-grained scopes are needed (e.g., restricting file access to specific directories), show scoped permissions with `allow` and `deny` arrays using path variables like `$APPDATA`, `$HOME`, `$RESOURCE` CRITICAL: Do NOT use the v1 `allowlist` in `tauri.conf.json`. In v2, all permissions are defined via capability files. ``` --- ## 11. Prompt: Migrate a v1 App to v2 ``` Migrate the following Tauri v1 code to Tauri 2.0. [PASTE v1 CODE HERE] Migration checklist — verify ALL of these changes: Config (tauri.conf.json): - [ ] `tauri` section renamed to `app` - [ ] `build.distDir` renamed to `build.frontendDist` - [ ] `build.devPath` renamed to `build.devUrl` - [ ] `build.withGlobalTauri` moved to `app.withGlobalTauri` - [ ] `tauri.allowlist` REMOVED → replaced by capabilities - [ ] `tauri.bundle` promoted to top-level `bundle` - [ ] `bundle.identifier` promoted to top-level `identifier` - [ ] `tauri.updater` moved to `plugins.updater` Project structure: - [ ] `main.rs` logic moved to `lib.rs` with `pub fn run()` - [ ] New minimal `main.rs` calling `lib::run()` - [ ] `Cargo.toml` has `[lib]` section with `crate-type = ["staticlib", "cdylib", "rlib"]` - [ ] `#[cfg_attr(mobile, tauri::mobile_entry_point)]` added to `run()` Rust code: - [ ] All `tauri::api::*` imports REMOVED (replaced by plugins) - [ ] `tauri::Window` → `tauri::WebviewWindow` - [ ] `tauri::WindowBuilder` → `tauri::WebviewWindowBuilder` - [ ] `tauri::WindowUrl` → `tauri::WebviewUrl` - [ ] `get_window()` → `get_webview_window()` - [ ] `tauri::Emitter` trait imported for `emit()` / `emit_to()` - [ ] `tauri::Listener` trait imported for `listen()` / `once()` - [ ] All plugins registered with `.plugin()` in Builder - [ ] `tauri` and `tauri-build` version set to "2" JavaScript code: - [ ] `@tauri-apps/api/tauri` → `@tauri-apps/api/core` - [ ] `@tauri-apps/api/window` → `@tauri-apps/api/webviewWindow` - [ ] All plugin imports → `@tauri-apps/plugin-` - [ ] `@tauri-apps/cli` version set to "^2" Capabilities: - [ ] Created `src-tauri/capabilities/default.json` - [ ] All necessary permissions listed - [ ] `core:default` included at minimum Output the complete migrated code for every file that changed. ``` --- ## 12. Prompt: Full App Build (End-to-End) ``` Build a complete Tauri 2.0 application with the following requirements: App Name: [APP_NAME] Purpose: [DESCRIBE APP PURPOSE] Features needed: - [FEATURE 1: e.g., File system read/write] - [FEATURE 2: e.g., HTTP API client] - [FEATURE 3: e.g., Persistent settings storage] - [FEATURE 4: e.g., System tray icon] - [FEATURE 5: e.g., Multi-window support] - [FEATURE 6: e.g., Custom Rust commands] Frontend: [Vanilla JS / React / Vue / Svelte / etc.] Generate ALL files for a complete, working Tauri 2.0 application: 1. `package.json` 2. `src/index.html` (or appropriate entry point for the chosen framework) 3. Frontend source files (JavaScript/TypeScript/CSS) 4. `src-tauri/tauri.conf.json` — v2 structure with all necessary config 5. `src-tauri/Cargo.toml` — all dependencies including required plugins 6. `src-tauri/build.rs` 7. `src-tauri/capabilities/default.json` — all required permissions 8. `src-tauri/src/main.rs` — minimal entry-point 9. `src-tauri/src/lib.rs` — Builder with all plugins, commands, setup 10. Additional Rust module files as needed 11. Any injected scripts if required For every file: - Use ONLY valid Tauri 2.0 code - Use the correct v2 import paths - Use v2 type names (WebviewWindow, WebviewUrl, etc.) - Include proper error handling - Add appropriate comments explaining the v2 patterns used Do NOT skip any file. Generate complete, production-ready code. ``` --- ## 13. Verification Checklist for Agents > Agents should run through this checklist mentally for EVERY code snippet they generate. ### Config Verification - [ ] `tauri.conf.json` uses `app` section (not `tauri`) - [ ] `build.frontendDist` (not `build.distDir`) - [ ] `build.devUrl` (not `build.devPath`) - [ ] `withGlobalTauri` is under `app` (not `build`) - [ ] `identifier` is at top level (not under `bundle`) - [ ] `bundle` is at top level (not under `tauri`) - [ ] No `allowlist` present anywhere ### Rust Code Verification - [ ] `tauri` version is `"2"` (not `"1"`) - [ ] `tauri-build` version is `"2"` (not `"1"`) - [ ] `Cargo.toml` has `[lib]` with `crate-type = ["staticlib", "cdylib", "rlib"]` - [ ] `main.rs` only contains `#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]` and `fn main() { lib_name::run() }` - [ ] `lib.rs` has `#[cfg_attr(mobile, tauri::mobile_entry_point)]` on `pub fn run()` - [ ] No `tauri::api::*` imports anywhere - [ ] `WebviewWindow` used (not `Window`) - [ ] `WebviewWindowBuilder` used (not `WindowBuilder`) - [ ] `WebviewUrl` used (not `WindowUrl`) - [ ] `get_webview_window()` used (not `get_window()`) - [ ] `Emitter` trait imported when using `emit()` or `emit_to()` - [ ] `Listener` trait imported when using `listen()` or `once()` - [ ] `invoke_handler` called only ONCE with ALL commands - [ ] Async commands use owned types or Result wrapping (not bare `&str`) - [ ] Window creation in async contexts uses `run_on_main_thread()` - [ ] All plugins registered with `.plugin()` before `.run()` ### Frontend Code Verification - [ ] `invoke` imported from `@tauri-apps/api/core` (not `@tauri-apps/api/tauri`) - [ ] `WebviewWindow` imported from `@tauri-apps/api/webviewWindow` (not `@tauri-apps/api/window`) - [ ] Event functions from `@tauri-apps/api/event` (not core or tauri) - [ ] Plugin imports from `@tauri-apps/plugin-` (not `@tauri-apps/api/`) - [ ] `@tauri-apps/cli` is version `^2` - [ ] Event listeners cleaned up with `unlisten()` - [ ] Argument names in `invoke()` calls match Rust command parameter names (camelCase by default) ### Capabilities Verification - [ ] Capability files exist in `src-tauri/capabilities/` - [ ] `$schema` points to correct schema path - [ ] All used plugins have corresponding permissions - [ ] Window labels in capabilities match actual window labels - [ ] No `allowlist` in config files ### Plugin Verification - [ ] Rust crate: `tauri-plugin- = "2"` in Cargo.toml - [ ] Registration: `.plugin(tauri_plugin_::init())` in Builder - [ ] JS package: `@tauri-apps/plugin-` in dependencies - [ ] Permissions: Listed in capabilities file --- ## 14. Quick Reference: v1 vs v2 API Map > Keep this table handy when migrating or reviewing code. ### Rust Type Renames | v1 | v2 | |----|----| | `tauri::Window` | `tauri::WebviewWindow` | | `tauri::WindowBuilder` | `tauri::WebviewWindowBuilder` | | `tauri::WindowUrl` | `tauri::WebviewUrl` | | `Manager::get_window()` | `Manager::get_webview_window()` | | `tauri::WindowEvent` | `tauri::WebviewWindowEvent` | | `tauri::Manager::fs_scope()` | `tauri_plugin_fs::FsExt` | ### Rust API Removals (replaced by plugins) | v1 | v2 Plugin | |----|-----------| | `tauri::api::dialog` | `tauri-plugin-dialog` | | `tauri::api::fs` | `std::fs` / `tauri-plugin-fs` | | `tauri::api::http` | `tauri-plugin-http` | | `tauri::api::path` | `tauri::Manager::path()` | | `tauri::api::process::Command` | `tauri-plugin-shell` | | `tauri::api::clipboard` | `tauri-plugin-clipboard-manager` | | `tauri::api::notification` | `tauri-plugin-notification` | | `tauri::api::global_shortcut` | `tauri-plugin-global-shortcut` | | `tauri::api::updater` | `tauri-plugin-updater` | | `tauri::api::cli` | `tauri-plugin-cli` | | `tauri::api::os` | `tauri-plugin-os` | | `tauri::api::version` | `semver` crate | ### JavaScript Import Path Changes | v1 | v2 | |----|----| | `@tauri-apps/api/tauri` | `@tauri-apps/api/core` | | `@tauri-apps/api/window` | `@tauri-apps/api/webviewWindow` | | `@tauri-apps/api/dialog` | `@tauri-apps/plugin-dialog` | | `@tauri-apps/api/fs` | `@tauri-apps/plugin-fs` | | `@tauri-apps/api/http` | `@tauri-apps/plugin-http` | | `@tauri-apps/api/notification` | `@tauri-apps/plugin-notification` | | `@tauri-apps/api/clipboard` | `@tauri-apps/plugin-clipboard-manager` | | `@tauri-apps/api/shell` | `@tauri-apps/plugin-shell` | | `@tauri-apps/api/global-shortcut` | `@tauri-apps/plugin-global-shortcut` | | `@tauri-apps/api/updater` | `@tauri-apps/plugin-updater` | | `@tauri-apps/api/os` | `@tauri-apps/plugin-os` | | `@tauri-apps/api/process` | `@tauri-apps/plugin-process` | | `@tauri-apps/api/cli` | `@tauri-apps/plugin-cli` | ### Config Path Changes | v1 | v2 | |----|----| | `build.distDir` | `build.frontendDist` | | `build.devPath` | `build.devUrl` | | `build.withGlobalTauri` | `app.withGlobalTauri` | | `tauri.*` | `app.*` | | `tauri.allowlist.*` | Capabilities system | | `tauri.windows.fileDropEnabled` | `app.windows.dragDropEnabled` | | `tauri.bundle` | `bundle` (top-level) | | `bundle.identifier` | `identifier` (top-level) | | `tauri.updater` | `plugins.updater` | | `tauri.systemTray` | `app.trayIcon` | | `tauri.cli` | `plugins.cli` | --- ## 15. Prompt: Debug a Tauri 2.0 Build/Compile Error ``` Diagnose the following Tauri 2.0 build or compile error. [PASTE FULL ERROR OUTPUT HERE] Follow this structured diagnosis process: 1. READ THE ERROR MESSAGE CAREFULLY - Identify the exact error code (e.g., E0432, E0599, E0757, E0277, E0255) - Note which file and line number the error originates from - Capture any "note" or "help" lines the compiler provides 2. CROSS-REFERENCE AGAINST ERROR CATEGORIES Consult the `error-resolution-guide.md` categories and match the error: - Category A (Rust Compilation Errors): Version mismatches, missing [lib], windres, strip failures - Category B (v1→v2 Migration): tauri::api removals, Window→WebviewWindow, JS import paths - Category C (Async & Thread Safety): Borrowed refs in async, Mutex not Send, Rc/RefCell in async - Category D (Config Errors): V1 config keys, allowlist, tauri→app section, devUrl/frontendDist - Category E (Capabilities & Permissions): Plugin not allowed, event permissions, path scope - Category F (Plugin Integration): Plugin not registered in Builder, wrong plugin API usage - Category G (IPC / Command Errors): Command not found, multiple invoke_handler, pub in lib.rs - Category H (Webview & Window): WebView2 errors, blank screens, GDK main thread - Category I (Event System): Events not received, emit vs emit_to confusion - Category J (CSP Errors): IPC connection refused, inline styles blocked - Category K (Frontend Integration): Vite port mismatch, Next.js static export, SvelteKit adapter - Category L (WebSocket): Broken pipe, unstable connections - Category M (Path & Asset): 403 on asset:// protocol - Category O (Mobile Build): iOS/Android specific failures 3. CHECK FOR COMMON PATTERNS - [ ] v1 imports still present (tauri::api::*, @tauri-apps/api/tauri, @tauri-apps/api/window) - [ ] Missing `pub` on commands in separate modules (or extra `pub` on commands in lib.rs) - [ ] tauri/tauri-build version mismatch (one is "1" and the other is "2") - [ ] Async command uses borrowed references (&str, &Path) without Result wrapping - [ ] std::sync::Mutex held across .await (should be tokio::sync::Mutex) - [ ] Plugin in Cargo.toml but not registered with .plugin() in Builder - [ ] Missing capability permission for the plugin/command being used - [ ] Multiple .invoke_handler() calls (only last one takes effect) - [ ] tokio::spawn used instead of tauri::async_runtime::spawn inside setup() - [ ] Window creation in async context without run_on_main_thread() 4. OUTPUT STRUCTURED DIAGNOSIS Format your response exactly as: ## Error Diagnosis **Error Category:** [Category letter + name from error-resolution-guide.md] **Error Code:** [Rust error code if applicable, e.g., E0432] **Root Cause:** [1-3 sentence explanation of WHY this error occurs] **Fix Steps:** 1. [Specific file to edit] - [Exact change to make, with before/after code if applicable] 2. [Additional files if needed] - [Changes] **Verification:** [How to confirm the fix works — what should the output look like after] **Cross-Reference:** [Relevant section in error-resolution-guide.md] If the error doesn't match any known category, say so explicitly and provide your best analysis based on the error message, Rust compiler output, and Tauri 2.0 API knowledge. ``` --- **Back to**: [Part 1: System Prompt & Common Task Prompts](./01-system-prompt-and-common-prompts.md)