Agent skill

managing-tauri-plugin-permissions

Guides users through configuring Tauri plugin permissions, capabilities, and security. Covers platform-specific capabilities, window-targeted permissions, using official and community plugin permissions, and writing custom plugin permissions with scopes.

Stars 12
Forks 1

Install this agent skill to your Project

npx add-skill https://github.com/dchuk/claude-code-tauri-skills/tree/main/tauri/tauri-plugin-permissions

SKILL.md

Managing Tauri Plugin Permissions

Tauri's capability and permission system provides granular security control for desktop and mobile applications. This skill covers configuring capabilities for windows and platforms, using plugin permissions effectively, and writing custom plugin permissions.

Core Concepts

Capabilities

Capabilities are JSON configuration files that assign permissions to specific windows and platforms. They follow the principle of least privilege.

Location: src-tauri/capabilities/

Structure:

json
{
  "identifier": "capability-name",
  "description": "Human-readable purpose",
  "local": true,
  "windows": ["window-label"],
  "permissions": ["plugin:allow-action"],
  "platforms": ["linux", "windows", "macos", "android", "ios"]
}

Permission Levels

Permissions operate at two levels:

  • Commands: Individual operations (e.g., allow-write-text-file)
  • Scopes: Path-based restrictions defining accessible files/directories

Platform-Specific Capabilities

Targeting Platforms

Restrict capabilities to specific operating systems using the platforms field:

json
{
  "identifier": "desktop-fs-access",
  "description": "Filesystem access for desktop platforms",
  "windows": ["main"],
  "permissions": ["fs:allow-home-read"],
  "platforms": ["linux", "windows", "macos"]
}

Available platforms: linux, windows, macos, android, ios

Mobile-Only Capabilities

json
{
  "identifier": "mobile-camera",
  "description": "Camera access for mobile devices",
  "windows": ["main"],
  "permissions": ["camera:allow-capture"],
  "platforms": ["android", "ios"]
}

Window-Specific Capabilities

Configuring Multiple Windows

Define windows in tauri.conf.json:

json
{
  "windows": [
    {
      "label": "main",
      "title": "Main Window",
      "width": 800,
      "height": 600
    },
    {
      "label": "settings",
      "title": "Settings",
      "width": 400,
      "height": 300
    }
  ]
}

Assigning Capabilities to Windows

Create separate capability files for each window's needs:

src-tauri/capabilities/main-window.json:

json
{
  "identifier": "main-window-capabilities",
  "description": "Full access for main window",
  "local": true,
  "windows": ["main"],
  "permissions": [
    "fs:allow-home-read",
    "fs:allow-home-write",
    "dialog:allow-open",
    "dialog:allow-save"
  ]
}

src-tauri/capabilities/settings-window.json:

json
{
  "identifier": "settings-window-capabilities",
  "description": "Limited access for settings window",
  "local": true,
  "windows": ["settings"],
  "permissions": [
    "fs:allow-app-read",
    "fs:allow-app-write"
  ]
}

Shared Capabilities Across Windows

json
{
  "identifier": "shared-dialog",
  "description": "Dialog access for multiple windows",
  "local": true,
  "windows": ["main", "settings"],
  "permissions": ["dialog:allow-ask", "dialog:allow-message"]
}

Using Plugin Permissions

Default Permission Sets

Every plugin provides a default permission set with baseline access. Enable it with:

json
{
  "permissions": ["plugin-name:default"]
}

Finding Available Permissions

  1. Official plugins: Check Tauri documentation's permission tables
  2. Plugin source: Look in permissions/autogenerated directories
  3. Community plugins: Check repository or crates.io page

Permission Identifier Format

plugin-name:permission-name

Examples:

  • fs:allow-read
  • fs:allow-write-text-file
  • dialog:allow-open
  • shell:allow-spawn

Configuring with Scopes

Restrict permissions to specific paths:

json
{
  "identifier": "default",
  "description": "Main window capabilities",
  "windows": ["main"],
  "permissions": [
    "fs:allow-write-text-file",
    {
      "identifier": "fs:allow-read",
      "allow": [{ "path": "$HOME/Documents/**" }]
    },
    {
      "identifier": "fs:allow-write",
      "allow": [{ "path": "$APP/**" }]
    }
  ]
}

Common Scope Variables

Variable Description
$APP Application data directory
$HOME User home directory
$RESOURCE Application resources
$TEMP Temporary directory
$DESKTOP User desktop
$DOCUMENT User documents
$DOWNLOAD User downloads

Deny Permissions

Explicitly deny specific operations:

json
{
  "permissions": [
    "fs:default",
    "fs:deny-write-text-file"
  ]
}

Writing Custom Plugin Permissions

Plugin Structure

Create a plugin with the Tauri CLI:

bash
cargo tauri plugin new my-plugin
cd tauri-plugin-my-plugin

Implementing Commands

src/commands.rs:

rust
use tauri::{command, AppHandle, Runtime};

#[command]
pub(crate) async fn read_data<R: Runtime>(
    key: String,
    app: AppHandle<R>,
) -> Result<String, String> {
    // Implementation
    Ok(format!("Data for key: {}", key))
}

#[command]
pub(crate) async fn write_data<R: Runtime>(
    key: String,
    value: String,
    app: AppHandle<R>,
) -> Result<(), String> {
    // Implementation
    Ok(())
}

#[command]
pub(crate) async fn delete_data<R: Runtime>(
    key: String,
    app: AppHandle<R>,
) -> Result<(), String> {
    // Implementation
    Ok(())
}

Auto-Generating Permissions

src/build.rs:

rust
const COMMANDS: &[&str] = &["read_data", "write_data", "delete_data"];

fn main() {
    tauri_plugin::Builder::new(COMMANDS)
        .global_api_script_path("./api-iife.js")
        .build();
}

This generates:

  • allow-read-data / deny-read-data
  • allow-write-data / deny-write-data
  • allow-delete-data / deny-delete-data

Defining Default Permissions

permissions/default.toml:

toml
"$schema" = "schemas/schema.json"

[default]
description = "Default permissions for my-plugin. Allows read operations only."
permissions = ["allow-read-data"]

Creating Permission Sets

permissions/read-write.toml:

toml
"$schema" = "schemas/schema.json"

[[set]]
identifier = "read-write"
description = "Allows both read and write operations"
permissions = ["allow-read-data", "allow-write-data"]

permissions/full-access.toml:

toml
"$schema" = "schemas/schema.json"

[[set]]
identifier = "full-access"
description = "Allows all operations including delete"
permissions = ["allow-read-data", "allow-write-data", "allow-delete-data"]

Registering Commands

src/lib.rs:

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

mod commands;

pub fn init<R: Runtime>() -> TauriPlugin<R> {
    Builder::new("my-plugin")
        .invoke_handler(tauri::generate_handler![
            commands::read_data,
            commands::write_data,
            commands::delete_data,
        ])
        .build()
}

Frontend JavaScript Bindings

guest-js/index.ts:

typescript
import { invoke } from '@tauri-apps/api/core';

export async function readData(key: string): Promise<string> {
  return await invoke('plugin:my-plugin|read_data', { key });
}

export async function writeData(key: string, value: string): Promise<void> {
  return await invoke('plugin:my-plugin|write_data', { key, value });
}

export async function deleteData(key: string): Promise<void> {
  return await invoke('plugin:my-plugin|delete_data', { key });
}

Using Custom Plugin Permissions

In your application's capability file:

json
{
  "identifier": "default",
  "windows": ["main"],
  "permissions": [
    "my-plugin:default",
    "my-plugin:read-write",
    "my-plugin:allow-delete-data"
  ]
}

Complete Example: Cross-Platform App

src-tauri/capabilities/desktop.json:

json
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "desktop",
  "windows": ["main"],
  "platforms": ["linux", "windows", "macos"],
  "permissions": [
    "core:default",
    "fs:default",
    { "identifier": "fs:allow-read", "allow": [{ "path": "$HOME/Documents/**" }] },
    { "identifier": "fs:allow-write", "allow": [{ "path": "$APP/**" }] },
    "dialog:allow-open",
    "dialog:allow-save",
    "shell:allow-open"
  ]
}

src-tauri/capabilities/mobile.json:

json
{
  "identifier": "mobile",
  "windows": ["main"],
  "platforms": ["android", "ios"],
  "permissions": [
    "fs:allow-app-read",
    "fs:allow-app-write",
    "notification:default"
  ]
}

Best Practices

Security

  1. Principle of least privilege: Grant only required permissions
  2. Use scopes: Restrict file access to specific paths rather than broad permissions
  3. Separate by window: Each window should have only the permissions it needs
  4. Platform targeting: Avoid granting mobile permissions on desktop and vice versa

Organization

  1. Organize by function: Group capabilities by feature area
  2. Use descriptive identifiers: Make capability purposes clear
  3. Document permissions: Include descriptions explaining why each permission is needed

Plugin Development

  1. Minimal defaults: Default permission sets should be restrictive
  2. Create permission sets: Offer tiered access levels (read-only, read-write, full)
  3. Use auto-generation: Let Tauri generate allow/deny permissions for commands
  4. Test permissions: Verify permission behavior with example applications

Troubleshooting

Permission Denied Errors

If you encounter permission errors:

  1. Check capability file syntax (valid JSON)
  2. Verify the window label matches your configuration
  3. Confirm the permission identifier is correct
  4. Check if a scope is required for path-based operations

Capability Not Applied

  1. Ensure capability files are in src-tauri/capabilities/
  2. Verify the windows array contains the correct window labels
  3. Check platforms includes your target OS
  4. Rebuild the application after capability changes

References

Expand your agent's capabilities with these related and highly-rated skills.

dchuk/claude-code-tauri-skills

understanding-tauri-ipc

Teaches the assistant about Tauri IPC (Inter-Process Communication) patterns including brownfield and isolation approaches for secure message passing between frontend and Rust backend.

12 1
Explore
dchuk/claude-code-tauri-skills

testing-tauri-apps

Guides developers through testing Tauri applications including unit testing with mock runtime, mocking Tauri APIs, WebDriver end-to-end testing with Selenium and WebdriverIO, and CI integration with GitHub Actions.

12 1
Explore
dchuk/claude-code-tauri-skills

migrating-tauri-apps

Assists users with migrating Tauri applications from v1 to v2 stable, and from v2 beta to v2 stable, covering breaking changes, configuration updates, API migrations, and plugin system changes.

12 1
Explore
dchuk/claude-code-tauri-skills

developing-tauri-plugins

Guides the user through Tauri plugin development, including creating plugin extensions, configuring permissions, and building mobile plugins for iOS and Android platforms.

12 1
Explore
dchuk/claude-code-tauri-skills

optimizing-tauri-binary-size

Guides users through Tauri binary size optimization techniques to produce small, efficient desktop application bundles using Cargo profile settings and build configurations.

12 1
Explore
dchuk/claude-code-tauri-skills

debugging-tauri-apps

Helps users debug Tauri v2 applications across VS Code, RustRover, IntelliJ, and Neovim. Covers console debugging, WebView DevTools, Rust backtrace, CrabNebula DevTools integration, and IDE-specific launch configurations.

12 1
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results