mcpField
T
tauri-v2

tauri-v2

github.com/robinebers開発4.5k43 回インストール今日更新
リポジトリ

tauri-v2 について

tauri-v2 は、Web フロントエンドと Rust バックエンドを使う Tauri v2 のデスクトップ・モバイルアプリ開発向けスキルです。コマンド、権限、状態管理、IPC、ビルドの実装パターンとトラブルシューティングを開発者に提供します。

主な機能

  1. 01Tauri v2 のコマンドと IPC パターン
  2. 02ケイパビリティと権限の設定
  3. 03Rust の状態管理とエラー処理
  4. 04イベント送信とチャネルストリーミング
  5. 05ビルド設定とトラブルシューティング

活用シーン

  1. 01フロントエンドから呼び出す Rust コマンドの登録
  2. 02権限や IPC の問題の調査
  3. 03Tauri アプリのモバイルビルド準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/robinebers/openusage --skill tauri-v2

インストール後、Claude Code で/tauri-v2を入力して読み込まれたか確認します。

同梱ファイルreferences/capabilities-reference.mdreferences/ipc-patterns.md

詳細

Tauri v2 開発スキル

Web フロントエンドと Rust バックエンドで、クロスプラットフォームのデスクトップアプリやモバイルアプリを構築します。

始める前に

このスキルを使うと、よくあるエラーを 8 件以上防ぎ、トークンを約 60%節約できます。

指標スキルなしスキルあり
セットアップ時間約 2 時間約 30 分
よくあるエラー8 件以上0 件
トークン使用量多い(調査)少ない(直接的なパターン)
このスキルで防げる既知の問題
  1. ケーパビリティ不足によるアクセス拒否エラー
  2. generate_handler! にコマンドが登録されていないことによる IPC の失敗
  3. 型の不一致による状態管理のパニック
  4. Rust ターゲット不足によるモバイルビルドの失敗
  5. 開発用 URL の設定ミスによるホワイトスクリーン

クイックスタート

ステップ 1:Tauri コマンドを作成する
// src-tauri/src/lib.rs
#[tauri::command]
fn greet(name: String) -> String {
    format!("Hello, {}!", name)
}

pub fn run() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

重要な理由: generate_handler![] に含まれていないコマンドは、フロントエンドから呼び出してもエラーが表示されずに失敗します。

ステップ 2:フロントエンドから呼び出す
import { invoke } from '@tauri-apps/api/core';

const greeting = await invoke<string>('greet', { name: 'World' });
console.log(greeting); // "Hello, World!"

重要な理由: @tauri-apps/api/tauri ではなく、@tauri-apps/api/core を使用してください(前者は 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 を使用する(モバイルビルドで必須)
絶対に行わないこと
  • 非同期コマンドでは借用型(&str)を使用せず、所有型を使用する
  • メインスレッドをブロックせず、I/O 操作には非同期処理を使用する
  • パスをハードコードせず、Tauri のパス API(app.path())を使用する
  • ケーパビリティの設定を省略しない。「安全な」操作にも権限が必要です
よくある間違い

誤り — 非同期処理での借用型:

#[tauri::command]
async fn bad(name: &str) -> String { // Compile error!
    name.to_string()
}

正しい — 所有型:

#[tauri::command]
async fn good(name: String) -> String {
    name
}

理由: 非同期コマンドでは await ポイントをまたいでデータを借用できません。Tauri では非同期コマンドのパラメーターに所有型が必要です。

既知の問題を防ぐ

問題根本原因解決策
「コマンドが見つからない」generate_handler! への登録漏れコマンドをハンドラーマクロに追加する
「アクセスが拒否された」ケーパビリティ不足capabilities/default.json に追加する
状態へのアクセス時にパニックState<T> の型の不一致.manage() で指定した型と完全に一致させる
起動時にホワイトスクリーンが表示されるフロントエンドがビルドされていない設定の beforeDevCommand を確認する
IPC のタイムアウト非同期コマンドがブロックされているブロッキングコードを削除するか、spawn を使用する
モバイルビルドの失敗Rust ターゲット不足rustup target add <target> を実行する

設定リファレンス

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:ケーパビリティファイル識別子の配列
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 種類すべてを含める必要があります

よく使われるパターン

エラー処理パターン
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())
}
状態管理パターン
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
}

// In builder:
tauri::Builder::default()
    .manage(Mutex::new(AppState { counter: 0 }))
イベント発行パターン
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);
});
// Call unlisten() when done
チャネルストリーミングパターン
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 });

同梱リソース

リファレンス

references/ にあります:

注: 特定のトピックを詳しく調べる場合は、上記のリファレンスファイルを参照してください。

依存関係

必須
パッケージバージョン用途
@tauri-apps/cli^2.0.0CLI ツール
@tauri-apps/api^2.0.0フロントエンド API
tauri^2.0.0Rust コア
tauri-build^2.0.0ビルドスクリプト
オプション(プラグイン)
パッケージバージョン用途
tauri-plugin-fs^2.0.0ファイルシステムへのアクセス
tauri-plugin-dialog^2.0.0ネイティブダイアログ
tauri-plugin-shell^2.0.0シェルコマンド、URL を開く
tauri-plugin-http^2.0.0HTTP クライアント
tauri-plugin-store^2.0.0キーと値のストレージ

公式ドキュメント

トラブルシューティング

起動時に画面が白くなる

症状: アプリは起動するものの、画面が白いままです

解決方法:

  1. devUrl がフロントエンドの開発サーバーのポートと一致していることを確認します
  2. beforeDevCommand で開発サーバーが起動することを確認します
  3. DevTools(Cmd+Option+I / Ctrl+Shift+I)を開いてエラーを確認します
コマンドが undefined を返す

症状: invoke() が期待する値ではなく undefined を返します

解決方法:

  1. コマンドが generate_handler![] に登録されていることを確認します
  2. Rust のコマンドが実際に値を返すことを確認します
  3. 引数名が一致していることを確認します(デフォルトでは JS では camelCase、Rust では snake_case)
モバイルビルドの失敗

症状: Android/iOS のビルドが、ターゲットが見つからないというエラーで失敗します

解決方法:

# Android targets
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android

# iOS targets (macOS only)
rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim

セットアップチェックリスト

このスキルを使用する前に、以下を確認してください。

  • npx tauri info に正しい Tauri v2 のバージョンが表示される
  • src-tauri/capabilities/default.json が存在し、少なくとも core:default が設定されている
  • すべてのコマンドが generate_handler![] に登録されている
  • lib.rs に共有コードが含まれている(モバイルサポート用)
  • 対象プラットフォームに必要な Rust ターゲットがインストールされている

コメント