mcpField
D
desktop-framework-tauri

desktop-framework-tauri

github.com/agents-inc开发2646 次安装2 天前更新
代码仓库

关于 desktop-framework-tauri

desktop-framework-tauri 面向使用 Tauri 2.x 开发桌面和移动应用的开发者,介绍 Rust 与前端命令桥接、能力权限、插件、平台功能和打包。

主要功能

  1. 01前端调用 Rust 命令
  2. 02能力与权限配置
  3. 03共享状态和后端事件
  4. 04插件安装与注册
  5. 05窗口、托盘和打包模式

适用场景

  1. 01构建 Tauri 桌面应用
  2. 02将前端调用桥接到 Rust 命令
  3. 03通过能力权限限制访问
  4. 04打包应用或添加窗口与托盘功能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agents-inc/skills --skill desktop-framework-tauri

安装后在 Claude Code 中输入/desktop-framework-tauri确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

metadata.yaml
reference.md
examples/
core.md
packaging.md
platform.md
plugins.md
security.md

详细介绍

Tauri 2.x 桌面和移动应用

快速指南: Tauri 2.x 使用系统 WebView(不捆绑 Chromium),并采用 Rust 后端。使用 #[tauri::command] 定义 Rust 命令,并在前端通过 @tauri-apps/api/core 中的 invoke() 调用。每项敏感操作都需要在 capability 文件中明确授予权限。插件采用双重安装模式:Cargo crate + npm package。Tauri 2 支持桌面平台(Windows、macOS、Linux)和移动平台(iOS、Android)。

当前版本: Tauri 2.x(稳定版,2024 年起)。Tauri 1.x 已过时,使用根本不同的安全模型(allowlist 与 capabilities)。


<critical_requirements>

重要:使用此技能前

所有代码都必须遵循项目在 CLAUDE.md 中的约定(kebab-case、命名导出、导入顺序、import type、命名常量)

(必须使用 Tauri 2.x 的 capability/permission 系统——v1 的 allowlist 已移除)

(必须在 tauri::generate_handler![] 中注册每个命令——未注册的命令在调用时会静默失败)

(必须将插件权限添加到 capability 文件——缺少权限的插件会引发运行时错误)

(为支持移动平台,必须在 pub fn run() 上使用 #[cfg_attr(mobile, tauri::mobile_entry_point)])

(必须使用 @tauri-apps/api/core 中的 invoke()——不要使用 v1 中已移除的 @tauri-apps/api/tauri 路径)

</critical_requirements>


自动检测: Tauri、tauri.conf.json、src-tauri、tauri::command、tauri::Builder、invoke、@tauri-apps/api、tauri-plugin、capabilities、#[tauri::command]、generate_handler、AppHandle、WebviewWindow、TrayIconBuilder

适用场景:

  • 使用系统 WebView + Rust 后端构建桌面应用
  • 定义 Rust 命令,并从前端 JavaScript/TypeScript 调用这些命令
  • 配置 capability/permission 安全模型
  • 使用官方 Tauri 插件(fs、dialog、http、notification、store、shell 等)
  • 系统托盘、窗口管理、菜单
  • 打包和分发桌面或移动应用
  • 从 Tauri v1 迁移到 v2

不适用场景:

  • 前端框架模式(组件架构、状态管理、路由——请使用相应的框架技能)
  • 与 Tauri API 无关的一般 Rust 编程
  • 构建工具配置(打包器、开发服务器——请使用单独的工具链技能)
  • 需要完整 Chromium 功能时(WebRTC、Chrome DevTools Protocol、Chrome 扩展——请评估替代方案)

涵盖的关键模式:

详细资源:


## 理念

Tauri 以安全为先、体积小巧且原生。它使用操作系统的系统 WebView,而不是捆绑 Chromium,因此生成的二进制文件比替代方案小 10–100 倍。Rust 后端提供内存安全和原生性能。权限系统强制实施最小权限原则——除非明确授予,否则一律不允许访问。

Tauri 与替代方案的对比——适合选择 Tauri 的情况:

  • 你希望二进制文件体积小(5–15 MB,而不是 150+ MB)
  • 你希望实现原生操作系统集成,而无需捆绑浏览器引擎
  • 你需要具有细粒度权限的强大安全模型
  • 你能够使用 Rust 编写后端逻辑
  • 你需要使用同一代码库支持移动平台(iOS/Android)

Tauri 可能不适合的情况:

  • 你需要确保各平台的渲染效果完全一致(Tauri 使用的操作系统 WebView 各不相同)
  • 你需要 Chrome 专属 API(WebRTC、Chrome 扩展、Pepper 插件)
  • 你的团队没有 Rust 经验,也无法投入时间学习
  • 你需要较旧 Windows WebView2 版本不支持的 WebView2 功能

核心模式

模式 1:Rust 命令 + 前端调用

使用 #[tauri::command] 在 Rust 中定义命令,使用 generate_handler![] 注册,再从前端调用。命令支持参数、返回值、异步操作和错误处理。

#[tauri::command]
fn greet(name: &str) -> String {
    format!("Hello, {}!", name)
}

// Register in main.rs or lib.rs
tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![greet])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
import { invoke } from "@tauri-apps/api/core";
const greeting = await invoke<string>("greet", { name: "World" });

**要点:**参数以单个对象的形式传递。Rust 参数名称必须与对象键名匹配。忘记在 generate_handler![] 中注册命令会导致调用静默失败。有关异步命令、错误处理和状态访问,请参阅 examples/core.md。


模式 2:权限/能力系统

每个 Tauri 2 应用都至少需要一个授予权限的能力文件。没有权限时,插件和核心 API 调用会在运行时失败。

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "shell:allow-open",
    "dialog:default",
    {
      "identifier": "fs:allow-write-text-file",
      "allow": [{ "path": "$APPDATA/*" }]
    }
  ]
}

**要点:**权限的作用范围限定为特定窗口。使用路径变量($APPDATA、$HOME 等)限制文件系统访问。v1 的 allowlist 已彻底移除。有关完整的权限模型,请参阅 examples/security.md。


模式 3:状态管理

使用 app.manage() 和 tauri::State<T> 在命令之间共享状态。对于可变状态,请使用 Mutex 或 RwLock 包装。

use std::sync::Mutex;

struct AppState {
    counter: Mutex<i32>,
}

#[tauri::command]
fn increment(state: tauri::State<AppState>) -> i32 {
    let mut counter = state.counter.lock().unwrap();
    *counter += 1;
    *counter
}

**要点:**声明为命令参数时,tauri::State<T> 会自动注入。该类型必须实现 Send + Sync。有关完整模式,请参阅 examples/core.md。


模式 4:事件系统

实现前端与后端之间的双向事件通信。前端使用 emit()/listen(),后端使用 app.emit()/app.listen()。

import { listen } from "@tauri-apps/api/event";

const unlisten = await listen<string>("download-progress", (event) => {
  console.log(`Progress: ${event.payload}`);
});
// Clean up when done
unlisten();
// Emit from backend to all windows
app.emit("download-progress", "50%").unwrap();

**要点:**务必调用取消监听函数,以防止内存泄漏。事件类型为字符串——请采用一致的命名约定。有关定向窗口事件和通道,请参阅 examples/core.md。


模式 5:插件安装模式

所有官方插件都遵循双重安装模式:Rust crate + npm 包。每个插件都需要在能力文件中配置权限。

# 1. Add Rust crate
cargo add tauri-plugin-store

# 2. Add JS bindings
npm add @tauri-apps/plugin-store

# 3. Register plugin in Rust
tauri::Builder::default()
    .plugin(tauri_plugin_store::Builder::new().build())

# 4. Add permission to capability file
# "store:allow-get", "store:allow-set"

**要点:**四个步骤(crate、npm、注册、权限)中缺少任何一个,都会导致运行时错误,而非编译错误。有关完整的插件列表,请参阅 examples/plugins.md。


模式 6:系统托盘

创建包含菜单和事件处理器的系统托盘图标。

use tauri::tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent};
use tauri::menu::{MenuBuilder, MenuItemBuilder};

tauri::Builder::default()
    .setup(|app| {
        let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?;
        let menu = MenuBuilder::new(app).items(&[&toggle]).build()?;
        TrayIconBuilder::new()
            .menu(&menu)
            .on_menu_event(move |_app, event| match event.id().as_ref() {
                "toggle" => println!("toggle clicked"),
                _ => (),
            })
            .on_tray_icon_event(|tray, event| {
                if let TrayIconEvent::Click {
                    button: MouseButton::Left,
                    button_state: MouseButtonState::Up, ..
                } = event {
                    let app = tray.app_handle();
                    if let Some(window) = app.get_webview_window("main") {
                        let _ = window.show();
                        let _ = window.set_focus();
                    }
                }
            })
            .build(app)?;
        Ok(())
    })

**要点:**在 Tauri 2 中,SystemTray 已由 TrayIconBuilder 取代。菜单事件和托盘图标事件分别处理。有关完整的托盘模式,请参阅 examples/platform.md。


<decision_framework>

决策框架

Tauri 2 应用架构
Where does this logic belong?
|-- Pure UI rendering, user interaction?
|   +-- Frontend (JavaScript/TypeScript in webview)
|-- File system, network, OS integration, heavy computation?
|   +-- Rust backend (Tauri commands)
|-- Sensitive operation (file write, shell exec, HTTP)?
|   +-- Rust command + explicit permission in capability file
+-- Shared state between commands?
    +-- app.manage() with Mutex/RwLock wrapper
命令设计
How to structure the command?
|-- Returns data synchronously?
|   +-- Regular #[tauri::command] fn
|-- Needs I/O, network, or long computation?
|   +-- async #[tauri::command] with Result<T, E>
|-- Needs to access managed state?
|   +-- Add tauri::State<T> parameter
|-- Needs app handle (emit events, manage windows)?
|   +-- Add app: tauri::AppHandle parameter
+-- Needs to stream data to frontend?
    +-- Use tauri::ipc::Channel<T> parameter
插件选择
Need OS integration?
|-- File system access?
|   +-- tauri-plugin-fs
|-- File/folder picker dialog?
|   +-- tauri-plugin-dialog
|-- HTTP requests from backend?
|   +-- tauri-plugin-http
|-- Persistent key-value storage?
|   +-- tauri-plugin-store
|-- System notifications?
|   +-- tauri-plugin-notification
|-- Run external processes?
|   +-- tauri-plugin-shell
|-- Auto-update?
|   +-- tauri-plugin-updater
|-- Clipboard?
|   +-- tauri-plugin-clipboard-manager
|-- Deep links (custom URL scheme)?
|   +-- tauri-plugin-deep-link
+-- Launch on system startup?
    +-- tauri-plugin-autostart

CLI 命令和配置参考请参阅 reference.md。

</decision_framework>


<red_flags>

危险信号

高优先级问题:

  • 使用 @tauri-apps/api/tauri 导入路径(已在 v2 中移除——请使用 @tauri-apps/api/core)
  • 在 tauri.conf.json 中使用 v1 的 allowlist(已在 v2 中由 capability 文件取代)
  • 忘记在 generate_handler![] 中注册命令(会静默失败,且不会出现编译错误)
  • capability 文件缺少插件权限(会产生运行时错误,而非编译错误)
  • 使用 SystemTray API(已在 v2 中移除——请使用 tauri::tray 中的 TrayIconBuilder)
  • 使用 tauri::api::*(已在 v2 中移除——相关功能已移至插件)
  • 调用 invoke() 时未使用 await(它返回的是 Promise,而非值)
  • run() 缺少 #[cfg_attr(mobile, tauri::mobile_entry_point)](会导致移动端构建失败)

中优先级问题:

  • 未清理事件监听器(调用 listen() 后未调用 unlisten 会导致内存泄漏)
  • 在命令中使用 unwrap(),而非返回 Result(会使命令崩溃,且不会向前端返回错误)
  • 授予权限范围过宽(例如使用 fs:allow-read-file,却未限定路径范围)
  • 将路径硬编码,而非使用 Tauri 路径变量($APPDATA、$HOME、$RESOURCE)
  • 未使用 Mutex/RwLock 管理可变状态(会造成数据竞争)

常见错误:

  • Rust 参数名称与 JS invoke 对象键之间的命令参数名称不匹配
  • 安装插件时忘记安装 npm 包(只添加了 Cargo crate)
  • 未在配置中设置 app.withGlobalTauri: true,却使用 window.__TAURI__
  • 认为各平台的 webview 渲染效果完全相同(Windows WebView2、macOS WebKit 和 Linux WebKitGTK 各不相同)
  • 未处理异步命令中的 Result 错误变体(会导致前端出现未处理的 Promise 拒绝)

注意事项与边缘情况:

  • Capability 范围:权限按窗口设置——次要窗口需要自己的 capability,或必须列在 windows 中
  • 路径变量:$APPDATA、$RESOURCE、$HOME 等是 Tauri 专用变量,不是环境变量
  • 移动端差异:某些插件仅适用于桌面端(shell、autostart、global-shortcut),请查阅插件文档
  • Windows 上的 WebView2:需要 WebView2 运行时(安装程序默认会打包,但较旧的 Windows 10 不一定具备)
  • 序列化:命令参数和返回值必须实现 serde::Serialize/Deserialize——复杂类型需要派生宏
  • 开发服务器:tauri dev 会代理前端开发服务器——请在 tauri.conf.json 中配置 devUrl,而非在前端构建工具中配置
  • 构建大小:Tauri 二进制文件为 5-15 MB,但 Rust 编译较慢——干净构建预计需要 2-5 分钟

</red_flags>


<critical_reminders>

重要提醒

所有代码必须遵循项目在 CLAUDE.md 中的约定(kebab-case、命名导出、导入顺序、import type、命名常量)

(必须使用 Tauri 2.x 的 capability/permission 系统——v1 的 allowlist 已被移除)

(必须在 tauri::generate_handler![] 中注册每个命令——未注册的命令在调用时会静默失败)

(必须将插件权限添加到 capability 文件中——缺少权限的插件会产生运行时错误)

(为支持移动端,必须在 pub fn run() 上添加 #[cfg_attr(mobile, tauri::mobile_entry_point)])

(必须使用 @tauri-apps/api/core 调用 invoke()——不可使用 v1 中已移除的 @tauri-apps/api/tauri 路径)

违反这些规则会导致命令静默失败、运行时权限错误或移动端构建失败。

</critical_reminders>

评论

支持 Markdown