关于 desktop-framework-tauri
desktop-framework-tauri 面向使用 Tauri 2.x 开发桌面和移动应用的开发者,介绍 Rust 与前端命令桥接、能力权限、插件、平台功能和打包。
主要功能
- 01前端调用 Rust 命令
- 02能力与权限配置
- 03共享状态和后端事件
- 04插件安装与注册
- 05窗口、托盘和打包模式
适用场景
- 01构建 Tauri 桌面应用
- 02将前端调用桥接到 Rust 命令
- 03通过能力权限限制访问
- 04打包应用或添加窗口与托盘功能
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ agents-inc/ skills --skill desktop-framework-tauri安装后在 Claude Code 中输入/desktop-framework-tauri确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
metadata.yamlreference.mdexamples/core.mdpackaging.mdplatform.mdplugins.mdsecurity.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 扩展——请评估替代方案)
涵盖的关键模式:
- Rust 命令 + 前端 invoke 桥接(examples/core.md)
- 通过
app.manage()+tauri::State<T>管理状态(examples/core.md) - 事件系统:在前端和后端之间发送/监听事件(examples/core.md)
- 权限/capability 系统(examples/security.md)
- 官方插件的安装和使用(examples/plugins.md)
- 窗口管理、系统托盘、菜单(examples/platform.md)
- 打包和分发(examples/packaging.md)
详细资源:
- examples/core.md - 命令、invoke、状态、事件、异步命令、错误处理
- examples/security.md - Capabilities、权限、作用域、CSP、自定义权限
- examples/plugins.md - 官方插件注册表、安装模式、常用插件
- examples/platform.md - Windows、系统托盘、菜单、多窗口、WebView 管理
- examples/packaging.md - 构建配置、平台目标、更新程序、CI/CD
- reference.md - CLI 命令、配置参考、路径变量、迁移检查清单
## 理念
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 文件缺少插件权限(会产生运行时错误,而非编译错误)
- 使用
SystemTrayAPI(已在 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>