一键导入
tauri-plugins
Tauri 插件开发与集成技能,指导如何使用官方插件和开发自定义插件。 触发场景: - 需要集成 Tauri 官方插件 - 需要开发自定义 Tauri 插件 - 需要理解插件的安装和配置流程 - 需要排查插件不可用的问题 触发词:插件、plugin、tauri-plugin、集成、扩展、第三方
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Tauri 插件开发与集成技能,指导如何使用官方插件和开发自定义插件。 触发场景: - 需要集成 Tauri 官方插件 - 需要开发自定义 Tauri 插件 - 需要理解插件的安装和配置流程 - 需要排查插件不可用的问题 触发词:插件、plugin、tauri-plugin、集成、扩展、第三方
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | tauri-plugins |
| description | Tauri 插件开发与集成技能,指导如何使用官方插件和开发自定义插件。 触发场景: - 需要集成 Tauri 官方插件 - 需要开发自定义 Tauri 插件 - 需要理解插件的安装和配置流程 - 需要排查插件不可用的问题 触发词:插件、plugin、tauri-plugin、集成、扩展、第三方 |
[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-opener = "2"
tauri-plugin-store = "2"
tauri-plugin-log = "2"
tauri-plugin-updater = "2"
tauri-plugin-process = "2"
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_store::Builder::new().build())
.plugin(tauri_plugin_log::Builder::new().build())
.plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_process::init())
.invoke_handler(tauri::generate_handler![...])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
{
"permissions": [
"core:default",
"opener:default",
"store:default",
"log:default",
"updater:default",
"process:default"
]
}
| 插件 | Cargo 依赖 | npm 包 | 用途 | 当前状态 |
|---|---|---|---|---|
| opener | tauri-plugin-opener | @tauri-apps/plugin-opener | 打开 URL/文件 | ✅ 已安装 |
| store | tauri-plugin-store | @tauri-apps/plugin-store | 键值存储 | ✅ 已安装 |
| log | tauri-plugin-log | @tauri-apps/plugin-log | 日志系统 | ✅ 已安装 |
| updater | tauri-plugin-updater | @tauri-apps/plugin-updater | 应用自动更新 | ✅ 已安装 |
| process | tauri-plugin-process | @tauri-apps/plugin-process | 进程管理(退出/重启) | ✅ 已安装 |
| shell | tauri-plugin-shell | @tauri-apps/plugin-shell | 执行系统命令 | 📦 推荐 |
| os | tauri-plugin-os | @tauri-apps/plugin-os | 操作系统信息(平台/架构/版本) | 📦 推荐 |
| dialog | tauri-plugin-dialog | @tauri-apps/plugin-dialog | 文件选择/消息对话框 | 📦 推荐 |
| notification | tauri-plugin-notification | @tauri-apps/plugin-notification | 系统通知 | 📦 推荐 |
| fs | tauri-plugin-fs | @tauri-apps/plugin-fs | 文件系统操作 | 📦 按需安装 |
| clipboard | tauri-plugin-clipboard-manager | @tauri-apps/plugin-clipboard-manager | 剪贴板 | 📦 按需安装 |
| pty | tauri-plugin-pty | @anthropic-ai/tauri-plugin-pty | 伪终端(终端模拟器) | 📦 按需安装 |
| 插件 | 用途 | 数据库支持 | 当前状态 |
|---|---|---|---|
| store | 键值存储 | JSON 文件持久化 | ✅ 已安装 |
| sql | SQL 数据库 | SQLite / MySQL / PostgreSQL | ⭕ 未安装(使用 rusqlite) |
注意: 本项目使用 rusqlite 直接操作 SQLite,而非 tauri-plugin-sql。
| 插件 | 用途 | 当前状态 |
|---|---|---|
| process | 进程管理(退出/重启) | ✅ 已安装 |
| updater | 应用自动更新 | ✅ 已安装 |
| shell | 执行系统命令、打开终端 | 📦 推荐 |
| os | 获取平台、架构、版本等系统信息 | 📦 推荐 |
| notification | 系统原生通知 | 📦 推荐 |
| dialog | 文件选择、消息确认对话框 | 📦 推荐 |
| global-shortcut | 全局快捷键 | 📦 按需安装 |
| http | HTTP 请求(前端发起) | 📦 按需安装(可用 reqwest 代替) |
| websocket | WebSocket 连接 | 📦 按需安装 |
| 初始化方式 | 适用插件 | 示例 |
|---|---|---|
::init() | 大多数插件 | tauri_plugin_opener::init() |
Builder::new().build() | 需要配置的插件 | tauri_plugin_store::Builder::new().build() |
Builder::new().xxx().build() | 需要链式配置 | tauri_plugin_log::Builder::new().level(...).build() |
Builder::new().build() | updater | tauri_plugin_updater::Builder::new().build() |
# src-tauri/Cargo.toml
[dependencies]
tauri-plugin-fs = "2"
pnpm add @tauri-apps/plugin-fs
// src-tauri/src/lib.rs
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_store::Builder::new().build())
.plugin(tauri_plugin_log::Builder::new().build())
.plugin(tauri_plugin_fs::init()) // 新增
.invoke_handler(tauri::generate_handler![...])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
// src-tauri/capabilities/default.json
{
"permissions": [
"core:default",
"opener:default",
"store:default",
"log:default",
"fs:default", // 新增
"fs:allow-read-text-file" // 新增(细粒度权限)
]
}
插件功能应遵循项目的三层架构(Database/Service/Command),避免在 Command 层直接堆砌业务逻辑。
适用于大多数插件(shell、os、dialog、notification 等),插件提供的能力作为业务逻辑的一部分。
// ── Service 层封装插件逻辑 ──
// src-tauri/src/services/system.rs
use crate::error::AppError;
/// 获取系统信息(封装 os 插件或 std 能力)
pub fn get_system_info() -> Result<SystemInfo, AppError> {
Ok(SystemInfo {
platform: std::env::consts::OS.to_string(),
arch: std::env::consts::ARCH.to_string(),
})
}
// ── Command 层暴露给前端 ──
// src-tauri/src/commands/system.rs
#[tauri::command]
pub fn get_system_info() -> Result<SystemInfo, String> {
crate::services::system::get_system_info()
.map_err(|e| e.to_string())
}
某些插件 API 需要 AppHandle(如 notification、dialog、updater),通过 Command 参数注入。
// ── Command 层(注入 AppHandle)──
#[tauri::command]
pub async fn check_update(app: tauri::AppHandle) -> Result<bool, String> {
crate::services::update::check_for_update(&app)
.await
.map_err(|e| e.to_string())
}
// ── Service 层(接收 AppHandle 引用)──
// src-tauri/src/services/update.rs
pub async fn check_for_update(app: &tauri::AppHandle) -> Result<bool, AppError> {
let update = app.updater_builder().build()
.map_err(|e| AppError::Custom(e.to_string()))?
.check()
.await
.map_err(|e| AppError::Custom(e.to_string()))?;
Ok(update.is_some())
}
某些插件支持前端直接调用,无需经过 Rust Command(适用于简单场景)。
// 前端直接使用 store 插件
import { Store } from "@tauri-apps/plugin-store";
const store = new Store("settings.json");
await store.set("theme", "dark");
// 前端直接使用 opener 插件
import { open } from "@tauri-apps/plugin-opener";
await open("https://example.com");
// 前端直接使用 process 插件
import { exit, relaunch } from "@tauri-apps/plugin-process";
await relaunch();
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 简单读写配置 | 前端 JS API(store) | 无需业务逻辑 |
| 打开 URL/文件 | 前端 JS API(opener) | 简单操作 |
| 涉及数据库的操作 | Rust Command(三层架构) | 需要事务/校验 |
| 需要系统权限的操作 | Rust Command(三层架构) | 安全控制 |
| 复杂业务流程 | Rust Command(三层架构) | 业务逻辑属于后端 |
| 需要组合多个插件 | Rust Command(三层架构) | 统一编排 |
use tauri::plugin::{Builder, TauriPlugin};
use tauri::Runtime;
// 定义插件命令
#[tauri::command]
fn my_plugin_command() -> String {
"Hello from plugin!".into()
}
// 构建插件
pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::new("my-plugin")
.invoke_handler(tauri::generate_handler![my_plugin_command])
.build()
}
// src-tauri/src/lib.rs
mod my_plugin;
pub fn run() {
tauri::Builder::default()
.plugin(my_plugin::init())
.invoke_handler(tauri::generate_handler![...])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
// 自定义插件的命令通过 invoke 调用
const result = await invoke("plugin:my-plugin|my_plugin_command");
本项目采用双数据存储方案:
| 存储方式 | 用途 | 数据类型 | 实现方式 |
|---|---|---|---|
| tauri-plugin-store | 应用配置 | 键值对 | JSON 文件 |
| rusqlite | 业务数据 | 结构化数据 | SQLite 数据库 |
// 前端直接使用
import { Store } from "@tauri-apps/plugin-store";
const store = new Store("settings.json");
await store.set("theme", "dark");
const theme = await store.get<string>("theme");
// 在三层架构中使用
// database/user.rs
use rusqlite::{Connection, Result};
use crate::models::User;
pub fn get_user(conn: &Connection, id: i64) -> Result<User, rusqlite::Error> {
conn.query_row(
"SELECT id, name FROM users WHERE id = ?1",
[id],
|row| Ok(User {
id: row.get(0)?,
name: row.get(1)?,
})
)
}
// services/user.rs
use crate::database;
use crate::error::AppError;
pub fn fetch_user(id: i64) -> Result<User, AppError> {
let conn = get_connection()?;
Ok(database::user::get_user(&conn, id)?)
}
// commands/user.rs
#[tauri::command]
pub fn get_user(id: i64) -> Result<User, String> {
crate::services::user::fetch_user(id)
.map_err(|e| e.to_string())
}
| 症状 | 可能原因 | 解决方法 |
|---|---|---|
| "Command not found" | 插件未注册 | 检查 lib.rs 中的 .plugin() |
| "Permission denied" | Capabilities 未声明 | 添加权限到 capabilities/default.json |
| 编译错误 | 版本不兼容 | Cargo.toml + package.json 版本对齐(都用 2.x) |
| 运行时无效 | 缺少 JS 绑定 | 检查是否安装对应的 npm 包 |
| 数据库错误 | rusqlite 配置问题 | 检查 features = ["bundled"] |
| 插件 init 方式错误 | 用了 init() 但插件需要 Builder | 参考"插件初始化方式速查"表 |
| 错误做法 | 正确做法 |
|---|---|
| 只装 Cargo 不装 npm | Rust 和 npm 包都要安装 |
| 注册插件但不声明权限 | 每个插件都要配 Capabilities |
| 不看插件文档直接用 | 先查看插件 README 了解 API |
| Tauri v1 API 用于 v2 | v1 和 v2 API 不同,检查版本 |
| 混用 tauri-plugin-sql 和 rusqlite | 选择一种数据库方案,本项目用 rusqlite |
| 在 Command 层直接使用插件 | 通过三层架构(Database → Service → Command)组织代码 |
| 所有操作都走 Rust Command | 简单插件操作可前端直接用 JS API |
| 不区分 init() 和 Builder 模式 | 查看插件文档确认正确的初始化方式 |
Git 工作流与版本管理技能,规范分支策略、提交信息和发布流程。 触发场景: - 用户需要创建分支或合并代码 - 用户需要规范提交信息格式 - 用户需要管理版本发布流程 触发词:Git、分支、提交、合并、版本发布
发布 Tauri 桌面应用新版本,处理版本号同步、Git tag、GitHub Actions 构建、Release 仓库产物同步、Cloudflare R2 上传、update.json 生成、自动更新发布和文档站重建。 触发场景: - 需要发布新版本或 release - 需要打 tag、推送发布分支或触发 CI 构建 - 需要生成或更新 update.json - 需要处理 Tauri updater 签名产物 - 需要同步 R2 CDN、GitHub/Gitee release 仓库或发布安装包 触发词:发布、release、版本发布、推送、打Tag、update.json、签名构建、安装包、自动更新、R2、CDN
Git 工作流与版本管理技能,规范分支策略、提交信息和发布流程。 触发场景: - 用户需要创建分支或合并代码 - 用户需要规范提交信息格式 - 用户需要管理版本发布流程 触发词:Git、分支、提交、合并、版本发布
自主连续开发方法论(Codex 版)。把一个项目按「每轮一个最小可提交单元」的方式推进到完成: 每轮读真相源 → 选下一个未做项 → 做一个最小单元 → 过验证门 → 记录勾选 → 最小提交 → 报进度。 适用于"按需求/台账建功能、还原原型、修一批 bug、补测试、重构、迁移、清理"等需要反复同构推进的任务。 与 Claude Code 的关系:Claude Code 有内置 `/loop` 自动续期(`/loop /dev-loop`),Codex 没有—— 所以 Codex 端由你(或脚本 / cron)反复触发"继续下一轮",方法论本身一致。 触发场景: - 想让 Codex 把某个项目/某个意图"一轮轮推进到完成" - 还原原型图、修一批 warning、补单测、重构模块等同构重复任务 - 需要"每步可编译、可回退、可恢复"的稳健推进方式 触发词:自主开发、连续开发、循环开发、一轮一提交、还原原型、批量修复、autonomous dev、continuous dev
Tauri 打包与分发技能,指导桌面端(Windows/macOS/Linux)与移动端(Android/iOS)的构建、签名和分发。 触发场景: - 需要构建生产安装包(exe/dmg/deb/apk/aab/ipa) - 需要配置各平台打包参数 - 需要代码签名(Windows 证书 / Android keystore / iOS 描述文件) - 需要减小安装包体积 - 需要设置应用图标和元数据 - 需要打包 Android / iOS App 触发词: 打包、构建、build、发布、安装包、exe、dmg、deb、apk、aab、ipa、签名、分发、release、android build、ios build、移动端打包
排查已发生的问题、定位 Bug 原因。 触发场景: - 代码运行报错,需要定位原因 - 功能不正常,需要排查 - Tauri Command 返回错误,需要分析 - 日志分析、调试代码 触发词:Bug、报错、不工作、调试、排查、为什么、出问题、失败、不生效、无效、找不到原因、定位问题