tauri-v2
Tauri v2以降を使ったRustバックエンドによるクロスプラットフォームアプリ開発を支援します。`tauri.conf.json`の設定、Rustコマンド(`#[tauri::command]`)の実装、IPCパターン(invoke・emit・channels)のセットアップ、パーミッション/ケイパビリティの設定、ビルドトラブルの解決、デスクトップ/モバイルアプリのデプロイ時に活用できます。`Tauri`・`src-tauri`・`invoke`・`emit`・`capabilities.json`をトリガーに起動します。
description の原文を見る
Tauri v2+ cross-platform app development with Rust backend. Use when configuring tauri.conf.json, implementing Rust commands (#[tauri::command]), setting up IPC patterns (invoke, emit, channels), configuring permissions/capabilities, troubleshooting build issues, or deploying desktop/mobile apps. Triggers on Tauri, src-tauri, invoke, emit, capabilities.json.
SKILL.md 本文
Tauri v2+ Development Skill
Web フロントエンドと Rust バックエンドを使用して、クロスプラットフォームのデスクトップおよびモバイルアプリを構築します。
始める前に
このスキルは 8+ 個の一般的なエラーを防ぎ、トークン使用量を約 60% 削減します。
| メトリクス | スキルなし | スキルあり |
|---|---|---|
| セットアップ時間 | 約 2 時間 | 約 30 分 |
| 一般的なエラー | 8+ | 0 |
| トークン使用量 | 高(探索) | 低(直接パターン) |
このスキルが防止する既知の問題
- 機能がない場合の許可拒否エラー
generate_handler!に未登録のコマンドによる IPC 失敗- 型の不一致によるステート管理パニック
- Rust ターゲットが欠落しているモバイルビルド失敗
- 不正に設定された開発 URL によるホワイトスクリーン問題
クイックスタート
ステップ 1: Tauri コマンドを作成
// src-tauri/src/lib.rs
#[tauri::command]
fn greet(name: String) -> String {
format!("Hello, {}!", name)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
重要な理由: generate_handler![] に登録されていないコマンドは、フロントエンドから呼び出されると暗黙的に失敗します。
main.rsは薄いままに保つ:src-tauri/src/main.rsは単なる薄いパススルーであり、すべてのアプリケーションロジックはlib.rsに存在する必要があります:// src-tauri/src/main.rs #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { app_lib::run(); }この分割はモバイルビルドに必須です — Tauri はモバイルターゲットで
main()をmobile_entry_pointに置き換えます。
ステップ 2: フロントエンドから呼び出し
import { invoke } from '@tauri-apps/api/core';
const greeting = await invoke<string>('greet', { name: 'World' });
console.log(greeting); // "Hello, World!"
重要な理由: @tauri-apps/api/core を使用します(@tauri-apps/api/tauri は v1 API です)。
ステップ 3: 必要な許可を追加
// src-tauri/capabilities/default.json
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"windows": ["main"],
"permissions": ["core:default"]
}
重要な理由: Tauri v2 はデフォルトですべてを拒否します - すべての操作に明示的な許可が必要です。
重要なルール
必ず行うこと
tauri::generate_handler![cmd1, cmd2, ...]にすべてのコマンドを登録する- コマンドから適切なエラーハンドリングのために
Result<T, E>を返す - 複数のコマンドからアクセスされる共有状態には
Mutex<T>を使用する - プラグイン機能を使用する前に機能を追加する
- 共有コードに
lib.rsを使用する(モバイルビルドに必須) - モバイル互換性のために
lib.rsのpub fn run()に#[cfg_attr(mobile, tauri::mobile_entry_point)]を使用する
絶対にしてはいけないこと
- 非同期コマンドで借用型(
&str)を使用しない - 所有型を使用する - メインスレッドをブロックしない - I/O 操作に非同期を使用する
- パスをハードコーディングしない - Tauri パス API を使用する(
app.path()) - 機能セットアップをスキップしない - 「安全な」操作でも許可が必要です
一般的なエラー
間違い - 非同期で借用型を使用:
#[tauri::command]
async fn bad(name: &str) -> String { // コンパイルエラー!
name.to_string()
}
正解 - 所有型を使用:
#[tauri::command]
async fn good(name: String) -> String {
name
}
理由: 非同期コマンドは await ポイント全体でデータを借用できません;Tauri は非同期コマンドパラメータに所有型を要求します。
既知の問題の防止
| 問題 | 根本原因 | 解決策 |
|---|---|---|
| "Command not found" | generate_handler! に欠落 | コマンドをハンドラマクロに追加 |
| "Permission denied" | 機能が欠落 | capabilities/default.json に追加 |
| プラグイン機能が暗黙的に失敗 | プラグインインストール済みだが機能に許可がない | プラグイン許可文字列を capabilities/default.json に追加 |
| 本番環境でアップデータが失敗 | 署名されていない成果物または HTTP エンドポイント | cargo tauri signer generate でキーを生成し、HTTPS エンドポイントのみを使用 |
| サイドカーが見つからない | tauri.conf.json に externalBin がないか実行ファイルが欠落 | パスを bundle.externalBin に追加し、バイナリがバンドルされていることを確認 |
| デスクトップでは機能するがモバイルで破損 | デスクトップ専用 API を使用 | API がモバイルサポートを持つかどうかを確認 — 一部プラグインはデスクトップ専用です |
| ステート アクセス時にパニック | State<T> の型の不一致 | .manage() から正確な型を使用 |
| 起動時にホワイトスクリーン | フロントエンドがビルドされていない | 設定で beforeDevCommand を確認 |
| IPC タイムアウト | ブロッキング非同期コマンド | ブロッキングコードを削除するか spawn を使用 |
| モバイルビルド失敗 | Rust ターゲットが欠落 | rustup target add <target> を実行 |
詳細リファレンス
- セキュリティと許可 →
references/capabilities-reference.md - IPC 決定ガイド →
references/ipc-patterns.md - 公式プラグイン →
references/plugin-reference.md - アップデーターと配布 →
references/updater-distribution-reference.md - トレイ、サイドカー、ディープリンク →
references/advanced-runtime-reference.md
設定リファレンス
tauri.conf.json
{
"$schema": "./gen/schemas/desktop-schema.json",
"productName": "my-app",
"version": "1.0.0",
"identifier": "com.example.myapp",
"build": {
"devUrl": "http://localhost:5173",
"frontendDist": "../dist",
"beforeDevCommand": "npm run dev",
"beforeBuildCommand": "npm run build"
},
"app": {
"windows": [{
"label": "main",
"title": "My App",
"width": 800,
"height": 600
}],
"security": {
"csp": "default-src 'self'; img-src 'self' data:",
"capabilities": ["default"]
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": ["icons/icon.icns", "icons/icon.ico", "icons/icon.png"]
}
}
重要な設定:
build.devUrl: フロントエンド開発サーバーのポートと一致する必要がありますapp.security.capabilities: 機能ファイル識別子の配列
プラグイン設定 — いくつかのプラグインは追加の tauri.conf.json ブロック(例:store、updater)を要求します。常に v2.tauri.app/plugin/<plugin-name>/ で特定のプラグインドキュメントを確認して、必須の設定キーを確認してください。
プロジェクト構造
my-tauri-app/
├── src/ # フロントエンドソース
├── src-tauri/
│ ├── src/
│ │ ├── main.rs # 薄いパススルー — lib::run() を呼び出し
│ │ └── lib.rs # すべてのアプリケーションロジックはここに存在
│ ├── capabilities/
│ │ └── default.json # 機能定義(ここで許可を付与)
│ ├── tauri.conf.json # アプリ設定(devUrl、バンドル、セキュリティ)
│ ├── Cargo.toml # Rust の依存関係
│ └── build.rs # ビルドスクリプト(tauri-build に必須)
└── package.json
lib.rs がすべてのロジックを所有する理由: Tauri はモバイルで main() を #[cfg_attr(mobile, tauri::mobile_entry_point)] に置き換えます。すべてのコマンド、ステート、ビルダー設定は lib.rs::run() に存在する必要があります。
Cargo.toml
[package]
name = "app"
version = "0.1.0"
edition = "2021"
[lib]
name = "app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2", features = [] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
重要な設定:
[lib]セクション:モバイルビルドに必須crate-type: クロスプラットフォームの3つのタイプをすべて含める必要があります
一般的なパターン
エラーハンドリング パターン
Result<T, E> と thiserror を使用して、IPC 境界全体での型安全なエラー伝播を行います。完全な実装詳細は を参照してください。references/ipc-patterns.md
use thiserror::Error;
#[derive(Debug, Error)]
enum AppError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Not found: {0}")]
NotFound(String),
}
impl serde::Serialize for AppError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where S: serde::ser::Serializer {
serializer.serialize_str(self.to_string().as_ref())
}
}
#[tauri::command]
fn risky_operation() -> Result<String, AppError> {
Ok("success".into())
}
Serde 境界ルール
すべてのコマンド引数は serde::Deserialize を実装し、戻り値の型は serde::Serialize を実装する必要があります。これは、Tauri が IPC 境界全体で JSON をブリッジする方法です。
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct CreateUserArgs {
name: String,
email: String,
role: Option<String>, // オプションフィールドは Option<T> を使用
}
#[derive(Serialize)]
struct User {
id: u64,
name: String,
}
#[tauri::command]
fn create_user(args: CreateUserArgs) -> Result<User, String> {
Ok(User { id: 1, name: args.name })
}
一般的な serde の落とし穴:
- フィールド名は JS では camelCase、Rust では snake_case です — Tauri は自動的に変換します
Option<T>はオプションの JS 引数にマップします(undefinedまたはnullにできます)- 複雑な列挙型は JSON 安全にするために
#[serde(tag = "type")]または類似が必要です - エラー型も
Serializeを実装する必要があります(上記のエラーハンドリング パターンを参照)
ステート管理 パターン
Tauri ステートはコマンド全体でアプリケーションデータを管理します。より複雑なステートパターンについては を参照してください。references/ipc-patterns.md
use std::sync::Mutex;
use tauri::State;
struct AppState {
counter: u32,
}
#[tauri::command]
fn increment(state: State<'_, Mutex<AppState>>) -> u32 {
let mut s = state.lock().unwrap();
s.counter += 1;
s.counter
}
// ビルダーで:
tauri::Builder::default()
.manage(Mutex::new(AppState { counter: 0 }))
イベント発行 パターン
イベントはファイア・アンド・フォーゲット通知です。双方向の例については を参照してください。references/ipc-patterns.md
use tauri::Emitter;
#[tauri::command]
fn start_task(app: tauri::AppHandle) {
std::thread::spawn(move || {
app.emit("task-progress", 50).unwrap();
app.emit("task-complete", "done").unwrap();
});
}
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen('task-progress', (e) => {
console.log('Progress:', e.payload);
});
// 完了時に unlisten() を呼び出す
チャネル ストリーミング パターン
チャネルは、Rust からフロントエンドへの高周波数のタイプ付きストリーミングを提供します。完全な実装詳細は を参照してください。references/ipc-patterns.md
use tauri::ipc::Channel;
#[derive(Clone, serde::Serialize)]
#[serde(tag = "event", content = "data")]
enum DownloadEvent {
Progress { percent: u32 },
Complete { path: String },
}
#[tauri::command]
async fn download(url: String, on_event: Channel<DownloadEvent>) {
for i in 0..=100 {
on_event.send(DownloadEvent::Progress { percent: i }).unwrap();
}
on_event.send(DownloadEvent::Complete { path: "/downloads/file".into() }).unwrap();
}
import { invoke, Channel } from '@tauri-apps/api/core';
const channel = new Channel<DownloadEvent>();
channel.onmessage = (msg) => console.log(msg.event, msg.data);
await invoke('download', { url: 'https://...', onEvent: channel });
ウィンドウアクセス パターン
Tauri v2 は、統一されたウィンドウと webview 管理に WebviewWindow を使用します。
use tauri::Manager;
#[tauri::command]
fn focus_window(app: tauri::AppHandle) {
if let Some(window) = app.get_webview_window("main") {
let _ = window.set_focus();
}
}
重要な理由: v2 では tauri::WebviewWindow と app.get_webview_window("label") を使用します — v1 の app.get_window() API は v2 で削除されました。
バンドルされたリソース
リファレンス
references/ にあります:
- 許可パターンと例capabilities-reference.md- 完全な IPC 例ipc-patterns.md- 公式プラグインのインストール、登録、許可文字列plugin-reference.md- 署名、HTTPS 要件、バンドル配布updater-distribution-reference.md-advanced-runtime-reference.mdTrayIconBuilder、サイドカー、ディープリンク、アセットプロトコル
注: 特定のトピックについて詳しく知りたい場合は、上記のリファレンスファイルを参照してください。
依存関係
必須
| パッケージ | バージョン | 目的 |
|---|---|---|
@tauri-apps/cli | ^2 (v2+) | CLI ツール |
@tauri-apps/api | ^2 (v2+) | フロントエンド API |
tauri | ^2 (v2+) | Rust コア |
tauri-build | ^2 (v2+) | ビルドスクリプト |
*最終確認:2026-04-02。機能のタイミングについては常に公式チェンジログを確認してください。
オプション(プラグイン)
| パッケージ | バージョン | 目的 | 重要な許可 |
|---|---|---|---|
tauri-plugin-fs | ^2 (v2+) | ファイルシステムアクセス | fs:default |
tauri-plugin-dialog | ^2 (v2+) | ネイティブダイアログ | dialog:default |
tauri-plugin-shell | ^2 (v2+) | シェルコマンド、URL 開く | shell:default |
tauri-plugin-http | ^2 (v2+) | HTTP クライアント | http:default |
tauri-plugin-store | ^2 (v2+) | キー値ストレージ | store:default |
プラグイン許可は必須です。 プラグインをインストールしても、許可文字列を機能ファイルに追加しないと、実行時にサイレント失敗します。すべての公式プラグインの完全なインストール + 許可詳細については、
を参照してください。references/plugin-reference.md
公式ドキュメント
トラブルシューティング
起動時にホワイトスクリーン
症状: アプリが起動するが、空の白い画面を表示
解決策:
devUrlがフロントエンド開発サーバーのポートと一致していることを確認beforeDevCommandが開発サーバーを実行していることを確認- DevTools(Cmd+Option+I / Ctrl+Shift+I)を開いてエラーを確認
コマンドが Undefined を返す
症状: invoke() が予期された値の代わりに undefined を返す
解決策:
- コマンドが
generate_handler![]に存在することを確認 - Rust コマンドが実際に値を返していることを確認
- 引数名が一致していることを確認(JS では camelCase、Rust では snake_case)
モバイルビルド失敗
症状: Android/iOS ビルドが欠落したターゲットで失敗
解決策:
# Android ターゲット
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
# iOS ターゲット(macOS のみ)
rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim
デスクトップとモバイル間の動作の違い
すべての Tauri API とプラグインがモバイル(iOS/Android)をサポートしているわけではありません。モバイルビルドでプラグインまたは API を使用する前に:
- プラグインページを確認 -
v2.tauri.app/plugin/<name>/でプラットフォームサポートマトリックスを確認 - デスクトップ専用の一般的なアイテム:システムトレイ(
TrayIconBuilder)、ウィンドウラベル/マルチウィンドウ、一部のシェルプラグイン機能 - モバイルセーフなパターン:IPC コマンド/イベント/チャネルはすべてのプラットフォームで機能;
tauri::AppHandleはモバイルセーフ - 条件付きコンパイル:プラットフォーム固有の Rust ロジックに
#[cfg(desktop)]/#[cfg(mobile)]を使用
#[tauri::command]
fn platform_info() -> String {
#[cfg(desktop)]
return "desktop".to_string();
#[cfg(mobile)]
return "mobile".to_string();
}
セットアップ チェックリスト
このスキルを使用する前に、以下を確認してください:
-
npx tauri infoが正しい Tauri v2 バージョンを表示 -
src-tauri/capabilities/default.jsonが少なくともcore:defaultで存在 - すべてのコマンドが
generate_handler![]に登録されている -
lib.rsに共有コード が含まれている(モバイルサポートの場合) - ターゲットプラットフォームに必要な Rust ターゲットがインストール
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- nodnarbnitram
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/nodnarbnitram/claude-code-extensions / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。