본문으로 건너뛰기
cccskills
무료GitHub에 공개

desktop-plugins-tauri

Tauri 2.x official plugin ecosystem, plugin APIs, permissions, and custom plugin development

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

연동 도구PostgreSQLMySQL
설치 방법 보기

포함된 파일(10)

  • SKILL.md17.0 KB
  • examples/core.md6.0 KB
  • examples/custom-plugins.md10.5 KB
  • examples/data-storage.md8.6 KB
  • examples/lifecycle.md8.4 KB
  • examples/mobile.md4.6 KB
  • examples/networking.md4.5 KB
  • examples/system.md5.6 KB
  • metadata.yaml724 B
  • reference.md11.6 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Tauri 2.x Plugin Ecosystem

Quick Guide: Tauri plugins follow a dual-install pattern: Cargo crate (Rust backend) + npm package (JS frontend). Every plugin must be registered with .plugin() in Rust AND have permissions granted in a capability file. Missing any step causes runtime errors, not compile errors. Custom plugins use tauri::plugin::Builder with optional mobile support (Swift/Kotlin). There are 30+ official plugins covering fs, http, dialog, store, notification, shell, updater, sql, log, stronghold, deep-link, global-shortcut, and more.

Current version: Tauri 2.x (stable). All plugins require Rust 1.77.2+.


<critical_requirements>

CRITICAL: Before Using This Skill

(You MUST complete ALL four installation steps for every plugin: 1) cargo add crate, 2) npm install bindings, 3) .plugin() registration in Rust, 4) permissions in capability file -- missing any step causes runtime errors)

(You MUST scope plugin permissions in capability files -- never grant unscoped fs:allow-read-text-file or http:default without URL restrictions)

(You MUST use @tauri-apps/plugin-* npm packages for JS bindings -- not @tauri-apps/api/* which is the core API)

(You MUST use #[cfg(desktop)] guard when registering desktop-only plugins -- mobile builds will fail otherwise)

(You MUST use tauri::plugin::Builder with an init() convention when creating custom plugins -- not raw command registration)

</critical_requirements>


Auto-detection: tauri-plugin, @tauri-apps/plugin, tauri_plugin, plugin registration, .plugin(), tauri-plugin-fs, tauri-plugin-http, tauri-plugin-store, tauri-plugin-dialog, tauri-plugin-notification, tauri-plugin-shell, tauri-plugin-updater, tauri-plugin-log, tauri-plugin-sql, tauri-plugin-stronghold, tauri-plugin-deep-link, tauri-plugin-global-shortcut, tauri-plugin-autostart, tauri-plugin-clipboard-manager, tauri-plugin-window-state, tauri-plugin-single-instance, tauri-plugin-barcode-scanner, tauri-plugin-biometric, tauri-plugin-os, tauri-plugin-process, custom plugin, plugin development, npx tauri plugin new

When to use:

  • Installing and configuring official Tauri plugins
  • Using plugin JavaScript APIs from the frontend
  • Scoping plugin permissions in capability files
  • Creating custom plugins with Rust backend + optional JS API
  • Adding mobile support (Swift/Kotlin) to custom plugins
  • Choosing between plugins for a specific use case (store vs stronghold, fs vs dialog)

When NOT to use:

  • Tauri core framework patterns (commands, invoke, state, events, tray, windows -- use the framework skill)
  • Frontend framework patterns (component architecture, state management -- use respective framework skills)
  • General Rust programming not related to Tauri plugin APIs
  • Build tool or bundler configuration (separate tooling concern)

Key patterns covered:

Detailed resources:


<philosophy>

Philosophy

Tauri plugins extend the core framework with native capabilities through a dual-architecture design: a Rust backend crate providing the implementation, and an npm package providing typed JavaScript bindings. This separation enforces security -- every plugin operation must be explicitly permitted in a capability file.

Plugin architecture principles:

  • Security by default: Plugins do nothing until permissions are granted. Permissions are scoped per-window and can restrict operations to specific paths, URLs, or commands.
  • Dual install: Rust crate handles native operations; npm package provides the typed JS API. Both are required.
  • Platform awareness: Some plugins are desktop-only (shell, autostart, global-shortcut), some are mobile-only (barcode-scanner, biometric, haptics), and many work on both.
  • Convention over configuration: All official plugins follow the same four-step install pattern. Custom plugins use tauri::plugin::Builder with an init() export.

When to use plugins vs custom commands:

  • Need file system, HTTP, notifications, or other OS features? Use the official plugin.
  • Need custom business logic that runs in Rust? Write a Tauri command (framework skill).
  • Need a reusable native capability shared across projects? Write a custom plugin.

When NOT to use a plugin:

  • The JS Web API already covers the need (e.g., navigator.clipboard for simple text copy in some contexts)
  • A custom Tauri command is simpler for a one-off operation
  • The plugin is mobile-only but your app is desktop-only (or vice versa)
</philosophy>
<patterns>

Core Patterns

Pattern 1: Four-Step Plugin Installation

Every official plugin requires exactly four steps. Missing any step causes runtime errors, not compile errors.

# Step 1: Add Rust crate
cargo add tauri-plugin-store

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

# Step 3: Register plugin in Rust (src-tauri/src/lib.rs)
# .plugin(tauri_plugin_store::Builder::new().build())

# Step 4: Add permissions to capability file (src-tauri/capabilities/main.json)
# "store:default"

Why all four steps: Cargo crate = backend implementation, npm package = typed JS bindings, .plugin() = runtime activation, capability permission = frontend authorization. Any missing piece causes a runtime error with an unhelpful message.

Shortcut: cargo tauri add <plugin> handles steps 1 and 3 automatically. You still need npm install (step 2) and permissions (step 4).

See examples/core.md for multi-plugin registration and permission scoping.


Pattern 2: Permission Scoping

Plugins operate under least-privilege. Scope permissions to specific paths, URLs, or commands.

{
  "permissions": [
    "core:default",
    {
      "identifier": "fs:allow-read-text-file",
      "allow": [{ "path": "$APPDATA/**" }]
    },
    {
      "identifier": "http:default",
      "allow": [{ "url": "https://api.example.com/**" }]
    }
  ]
}

Why scoping matters: Unscoped fs:allow-read-text-file grants access to ANY file on the system. Unscoped http:default allows requests to ANY domain. Always restrict to the minimum required scope.

See examples/core.md for shell command scoping and window-specific permissions.


Pattern 3: Desktop-Only Plugin Guard

Desktop-only plugins (shell, autostart, global-shortcut, single-instance, window-state, positioner) must be wrapped in #[cfg(desktop)] to prevent mobile build failures.

tauri::Builder::default()
    .setup(|app| {
        #[cfg(desktop)]
        {
            app.handle().plugin(tauri_plugin_autostart::init(
                tauri_plugin_autostart::MacosLauncher::LaunchAgent,
                None,
            ));
            app.handle().plugin(tauri_plugin_global_shortcut::Builder::new().build());
        }
        Ok(())
    })

Key point: Without #[cfg(desktop)], the Rust compiler will fail on mobile targets because these crates do not support iOS/Android.


Pattern 4: Store vs Stronghold vs SQL

Three storage plugins serve different needs:

PluginUse CaseEncryptionQueryPlatform
StoreApp preferences, settingsNoKey-value onlyAll
StrongholdSecrets, API keys, tokensYes (Argon2)Key-value onlyDesktop
SQLStructured data, relationsNo (app-level)Full SQL (SQLite/MySQL/Postgres)All

Decision: User preferences and simple config? Store. Sensitive credentials? Stronghold. Structured relational data? SQL.

See examples/data-storage.md for complete API examples for each.


Pattern 5: Updater with Signed Releases

The updater plugin requires cryptographic signatures -- this cannot be disabled. Updates check an endpoint, verify the signature, download, and install.

import { check } from "@tauri-apps/plugin-updater";
import { relaunch } from "@tauri-apps/plugin-process";

const update = await check();
if (update) {
  await update.downloadAndInstall((event) => {
    // event.event: "Started" | "Progress" | "Finished"
  });
  await relaunch();
}

Key point: Generate signing keys with cargo tauri signer generate. Set TAURI_SIGNING_PRIVATE_KEY during builds. The public key goes in tauri.conf.json. Losing the private key means you cannot ship updates to existing users.

See examples/lifecycle.md for endpoint JSON format and Rust API.


Pattern 6: Custom Plugin Development

Custom plugins use tauri::plugin::Builder with the init() convention.

use tauri::plugin::{Builder, TauriPlugin};
use tauri::Runtime;

#[tauri::command]
fn my_command() -> String {
    "Hello from plugin".into()
}

pub fn init<R: Runtime>() -> TauriPlugin<R> {
    Builder::new("my-plugin")
        .invoke_handler(tauri::generate_handler![my_command])
        .setup(|app, _api| {
            // Initialize state, start background tasks
            Ok(())
        })
        .build()
}

Key points: Plugin commands are invoked as plugin:my-plugin|my_command from JS. Scaffold a full plugin project with npx @tauri-apps/cli plugin new <name>. The template includes desktop.rs, mobile.rs, permissions, and JS bindings.

See examples/custom-plugins.md for lifecycle hooks, configuration, and mobile support.

</patterns>

<decision_framework>

Decision Framework

Plugin Selection

What native capability do you need?
|
+-- File system read/write?
|   +-- tauri-plugin-fs (scoped to specific directories)
|
+-- File/folder picker dialog?
|   +-- tauri-plugin-dialog (open, save, message, ask)
|
+-- HTTP requests bypassing CORS?
|   +-- tauri-plugin-http (scope to specific domains)
|
+-- Persistent key-value storage?
|   +-- Sensitive data (tokens, keys)? -> tauri-plugin-stronghold
|   +-- App preferences/settings? -> tauri-plugin-store
|
+-- Relational/structured data?
|   +-- tauri-plugin-sql (SQLite, MySQL, PostgreSQL)
|
+-- System notifications?
|   +-- tauri-plugin-notification (check permissions first on macOS/mobile)
|
+-- Run external processes?
|   +-- tauri-plugin-shell (desktop only, scope allowed commands)
|
+-- Auto-update?
|   +-- tauri-plugin-updater (requires signed releases)
|
+-- Structured logging?
|   +-- tauri-plugin-log (targets: stdout, file, webview)
|
+-- Custom URL scheme handling?
|   +-- tauri-plugin-deep-link (configure per-platform)
|
+-- System-wide keyboard shortcuts?
|   +-- tauri-plugin-global-shortcut (desktop only)
|
+-- Launch on system startup?
|   +-- tauri-plugin-autostart (desktop only)
|
+-- Single app instance?
|   +-- tauri-plugin-single-instance (desktop only)
|
+-- Remember window position/size?
|   +-- tauri-plugin-window-state (desktop only)
|
+-- Clipboard access?
|   +-- tauri-plugin-clipboard-manager
|
+-- Mobile camera/scanner?
|   +-- tauri-plugin-barcode-scanner (mobile only)
|
+-- Biometric auth?
|   +-- tauri-plugin-biometric (mobile only)
|
+-- OS/platform info?
|   +-- tauri-plugin-os
|
+-- App restart/exit?
    +-- tauri-plugin-process

Custom Plugin vs Custom Command

Is this a reusable capability shared across projects?
+-- YES -> Custom plugin (npx @tauri-apps/cli plugin new)
+-- NO  -> Is it complex enough to need its own permission model?
    +-- YES -> Custom plugin
    +-- NO  -> Regular Tauri command (simpler, framework skill)

</decision_framework>


<red_flags>

RED FLAGS

High Priority Issues:

  • Missing any of the four installation steps (cargo, npm, .plugin(), permissions) -- causes runtime error with unhelpful message
  • Unscoped filesystem permissions (fs:allow-read-text-file without path restriction) -- grants access to entire filesystem
  • Unscoped HTTP permissions (http:default without URL pattern) -- allows requests to any domain
  • Unscoped shell execute (shell:allow-execute without command allowlist) -- allows running arbitrary commands
  • Using @tauri-apps/api/* imports for plugin functionality -- plugins use @tauri-apps/plugin-* packages
  • Registering desktop-only plugins without #[cfg(desktop)] -- breaks mobile builds
  • Losing the updater signing private key -- makes shipping updates to existing users impossible

Medium Priority Issues:

  • Using Store plugin for sensitive data (API keys, tokens) -- Store is NOT encrypted, use Stronghold
  • Not checking isPermissionGranted() before sending notifications on macOS/mobile
  • Granting shell:allow-execute when only shell:allow-open (URLs/files) is needed
  • Missing sql:allow-execute permission (default only includes read operations)
  • Forgetting to call stronghold.save() after modifications (changes are lost)

Common Mistakes:

  • Installing the cargo crate but forgetting the npm package (or vice versa)
  • Using cargo tauri add and assuming all four steps are done (npm install and permissions still needed)
  • Not scoping HTTP plugin URLs -- allows the app to make requests to arbitrary servers
  • Using the updater plugin on mobile (it is desktop-only)
  • Expecting Store data to persist across app reinstalls (store location depends on app identifier)

Gotchas & Edge Cases:

  • Plugin init variants: Some plugins use .init() (fs, dialog, shell, notification), others use Builder::new().build() (store, updater, global-shortcut, log) -- check each plugin's docs
  • Store autoSave: When autoSave: false, you must call store.save() manually. When autoSave is a number, it debounces saves by that many milliseconds.
  • SQL default permissions: Only read operations (select, load, close) are granted by default -- sql:allow-execute must be added explicitly for INSERT/UPDATE/DELETE
  • Stronghold platform: Desktop-only. Store data as Uint8Array (not strings) -- use TextEncoder/TextDecoder for string conversion
  • Deep link desktop: On desktop, deep links arrive as command-line arguments. Combine with single-instance plugin to handle links when the app is already running.
  • Global shortcut conflicts: Registering a shortcut already bound system-wide (e.g., Ctrl+C) silently fails or overrides the system binding depending on the OS
  • Window-state plugin: Automatically restores window position/size on startup with zero JS code needed -- just register the plugin
  • Plugin registration order: Does not matter. Each .plugin() call is independent.

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

(You MUST complete ALL four installation steps for every plugin: 1) cargo add crate, 2) npm install bindings, 3) .plugin() registration in Rust, 4) permissions in capability file -- missing any step causes runtime errors)

(You MUST scope plugin permissions in capability files -- never grant unscoped fs:allow-read-text-file or http:default without URL restrictions)

(You MUST use @tauri-apps/plugin-* npm packages for JS bindings -- not @tauri-apps/api/* which is the core API)

(You MUST use #[cfg(desktop)] guard when registering desktop-only plugins -- mobile builds will fail otherwise)

(You MUST use tauri::plugin::Builder with an init() convention when creating custom plugins -- not raw command registration)

Failure to follow these rules will cause silent runtime errors, security vulnerabilities from unscoped permissions, or broken mobile builds.

</critical_reminders>

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

agents-inc의 스킬 모두 보기

이 스킬의 문제 신고